summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYoann Lopes <yoann.lopes@theqtcompany.com>2015-01-21 14:11:42 +0100
committerYoann Lopes <yoann.lopes@theqtcompany.com>2015-02-18 13:14:59 +0000
commitd9354b2299a9a521854c5c6e6ab29163376f8ebc (patch)
tree2914442ba45110e6bd93f01a226e5be4869726a8
parente49d92959c59f7d9650a37b1860c556e5d0cf2a3 (diff)
GStreamer: fix camerabin state and status changes.
Not all status changes where reported and setting the QCamera to LoadedState was not actually loading anything. State and status changes have been refactored. Camera status is now reported directly by the camera session. Setting the camera state to LoadedState now sets the camerabin to GST_STATE_READY, that allows to query for camera capabilities without having to start the camera (and have a valid viewfinder). Change-Id: I249b1ad32690679ff34a427410bc709ed3ab461c Reviewed-by: Christian Stromme <christian.stromme@theqtcompany.com>
-rw-r--r--src/plugins/gstreamer/camerabin/camerabincontrol.cpp56
-rw-r--r--src/plugins/gstreamer/camerabin/camerabincontrol.h4
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinfocus.cpp14
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinfocus.h4
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinimagecapture.cpp4
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinrecorder.cpp8
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinsession.cpp185
-rw-r--r--src/plugins/gstreamer/camerabin/camerabinsession.h15
8 files changed, 152 insertions, 138 deletions
diff --git a/src/plugins/gstreamer/camerabin/camerabincontrol.cpp b/src/plugins/gstreamer/camerabin/camerabincontrol.cpp
index b46b92b17..cd7e37628 100644
--- a/src/plugins/gstreamer/camerabin/camerabincontrol.cpp
+++ b/src/plugins/gstreamer/camerabin/camerabincontrol.cpp
@@ -51,11 +51,10 @@ CameraBinControl::CameraBinControl(CameraBinSession *session)
:QCameraControl(session),
m_session(session),
m_state(QCamera::UnloadedState),
- m_status(QCamera::UnloadedStatus),
m_reloadPending(false)
{
- connect(m_session, SIGNAL(stateChanged(QCamera::State)),
- this, SLOT(updateStatus()));
+ connect(m_session, SIGNAL(statusChanged(QCamera::Status)),
+ this, SIGNAL(statusChanged(QCamera::Status)));
connect(m_session, SIGNAL(viewfinderChanged()),
SLOT(reloadLater()));
@@ -116,7 +115,7 @@ void CameraBinControl::setState(QCamera::State state)
//special case for stopping the camera while it's busy,
//it should be delayed until the camera is idle
if (state == QCamera::LoadedState &&
- m_session->state() == QCamera::ActiveState &&
+ m_session->status() == QCamera::ActiveStatus &&
m_session->isBusy()) {
#ifdef CAMEABIN_DEBUG
qDebug() << Q_FUNC_INFO << "Camera is busy, QCamera::stop() is delayed";
@@ -165,52 +164,9 @@ QCamera::State CameraBinControl::state() const
return m_state;
}
-void CameraBinControl::updateStatus()
+QCamera::Status CameraBinControl::status() const
{
- QCamera::State sessionState = m_session->state();
- QCamera::Status oldStatus = m_status;
-
- switch (m_state) {
- case QCamera::UnloadedState:
- m_status = QCamera::UnloadedStatus;
- break;
- case QCamera::LoadedState:
- switch (sessionState) {
- case QCamera::UnloadedState:
- m_status = m_resourcePolicy->isResourcesGranted()
- ? QCamera::LoadingStatus
- : QCamera::UnavailableStatus;
- break;
- case QCamera::LoadedState:
- m_status = QCamera::LoadedStatus;
- break;
- case QCamera::ActiveState:
- m_status = QCamera::ActiveStatus;
- break;
- }
- break;
- case QCamera::ActiveState:
- switch (sessionState) {
- case QCamera::UnloadedState:
- m_status = m_resourcePolicy->isResourcesGranted()
- ? QCamera::LoadingStatus
- : QCamera::UnavailableStatus;
- break;
- case QCamera::LoadedState:
- m_status = QCamera::StartingStatus;
- break;
- case QCamera::ActiveState:
- m_status = QCamera::ActiveStatus;
- break;
- }
- }
-
- if (m_status != oldStatus) {
-#ifdef CAMEABIN_DEBUG
- qDebug() << "Camera status changed" << ENUM_NAME(QCamera, "Status", m_status);
-#endif
- emit statusChanged(m_status);
- }
+ return m_session->status();
}
void CameraBinControl::reloadLater()
@@ -254,7 +210,7 @@ void CameraBinControl::handleResourcesGranted()
void CameraBinControl::handleBusyChanged(bool busy)
{
- if (!busy && m_session->state() == QCamera::ActiveState) {
+ if (!busy && m_session->status() == QCamera::ActiveStatus) {
if (m_state == QCamera::LoadedState) {
//handle delayed stop() because of busy camera
m_resourcePolicy->setResourceSet(CamerabinResourcePolicy::LoadedResources);
diff --git a/src/plugins/gstreamer/camerabin/camerabincontrol.h b/src/plugins/gstreamer/camerabin/camerabincontrol.h
index fc0d8b9ca..6a6b47d50 100644
--- a/src/plugins/gstreamer/camerabin/camerabincontrol.h
+++ b/src/plugins/gstreamer/camerabin/camerabincontrol.h
@@ -56,7 +56,7 @@ public:
QCamera::State state() const;
void setState(QCamera::State state);
- QCamera::Status status() const { return m_status; }
+ QCamera::Status status() const;
QCamera::CaptureModes captureMode() const;
void setCaptureMode(QCamera::CaptureModes mode);
@@ -72,7 +72,6 @@ public slots:
void setViewfinderColorSpaceConversion(bool enabled);
private slots:
- void updateStatus();
void delayedReload();
void handleResourcesGranted();
@@ -86,7 +85,6 @@ private:
CameraBinSession *m_session;
QCamera::State m_state;
- QCamera::Status m_status;
CamerabinResourcePolicy *m_resourcePolicy;
bool m_reloadPending;
diff --git a/src/plugins/gstreamer/camerabin/camerabinfocus.cpp b/src/plugins/gstreamer/camerabin/camerabinfocus.cpp
index 2b777e3ff..32b8d9454 100644
--- a/src/plugins/gstreamer/camerabin/camerabinfocus.cpp
+++ b/src/plugins/gstreamer/camerabin/camerabinfocus.cpp
@@ -56,7 +56,7 @@ CameraBinFocus::CameraBinFocus(CameraBinSession *session)
QGstreamerBufferProbe(ProbeBuffers),
#endif
m_session(session),
- m_cameraState(QCamera::UnloadedState),
+ m_cameraStatus(QCamera::UnloadedStatus),
m_focusMode(QCameraFocus::AutoFocus),
m_focusPointMode(QCameraFocus::FocusPointAuto),
m_focusStatus(QCamera::Unlocked),
@@ -68,8 +68,8 @@ CameraBinFocus::CameraBinFocus(CameraBinSession *session)
gst_photography_set_focus_mode(m_session->photography(), GST_PHOTOGRAPHY_FOCUS_MODE_AUTO);
- connect(m_session, SIGNAL(stateChanged(QCamera::State)),
- this, SLOT(_q_handleCameraStateChange(QCamera::State)));
+ connect(m_session, SIGNAL(statusChanged(QCamera::Status)),
+ this, SLOT(_q_handleCameraStatusChange(QCamera::Status)));
}
CameraBinFocus::~CameraBinFocus()
@@ -319,10 +319,10 @@ void CameraBinFocus::_q_setFocusStatus(QCamera::LockStatus status, QCamera::Lock
}
}
-void CameraBinFocus::_q_handleCameraStateChange(QCamera::State state)
+void CameraBinFocus::_q_handleCameraStatusChange(QCamera::Status status)
{
- m_cameraState = state;
- if (state == QCamera::ActiveState) {
+ m_cameraStatus = status;
+ if (status == QCamera::ActiveStatus) {
if (GstPad *pad = gst_element_get_static_pad(m_session->cameraSource(), "vfsrc")) {
if (GstCaps *caps = qt_gst_pad_get_current_caps(pad)) {
if (GstStructure *structure = gst_caps_get_structure(caps, 0)) {
@@ -415,7 +415,7 @@ void CameraBinFocus::updateRegionOfInterest(const QRectF &rectangle)
void CameraBinFocus::updateRegionOfInterest(const QVector<QRect> &rectangles)
{
- if (m_cameraState != QCamera::ActiveState)
+ if (m_cameraStatus != QCamera::ActiveStatus)
return;
GstElement * const cameraSource = m_session->cameraSource();
diff --git a/src/plugins/gstreamer/camerabin/camerabinfocus.h b/src/plugins/gstreamer/camerabin/camerabinfocus.h
index 6c4ad2375..667e6b679 100644
--- a/src/plugins/gstreamer/camerabin/camerabinfocus.h
+++ b/src/plugins/gstreamer/camerabin/camerabinfocus.h
@@ -93,7 +93,7 @@ protected:
private Q_SLOTS:
void _q_setFocusStatus(QCamera::LockStatus status, QCamera::LockChangeReason reason);
- void _q_handleCameraStateChange(QCamera::State state);
+ void _q_handleCameraStatusChange(QCamera::Status status);
#if GST_CHECK_VERSION(1,0,0)
void _q_updateFaces();
@@ -109,7 +109,7 @@ private:
#endif
CameraBinSession *m_session;
- QCamera::State m_cameraState;
+ QCamera::Status m_cameraStatus;
QCameraFocus::FocusModes m_focusMode;
QCameraFocus::FocusPointMode m_focusPointMode;
QCamera::LockStatus m_focusStatus;
diff --git a/src/plugins/gstreamer/camerabin/camerabinimagecapture.cpp b/src/plugins/gstreamer/camerabin/camerabinimagecapture.cpp
index ba4291c36..2cf14ea3f 100644
--- a/src/plugins/gstreamer/camerabin/camerabinimagecapture.cpp
+++ b/src/plugins/gstreamer/camerabin/camerabinimagecapture.cpp
@@ -61,7 +61,7 @@ CameraBinImageCapture::CameraBinImageCapture(CameraBinSession *session)
, m_requestId(0)
, m_ready(false)
{
- connect(m_session, SIGNAL(stateChanged(QCamera::State)), SLOT(updateState()));
+ connect(m_session, SIGNAL(statusChanged(QCamera::Status)), 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()));
@@ -100,7 +100,7 @@ void CameraBinImageCapture::cancelCapture()
void CameraBinImageCapture::updateState()
{
- bool ready = m_session->state() == QCamera::ActiveState
+ bool ready = m_session->status() == QCamera::ActiveStatus
&& m_session->cameraControl()->resourcePolicy()->canCapture();
if (m_ready != ready) {
#ifdef DEBUG_CAPTURE
diff --git a/src/plugins/gstreamer/camerabin/camerabinrecorder.cpp b/src/plugins/gstreamer/camerabin/camerabinrecorder.cpp
index ae9ec812b..4154e1d65 100644
--- a/src/plugins/gstreamer/camerabin/camerabinrecorder.cpp
+++ b/src/plugins/gstreamer/camerabin/camerabinrecorder.cpp
@@ -49,7 +49,7 @@ CameraBinRecorder::CameraBinRecorder(CameraBinSession *session)
m_state(QMediaRecorder::StoppedState),
m_status(QMediaRecorder::UnloadedStatus)
{
- connect(m_session, SIGNAL(stateChanged(QCamera::State)), SLOT(updateStatus()));
+ connect(m_session, SIGNAL(statusChanged(QCamera::Status)), SLOT(updateStatus()));
connect(m_session, SIGNAL(pendingStateChanged(QCamera::State)), SLOT(updateStatus()));
connect(m_session, SIGNAL(busyChanged(bool)), SLOT(updateStatus()));
@@ -86,12 +86,12 @@ QMediaRecorder::Status CameraBinRecorder::status() const
void CameraBinRecorder::updateStatus()
{
- QCamera::State sessionState = m_session->state();
+ QCamera::Status sessionStatus = m_session->status();
QMediaRecorder::State oldState = m_state;
QMediaRecorder::Status oldStatus = m_status;
- if (sessionState == QCamera::ActiveState &&
+ if (sessionStatus == QCamera::ActiveStatus &&
m_session->captureMode().testFlag(QCamera::CaptureVideo)) {
if (!m_session->cameraControl()->resourcePolicy()->canCapture()) {
@@ -214,7 +214,7 @@ void CameraBinRecorder::setState(QMediaRecorder::State state)
break;
case QMediaRecorder::RecordingState:
- if (m_session->state() != QCamera::ActiveState) {
+ if (m_session->status() != QCamera::ActiveStatus) {
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"));
diff --git a/src/plugins/gstreamer/camerabin/camerabinsession.cpp b/src/plugins/gstreamer/camerabin/camerabinsession.cpp
index f60ba290b..72d72fdef 100644
--- a/src/plugins/gstreamer/camerabin/camerabinsession.cpp
+++ b/src/plugins/gstreamer/camerabin/camerabinsession.cpp
@@ -106,17 +106,12 @@
#define PREVIEW_CAPS_4_3 \
"video/x-raw-rgb, width = (int) 640, height = (int) 480"
-//using GST_STATE_READY for QCamera::LoadedState
-//may not work reliably at least with some webcams.
-
-//#define USE_READY_STATE_ON_LOADED
-
QT_BEGIN_NAMESPACE
CameraBinSession::CameraBinSession(GstElementFactory *sourceFactory, QObject *parent)
:QObject(parent),
m_recordingActive(false),
- m_state(QCamera::UnloadedState),
+ m_status(QCamera::UnloadedStatus),
m_pendingState(QCamera::UnloadedState),
m_muted(false),
m_busy(false),
@@ -230,9 +225,6 @@ CameraBinSession::CameraRole CameraBinSession::cameraRole() const
return BackCamera;
}
-/*
- Configure camera during Loaded->Active states stansition.
-*/
bool CameraBinSession::setupCameraBin()
{
if (!buildCameraSource())
@@ -248,7 +240,8 @@ bool CameraBinSession::setupCameraBin()
#endif
m_viewfinderHasChanged = false;
if (!m_viewfinderElement) {
- qWarning() << "Staring camera without viewfinder available";
+ if (m_pendingState == QCamera::ActiveState)
+ qWarning() << "Starting camera without viewfinder available";
m_viewfinderElement = gst_element_factory_make("fakesink", NULL);
}
g_object_set(G_OBJECT(m_viewfinderElement), "sync", FALSE, NULL);
@@ -663,9 +656,20 @@ void CameraBinSession::handleViewfinderChange()
emit viewfinderChanged();
}
-QCamera::State CameraBinSession::state() const
+void CameraBinSession::setStatus(QCamera::Status status)
{
- return m_state;
+ if (m_status == status)
+ return;
+
+ m_status = status;
+ emit statusChanged(m_status);
+
+ setStateHelper(m_pendingState);
+}
+
+QCamera::Status CameraBinSession::status() const
+{
+ return m_status;
}
QCamera::State CameraBinSession::pendingState() const
@@ -685,64 +689,112 @@ void CameraBinSession::setState(QCamera::State newState)
qDebug() << Q_FUNC_INFO << newState;
#endif
- switch (newState) {
- case QCamera::UnloadedState:
- if (m_recordingActive)
- stopVideoRecording();
-
- if (m_viewfinderInterface)
- m_viewfinderInterface->stopRenderer();
-
- gst_element_set_state(m_camerabin, GST_STATE_NULL);
- m_state = newState;
- if (m_busy)
- emit busyChanged(m_busy = false);
+ setStateHelper(newState);
+}
- emit stateChanged(m_state);
+void CameraBinSession::setStateHelper(QCamera::State state)
+{
+ switch (state) {
+ case QCamera::UnloadedState:
+ unload();
break;
case QCamera::LoadedState:
- if (m_recordingActive)
- stopVideoRecording();
-
- if (m_videoInputHasChanged) {
- if (m_viewfinderInterface)
- m_viewfinderInterface->stopRenderer();
-
- gst_element_set_state(m_camerabin, GST_STATE_NULL);
- buildCameraSource();
- }
-#ifdef USE_READY_STATE_ON_LOADED
- gst_element_set_state(m_camerabin, GST_STATE_READY);
-#else
- m_state = QCamera::LoadedState;
- if (m_viewfinderInterface)
- m_viewfinderInterface->stopRenderer();
- gst_element_set_state(m_camerabin, GST_STATE_NULL);
- emit stateChanged(m_state);
-#endif
+ if (m_status == QCamera::ActiveStatus)
+ stop();
+ else if (m_status == QCamera::UnloadedStatus)
+ load();
break;
case QCamera::ActiveState:
- if (setupCameraBin()) {
- GstState binState = GST_STATE_NULL;
- GstState pending = GST_STATE_NULL;
- gst_element_get_state(m_camerabin, &binState, &pending, 0);
+ // If the viewfinder changed while in the loaded state, we need to reload the pipeline
+ if (m_status == QCamera::LoadedStatus && !m_viewfinderHasChanged)
+ start();
+ else if (m_status == QCamera::UnloadedStatus || m_viewfinderHasChanged)
+ load();
+ }
+}
- m_recorderControl->applySettings();
+void CameraBinSession::setError(int err, const QString &errorString)
+{
+ m_pendingState = QCamera::UnloadedState;
+ emit error(err, errorString);
+ setStatus(QCamera::UnloadedStatus);
+}
- GstEncodingContainerProfile *profile = m_recorderControl->videoProfile();
- g_object_set (G_OBJECT(m_camerabin),
- "video-profile",
- profile,
- NULL);
- gst_encoding_profile_unref(profile);
+void CameraBinSession::load()
+{
+ if (m_status != QCamera::UnloadedStatus && !m_viewfinderHasChanged)
+ return;
- setAudioCaptureCaps();
+ setStatus(QCamera::LoadingStatus);
- setupCaptureResolution();
+ gst_element_set_state(m_camerabin, GST_STATE_NULL);
- gst_element_set_state(m_camerabin, GST_STATE_PLAYING);
- }
+ if (!setupCameraBin()) {
+ setError(QCamera::CameraError, QStringLiteral("No camera source available"));
+ return;
}
+
+ gst_element_set_state(m_camerabin, GST_STATE_READY);
+}
+
+void CameraBinSession::unload()
+{
+ if (m_status == QCamera::UnloadedStatus || m_status == QCamera::UnloadingStatus)
+ return;
+
+ setStatus(QCamera::UnloadingStatus);
+
+ if (m_recordingActive)
+ stopVideoRecording();
+
+ if (m_viewfinderInterface)
+ m_viewfinderInterface->stopRenderer();
+
+ gst_element_set_state(m_camerabin, GST_STATE_NULL);
+
+ if (m_busy)
+ emit busyChanged(m_busy = false);
+
+ setStatus(QCamera::UnloadedStatus);
+}
+
+void CameraBinSession::start()
+{
+ if (m_status != QCamera::LoadedStatus)
+ return;
+
+ setStatus(QCamera::StartingStatus);
+
+ m_recorderControl->applySettings();
+
+ GstEncodingContainerProfile *profile = m_recorderControl->videoProfile();
+ g_object_set (G_OBJECT(m_camerabin),
+ "video-profile",
+ profile,
+ NULL);
+ gst_encoding_profile_unref(profile);
+
+ setAudioCaptureCaps();
+
+ setupCaptureResolution();
+
+ gst_element_set_state(m_camerabin, GST_STATE_PLAYING);
+}
+
+void CameraBinSession::stop()
+{
+ if (m_status != QCamera::ActiveStatus)
+ return;
+
+ setStatus(QCamera::StoppingStatus);
+
+ if (m_recordingActive)
+ stopVideoRecording();
+
+ if (m_viewfinderInterface)
+ m_viewfinderInterface->stopRenderer();
+
+ gst_element_set_state(m_camerabin, GST_STATE_READY);
}
bool CameraBinSession::isBusy() const
@@ -889,7 +941,7 @@ bool CameraBinSession::processBusMessage(const QGstreamerMessage &message)
if (message.isEmpty())
message = tr("Camera error");
- emit error(int(QMediaRecorder::ResourceError), message);
+ setError(int(QMediaRecorder::ResourceError), message);
}
#ifdef CAMERABIN_DEBUG_DUMP_BIN
@@ -955,17 +1007,17 @@ bool CameraBinSession::processBusMessage(const QGstreamerMessage &message)
switch (newState) {
case GST_STATE_VOID_PENDING:
case GST_STATE_NULL:
- if (m_state != QCamera::UnloadedState)
- emit stateChanged(m_state = QCamera::UnloadedState);
+ setStatus(QCamera::UnloadedStatus);
break;
case GST_STATE_READY:
setMetaData(m_metaData);
- if (m_state != QCamera::LoadedState)
- emit stateChanged(m_state = QCamera::LoadedState);
+ setStatus(QCamera::LoadedStatus);
break;
- case GST_STATE_PAUSED:
case GST_STATE_PLAYING:
- emit stateChanged(m_state = QCamera::ActiveState);
+ setStatus(QCamera::ActiveStatus);
+ break;
+ case GST_STATE_PAUSED:
+ default:
break;
}
}
@@ -973,7 +1025,6 @@ bool CameraBinSession::processBusMessage(const QGstreamerMessage &message)
default:
break;
}
- //qDebug() << "New session state:" << ENUM_NAME(CameraBinSession,"State",m_state);
}
}
diff --git a/src/plugins/gstreamer/camerabin/camerabinsession.h b/src/plugins/gstreamer/camerabin/camerabinsession.h
index 723759b6a..d4214a620 100644
--- a/src/plugins/gstreamer/camerabin/camerabinsession.h
+++ b/src/plugins/gstreamer/camerabin/camerabinsession.h
@@ -148,7 +148,7 @@ public:
void captureImage(int requestId, const QString &fileName);
- QCamera::State state() const;
+ QCamera::Status status() const;
QCamera::State pendingState() const;
bool isBusy() const;
@@ -163,7 +163,7 @@ public:
bool processBusMessage(const QGstreamerMessage &message);
signals:
- void stateChanged(QCamera::State state);
+ void statusChanged(QCamera::Status status);
void pendingStateChanged(QCamera::State state);
void durationChanged(qint64 duration);
void error(int error, const QString &errorString);
@@ -185,6 +185,15 @@ private slots:
void handleViewfinderChange();
private:
+ void load();
+ void unload();
+ void start();
+ void stop();
+
+ void setStatus(QCamera::Status status);
+ void setStateHelper(QCamera::State state);
+ void setError(int error, const QString &errorString);
+
bool setupCameraBin();
void setupCaptureResolution();
void setAudioCaptureCaps();
@@ -197,7 +206,7 @@ private:
QUrl m_actualSink;
bool m_recordingActive;
QString m_captureDevice;
- QCamera::State m_state;
+ QCamera::Status m_status;
QCamera::State m_pendingState;
QString m_inputDevice;
bool m_muted;