Only acquire resources as required in gstreamer backend.
authorAndrew den Exter <andrew.den.exter@jollamobile.com>
Wed, 11 Dec 2013 04:29:57 +0000 (14:29 +1000)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Mon, 13 Jan 2014 05:06:33 +0000 (06:06 +0100)
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>
12 files changed:
src/plugins/gstreamer/camerabin/camerabincontrol.cpp
src/plugins/gstreamer/camerabin/camerabincontrol.h
src/plugins/gstreamer/camerabin/camerabinimagecapture.cpp
src/plugins/gstreamer/camerabin/camerabinrecorder.cpp
src/plugins/gstreamer/camerabin/camerabinrecorder.h
src/plugins/gstreamer/camerabin/camerabinresourcepolicy.cpp
src/plugins/gstreamer/camerabin/camerabinresourcepolicy.h
src/plugins/gstreamer/camerabin/camerabinservice.cpp
src/plugins/gstreamer/camerabin/camerabinservice.h
src/plugins/gstreamer/camerabin/camerabinsession.cpp
src/plugins/gstreamer/camerabin/camerabinsession.h
src/plugins/resourcepolicy/resourcepolicyimpl.cpp

index 6200606..8c63959 100644 (file)
@@ -201,7 +201,9 @@ void CameraBinControl::updateStatus()
     case QCamera::LoadedState:
         switch (sessionState) {
         case QCamera::UnloadedState:
-            m_status = QCamera::LoadingStatus;
+            m_status = m_resourcePolicy->isResourcesGranted()
+                    ? QCamera::LoadingStatus
+                    : QCamera::UnavailableStatus;
             break;
         case QCamera::LoadedState:
             m_status = QCamera::LoadedStatus;
@@ -214,7 +216,9 @@ void CameraBinControl::updateStatus()
     case QCamera::ActiveState:
         switch (sessionState) {
         case QCamera::UnloadedState:
-            m_status = QCamera::LoadingStatus;
+            m_status = m_resourcePolicy->isResourcesGranted()
+                    ? QCamera::LoadingStatus
+                    : QCamera::UnavailableStatus;
             break;
         case QCamera::LoadedState:
             m_status = QCamera::StartingStatus;
index 821bee3..8958974 100644 (file)
@@ -73,6 +73,8 @@ public:
     bool canChangeProperty(PropertyChangeType changeType, QCamera::Status status) const;
     bool viewfinderColorSpaceConversion() const;
 
+    CamerabinResourcePolicy *resourcePolicy() { return m_resourcePolicy; }
+
 public slots:
     void reloadLater();
     void setViewfinderColorSpaceConversion(bool enabled);
index 79cfca3..122a10e 100644 (file)
 ****************************************************************************/
 
 #include "camerabinimagecapture.h"
+#include "camerabincontrol.h"
 #include "camerabincapturedestination.h"
 #include "camerabincapturebufferformat.h"
 #include "camerabinsession.h"
+#include "camerabinresourcepolicy.h"
 #include <private/qgstvideobuffer_p.h>
 #include <private/qvideosurfacegstsink_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(imageExposed(int)), this, SIGNAL(imageExposed(int)));
     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);
 }
@@ -103,7 +106,8 @@ void CameraBinImageCapture::cancelCapture()
 
 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) {
 #ifdef DEBUG_CAPTURE
         qDebug() << "readyForCaptureChanged" << ready;
index e45f187..c8967df 100644 (file)
@@ -40,6 +40,8 @@
 ****************************************************************************/
 
 #include "camerabinrecorder.h"
+#include "camerabincontrol.h"
+#include "camerabinresourcepolicy.h"
 #include "camerabinaudioencoder.h"
 #include "camerabinvideoencoder.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(mutedChanged(bool)), this, SIGNAL(mutedChanged(bool)));
+    connect(m_session->cameraControl()->resourcePolicy(), SIGNAL(canCaptureChanged()),
+            this, SLOT(updateStatus()));
 }
 
 CameraBinRecorder::~CameraBinRecorder()
@@ -98,7 +102,11 @@ void CameraBinRecorder::updateStatus()
     if (sessionState == QCamera::ActiveState &&
             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;
         } else {
             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."));
         break;
     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_state = state;
             m_status = QMediaRecorder::RecordingStatus;
             emit actualLocationChanged(m_session->outputLocation());
-        } else {
-            emit error(QMediaRecorder::ResourceError, tr("Service has not been started"));
         }
     }
 
index 2f8fe5d..691fc12 100644 (file)
@@ -76,7 +76,6 @@ public slots:
     void setMuted(bool);
     void setVolume(qreal volume);
 
-private slots:
     void updateStatus();
 
 private:
