diff options
author | Lars Knoll <lars.knoll@qt.io> | 2021-05-12 16:05:20 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2021-05-18 08:42:13 +0000 |
commit | abb3d5589cdb640527e2ab4cd01d7845984c0305 (patch) | |
tree | b933272b88e6649b585d508d0e3e84b0fa7ada65 | |
parent | 202ce66b89e3924a81f5d2d63f217c8a72a41478 (diff) |
Fix some code that was not thread safe
new_sample() could get called from a different thread, but would
write into the object living on the main thread without any
protection. Fix that by posting the GstSample to the main
thread and processing it there.
Change-Id: I6e8b8cb84c956794aac3ac00e89178d03bbf3f92
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Reviewed-by: André de la Rocha <andre.rocha@qt.io>
-rw-r--r-- | src/multimedia/platform/gstreamer/audio/qaudioinput_gstreamer.cpp | 46 | ||||
-rw-r--r-- | src/multimedia/platform/gstreamer/audio/qaudioinput_gstreamer_p.h | 7 |
2 files changed, 35 insertions, 18 deletions
diff --git a/src/multimedia/platform/gstreamer/audio/qaudioinput_gstreamer.cpp b/src/multimedia/platform/gstreamer/audio/qaudioinput_gstreamer.cpp index 57f701e47..40396b097 100644 --- a/src/multimedia/platform/gstreamer/audio/qaudioinput_gstreamer.cpp +++ b/src/multimedia/platform/gstreamer/audio/qaudioinput_gstreamer.cpp @@ -48,13 +48,17 @@ #include <unistd.h> #include <gst/gst.h> +Q_DECLARE_OPAQUE_POINTER(GstSample *); +Q_DECLARE_METATYPE(GstSample *); QT_BEGIN_NAMESPACE + QGStreamerAudioInput::QGStreamerAudioInput(const QAudioDeviceInfo &device) : m_info(device), m_device(device.id()) { + qRegisterMetaType<GstSample *>(); } QGStreamerAudioInput::~QGStreamerAudioInput() @@ -330,29 +334,37 @@ QGstElement QGStreamerAudioInput::createAppSink() return sink; } +void QGStreamerAudioInput::newDataAvailable(GstSample *sample) +{ + if (m_audioSink) { + GstBuffer *buffer = gst_sample_get_buffer(sample); + GstMapInfo mapInfo; + gst_buffer_map(buffer, &mapInfo, GST_MAP_READ); + const char *bufferData = (const char*)mapInfo.data; + gsize bufferSize = mapInfo.size; + + if (!m_pullMode) { + // need to store that data in the QBuffer + m_buffer.append(bufferData, bufferSize); + m_audioSink->readyRead(); + } else { + m_bytesWritten += bufferSize; + m_audioSink->write(bufferData, bufferSize); + } + + gst_buffer_unmap(buffer, &mapInfo); + } + + gst_sample_unref(sample); +} + GstFlowReturn QGStreamerAudioInput::new_sample(GstAppSink *sink, gpointer user_data) { // "Note that the preroll buffer will also be returned as the first buffer when calling gst_app_sink_pull_buffer()." QGStreamerAudioInput *control = static_cast<QGStreamerAudioInput*>(user_data); GstSample *sample = gst_app_sink_pull_sample(sink); - GstBuffer *buffer = gst_sample_get_buffer(sample); - GstMapInfo mapInfo; - gst_buffer_map(buffer, &mapInfo, GST_MAP_READ); - const char *bufferData = (const char*)mapInfo.data; - gsize bufferSize = mapInfo.size; - - if (!control->m_pullMode) { - // need to store that data in the QBuffer - control->m_buffer.append(bufferData, bufferSize); - control->m_audioSink->readyRead(); - } else { - control->m_bytesWritten += bufferSize; - control->m_audioSink->write(bufferData, bufferSize); - } - - gst_buffer_unmap(buffer, &mapInfo); - gst_sample_unref(sample); + QMetaObject::invokeMethod(control, "newDataAvailable", Qt::AutoConnection, Q_ARG(GstSample *, sample)); return GST_FLOW_OK; } diff --git a/src/multimedia/platform/gstreamer/audio/qaudioinput_gstreamer_p.h b/src/multimedia/platform/gstreamer/audio/qaudioinput_gstreamer_p.h index 7134c697a..2997b0084 100644 --- a/src/multimedia/platform/gstreamer/audio/qaudioinput_gstreamer_p.h +++ b/src/multimedia/platform/gstreamer/audio/qaudioinput_gstreamer_p.h @@ -57,6 +57,8 @@ #include <QtCore/qstringlist.h> #include <QtCore/qelapsedtimer.h> #include <QtCore/qiodevice.h> +#include <QtCore/qmutex.h> +#include <QtCore/qatomic.h> #include <QtCore/private/qringbuffer_p.h> #include "qaudio.h" @@ -98,6 +100,9 @@ public: void setVolume(qreal volume) override; qreal volume() const override; +private Q_SLOTS: + void newDataAvailable(GstSample *sample); + private: void setState(QAudio::State state); void setError(QAudio::Error error); @@ -120,7 +125,7 @@ private: qreal m_volume = 1.; QRingBuffer m_buffer; - bool m_pullMode = true; + QAtomicInteger<bool> m_pullMode = true; bool m_opened = false; int m_bufferSize = 0; qint64 m_elapsedTimeOffset = 0; |