diff options
author | Tim Blechmann <tim@klingt.org> | 2024-04-16 15:51:54 +0800 |
---|---|---|
committer | Tim Blechmann <tim@klingt.org> | 2024-04-18 20:43:17 +0800 |
commit | 7c214817645d0f3475945fc1dcbb94f455280e25 (patch) | |
tree | 846c47ce66ef284e8d7b11293d0f32f3455dd366 /src/plugins | |
parent | 324838268cd1a285b4fafad31b3485714d1c9f44 (diff) |
GStreamer: QGstAppSource - avoid pingpoing with main thread
By avoid the event queue when interacting with the QIODevice we work
around deadlocks when waiting for data which may be fed to the QIODevice
from the main event loop.
Pick-to: 6.5 6.7
Change-Id: I98c302b55d109a748cdf70401dd77cff6d3da008
Reviewed-by: Artem Dyomin <artem.dyomin@qt.io>
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/multimedia/gstreamer/common/qgstappsource.cpp | 50 | ||||
-rw-r--r-- | src/plugins/multimedia/gstreamer/common/qgstappsource_p.h | 16 |
2 files changed, 51 insertions, 15 deletions
diff --git a/src/plugins/multimedia/gstreamer/common/qgstappsource.cpp b/src/plugins/multimedia/gstreamer/common/qgstappsource.cpp index 0ec4fc889..99af8443c 100644 --- a/src/plugins/multimedia/gstreamer/common/qgstappsource.cpp +++ b/src/plugins/multimedia/gstreamer/common/qgstappsource.cpp @@ -36,6 +36,8 @@ QGstAppSource::~QGstAppSource() bool QGstAppSource::setup(QIODevice *stream, qint64 offset) { + QMutexLocker locker(&m_mutex); + if (m_appSrc.isNull()) return false; @@ -67,6 +69,8 @@ bool QGstAppSource::setup(QIODevice *stream, qint64 offset) void QGstAppSource::setAudioFormat(const QAudioFormat &f) { + QMutexLocker locker(&m_mutex); + m_format = f; if (!m_format.isValid()) return; @@ -79,14 +83,15 @@ void QGstAppSource::setAudioFormat(const QAudioFormat &f) void QGstAppSource::setExternalAppSrc(QGstAppSrc appsrc) { + QMutexLocker locker(&m_mutex); m_appSrc = std::move(appsrc); } bool QGstAppSource::setStream(QIODevice *stream, qint64 offset) { if (m_stream) { - disconnect(m_stream, SIGNAL(readyRead()), this, SLOT(onDataReady())); - disconnect(m_stream, SIGNAL(destroyed()), this, SLOT(streamDestroyed())); + disconnect(m_stream, &QIODevice::readyRead, this, &QGstAppSource::onDataReady); + disconnect(m_stream, &QIODevice::destroyed, this, &QGstAppSource::streamDestroyed); m_stream = nullptr; } @@ -99,21 +104,28 @@ bool QGstAppSource::setStream(QIODevice *stream, qint64 offset) if (!stream->isOpen() && !stream->open(QIODevice::ReadOnly)) return false; m_stream = stream; - connect(m_stream, SIGNAL(destroyed()), SLOT(streamDestroyed())); - connect(m_stream, SIGNAL(readyRead()), this, SLOT(onDataReady())); + connect(m_stream, &QIODevice::destroyed, this, &QGstAppSource::streamDestroyed); + connect(m_stream, &QIODevice::readyRead, this, &QGstAppSource::onDataReady); m_sequential = m_stream->isSequential(); m_offset = offset; } return true; } -QGstElement QGstAppSource::element() +bool QGstAppSource::isStreamValid() const +{ + return m_stream != nullptr && m_stream->isOpen(); +} + +QGstElement QGstAppSource::element() const { return m_appSrc; } void QGstAppSource::write(const char *data, qsizetype size) { + QMutexLocker locker(&m_mutex); + qCDebug(qLcAppSrc) << "write" << size << m_noMoreData << m_dataRequestSize; if (!size) return; @@ -123,6 +135,25 @@ void QGstAppSource::write(const char *data, qsizetype size) pushData(); } +bool QGstAppSource::canAcceptMoreData() const +{ + QMutexLocker locker(&m_mutex); + return m_noMoreData || m_dataRequestSize != 0; +} + +void QGstAppSource::suspend() +{ + QMutexLocker locker(&m_mutex); + m_suspended = true; +} + +void QGstAppSource::resume() +{ + QMutexLocker locker(&m_mutex); + m_suspended = false; + m_noMoreData = true; +} + void QGstAppSource::onDataReady() { qCDebug(qLcAppSrc) << "onDataReady" << m_stream->bytesAvailable() << m_stream->size(); @@ -227,10 +258,13 @@ gboolean QGstAppSource::on_seek_data(GstAppSrc *, guint64 arg0, gpointer userdat QGstAppSource *self = reinterpret_cast<QGstAppSource *>(userdata); Q_ASSERT(self); + + QMutexLocker locker(&self->m_mutex); + if (self->m_sequential) return false; - QMetaObject::invokeMethod(self, "doSeek", Qt::AutoConnection, Q_ARG(qint64, arg0)); + self->doSeek(arg0); return true; } @@ -239,6 +273,7 @@ void QGstAppSource::on_enough_data(GstAppSrc *, gpointer userdata) qCDebug(qLcAppSrc) << "on_enough_data"; QGstAppSource *self = static_cast<QGstAppSource *>(userdata); Q_ASSERT(self); + QMutexLocker locker(&self->m_mutex); self->m_dataRequestSize = 0; } @@ -247,8 +282,9 @@ void QGstAppSource::on_need_data(GstAppSrc *, guint arg0, gpointer userdata) qCDebug(qLcAppSrc) << "on_need_data requesting bytes" << arg0; QGstAppSource *self = static_cast<QGstAppSource *>(userdata); Q_ASSERT(self); + QMutexLocker locker(&self->m_mutex); self->m_dataRequestSize = arg0; - QMetaObject::invokeMethod(self, "pushData", Qt::AutoConnection); + self->pushData(); qCDebug(qLcAppSrc) << "done on_need_data"; } diff --git a/src/plugins/multimedia/gstreamer/common/qgstappsource_p.h b/src/plugins/multimedia/gstreamer/common/qgstappsource_p.h index bcfb0b530..59ced00dc 100644 --- a/src/plugins/multimedia/gstreamer/common/qgstappsource_p.h +++ b/src/plugins/multimedia/gstreamer/common/qgstappsource_p.h @@ -23,6 +23,7 @@ #include <QtCore/qiodevice.h> #include <QtCore/private/qringbuffer_p.h> #include <QtCore/qatomic.h> +#include <QtCore/qmutex.h> #include <common/qgst_p.h> #include <gst/app/gstappsrc.h> @@ -40,14 +41,14 @@ public: void setAudioFormat(const QAudioFormat &f); void setExternalAppSrc(QGstAppSrc); - QGstElement element(); + QGstElement element() const; void write(const char *data, qsizetype size); - bool canAcceptMoreData() { return m_noMoreData || m_dataRequestSize != 0; } + bool canAcceptMoreData() const; - void suspend() { m_suspended = true; } - void resume() { m_suspended = false; m_noMoreData = true; } + void suspend(); + void resume(); Q_SIGNALS: void bytesProcessed(int bytes); @@ -63,10 +64,7 @@ private: QGstAppSource(QGstAppSrc appsrc, QObject *parent); bool setStream(QIODevice *, qint64 offset); - bool isStreamValid() const - { - return m_stream != nullptr && m_stream->isOpen(); - } + bool isStreamValid() const; static gboolean on_seek_data(GstAppSrc *element, guint64 arg0, gpointer userdata); static void on_enough_data(GstAppSrc *element, gpointer userdata); @@ -75,6 +73,8 @@ private: void sendEOS(); void eosOrIdle(); + mutable QMutex m_mutex; + QIODevice *m_stream = nullptr; QRingBuffer m_buffer; QAudioFormat m_format; |