index 11b04a9..d6df420 100644 (file)
@@ -56,7 +56,8 @@ QT_BEGIN_NAMESPACE
 CamerabinResourcePolicy::CamerabinResourcePolicy(QObject *parent) :
     QObject(parent),
     m_resourceSet(NoResources),
-    m_releasingResources(false)
+    m_releasingResources(false),
+    m_canCapture(false)
 {
 #ifdef HAVE_RESOURCE_POLICY
     //loaded resource set is also kept requested for image and video capture sets
@@ -65,10 +66,13 @@ CamerabinResourcePolicy::CamerabinResourcePolicy(QObject *parent) :
     m_resource->initAndConnect();
 
     connect(m_resource, SIGNAL(resourcesGranted(const QList<ResourcePolicy::ResourceType>)),
-            SIGNAL(resourcesGranted()));
+            SLOT(handleResourcesGranted()));
     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(resourcesBecameAvailable(QList<ResourcePolicy::ResourceType>)),
+            this, SLOT(resourcesAvailable()));
+    connect(m_resource, SIGNAL(updateOK()), this, SLOT(updateCanCapture()));
 #endif
 }
 
@@ -112,17 +116,13 @@ void CamerabinResourcePolicy::setResourceSet(CamerabinResourcePolicy::ResourceSe
         break;
     case LoadedResources:
         requestedTypes << ResourcePolicy::LensCoverType //to detect lens cover is opened/closed
-                       << ResourcePolicy::VideoRecorderType //to open camera device
-                       << ResourcePolicy::SnapButtonType; //to detect capture button events
+                       << ResourcePolicy::VideoRecorderType; //to open camera device
         break;
     case ImageCaptureResources:
         requestedTypes << ResourcePolicy::LensCoverType
                        << ResourcePolicy::VideoPlaybackType
                        << ResourcePolicy::VideoRecorderType
-                       << ResourcePolicy::AudioPlaybackType
-                       << ResourcePolicy::ScaleButtonType
-                       << ResourcePolicy::LedsType
-                       << ResourcePolicy::SnapButtonType;
+                       << ResourcePolicy::LedsType;
         break;
     case VideoCaptureResources:
         requestedTypes << ResourcePolicy::LensCoverType
@@ -130,9 +130,7 @@ void CamerabinResourcePolicy::setResourceSet(CamerabinResourcePolicy::ResourceSe
                        << ResourcePolicy::VideoRecorderType
                        << ResourcePolicy::AudioPlaybackType
                        << ResourcePolicy::AudioRecorderType
-                       << ResourcePolicy::ScaleButtonType
-                       << ResourcePolicy::LedsType
-                       << ResourcePolicy::SnapButtonType;
+                       << ResourcePolicy::LedsType;
         break;
     }
 
@@ -148,6 +146,14 @@ void CamerabinResourcePolicy::setResourceSet(CamerabinResourcePolicy::ResourceSe
             ResourcePolicy::LensCoverResource *lensCoverResource = new ResourcePolicy::LensCoverResource;
             lensCoverResource->setOptional(true);
             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 {
             m_resource->addResource(resourceType);
         }
@@ -164,6 +170,7 @@ void CamerabinResourcePolicy::setResourceSet(CamerabinResourcePolicy::ResourceSe
     }
 #else
     Q_UNUSED(oldSet);
+    updateCanCapture();
 #endif
 }
 
@@ -177,6 +184,18 @@ bool CamerabinResourcePolicy::isResourcesGranted() const
     return true;
 }
 
+void CamerabinResourcePolicy::handleResourcesLost()
+{
+    updateCanCapture();
+    emit resourcesLost();
+}
+
+void CamerabinResourcePolicy::handleResourcesGranted()
+{
+    updateCanCapture();
+    emit resourcesGranted();
+}
+
 void CamerabinResourcePolicy::handleResourcesReleased()
 {
 #ifdef HAVE_RESOURCE_POLICY
@@ -185,6 +204,35 @@ void CamerabinResourcePolicy::handleResourcesReleased()
 #endif
     m_releasingResources = false;
 #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
index 3170095..f4cbb7c 100644 (file)
@@ -69,18 +69,27 @@ public:
 
     bool isResourcesGranted() const;
 
+    bool canCapture() const;
+
 Q_SIGNALS:
     void resourcesDenied();
     void resourcesGranted();
     void resourcesLost();
+    void canCaptureChanged();
 
 private Q_SLOTS:
+    void handleResourcesLost();
+    void handleResourcesGranted();
     void handleResourcesReleased();
+    void resourcesAvailable();
+    void updateCanCapture();
+
 
 private:
     ResourceSet m_resourceSet;
     ResourcePolicy::ResourceSet *m_resource;
     bool m_releasingResources;
+    bool m_canCapture;
 };
 
 QT_END_NAMESPACE
