summaryrefslogtreecommitdiffstats
path: root/src/multimedia
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2021-05-12 13:19:07 +0200
committerLars Knoll <lars.knoll@qt.io>2021-05-18 08:41:44 +0000
commit202ce66b89e3924a81f5d2d63f217c8a72a41478 (patch)
tree1f06382f7ca13df080c1d6bb45f66e675b00d4e9 /src/multimedia
parentf6b68bb6834214dd3a05f95421b0ae5aa2404b03 (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.cpp46
-rw-r--r--src/multimedia/platform/gstreamer/common/qgstappsrc.cpp17
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()