diff options
-rw-r--r-- | src/plugins/gstreamer/qvideosurfacegstsink.cpp | 33 | ||||
-rw-r--r-- | src/plugins/gstreamer/qvideosurfacegstsink.h | 1 |
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 |