summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolker Hilsheimer <volker.hilsheimer@qt.io>2023-02-04 14:46:03 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2023-02-07 10:34:05 +0000
commit909fc7187f688c2f8c515a8eb8237ec8f35c924d (patch)
tree2ae8f1f5d7f6185252dfce77a70e5323d979f0eb
parentc591a383edaa43c81c07f49ce35a4cc37968e176 (diff)
downloadqtmultimedia-909fc7187f688c2f8c515a8eb8237ec8f35c924d.tar.gz
Fix behavior of QAudioSink::resume in push mode
Up to now, a QAudioSink in push mode (ie. started without a QIODevice, but returning a QIODevice buffer that the client has to push data into) transitioned to IdleState when resuming after a suspend, even if there was still data in the buffer or device to play. This resulted in the sink playing audio even though it was in IdleState, and the client not getting notified when the audio data was actually drained (as the stateChanged signal did not get emitted again). Fix this by storing the state in which the sink gets suspended, and restore to that state when resuming. If the sink then runs into an underrun because not enough data is available in the push-buffer, then it will transition to IdleState with UnderrunError later. Implement this consistently in all platform implementations, adjust the test, which previously verified that a push-sink transitions to IdleState when resuming, and change the documentation accordingly. [ChangeLog][QtMutimedia][QAudioSink] Calling QAudioSink::resume() now returns the sink to the state it had when QAudioSink::suspend() was called, no matter whether the sink operates in pull or push mode. Change-Id: If0c7fe8629627de814276d629d825e469c998d2d Reviewed-by: Lars Knoll <lars@knoll.priv.no> Reviewed-by: Artem Dyomin <artem.dyomin@qt.io> (cherry picked from commit 0220951e712322e4e80253431a322317063e104a) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/multimedia/alsa/qalsaaudiosink.cpp25
-rw-r--r--src/multimedia/alsa/qalsaaudiosink_p.h41
-rw-r--r--src/multimedia/android/qandroidaudiosink.cpp43
-rw-r--r--src/multimedia/android/qandroidaudiosink_p.h39
-rw-r--r--src/multimedia/audio/qaudiosink.cpp7
-rw-r--r--src/multimedia/darwin/qdarwinaudiosink.mm3
-rw-r--r--src/multimedia/darwin/qdarwinaudiosink_p.h1
-rw-r--r--src/multimedia/pulseaudio/qpulseaudiosink.cpp3
-rw-r--r--src/multimedia/pulseaudio/qpulseaudiosink_p.h1
-rw-r--r--src/multimedia/qnx/qqnxaudiosink.cpp6
-rw-r--r--src/multimedia/qnx/qqnxaudiosink_p.h1
-rw-r--r--src/multimedia/wasm/qwasmaudiosink.cpp1
-rw-r--r--src/multimedia/wasm/qwasmaudiosink_p.h1
-rw-r--r--src/multimedia/windows/qwindowsaudiosink.cpp8
-rw-r--r--src/multimedia/windows/qwindowsaudiosink_p.h1
-rw-r--r--src/plugins/multimedia/gstreamer/audio/qgstreameraudiosink.cpp3
-rw-r--r--src/plugins/multimedia/gstreamer/audio/qgstreameraudiosink_p.h1
-rw-r--r--tests/auto/integration/qaudiosink/tst_qaudiosink.cpp3
18 files changed, 81 insertions, 107 deletions
diff --git a/src/multimedia/alsa/qalsaaudiosink.cpp b/src/multimedia/alsa/qalsaaudiosink.cpp
index 84b9e2432..6f92f62b3 100644
--- a/src/multimedia/alsa/qalsaaudiosink.cpp
+++ b/src/multimedia/alsa/qalsaaudiosink.cpp
@@ -27,27 +27,6 @@ static Q_LOGGING_CATEGORY(lcAlsaOutput, "qt.multimedia.alsa.output")
QAlsaAudioSink::QAlsaAudioSink(const QByteArray &device, QObject *parent)
: QPlatformAudioSink(parent)
{
- bytesAvailable = 0;
- handle = 0;
- access = SND_PCM_ACCESS_RW_INTERLEAVED;
- pcmformat = SND_PCM_FORMAT_S16;
- buffer_frames = 0;
- period_frames = 0;
- buffer_size = 0;
- period_size = 0;
- buffer_time = 100000;
- period_time = 20000;
- totalTimeValue = 0;
- audioBuffer = 0;
- errorState = QAudio::NoError;
- deviceState = QAudio::StoppedState;
- audioSource = 0;
- pullMode = true;
- resuming = false;
- opened = false;
-
- m_volume = 1.0f;
-
m_device = device;
timer = new QTimer(this);
@@ -551,8 +530,7 @@ void QAlsaAudioSink::resume()
}
resuming = true;
- deviceState = pullMode ? QAudio::ActiveState : QAudio::IdleState;
-
+ deviceState = suspendedInState;
errorState = QAudio::NoError;
timer->start(period_time/1000);
emit stateChanged(deviceState);
@@ -572,6 +550,7 @@ QAudioFormat QAlsaAudioSink::format() const
void QAlsaAudioSink::suspend()
{
if(deviceState == QAudio::ActiveState || deviceState == QAudio::IdleState || resuming) {
+ suspendedInState = deviceState;
snd_pcm_drain(handle);
timer->stop();
deviceState = QAudio::SuspendedState;
diff --git a/src/multimedia/alsa/qalsaaudiosink_p.h b/src/multimedia/alsa/qalsaaudiosink_p.h
index 9df697522..8ab402a4c 100644
--- a/src/multimedia/alsa/qalsaaudiosink_p.h
+++ b/src/multimedia/alsa/qalsaaudiosink_p.h
@@ -59,10 +59,11 @@ public:
qreal volume() const override;
- QIODevice* audioSource;
+ QIODevice* audioSource = nullptr;
QAudioFormat settings;
- QAudio::Error errorState;
- QAudio::State deviceState;
+ QAudio::Error errorState = QAudio::NoError;
+ QAudio::State deviceState = QAudio::StoppedState;
+ QAudio::State suspendedInState = QAudio::SuspendedState;
private slots:
void userFeed();
@@ -72,14 +73,14 @@ signals:
void processMore();
private:
- bool opened;
- bool pullMode;
- bool resuming;
- int buffer_size;
- int period_size;
- qint64 totalTimeValue;
- unsigned int buffer_time;
- unsigned int period_time;
+ bool opened = false;
+ bool pullMode = true;
+ bool resuming = false;
+ int buffer_size = 0;
+ int period_size = 0;
+ qint64 totalTimeValue = 0;
+ unsigned int buffer_time = 100000;
+ unsigned int period_time = 20000;
snd_pcm_uframes_t buffer_frames;
snd_pcm_uframes_t period_frames;
int xrun_recovery(int err);
@@ -88,16 +89,16 @@ private:
bool open();
void close();
- QTimer* timer;
+ QTimer* timer = nullptr;
QByteArray m_device;
- int bytesAvailable;
- qint64 elapsedTimeOffset;
- char* audioBuffer;
- snd_pcm_t* handle;
- snd_pcm_access_t access;
- snd_pcm_format_t pcmformat;
- snd_pcm_hw_params_t *hwparams;
- qreal m_volume;
+ int bytesAvailable = 0;
+ qint64 elapsedTimeOffset = 0;
+ char* audioBuffer = nullptr;
+ snd_pcm_t* handle = nullptr;
+ snd_pcm_access_t access SND_PCM_ACCESS_RW_INTERLEAVED;
+ snd_pcm_format_t pcmformat SND_PCM_FORMAT_S16;
+ snd_pcm_hw_params_t *hwparams = nullptr;
+ qreal m_volume = 1.0f;
};
class AlsaOutputPrivate : public QIODevice
diff --git a/src/multimedia/android/qandroidaudiosink.cpp b/src/multimedia/android/qandroidaudiosink.cpp
index 3cbb7dd0a..1f77cc6c2 100644
--- a/src/multimedia/android/qandroidaudiosink.cpp
+++ b/src/multimedia/android/qandroidaudiosink.cpp
@@ -12,8 +12,6 @@
#include <SLES/OpenSLES_AndroidConfiguration.h>
#endif // ANDROID
-#define BUFFER_COUNT 2
-
QT_BEGIN_NAMESPACE
static inline void openSlDebugInfo()
@@ -30,25 +28,7 @@ static inline void openSlDebugInfo()
QAndroidAudioSink::QAndroidAudioSink(const QByteArray &device, QObject *parent)
: QPlatformAudioSink(parent),
- m_deviceName(device),
- m_state(QAudio::StoppedState),
- m_error(QAudio::NoError),
- m_outputMixObject(nullptr),
- m_playerObject(nullptr),
- m_playItf(nullptr),
- m_volumeItf(nullptr),
- m_bufferQueueItf(nullptr),
- m_audioSource(nullptr),
- m_buffers(nullptr),
- m_volume(1.0),
- m_pullMode(false),
- m_nextBuffer(0),
- m_bufferSize(0),
- m_elapsedTime(0),
- m_processedBytes(0),
- m_availableBuffers(BUFFER_COUNT),
- m_eventMask(SL_PLAYEVENT_HEADATEND),
- m_startRequiresInit(true)
+ m_deviceName(device)
{
#ifndef ANDROID
m_streamType = -1;
@@ -86,12 +66,12 @@ void QAndroidAudioSink::start(QIODevice *device)
m_audioSource = device;
m_nextBuffer = 0;
m_processedBytes = 0;
- m_availableBuffers = BUFFER_COUNT;
+ m_availableBuffers = BufferCount;
setState(QAudio::ActiveState);
setError(QAudio::NoError);
// Attempt to fill buffers first.
- for (int i = 0; i != BUFFER_COUNT; ++i) {
+ for (int i = 0; i != BufferCount; ++i) {
const int index = i * m_bufferSize;
const qint64 readSize = m_audioSource->read(m_buffers + index, m_bufferSize);
if (readSize && SL_RESULT_SUCCESS != (*m_bufferQueueItf)->Enqueue(m_bufferQueueItf,
@@ -122,7 +102,7 @@ QIODevice *QAndroidAudioSink::start()
m_pullMode = false;
m_processedBytes = 0;
- m_availableBuffers = BUFFER_COUNT;
+ m_availableBuffers = BufferCount;
m_audioSource = new SLIODevicePrivate(this);
m_audioSource->open(QIODevice::WriteOnly | QIODevice::Unbuffered);
@@ -187,7 +167,7 @@ void QAndroidAudioSink::resume()
return;
}
- setState(m_pullMode ? QAudio::ActiveState : QAudio::IdleState);
+ setState(m_suspendedInState);
setError(QAudio::NoError);
}
@@ -213,6 +193,7 @@ void QAndroidAudioSink::suspend()
return;
}
+ m_suspendedInState = m_state;
setState(QAudio::SuspendedState);
setError(QAudio::NoError);
}
@@ -267,7 +248,7 @@ void QAndroidAudioSink::bufferAvailable(quint32 count, quint32 playIndex)
if (!m_pullMode) { // We're in push mode.
// Signal that there is a new open slot in the buffer and return
const int val = m_availableBuffers.fetchAndAddRelease(1) + 1;
- if (val == BUFFER_COUNT)
+ if (val == BufferCount)
QMetaObject::invokeMethod(this, "onEOSEvent", Qt::QueuedConnection);
return;
@@ -291,7 +272,7 @@ void QAndroidAudioSink::bufferAvailable(quint32 count, quint32 playIndex)
return;
}
- m_nextBuffer = (m_nextBuffer + 1) % BUFFER_COUNT;
+ m_nextBuffer = (m_nextBuffer + 1) % BufferCount;
QMetaObject::invokeMethod(this, "onBytesProcessed", Qt::QueuedConnection, Q_ARG(qint64, readSize));
if (m_audioSource->atEnd())
@@ -331,7 +312,7 @@ bool QAndroidAudioSink::preparePlayer()
return false;
}
- SLDataLocator_BufferQueue bufferQueueLocator = { SL_DATALOCATOR_BUFFERQUEUE, BUFFER_COUNT };
+ SLDataLocator_BufferQueue bufferQueueLocator = { SL_DATALOCATOR_BUFFERQUEUE, BufferCount };
SLAndroidDataFormat_PCM_EX pcmFormat = QOpenSLESEngine::audioFormatToSLFormatPCM(m_format);
SLDataSource audioSrc = { &bufferQueueLocator, &pcmFormat };
@@ -463,7 +444,7 @@ bool QAndroidAudioSink::preparePlayer()
}
if (!m_buffers)
- m_buffers = new char[BUFFER_COUNT * m_bufferSize];
+ m_buffers = new char[BufferCount * m_bufferSize];
setError(QAudio::NoError);
m_startRequiresInit = false;
@@ -496,7 +477,7 @@ void QAndroidAudioSink::destroyPlayer()
m_buffers = nullptr;
m_processedBytes = 0;
m_nextBuffer = 0;
- m_availableBuffers.storeRelease(BUFFER_COUNT);
+ m_availableBuffers.storeRelease(BufferCount);
m_playItf = nullptr;
m_volumeItf = nullptr;
m_bufferQueueItf = nullptr;
@@ -570,7 +551,7 @@ qint64 QAndroidAudioSink::writeData(const char *data, qint64 len)
m_processedBytes += len;
setState(QAudio::ActiveState);
setError(QAudio::NoError);
- m_nextBuffer = (m_nextBuffer + 1) % BUFFER_COUNT;
+ m_nextBuffer = (m_nextBuffer + 1) % BufferCount;
return len;
}
diff --git a/src/multimedia/android/qandroidaudiosink_p.h b/src/multimedia/android/qandroidaudiosink_p.h
index ca86d9a24..c080ca72c 100644
--- a/src/multimedia/android/qandroidaudiosink_p.h
+++ b/src/multimedia/android/qandroidaudiosink_p.h
@@ -71,25 +71,28 @@ private:
SLmillibel adjustVolume(qreal vol);
+ static constexpr int BufferCount = 2;
+
QByteArray m_deviceName;
- QAudio::State m_state;
- QAudio::Error m_error;
- SLObjectItf m_outputMixObject;
- SLObjectItf m_playerObject;
- SLPlayItf m_playItf;
- SLVolumeItf m_volumeItf;
- SLBufferQueueItf m_bufferQueueItf;
- QIODevice *m_audioSource;
- char *m_buffers;
- qreal m_volume;
- bool m_pullMode;
- int m_nextBuffer;
- int m_bufferSize;
- qint64 m_elapsedTime;
- qint64 m_processedBytes;
- QAtomicInt m_availableBuffers;
- SLuint32 m_eventMask;
- bool m_startRequiresInit;
+ QAudio::State m_state = QAudio::StoppedState;
+ QAudio::State m_suspendedInState = QAudio::SuspendedState;
+ QAudio::Error m_error = QAudio::NoError;
+ SLObjectItf m_outputMixObject = nullptr;
+ SLObjectItf m_playerObject = nullptr;
+ SLPlayItf m_playItf = nullptr;
+ SLVolumeItf m_volumeItf = nullptr;
+ SLBufferQueueItf m_bufferQueueItf = nullptr;
+ QIODevice *m_audioSource = nullptr;
+ char *m_buffers = nullptr;
+ qreal m_volume = 1.0;
+ bool m_pullMode = false;
+ int m_nextBuffer = 0;
+ int m_bufferSize = 0;
+ qint64 m_elapsedTime = 0;
+ qint64 m_processedBytes = 0;
+ QAtomicInt m_availableBuffers = BufferCount;
+ SLuint32 m_eventMask = SL_PLAYEVENT_HEADATEND;
+ bool m_startRequiresInit = true;
qint32 m_streamType;
QAudioFormat m_format;
diff --git a/src/multimedia/audio/qaudiosink.cpp b/src/multimedia/audio/qaudiosink.cpp
index 5f38bbc98..47d522d2c 100644
--- a/src/multimedia/audio/qaudiosink.cpp
+++ b/src/multimedia/audio/qaudiosink.cpp
@@ -203,10 +203,9 @@ void QAudioSink::suspend()
/*!
Resumes processing audio data after a suspend().
- Sets error() to QAudio::NoError.
- Sets state() to QAudio::ActiveState if you previously called start(QIODevice*).
- Sets state() to QAudio::IdleState if you previously called start().
- emits stateChanged() signal.
+ Sets state() to the state the sink had when suspend() was called, and sets
+ error() to QAudioError::NoError. This function does nothing if the audio sink's
+ state is not QAudio::SuspendedState.
*/
void QAudioSink::resume()
{
diff --git a/src/multimedia/darwin/qdarwinaudiosink.mm b/src/multimedia/darwin/qdarwinaudiosink.mm
index 340472671..56bfe5397 100644
--- a/src/multimedia/darwin/qdarwinaudiosink.mm
+++ b/src/multimedia/darwin/qdarwinaudiosink.mm
@@ -292,6 +292,7 @@ void QDarwinAudioSink::suspend()
audioThreadStop();
+ m_suspendedInStateCode = m_stateCode;
m_stateCode = QAudio::SuspendedState;
m_errorCode = QAudio::NoError;
emit stateChanged(m_stateCode);
@@ -304,7 +305,7 @@ void QDarwinAudioSink::resume()
audioThreadStart();
- m_stateCode = m_pullMode ? QAudio::ActiveState : QAudio::IdleState;
+ m_stateCode = m_suspendedInStateCode;
m_errorCode = QAudio::NoError;
emit stateChanged(m_stateCode);
}
diff --git a/src/multimedia/darwin/qdarwinaudiosink_p.h b/src/multimedia/darwin/qdarwinaudiosink_p.h
index 4d528de79..f929d36d9 100644
--- a/src/multimedia/darwin/qdarwinaudiosink_p.h
+++ b/src/multimedia/darwin/qdarwinaudiosink_p.h
@@ -169,6 +169,7 @@ private:
QAudio::Error m_errorCode = QAudio::NoError;
QAudio::State m_stateCode = QAudio::StoppedState;
+ QAudio::State m_suspendedInStateCode = QAudio::SuspendedState;
};
QT_END_NAMESPACE
diff --git a/src/multimedia/pulseaudio/qpulseaudiosink.cpp b/src/multimedia/pulseaudio/qpulseaudiosink.cpp
index 2b8264012..f12d0f6ed 100644
--- a/src/multimedia/pulseaudio/qpulseaudiosink.cpp
+++ b/src/multimedia/pulseaudio/qpulseaudiosink.cpp
@@ -645,7 +645,7 @@ void QPulseAudioSink::resume()
m_tickTimer.start(m_periodTime, this);
- setState(m_pullMode ? QAudio::ActiveState : QAudio::IdleState);
+ setState(m_suspendedInState);
setError(QAudio::NoError);
}
}
@@ -663,6 +663,7 @@ QAudioFormat QPulseAudioSink::format() const
void QPulseAudioSink::suspend()
{
if (m_deviceState == QAudio::ActiveState || m_deviceState == QAudio::IdleState) {
+ m_suspendedInState = m_deviceState;
setError(QAudio::NoError);
setState(QAudio::SuspendedState);
diff --git a/src/multimedia/pulseaudio/qpulseaudiosink_p.h b/src/multimedia/pulseaudio/qpulseaudiosink_p.h
index c2c62d109..4b3b1cf91 100644
--- a/src/multimedia/pulseaudio/qpulseaudiosink_p.h
+++ b/src/multimedia/pulseaudio/qpulseaudiosink_p.h
@@ -100,6 +100,7 @@ private:
QAudio::Error m_errorState = QAudio::NoError;
QAudio::State m_deviceState = QAudio::StoppedState;
+ QAudio::State m_suspendedInState = QAudio::SuspendedState;
int m_periodSize = 0;
int m_bufferSize = 0;
int m_maxBufferSize = 0;
diff --git a/src/multimedia/qnx/qqnxaudiosink.cpp b/src/multimedia/qnx/qqnxaudiosink.cpp
index f78371b02..fa4b97ab6 100644
--- a/src/multimedia/qnx/qqnxaudiosink.cpp
+++ b/src/multimedia/qnx/qqnxaudiosink.cpp
@@ -21,6 +21,7 @@ QQnxAudioSink::QQnxAudioSink(const QAudioDevice &deviceInfo, QObject *parent)
, m_timer(new QTimer(this))
, m_error(QAudio::NoError)
, m_state(QAudio::StoppedState)
+ , m_suspendedInState(QAudio::SuspendedState)
, m_volume(1.0)
, m_periodSize(0)
, m_bytesWritten(0)
@@ -416,14 +417,13 @@ void QQnxAudioSink::suspendInternal(QAudio::State suspendState)
if (!m_pushSource)
m_timer->stop();
+ m_suspendedInState = m_state;
changeState(suspendState, QAudio::NoError);
}
void QQnxAudioSink::resumeInternal()
{
- const QAudio::State state = m_pushSource ? QAudio::IdleState : QAudio::ActiveState;
-
- changeState(state, QAudio::NoError);
+ changeState(m_suspendedInState, QAudio::NoError);
m_timer->start();
}
diff --git a/src/multimedia/qnx/qqnxaudiosink_p.h b/src/multimedia/qnx/qqnxaudiosink_p.h
index 94669ecb7..1275121b3 100644
--- a/src/multimedia/qnx/qqnxaudiosink_p.h
+++ b/src/multimedia/qnx/qqnxaudiosink_p.h
@@ -83,6 +83,7 @@ private:
QAudio::Error m_error;
QAudio::State m_state;
+ QAudio::State m_suspendedInState;
QAudioFormat m_format;
qreal m_volume;
int m_periodSize;
diff --git a/src/multimedia/wasm/qwasmaudiosink.cpp b/src/multimedia/wasm/qwasmaudiosink.cpp
index a6a27ef9e..4c698f36f 100644
--- a/src/multimedia/wasm/qwasmaudiosink.cpp
+++ b/src/multimedia/wasm/qwasmaudiosink.cpp
@@ -200,6 +200,7 @@ void QWasmAudioSink::suspend()
if (!m_running)
return;
+ m_suspendedInState = m_state;
alSourcePause(aldata->source);
}
diff --git a/src/multimedia/wasm/qwasmaudiosink_p.h b/src/multimedia/wasm/qwasmaudiosink_p.h
index 5f8759c34..ec703c871 100644
--- a/src/multimedia/wasm/qwasmaudiosink_p.h
+++ b/src/multimedia/wasm/qwasmaudiosink_p.h
@@ -36,6 +36,7 @@ class QWasmAudioSink : public QPlatformAudioSink
QAudio::Error m_error = QAudio::NoError;
bool m_running = false;
QAudio::State m_state = QAudio::StoppedState;
+ QAudio::State m_suspendedInState = QAudio::SuspendedState;
int m_bufferSize = 0;
quint64 m_processed = 0;
QElapsedTimer m_elapsedTimer;
diff --git a/src/multimedia/windows/qwindowsaudiosink.cpp b/src/multimedia/windows/qwindowsaudiosink.cpp
index d8e10eeb4..f95f0dba2 100644
--- a/src/multimedia/windows/qwindowsaudiosink.cpp
+++ b/src/multimedia/windows/qwindowsaudiosink.cpp
@@ -363,9 +363,7 @@ void QWindowsAudioSink::resume()
if (m_pullSource) {
pullSource();
} else {
- // FIXME: Set IdleState to be consistent with implementations on other platforms
- // even when playing the audio part that was in the buffer when suspended
- deviceStateChange(QAudio::IdleState, QAudio::NoError);
+ deviceStateChange(suspendedInState, QAudio::NoError);
if (remainingPlayTimeUs() > 0)
m_audioClient->Start();
}
@@ -375,8 +373,10 @@ void QWindowsAudioSink::resume()
void QWindowsAudioSink::suspend()
{
qCDebug(qLcAudioOutput) << "suspend()";
- if (deviceState == QAudio::ActiveState || deviceState == QAudio::IdleState)
+ if (deviceState == QAudio::ActiveState || deviceState == QAudio::IdleState) {
+ suspendedInState = deviceState;
deviceStateChange(QAudio::SuspendedState, QAudio::NoError);
+ }
}
void QWindowsAudioSink::setVolume(qreal v)
diff --git a/src/multimedia/windows/qwindowsaudiosink_p.h b/src/multimedia/windows/qwindowsaudiosink_p.h
index e977a9111..48b948004 100644
--- a/src/multimedia/windows/qwindowsaudiosink_p.h
+++ b/src/multimedia/windows/qwindowsaudiosink_p.h
@@ -77,6 +77,7 @@ private:
QAudioFormat m_format;
QAudio::Error errorState = QAudio::NoError;
QAudio::State deviceState = QAudio::StoppedState;
+ QAudio::State suspendedInState = QAudio::SuspendedState;
qsizetype m_bufferSize = 0;
qreal m_volume = 1.0;
diff --git a/src/plugins/multimedia/gstreamer/audio/qgstreameraudiosink.cpp b/src/plugins/multimedia/gstreamer/audio/qgstreameraudiosink.cpp
index 86a10da66..b66fc6623 100644
--- a/src/plugins/multimedia/gstreamer/audio/qgstreameraudiosink.cpp
+++ b/src/plugins/multimedia/gstreamer/audio/qgstreameraudiosink.cpp
@@ -294,7 +294,7 @@ void QGStreamerAudioSink::resume()
m_appSrc->resume();
gstPipeline.setState(GST_STATE_PLAYING);
- setState(QAudio::ActiveState);
+ setState(m_suspendedInState);
setError(QAudio::NoError);
}
}
@@ -312,6 +312,7 @@ QAudioFormat QGStreamerAudioSink::format() const
void QGStreamerAudioSink::suspend()
{
if (m_deviceState == QAudio::ActiveState || m_deviceState == QAudio::IdleState) {
+ m_suspendedInState = m_deviceState;
setError(QAudio::NoError);
setState(QAudio::SuspendedState);
diff --git a/src/plugins/multimedia/gstreamer/audio/qgstreameraudiosink_p.h b/src/plugins/multimedia/gstreamer/audio/qgstreameraudiosink_p.h
index 07286a3b5..9574960ae 100644
--- a/src/plugins/multimedia/gstreamer/audio/qgstreameraudiosink_p.h
+++ b/src/plugins/multimedia/gstreamer/audio/qgstreameraudiosink_p.h
@@ -86,6 +86,7 @@ private:
QAudioFormat m_format;
QAudio::Error m_errorState = QAudio::NoError;
QAudio::State m_deviceState = QAudio::StoppedState;
+ QAudio::State m_suspendedInState = QAudio::SuspendedState;
bool m_pullMode = true;
bool m_opened = false;
QIODevice *m_audioSource = nullptr;
diff --git a/tests/auto/integration/qaudiosink/tst_qaudiosink.cpp b/tests/auto/integration/qaudiosink/tst_qaudiosink.cpp
index b66acaf4a..d9a318e83 100644
--- a/tests/auto/integration/qaudiosink/tst_qaudiosink.cpp
+++ b/tests/auto/integration/qaudiosink/tst_qaudiosink.cpp
@@ -697,6 +697,7 @@ void tst_QAudioSink::pushSuspendResume()
}
stateSignal.clear();
+ const auto suspendedInState = audioOutput.state();
audioOutput.suspend();
QTRY_VERIFY2((stateSignal.size() == 1),
@@ -722,7 +723,7 @@ void tst_QAudioSink::pushSuspendResume()
// Check that QAudioSink immediately transitions to IdleState
QVERIFY2((stateSignal.size() == 1),
QString("didn't emit signal after resume(), got %1 signals instead").arg(stateSignal.size()).toUtf8().constData());
- QVERIFY2((audioOutput.state() == QAudio::IdleState), "didn't transition to IdleState after resume()");
+ QVERIFY2((audioOutput.state() == suspendedInState), "resume() didn't transition to state before suspend()");
QVERIFY2((audioOutput.error() == QAudio::NoError), "error state is not equal to QAudio::NoError after resume()");
stateSignal.clear();