From 7083a5d93a99945bfae6010eee6ab5207ba97cf0 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 19 May 2021 14:59:36 +0200 Subject: Fixes for qaudiooutput on gstreamer Add a queue element into the pipeline to decouple things between input and output. Add ability to suspend/resume the QGstAppSrc. This finally makes the autotest pass consistently. Change-Id: Ib20d1f9e6932aa9459085ad46fe78fdd03749723 Reviewed-by: Doris Verria Reviewed-by: Lars Knoll --- .../platform/gstreamer/audio/qaudiooutput_gstreamer.cpp | 8 ++++++-- src/multimedia/platform/gstreamer/common/qgstappsrc.cpp | 6 +++++- src/multimedia/platform/gstreamer/common/qgstappsrc_p.h | 7 ++++++- tests/auto/integration/qaudiooutput/tst_qaudiooutput.cpp | 1 - 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/multimedia/platform/gstreamer/audio/qaudiooutput_gstreamer.cpp b/src/multimedia/platform/gstreamer/audio/qaudiooutput_gstreamer.cpp index 1b0fec46a..1d1e94ff6 100644 --- a/src/multimedia/platform/gstreamer/audio/qaudiooutput_gstreamer.cpp +++ b/src/multimedia/platform/gstreamer/audio/qaudiooutput_gstreamer.cpp @@ -67,6 +67,7 @@ QGStreamerAudioOutput::QGStreamerAudioOutput(const QAudioDeviceInfo &device) gstAppSrc = m_appSrc->element(); // gstDecodeBin = gst_element_factory_make ("decodebin", "dec"); + QGstElement queue("queue", "queue"); QGstElement conv("audioconvert", "conv"); gstVolume = QGstElement("volume", "volume"); if (m_volume != 1.) @@ -78,8 +79,8 @@ QGStreamerAudioOutput::QGStreamerAudioOutput(const QAudioDeviceInfo &device) const auto *audioInfo = static_cast(device.handle()); gstOutput = gst_device_create_element(audioInfo->gstDevice, nullptr); - gstPipeline.add(gstAppSrc, /*gstDecodeBin, */ conv, gstVolume, gstOutput); - gstAppSrc.link(conv, gstVolume, gstOutput); + gstPipeline.add(gstAppSrc, queue, /*gstDecodeBin, */ conv, gstVolume, gstOutput); + gstAppSrc.link(queue, conv, gstVolume, gstOutput); } QGStreamerAudioOutput::~QGStreamerAudioOutput() @@ -258,6 +259,7 @@ qint64 QGStreamerAudioOutput::write(const char *data, qint64 len) return 0; if (m_errorState == QAudio::UnderrunError) m_errorState = QAudio::NoError; + m_appSrc->write(data, len); return len; } @@ -305,6 +307,7 @@ qint64 QGStreamerAudioOutput::processedUSecs() const void QGStreamerAudioOutput::resume() { if (m_deviceState == QAudio::SuspendedState) { + m_appSrc->resume(); gstPipeline.setState(GST_STATE_PLAYING); setState(m_pullMode ? QAudio::ActiveState : QAudio::IdleState); @@ -329,6 +332,7 @@ void QGStreamerAudioOutput::suspend() setState(QAudio::SuspendedState); gstPipeline.setState(GST_STATE_PAUSED); + m_appSrc->suspend(); // ### elapsed time } } diff --git a/src/multimedia/platform/gstreamer/common/qgstappsrc.cpp b/src/multimedia/platform/gstreamer/common/qgstappsrc.cpp index 801db5aff..027cc1850 100644 --- a/src/multimedia/platform/gstreamer/common/qgstappsrc.cpp +++ b/src/multimedia/platform/gstreamer/common/qgstappsrc.cpp @@ -78,6 +78,7 @@ bool QGstAppSrc::setup(QIODevice *stream, qint64 offset) gst_app_src_set_callbacks(appSrc, (GstAppSrcCallbacks*)&m_callbacks, this, nullptr); m_maxBytes = gst_app_src_get_max_bytes(appSrc); + m_suspended = false; if (m_sequential) m_streamType = GST_APP_STREAM_TYPE_STREAM; @@ -87,6 +88,7 @@ bool QGstAppSrc::setup(QIODevice *stream, qint64 offset) gst_app_src_set_size(appSrc, m_sequential ? -1 : m_stream->size() - m_offset); m_networkReply = qobject_cast(m_stream); + m_noMoreData = true; return true; } @@ -164,8 +166,10 @@ void QGstAppSrc::streamDestroyed() void QGstAppSrc::pushData() { - if (m_appSrc.isNull() || !m_dataRequestSize) + if (m_appSrc.isNull() || !m_dataRequestSize || m_suspended) { + qCDebug(qLcAppSrc) << "push data: return immediately" << m_appSrc.isNull() << m_dataRequestSize << m_suspended; return; + } qCDebug(qLcAppSrc) << "pushData" << (m_stream ? m_stream : nullptr) << m_buffer.size(); if ((m_stream && m_stream->atEnd())) { diff --git a/src/multimedia/platform/gstreamer/common/qgstappsrc_p.h b/src/multimedia/platform/gstreamer/common/qgstappsrc_p.h index 4a1ad5003..3a978454c 100644 --- a/src/multimedia/platform/gstreamer/common/qgstappsrc_p.h +++ b/src/multimedia/platform/gstreamer/common/qgstappsrc_p.h @@ -57,6 +57,7 @@ #include #include #include +#include #include #include @@ -82,6 +83,9 @@ public: bool canAcceptMoreData() { return m_noMoreData || m_dataRequestSize != 0; } + void suspend() { m_suspended = true; } + void resume() { m_suspended = false; m_noMoreData = true; } + Q_SIGNALS: void bytesProcessed(int bytes); void noMoreData(); @@ -113,12 +117,13 @@ private: QGstElement m_appSrc; bool m_sequential = true; + bool m_suspended = false; bool m_noMoreData = false; GstAppStreamType m_streamType = GST_APP_STREAM_TYPE_RANDOM_ACCESS; qint64 m_offset = 0; qint64 m_maxBytes = 0; qint64 bytesReadSoFar = 0; - unsigned int m_dataRequestSize = 0; + QAtomicInteger m_dataRequestSize = 0; int streamedSamples = 0; }; diff --git a/tests/auto/integration/qaudiooutput/tst_qaudiooutput.cpp b/tests/auto/integration/qaudiooutput/tst_qaudiooutput.cpp index 2cd59f472..8b20649b9 100644 --- a/tests/auto/integration/qaudiooutput/tst_qaudiooutput.cpp +++ b/tests/auto/integration/qaudiooutput/tst_qaudiooutput.cpp @@ -626,7 +626,6 @@ void tst_QAudioOutput::pushSuspendResume() qint64 written = 0; bool firstBuffer = true; - QByteArray buffer(AUDIO_BUFFER, 0); // Play half of the clip while (written < (audioFile->size() - QWaveDecoder::headerLength()) / 2) { -- cgit v1.2.3