Only acquire resources as required in gstreamer backend.

Make resources required for capture optional and disable just the
capture features if they are not available, so the camera viewfinder
can be displayed and images captured without blocking the music
playback and the other way around.

Change-Id: Ic9692195156d994ccd4a911ae41d2242a00d575b
Reviewed-by: John Brooks <john.brooks@dereferenced.net>
Reviewed-by: Yoann Lopes <yoann.lopes@digia.com>
This commit is contained in:
Andrew den Exter
2013-12-11 14:29:57 +10:00
committed by The Qt Project
parent b27913b76d
commit 15025088ea
12 changed files with 107 additions and 25 deletions

View File

@@ -201,7 +201,9 @@ void CameraBinControl::updateStatus()
case QCamera::LoadedState: case QCamera::LoadedState:
switch (sessionState) { switch (sessionState) {
case QCamera::UnloadedState: case QCamera::UnloadedState:
m_status = QCamera::LoadingStatus; m_status = m_resourcePolicy->isResourcesGranted()
? QCamera::LoadingStatus
: QCamera::UnavailableStatus;
break; break;
case QCamera::LoadedState: case QCamera::LoadedState:
m_status = QCamera::LoadedStatus; m_status = QCamera::LoadedStatus;
@@ -214,7 +216,9 @@ void CameraBinControl::updateStatus()
case QCamera::ActiveState: case QCamera::ActiveState:
switch (sessionState) { switch (sessionState) {
case QCamera::UnloadedState: case QCamera::UnloadedState:
m_status = QCamera::LoadingStatus; m_status = m_resourcePolicy->isResourcesGranted()
? QCamera::LoadingStatus
: QCamera::UnavailableStatus;
break; break;
case QCamera::LoadedState: case QCamera::LoadedState:
m_status = QCamera::StartingStatus; m_status = QCamera::StartingStatus;

View File

@@ -73,6 +73,8 @@ public:
bool canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const; bool canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const;
bool viewfinderColorSpaceConversion() const; bool viewfinderColorSpaceConversion() const;
CamerabinResourcePolicy *resourcePolicy() { return m_resourcePolicy; }
public slots: public slots:
void reloadLater(); void reloadLater();
void setViewfinderColorSpaceConversion(bool enabled); void setViewfinderColorSpaceConversion(bool enabled);

View File

@@ -40,9 +40,11 @@
****************************************************************************/ ****************************************************************************/
#include "camerabinimagecapture.h" #include "camerabinimagecapture.h"
#include "camerabincontrol.h"
#include "camerabincapturedestination.h" #include "camerabincapturedestination.h"
#include "camerabincapturebufferformat.h" #include "camerabincapturebufferformat.h"
#include "camerabinsession.h" #include "camerabinsession.h"
#include "camerabinresourcepolicy.h"
#include <private/qgstvideobuffer_p.h> #include <private/qgstvideobuffer_p.h>
#include <private/qvideosurfacegstsink_p.h> #include <private/qvideosurfacegstsink_p.h>
#include <private/qgstutils_p.h> #include <private/qgstutils_p.h>
@@ -68,6 +70,7 @@ CameraBinImageCapture::CameraBinImageCapture(CameraBinSession *session)
connect(m_session, SIGNAL(stateChanged(QCamera::State)), SLOT(updateState())); connect(m_session, SIGNAL(stateChanged(QCamera::State)), SLOT(updateState()));
connect(m_session, SIGNAL(imageExposed(int)), this, SIGNAL(imageExposed(int))); connect(m_session, SIGNAL(imageExposed(int)), this, SIGNAL(imageExposed(int)));
connect(m_session, SIGNAL(imageCaptured(int,QImage)), this, SIGNAL(imageCaptured(int,QImage))); connect(m_session, SIGNAL(imageCaptured(int,QImage)), this, SIGNAL(imageCaptured(int,QImage)));
connect(m_session->cameraControl()->resourcePolicy(), SIGNAL(canCaptureChanged()), this, SLOT(updateState()));
m_session->bus()->installMessageFilter(this); m_session->bus()->installMessageFilter(this);
} }
@@ -103,7 +106,8 @@ void CameraBinImageCapture::cancelCapture()
void CameraBinImageCapture::updateState() void CameraBinImageCapture::updateState()
{ {
bool ready = m_session->state() == QCamera::ActiveState; bool ready = m_session->state() == QCamera::ActiveState
&& m_session->cameraControl()->resourcePolicy()->canCapture();
if (m_ready != ready) { if (m_ready != ready) {
#ifdef DEBUG_CAPTURE #ifdef DEBUG_CAPTURE
qDebug() << "readyForCaptureChanged" << ready; qDebug() << "readyForCaptureChanged" << ready;

View File

@@ -40,6 +40,8 @@
****************************************************************************/ ****************************************************************************/
#include "camerabinrecorder.h" #include "camerabinrecorder.h"
#include "camerabincontrol.h"
#include "camerabinresourcepolicy.h"
#include "camerabinaudioencoder.h" #include "camerabinaudioencoder.h"
#include "camerabinvideoencoder.h" #include "camerabinvideoencoder.h"
#include "camerabincontainer.h" #include "camerabincontainer.h"
@@ -61,6 +63,8 @@ CameraBinRecorder::CameraBinRecorder(CameraBinSession *session)
connect(m_session, SIGNAL(durationChanged(qint64)), SIGNAL(durationChanged(qint64))); connect(m_session, SIGNAL(durationChanged(qint64)), SIGNAL(durationChanged(qint64)));
connect(m_session, SIGNAL(mutedChanged(bool)), this, SIGNAL(mutedChanged(bool))); connect(m_session, SIGNAL(mutedChanged(bool)), this, SIGNAL(mutedChanged(bool)));
connect(m_session->cameraControl()->resourcePolicy(), SIGNAL(canCaptureChanged()),
this, SLOT(updateStatus()));
} }
CameraBinRecorder::~CameraBinRecorder() CameraBinRecorder::~CameraBinRecorder()
@@ -98,7 +102,11 @@ void CameraBinRecorder::updateStatus()
if (sessionState == QCamera::ActiveState && if (sessionState == QCamera::ActiveState &&
m_session->captureMode().testFlag(QCamera::CaptureVideo)) { m_session->captureMode().testFlag(QCamera::CaptureVideo)) {
if (m_state == QMediaRecorder::RecordingState) { if (!m_session->cameraControl()->resourcePolicy()->canCapture()) {
m_status = QMediaRecorder::UnavailableStatus;
m_state = QMediaRecorder::StoppedState;
m_session->stopVideoRecording();
} else if (m_state == QMediaRecorder::RecordingState) {
m_status = QMediaRecorder::RecordingStatus; m_status = QMediaRecorder::RecordingStatus;
} else { } else {
m_status = m_session->isBusy() ? m_status = m_session->isBusy() ?
@@ -208,13 +216,16 @@ void CameraBinRecorder::setState(QMediaRecorder::State state)
emit error(QMediaRecorder::ResourceError, tr("QMediaRecorder::pause() is not supported by camerabin2.")); emit error(QMediaRecorder::ResourceError, tr("QMediaRecorder::pause() is not supported by camerabin2."));
break; break;
case QMediaRecorder::RecordingState: case QMediaRecorder::RecordingState:
if (m_session->state() == QCamera::ActiveState) {
if (m_session->state() != QCamera::ActiveState) {
emit error(QMediaRecorder::ResourceError, tr("Service has not been started"));
} else if (!m_session->cameraControl()->resourcePolicy()->canCapture()) {
emit error(QMediaRecorder::ResourceError, tr("Recording permissions are not available"));
} else {
m_session->recordVideo(); m_session->recordVideo();
m_state = state; m_state = state;
m_status = QMediaRecorder::RecordingStatus; m_status = QMediaRecorder::RecordingStatus;
emit actualLocationChanged(m_session->outputLocation()); emit actualLocationChanged(m_session->outputLocation());
} else {
emit error(QMediaRecorder::ResourceError, tr("Service has not been started"));
} }
} }

View File

@@ -76,7 +76,6 @@ public slots:
void setMuted(bool); void setMuted(bool);
void setVolume(qreal volume); void setVolume(qreal volume);
private slots:
void updateStatus(); void updateStatus();
private: private:

View File

@@ -56,7 +56,8 @@ QT_BEGIN_NAMESPACE
CamerabinResourcePolicy::CamerabinResourcePolicy(QObject *parent) : CamerabinResourcePolicy::CamerabinResourcePolicy(QObject *parent) :
QObject(parent), QObject(parent),
m_resourceSet(NoResources), m_resourceSet(NoResources),
m_releasingResources(false) m_releasingResources(false),
m_canCapture(false)
{ {
#ifdef HAVE_RESOURCE_POLICY #ifdef HAVE_RESOURCE_POLICY
//loaded resource set is also kept requested for image and video capture sets //loaded resource set is also kept requested for image and video capture sets
@@ -65,10 +66,13 @@ CamerabinResourcePolicy::CamerabinResourcePolicy(QObject *parent) :
m_resource->initAndConnect(); m_resource->initAndConnect();
connect(m_resource, SIGNAL(resourcesGranted(const QList<ResourcePolicy::ResourceType>)), connect(m_resource, SIGNAL(resourcesGranted(const QList<ResourcePolicy::ResourceType>)),
SIGNAL(resourcesGranted())); SLOT(handleResourcesGranted()));
connect(m_resource, SIGNAL(resourcesDenied()), SIGNAL(resourcesDenied())); connect(m_resource, SIGNAL(resourcesDenied()), SIGNAL(resourcesDenied()));
connect(m_resource, SIGNAL(lostResources()), SIGNAL(resourcesLost())); connect(m_resource, SIGNAL(lostResources()), SLOT(handleResourcesLost()));
connect(m_resource, SIGNAL(resourcesReleased()), SLOT(handleResourcesReleased())); connect(m_resource, SIGNAL(resourcesReleased()), SLOT(handleResourcesReleased()));
connect(m_resource, SIGNAL(resourcesBecameAvailable(QList<ResourcePolicy::ResourceType>)),
this, SLOT(resourcesAvailable()));
connect(m_resource, SIGNAL(updateOK()), this, SLOT(updateCanCapture()));
#endif #endif
} }
@@ -112,17 +116,13 @@ void CamerabinResourcePolicy::setResourceSet(CamerabinResourcePolicy::ResourceSe
break; break;
case LoadedResources: case LoadedResources:
requestedTypes << ResourcePolicy::LensCoverType //to detect lens cover is opened/closed requestedTypes << ResourcePolicy::LensCoverType //to detect lens cover is opened/closed
<< ResourcePolicy::VideoRecorderType //to open camera device << ResourcePolicy::VideoRecorderType; //to open camera device
<< ResourcePolicy::SnapButtonType; //to detect capture button events
break; break;
case ImageCaptureResources: case ImageCaptureResources:
requestedTypes << ResourcePolicy::LensCoverType requestedTypes << ResourcePolicy::LensCoverType
<< ResourcePolicy::VideoPlaybackType << ResourcePolicy::VideoPlaybackType
<< ResourcePolicy::VideoRecorderType << ResourcePolicy::VideoRecorderType
<< ResourcePolicy::AudioPlaybackType << ResourcePolicy::LedsType;
<< ResourcePolicy::ScaleButtonType
<< ResourcePolicy::LedsType
<< ResourcePolicy::SnapButtonType;
break; break;
case VideoCaptureResources: case VideoCaptureResources:
requestedTypes << ResourcePolicy::LensCoverType requestedTypes << ResourcePolicy::LensCoverType
@@ -130,9 +130,7 @@ void CamerabinResourcePolicy::setResourceSet(CamerabinResourcePolicy::ResourceSe
<< ResourcePolicy::VideoRecorderType << ResourcePolicy::VideoRecorderType
<< ResourcePolicy::AudioPlaybackType << ResourcePolicy::AudioPlaybackType
<< ResourcePolicy::AudioRecorderType << ResourcePolicy::AudioRecorderType
<< ResourcePolicy::ScaleButtonType << ResourcePolicy::LedsType;
<< ResourcePolicy::LedsType
<< ResourcePolicy::SnapButtonType;
break; break;
} }
@@ -148,6 +146,14 @@ void CamerabinResourcePolicy::setResourceSet(CamerabinResourcePolicy::ResourceSe
ResourcePolicy::LensCoverResource *lensCoverResource = new ResourcePolicy::LensCoverResource; ResourcePolicy::LensCoverResource *lensCoverResource = new ResourcePolicy::LensCoverResource;
lensCoverResource->setOptional(true); lensCoverResource->setOptional(true);
m_resource->addResourceObject(lensCoverResource); m_resource->addResourceObject(lensCoverResource);
} else if (resourceType == ResourcePolicy::AudioPlaybackType) {
ResourcePolicy::Resource *resource = new ResourcePolicy::AudioResource;
resource->setOptional(true);
m_resource->addResourceObject(resource);
} else if (resourceType == ResourcePolicy::AudioRecorderType) {
ResourcePolicy::Resource *resource = new ResourcePolicy::AudioRecorderResource;
resource->setOptional(true);
m_resource->addResourceObject(resource);
} else { } else {
m_resource->addResource(resourceType); m_resource->addResource(resourceType);
} }
@@ -164,6 +170,7 @@ void CamerabinResourcePolicy::setResourceSet(CamerabinResourcePolicy::ResourceSe
} }
#else #else
Q_UNUSED(oldSet); Q_UNUSED(oldSet);
updateCanCapture();
#endif #endif
} }
@@ -177,6 +184,18 @@ bool CamerabinResourcePolicy::isResourcesGranted() const
return true; return true;
} }
void CamerabinResourcePolicy::handleResourcesLost()
{
updateCanCapture();
emit resourcesLost();
}
void CamerabinResourcePolicy::handleResourcesGranted()
{
updateCanCapture();
emit resourcesGranted();
}
void CamerabinResourcePolicy::handleResourcesReleased() void CamerabinResourcePolicy::handleResourcesReleased()
{ {
#ifdef HAVE_RESOURCE_POLICY #ifdef HAVE_RESOURCE_POLICY
@@ -185,6 +204,35 @@ void CamerabinResourcePolicy::handleResourcesReleased()
#endif #endif
m_releasingResources = false; m_releasingResources = false;
#endif #endif
updateCanCapture();
}
void CamerabinResourcePolicy::resourcesAvailable()
{
#ifdef HAVE_RESOURCE_POLICY
if (m_resourceSet != NoResources) {
m_resource->acquire();
}
#endif
}
bool CamerabinResourcePolicy::canCapture() const
{
return m_canCapture;
}
void CamerabinResourcePolicy::updateCanCapture()
{
const bool wasAbleToRecord = m_canCapture;
m_canCapture = (m_resourceSet == VideoCaptureResources) || (m_resourceSet == ImageCaptureResources);
#ifdef HAVE_RESOURCE_POLICY
foreach (ResourcePolicy::Resource *resource, m_resource->resources()) {
if (resource->type() != ResourcePolicy::LensCoverType)
m_canCapture = m_canCapture && resource->isGranted();
}
#endif
if (wasAbleToRecord != m_canCapture)
emit canCaptureChanged();
} }
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@@ -69,18 +69,27 @@ public:
bool isResourcesGranted() const; bool isResourcesGranted() const;
bool canCapture() const;
Q_SIGNALS: Q_SIGNALS:
void resourcesDenied(); void resourcesDenied();
void resourcesGranted(); void resourcesGranted();
void resourcesLost(); void resourcesLost();
void canCaptureChanged();
private Q_SLOTS: private Q_SLOTS:
void handleResourcesLost();
void handleResourcesGranted();
void handleResourcesReleased(); void handleResourcesReleased();
void resourcesAvailable();
void updateCanCapture();
private: private:
ResourceSet m_resourceSet; ResourceSet m_resourceSet;
ResourcePolicy::ResourceSet *m_resource; ResourcePolicy::ResourceSet *m_resource;
bool m_releasingResources; bool m_releasingResources;
bool m_canCapture;
}; };
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@@ -92,7 +92,6 @@ CameraBinService::CameraBinService(const QString &service, QObject *parent):
QMediaService(parent) QMediaService(parent)
{ {
m_captureSession = 0; m_captureSession = 0;
m_cameraControl = 0;
m_metaDataControl = 0; m_metaDataControl = 0;
m_audioInputSelector = 0; m_audioInputSelector = 0;
@@ -108,7 +107,6 @@ CameraBinService::CameraBinService(const QString &service, QObject *parent):
if (service == Q_MEDIASERVICE_CAMERA) { if (service == Q_MEDIASERVICE_CAMERA) {
m_captureSession = new CameraBinSession(this); m_captureSession = new CameraBinSession(this);
m_cameraControl = new CameraBinControl(m_captureSession);
m_videoInputDevice = new QGstreamerVideoInputDeviceControl( m_videoInputDevice = new QGstreamerVideoInputDeviceControl(
m_captureSession->buildCameraSource(), m_captureSession); m_captureSession->buildCameraSource(), m_captureSession);
m_imageCaptureControl = new CameraBinImageCapture(m_captureSession); m_imageCaptureControl = new CameraBinImageCapture(m_captureSession);
@@ -208,7 +206,7 @@ QMediaControl *CameraBinService::requestControl(const char *name)
return m_captureSession->mediaContainerControl(); return m_captureSession->mediaContainerControl();
if (qstrcmp(name,QCameraControl_iid) == 0) if (qstrcmp(name,QCameraControl_iid) == 0)
return m_cameraControl; return m_captureSession->cameraControl();
if (qstrcmp(name,QMetaDataWriterControl_iid) == 0) if (qstrcmp(name,QMetaDataWriterControl_iid) == 0)
return m_metaDataControl; return m_metaDataControl;

View File

@@ -79,7 +79,6 @@ private:
void setAudioPreview(GstElement*); void setAudioPreview(GstElement*);
CameraBinSession *m_captureSession; CameraBinSession *m_captureSession;
CameraBinControl *m_cameraControl;
CameraBinMetaData *m_metaDataControl; CameraBinMetaData *m_metaDataControl;
QAudioInputSelectorControl *m_audioInputSelector; QAudioInputSelectorControl *m_audioInputSelector;

View File

@@ -39,6 +39,7 @@
** **
****************************************************************************/ ****************************************************************************/
#include "camerabinsession.h" #include "camerabinsession.h"
#include "camerabincontrol.h"
#include "camerabinrecorder.h" #include "camerabinrecorder.h"
#include "camerabincontainer.h" #include "camerabincontainer.h"
#include "camerabinaudioencoder.h" #include "camerabinaudioencoder.h"
@@ -152,6 +153,7 @@ CameraBinSession::CameraBinSession(QObject *parent)
m_busHelper = new QGstreamerBusHelper(m_bus, this); m_busHelper = new QGstreamerBusHelper(m_bus, this);
m_busHelper->installMessageFilter(this); m_busHelper->installMessageFilter(this);
m_cameraControl = new CameraBinControl(this);
m_audioEncodeControl = new CameraBinAudioEncoder(this); m_audioEncodeControl = new CameraBinAudioEncoder(this);
m_videoEncodeControl = new CameraBinVideoEncoder(this); m_videoEncodeControl = new CameraBinVideoEncoder(this);
m_imageEncodeControl = new CameraBinImageEncoder(this); m_imageEncodeControl = new CameraBinImageEncoder(this);
@@ -450,6 +452,8 @@ void CameraBinSession::setCaptureMode(QCamera::CaptureModes mode)
g_object_set(m_camerabin, MODE_PROPERTY, CAMERABIN_VIDEO_MODE, NULL); g_object_set(m_camerabin, MODE_PROPERTY, CAMERABIN_VIDEO_MODE, NULL);
break; break;
} }
m_recorderControl->updateStatus();
} }
QUrl CameraBinSession::outputLocation() const QUrl CameraBinSession::outputLocation() const