index 58d4433..a916ee8 100644 (file)
@@ -92,7 +92,6 @@ CameraBinService::CameraBinService(const QString &service, QObject *parent):
     QMediaService(parent)
 {
     m_captureSession = 0;
-    m_cameraControl = 0;
     m_metaDataControl = 0;
 
     m_audioInputSelector = 0;
@@ -108,7 +107,6 @@ CameraBinService::CameraBinService(const QString &service, QObject *parent):
 
     if (service == Q_MEDIASERVICE_CAMERA) {
         m_captureSession = new CameraBinSession(this);
-        m_cameraControl = new CameraBinControl(m_captureSession);
         m_videoInputDevice = new QGstreamerVideoInputDeviceControl(
                     m_captureSession->buildCameraSource(), m_captureSession);
         m_imageCaptureControl = new CameraBinImageCapture(m_captureSession);
@@ -208,7 +206,7 @@ QMediaControl *CameraBinService::requestControl(const char *name)
         return m_captureSession->mediaContainerControl();
 
     if (qstrcmp(name,QCameraControl_iid) == 0)
-        return m_cameraControl;
+        return m_captureSession->cameraControl();
 
     if (qstrcmp(name,QMetaDataWriterControl_iid) == 0)
         return m_metaDataControl;
index 2d965ff..7d3b3df 100644 (file)
@@ -79,7 +79,6 @@ private:
     void setAudioPreview(GstElement*);
 
     CameraBinSession *m_captureSession;
-    CameraBinControl *m_cameraControl;
     CameraBinMetaData *m_metaDataControl;
 
     QAudioInputSelectorControl *m_audioInputSelector;
index 6e857d5..18f6d54 100644 (file)
@@ -39,6 +39,7 @@
 **
 ****************************************************************************/
 #include "camerabinsession.h"
+#include "camerabincontrol.h"
 #include "camerabinrecorder.h"
 #include "camerabincontainer.h"
 #include "camerabinaudioencoder.h"
@@ -152,6 +153,7 @@ CameraBinSession::CameraBinSession(QObject *parent)
     m_busHelper = new QGstreamerBusHelper(m_bus, this);
     m_busHelper->installMessageFilter(this);
 
+    m_cameraControl = new CameraBinControl(this);
     m_audioEncodeControl = new CameraBinAudioEncoder(this);
     m_videoEncodeControl = new CameraBinVideoEncoder(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);
         break;
     }
+
+    m_recorderControl->updateStatus();
 }
 
 QUrl CameraBinSession::outputLocation() const
index bdc27f3..dab8d84 100644 (file)
@@ -59,6 +59,7 @@ QT_BEGIN_NAMESPACE
 
 class QGstreamerMessage;
 class QGstreamerBusHelper;
+class CameraBinControl;
 class CameraBinAudioEncoder;
 class CameraBinVideoEncoder;
 class CameraBinImageEncoder;
@@ -119,6 +120,7 @@ public:
 
     GstElement *buildCameraSource();
 
+    CameraBinControl *cameraControl() const { return m_cameraControl; }
     CameraBinAudioEncoder *audioEncodeControl() const { return m_audioEncodeControl; }
     CameraBinVideoEncoder *videoEncodeControl() const { return m_videoEncodeControl; }
     CameraBinImageEncoder *imageEncodeControl() const { return m_imageEncodeControl; }
@@ -210,6 +212,7 @@ private:
     QObject *m_viewfinder;
     QGstreamerVideoRendererInterface *m_viewfinderInterface;
 
+    CameraBinControl *m_cameraControl;
     CameraBinAudioEncoder *m_audioEncodeControl;
     CameraBinVideoEncoder *m_videoEncodeControl;
     CameraBinImageEncoder *m_imageEncodeControl;
index 26f7135..aed9ccb 100644 (file)
@@ -48,6 +48,8 @@
 
 ResourcePolicyImpl::ResourcePolicyImpl(QObject *parent)
     : QMediaPlayerResourceSetInterface(parent)
+    , m_status(Initial)
+    , m_videoEnabled(false)
 {
     m_resourceSet = new ResourcePolicy::ResourceSet("player", this);
     m_resourceSet->setAlwaysReply();
@@ -57,7 +59,6 @@ ResourcePolicyImpl::ResourcePolicyImpl(QObject *parent)
     audioResource->setStreamTag("media.name", "*");
     m_resourceSet->addResourceObject(audioResource);
 
-    m_resourceSet->addResource(ResourcePolicy::VideoPlaybackType);
     m_resourceSet->update();
 
     connect(m_resourceSet, SIGNAL(resourcesGranted(const QList<ResourcePolicy::ResourceType>)),