summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorTim Blechmann <tim@klingt.org>2024-04-16 15:51:54 +0800
committerTim Blechmann <tim@klingt.org>2024-04-18 20:43:17 +0800
commit7c214817645d0f3475945fc1dcbb94f455280e25 (patch)
tree846c47ce66ef284e8d7b11293d0f32f3455dd366 /src/plugins
parent324838268cd1a285b4fafad31b3485714d1c9f44 (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.cpp50
-rw-r--r--src/plugins/multimedia/gstreamer/common/qgstappsource_p.h16
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;