diff options
author | Lars Knoll <lars.knoll@qt.io> | 2021-05-12 13:19:07 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2021-05-18 08:41:44 +0000 |
commit | 202ce66b89e3924a81f5d2d63f217c8a72a41478 (patch) | |
tree | 1f06382f7ca13df080c1d6bb45f66e675b00d4e9 /src/multimedia | |
parent | f6b68bb6834214dd3a05f95421b0ae5aa2404b03 (diff) |
Fix a crash in the gstreamer audio output
Closing the audio output would delete the pipeline, and would
lead to deleting the GstAppSrc from within QGstAppSrc::pushData().
Speed up the qsoundeffect autotest (this uncovered the issue).
Change-Id: I3c5843854f5a74d563eb271df553c8a1a5854f63
Reviewed-by: André de la Rocha <andre.rocha@qt.io>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/multimedia')
-rw-r--r-- | src/multimedia/platform/gstreamer/audio/qaudiooutput_gstreamer.cpp | 46 | ||||
-rw-r--r-- | src/multimedia/platform/gstreamer/common/qgstappsrc.cpp | 17 |
2 files changed, 37 insertions, 26 deletions
diff --git a/src/multimedia/platform/gstreamer/audio/qaudiooutput_gstreamer.cpp b/src/multimedia/platform/gstreamer/audio/qaudiooutput_gstreamer.cpp index eb74c2ee6..1b0fec46a 100644 --- a/src/multimedia/platform/gstreamer/audio/qaudiooutput_gstreamer.cpp +++ b/src/multimedia/platform/gstreamer/audio/qaudiooutput_gstreamer.cpp @@ -61,14 +61,35 @@ QGStreamerAudioOutput::QGStreamerAudioOutput(const QAudioDeviceInfo &device) { gstPipeline.installMessageFilter(this); + m_appSrc = new QGstAppSrc; + connect(m_appSrc, &QGstAppSrc::bytesProcessed, this, &QGStreamerAudioOutput::bytesProcessedByAppSrc); + connect(m_appSrc, &QGstAppSrc::noMoreData, this, &QGStreamerAudioOutput::needData); + gstAppSrc = m_appSrc->element(); + + // gstDecodeBin = gst_element_factory_make ("decodebin", "dec"); + QGstElement conv("audioconvert", "conv"); + gstVolume = QGstElement("volume", "volume"); + if (m_volume != 1.) + gstVolume.set("volume", m_volume); + + // link decodeBin to audioconvert in a callback once we get a pad from the decoder + // g_signal_connect (gstDecodeBin, "pad-added", (GCallback) padAdded, conv); + const auto *audioInfo = static_cast<const QGStreamerAudioDeviceInfo *>(device.handle()); gstOutput = gst_device_create_element(audioInfo->gstDevice, nullptr); + + gstPipeline.add(gstAppSrc, /*gstDecodeBin, */ conv, gstVolume, gstOutput); + gstAppSrc.link(conv, gstVolume, gstOutput); } QGStreamerAudioOutput::~QGStreamerAudioOutput() { close(); - QCoreApplication::processEvents(); + gstPipeline = {}; + gstVolume = {}; + gstAppSrc = {}; + delete m_appSrc; + m_appSrc = nullptr; } void QGStreamerAudioOutput::setError(QAudio::Error error) @@ -203,26 +224,9 @@ bool QGStreamerAudioOutput::open() } // qDebug() << "GST caps:" << gst_caps_to_string(caps); - m_appSrc = new QGstAppSrc; m_appSrc->setup(m_audioSource, m_audioSource ? m_audioSource->pos() : 0); m_appSrc->setAudioFormat(m_format); - connect(m_appSrc, &QGstAppSrc::bytesProcessed, this, &QGStreamerAudioOutput::bytesProcessedByAppSrc); - connect(m_appSrc, &QGstAppSrc::noMoreData, this, &QGStreamerAudioOutput::needData); - gstAppSrc = m_appSrc->element(); - -// gstDecodeBin = gst_element_factory_make ("decodebin", "dec"); - QGstElement conv("audioconvert", "conv"); - gstVolume = QGstElement("volume", "volume"); - if (m_volume != 1.) - gstVolume.set("volume", m_volume); - - gstPipeline.add(gstAppSrc, /*gstDecodeBin, */ conv, gstVolume, gstOutput); - gstAppSrc.link(conv, gstVolume, gstOutput); - - // link decodeBin to audioconvert in a callback once we get a pad from the decoder -// g_signal_connect (gstDecodeBin, "pad-added", (GCallback) padAdded, conv); - /* run */ gstPipeline.setState(GST_STATE_PLAYING); @@ -239,10 +243,8 @@ void QGStreamerAudioOutput::close() if (!m_opened) return; - gstPipeline.setStateSync(GST_STATE_NULL); - gstPipeline = {}; - gstVolume = {}; - gstAppSrc = {}; + if (!gstPipeline.setStateSync(GST_STATE_NULL)) + qWarning() << "failed to close the audio output stream"; if (!m_pullMode && m_audioSource) delete m_audioSource; diff --git a/src/multimedia/platform/gstreamer/common/qgstappsrc.cpp b/src/multimedia/platform/gstreamer/common/qgstappsrc.cpp index 7ff9b177f..2cf33fbce 100644 --- a/src/multimedia/platform/gstreamer/common/qgstappsrc.cpp +++ b/src/multimedia/platform/gstreamer/common/qgstappsrc.cpp @@ -56,6 +56,9 @@ QGstAppSrc::QGstAppSrc(QObject *parent) QGstAppSrc::~QGstAppSrc() { + m_appSrc.setStateSync(GST_STATE_NULL); + streamDestroyed(); + qCDebug(qLcAppSrc) << "~QGstAppSrc"; } bool QGstAppSrc::setup(QIODevice *stream, qint64 offset) @@ -68,6 +71,7 @@ bool QGstAppSrc::setup(QIODevice *stream, qint64 offset) auto *appSrc = GST_APP_SRC(m_appSrc.element()); GstAppSrcCallbacks m_callbacks; + memset(&m_callbacks, 0, sizeof(GstAppSrcCallbacks)); m_callbacks.need_data = &QGstAppSrc::on_need_data; m_callbacks.enough_data = &QGstAppSrc::on_enough_data; m_callbacks.seek_data = &QGstAppSrc::on_seek_data; @@ -141,20 +145,20 @@ void QGstAppSrc::write(const char *data, qsizetype size) Q_ASSERT(!m_stream); m_buffer.append(data, size); m_noMoreData = false; - if (m_dataRequestSize) - pushData(); + pushData(); } void QGstAppSrc::onDataReady() { qCDebug(qLcAppSrc) << "onDataReady" << m_stream->bytesAvailable() << m_stream->size(); - if (m_dataRequestSize) - pushData(); + pushData(); } void QGstAppSrc::streamDestroyed() { + qCDebug(qLcAppSrc) << "stream destroyed"; m_stream = nullptr; + m_dataRequestSize = 0; sendEOS(); } @@ -166,6 +170,7 @@ void QGstAppSrc::pushData() qCDebug(qLcAppSrc) << "pushData" << m_stream << m_stream->atEnd() << m_buffer.size(); if ((m_stream && m_stream->atEnd())) { eosOrIdle(); + qCDebug(qLcAppSrc) << "end pushData" << m_stream << m_stream->atEnd() << m_buffer.size(); return; } @@ -213,6 +218,7 @@ void QGstAppSrc::pushData() if (bytesRead == 0) { gst_buffer_unref(buffer); eosOrIdle(); + qCDebug(qLcAppSrc) << "end pushData" << m_stream << m_stream->atEnd() << m_buffer.size(); return; } m_noMoreData = false; @@ -224,6 +230,8 @@ void QGstAppSrc::pushData() } else if (ret == GST_FLOW_FLUSHING) { qWarning() << "QGstAppSrc: push buffer wrong state"; } + qCDebug(qLcAppSrc) << "end pushData" << m_stream << m_stream->atEnd() << m_buffer.size(); + } bool QGstAppSrc::doSeek(qint64 value) @@ -264,6 +272,7 @@ void QGstAppSrc::on_need_data(GstAppSrc *, guint arg0, gpointer userdata) Q_ASSERT(self); self->m_dataRequestSize = arg0; QMetaObject::invokeMethod(self, "pushData", Qt::AutoConnection); + qCDebug(qLcAppSrc) << "done on_need_data"; } void QGstAppSrc::sendEOS() |