View File

@@ -59,6 +59,7 @@ QT_BEGIN_NAMESPACE
class QGstreamerMessage; class QGstreamerMessage;
class QGstreamerBusHelper; class QGstreamerBusHelper;
class CameraBinControl;
class CameraBinAudioEncoder; class CameraBinAudioEncoder;
class CameraBinVideoEncoder; class CameraBinVideoEncoder;
class CameraBinImageEncoder; class CameraBinImageEncoder;
@@ -119,6 +120,7 @@ public:
GstElement *buildCameraSource(); GstElement *buildCameraSource();
CameraBinControl *cameraControl() const { return m_cameraControl; }
CameraBinAudioEncoder *audioEncodeControl() const { return m_audioEncodeControl; } CameraBinAudioEncoder *audioEncodeControl() const { return m_audioEncodeControl; }
CameraBinVideoEncoder *videoEncodeControl() const { return m_videoEncodeControl; } CameraBinVideoEncoder *videoEncodeControl() const { return m_videoEncodeControl; }
CameraBinImageEncoder *imageEncodeControl() const { return m_imageEncodeControl; } CameraBinImageEncoder *imageEncodeControl() const { return m_imageEncodeControl; }
@@ -210,6 +212,7 @@ private:
QObject *m_viewfinder; QObject *m_viewfinder;
QGstreamerVideoRendererInterface *m_viewfinderInterface; QGstreamerVideoRendererInterface *m_viewfinderInterface;
CameraBinControl *m_cameraControl;
CameraBinAudioEncoder *m_audioEncodeControl; CameraBinAudioEncoder *m_audioEncodeControl;
CameraBinVideoEncoder *m_videoEncodeControl; CameraBinVideoEncoder *m_videoEncodeControl;
CameraBinImageEncoder *m_imageEncodeControl; CameraBinImageEncoder *m_imageEncodeControl;

