summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDmytro Poplavskiy <dmytro.poplavskiy@nokia.com>2011-07-20 10:45:06 +1000
committerQt by Nokia <qt-info@nokia.com>2011-07-25 09:35:44 +0200
commite45902822c8161c84d2148244f0ff72fff0ba515 (patch)
tree01589dd5c178748b8403e47977f0e772cf0d6542 /src
parente47fa8b5a56e493c8fec065d41ac2266a5acfb93 (diff)
Gst backend: Fixed deadlock when pipeline is stopped during prerolling.
Waiting for start() to be invoked in the main thread may block if gstreamer blocks the main thread until this call is finished. This situation is rare and usually caused by setState(Null) while pipeline is being prerolled. The proper solution to this involves controlling gstreamer pipeline from other thread than video surface. Currently start() fails if wait() timed out. Task-number: QTMOBILITY-1663 Reviewed-by: Michael Goddard Change-Id: Ib95e589a814e53efb9b4c454ef9f233658ff8c6a (cherry picked from commit ac9762e2dbc06d696c6c74825ee22ac1fc176d9c) Reviewed-on: http://codereview.qt.nokia.com/2073 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Michael Goddard <michael.goddard@nokia.com>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/gstreamer/qvideosurfacegstsink.cpp33
-rw-r--r--src/plugins/gstreamer/qvideosurfacegstsink.h1
2 files changed, 27 insertions, 7 deletions
diff --git a/src/plugins/gstreamer/qvideosurfacegstsink.cpp b/src/plugins/gstreamer/qvideosurfacegstsink.cpp
index 8bd04f42b..58fabeda4 100644
--- a/src/plugins/gstreamer/qvideosurfacegstsink.cpp
+++ b/src/plugins/gstreamer/qvideosurfacegstsink.cpp
@@ -66,6 +66,7 @@ QVideoSurfaceGstDelegate::QVideoSurfaceGstDelegate(
, m_pool(0)
, m_renderReturn(GST_FLOW_ERROR)
, m_bytesPerLine(0)
+ , m_startCanceled(false)
{
if (m_surface) {
#if defined(Q_WS_X11) && !defined(QT_NO_XVIDEO)
@@ -114,9 +115,25 @@ bool QVideoSurfaceGstDelegate::start(const QVideoSurfaceFormat &format, int byte
if (QThread::currentThread() == thread()) {
m_started = !m_surface.isNull() ? m_surface->start(m_format) : false;
} else {
+ m_started = false;
+ m_startCanceled = false;
QMetaObject::invokeMethod(this, "queuedStart", Qt::QueuedConnection);
- m_setupCondition.wait(&m_mutex);
+ /*
+ Waiting for start() to be invoked in the main thread may block
+ if gstreamer blocks the main thread until this call is finished.
+ This situation is rare and usually caused by setState(Null)
+ while pipeline is being prerolled.
+
+ The proper solution to this involves controlling gstreamer pipeline from
+ other thread than video surface.
+
+ Currently start() fails if wait() timed out.
+ */
+ if (!m_setupCondition.wait(&m_mutex, 1000)) {
+ qWarning() << "Failed to start video surface due to main thread blocked.";
+ m_startCanceled = true;
+ }
}
m_format = m_surface->surfaceFormat();
@@ -137,7 +154,9 @@ void QVideoSurfaceGstDelegate::stop()
} else {
QMetaObject::invokeMethod(this, "queuedStop", Qt::QueuedConnection);
- m_setupCondition.wait(&m_mutex);
+ // Waiting for stop() to be invoked in the main thread may block
+ // if gstreamer blocks the main thread until this call is finished.
+ m_setupCondition.wait(&m_mutex, 500);
}
m_started = false;
@@ -195,11 +214,11 @@ GstFlowReturn QVideoSurfaceGstDelegate::render(GstBuffer *buffer)
void QVideoSurfaceGstDelegate::queuedStart()
{
- QMutexLocker locker(&m_mutex);
-
- m_started = m_surface->start(m_format);
-
- m_setupCondition.wakeAll();
+ if (!m_startCanceled) {
+ QMutexLocker locker(&m_mutex);
+ m_started = m_surface->start(m_format);
+ m_setupCondition.wakeAll();
+ }
}
void QVideoSurfaceGstDelegate::queuedStop()
diff --git a/src/plugins/gstreamer/qvideosurfacegstsink.h b/src/plugins/gstreamer/qvideosurfacegstsink.h
index 80f7bb951..4110579e5 100644
--- a/src/plugins/gstreamer/qvideosurfacegstsink.h
+++ b/src/plugins/gstreamer/qvideosurfacegstsink.h
@@ -109,6 +109,7 @@ private:
GstFlowReturn m_renderReturn;
int m_bytesPerLine;
bool m_started;
+ bool m_startCanceled;
};
class QVideoSurfaceGstSink