[qtmultimedia] don't stop the camera pipeline until it's done recording. Fixes JB#30862
stopping video recording is asynchronous. Aan EOS event gets sent from camera source, travels across the whole pipeline until it reaches the muxer which then finalizes the file by writing the mov atom and friends and then pushes the EOS event farther downstream until it reaches our file writer (multifilesink in our case). The sink sends an EOS _message_ which is then caught by camerabin and causes it to flip the idle property from FALSE to TRUE. Any attempt to stop the pipeline before this property gets flipped will cause corrupted videos. Probably because the muxer gets shut down before it gets the EOS event so it does not write the needed header. When we are unloading camera we stop video recording and immediately switch camera bin to NULL state. This can lead to corrupted files. A more proper solution would be to postpone this pipeline tear down until we are idle. Since an application can attempt to start the pipeline again before it's completely unloaded, I have added a check to make sure we never tear down the pipeline if we are not in unloaded state. This check is also needed because we will be notified about the idle property change while we are loading the camera and we should not unload it when that happens. This also required removing the pipeline state change to NULL when we are loading camera.
This commit is contained in:
committed by
Martin Jones
parent
770e009cff
commit
6ecbfc3cb1
@@ -757,8 +757,6 @@ void CameraBinSession::load()
|
|||||||
|
|
||||||
setStatus(QCamera::LoadingStatus);
|
setStatus(QCamera::LoadingStatus);
|
||||||
|
|
||||||
gst_element_set_state(m_camerabin, GST_STATE_NULL);
|
|
||||||
|
|
||||||
if (!setupCameraBin()) {
|
if (!setupCameraBin()) {
|
||||||
setError(QCamera::CameraError, QStringLiteral("No camera source available"));
|
setError(QCamera::CameraError, QStringLiteral("No camera source available"));
|
||||||
return;
|
return;
|
||||||
@@ -785,22 +783,16 @@ void CameraBinSession::unload()
|
|||||||
if (m_status == QCamera::UnloadedStatus || m_status == QCamera::UnloadingStatus)
|
if (m_status == QCamera::UnloadedStatus || m_status == QCamera::UnloadingStatus)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// We save the recording state in case something reacted to setStatus() and
|
||||||
|
// stopped recording.
|
||||||
|
bool wasRecording = m_recordingActive;
|
||||||
|
|
||||||
setStatus(QCamera::UnloadingStatus);
|
setStatus(QCamera::UnloadingStatus);
|
||||||
|
|
||||||
if (m_recordingActive)
|
if (m_recordingActive)
|
||||||
stopVideoRecording();
|
stopVideoRecording();
|
||||||
|
else if (!wasRecording)
|
||||||
if (m_viewfinderInterface)
|
handleBusyChanged(false);
|
||||||
m_viewfinderInterface->stopRenderer();
|
|
||||||
|
|
||||||
gst_element_set_state(m_camerabin, GST_STATE_NULL);
|
|
||||||
|
|
||||||
if (m_busy)
|
|
||||||
emit busyChanged(m_busy = false);
|
|
||||||
|
|
||||||
m_supportedViewfinderSettings.clear();
|
|
||||||
|
|
||||||
setStatus(QCamera::UnloadedStatus);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CameraBinSession::start()
|
void CameraBinSession::start()
|
||||||
@@ -860,7 +852,7 @@ void CameraBinSession::updateBusyStatus(GObject *o, GParamSpec *p, gpointer d)
|
|||||||
|
|
||||||
if (session->m_busy != busy) {
|
if (session->m_busy != busy) {
|
||||||
session->m_busy = busy;
|
session->m_busy = busy;
|
||||||
QMetaObject::invokeMethod(session, "busyChanged",
|
QMetaObject::invokeMethod(session, "handleBusyChanged",
|
||||||
Qt::QueuedConnection,
|
Qt::QueuedConnection,
|
||||||
Q_ARG(bool, busy));
|
Q_ARG(bool, busy));
|
||||||
}
|
}
|
||||||
@@ -1509,4 +1501,28 @@ void CameraBinSession::elementRemoved(GstBin *, GstElement *element, CameraBinSe
|
|||||||
session->m_muxer = 0;
|
session->m_muxer = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CameraBinSession::handleBusyChanged(bool busy)
|
||||||
|
{
|
||||||
|
// don't do anything if we are not unloading.
|
||||||
|
// It could be that the camera is starting again while it is being unloaded
|
||||||
|
if (m_status != QCamera::UnloadingStatus) {
|
||||||
|
if (m_busy != busy)
|
||||||
|
emit busyChanged(m_busy = busy);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now we can really stop
|
||||||
|
if (m_viewfinderInterface)
|
||||||
|
m_viewfinderInterface->stopRenderer();
|
||||||
|
|
||||||
|
gst_element_set_state(m_camerabin, GST_STATE_NULL);
|
||||||
|
|
||||||
|
if (m_busy != busy)
|
||||||
|
emit busyChanged(m_busy = busy);
|
||||||
|
|
||||||
|
m_supportedViewfinderSettings.clear();
|
||||||
|
|
||||||
|
setStatus(QCamera::UnloadedStatus);
|
||||||
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|||||||
@@ -180,6 +180,7 @@ public slots:
|
|||||||
private slots:
|
private slots:
|
||||||
void handleViewfinderChange();
|
void handleViewfinderChange();
|
||||||
void setupCaptureResolution();
|
void setupCaptureResolution();
|
||||||
|
void handleBusyChanged(bool busy);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void load();
|
void load();
|
||||||
|
|||||||
Reference in New Issue
Block a user