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:
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;

View 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);

View File

@@ -40,9 +40,11 @@
****************************************************************************/
#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;

View 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"));
}
}

View File

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

View 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

View 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

View 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;

View File

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

View 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

View 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;