View File

@@ -48,6 +48,8 @@
ResourcePolicyImpl::ResourcePolicyImpl(QObject *parent) ResourcePolicyImpl::ResourcePolicyImpl(QObject *parent)
: QMediaPlayerResourceSetInterface(parent) : QMediaPlayerResourceSetInterface(parent)
, m_status(Initial)
, m_videoEnabled(false)
{ {
m_resourceSet = new ResourcePolicy::ResourceSet("player", this); m_resourceSet = new ResourcePolicy::ResourceSet("player", this);
m_resourceSet->setAlwaysReply(); m_resourceSet->setAlwaysReply();
@@ -57,7 +59,6 @@ ResourcePolicyImpl::ResourcePolicyImpl(QObject *parent)
audioResource->setStreamTag("media.name", "*"); audioResource->setStreamTag("media.name", "*");
m_resourceSet->addResourceObject(audioResource); m_resourceSet->addResourceObject(audioResource);
m_resourceSet->addResource(ResourcePolicy::VideoPlaybackType);
m_resourceSet->update(); m_resourceSet->update();
connect(m_resourceSet, SIGNAL(resourcesGranted(const QList<ResourcePolicy::ResourceType>)), connect(m_resourceSet, SIGNAL(resourcesGranted(const QList<ResourcePolicy::ResourceType>)),