summaryrefslogtreecommitdiffstats
path: root/src/multimedia/darwin/qdarwinaudiosink.mm
diff options
context:
space:
mode:
authorArtem Dyomin <artem.dyomin@qt.io>2023-03-02 20:54:15 +0100
committerArtem Dyomin <artem.dyomin@qt.io>2023-03-05 23:29:42 +0000
commit03a44e5a6b6aa452143948e71c364d11f6b5992e (patch)
treef270abd6c449e30059b510c0c57cd593fefc9aae /src/multimedia/darwin/qdarwinaudiosink.mm
parente6c476d407fd282d064065941eba477a911bb3c9 (diff)
Fix audiosink issues on darwin6.4
Fixed problems: - Fix sound stucks on multiple resets/starts of QAudioSink. It was possible to reproduce on playback position change in mediaplayer. - Improve audiosink stop (reduce waiting time). The optimization is based on the fact that it's possible to call AudioOutputUnitStop from the thread where it was started. - add some auto test + imrove errors logging in tests. Tests work fine locally but still need some tune on CI Task-number: QTBUG-111567 Change-Id: I0eb5c32af4c12dfc0694ee8f5967b4960a0b4ab2 Reviewed-by: Doris Verria <doris.verria@qt.io> (cherry picked from commit 919b3d308b711c0b267808c783327f2c95233428) Reviewed-by: Lars Knoll <lars@knoll.priv.no>
Diffstat (limited to 'src/multimedia/darwin/qdarwinaudiosink.mm')
-rw-r--r--src/multimedia/darwin/qdarwinaudiosink.mm65
1 files changed, 48 insertions, 17 deletions
diff --git a/src/multimedia/darwin/qdarwinaudiosink.mm b/src/multimedia/darwin/qdarwinaudiosink.mm
index 340472671..f29b642c2 100644
--- a/src/multimedia/darwin/qdarwinaudiosink.mm
+++ b/src/multimedia/darwin/qdarwinaudiosink.mm
@@ -104,7 +104,7 @@ int QDarwinAudioSinkBuffer::available() const
void QDarwinAudioSinkBuffer::reset()
{
m_buffer->reset();
- m_device = 0;
+ m_device = nullptr;
m_deviceError = false;
}
@@ -582,7 +582,7 @@ bool QDarwinAudioSink::open()
void QDarwinAudioSink::close()
{
if (m_audioUnit != 0) {
- AudioOutputUnitStop(m_audioUnit);
+ audioDeviceStop();
AudioUnitUninitialize(m_audioUnit);
AudioComponentInstanceDispose(m_audioUnit);
}
@@ -592,32 +592,61 @@ void QDarwinAudioSink::close()
void QDarwinAudioSink::audioThreadStart()
{
- QMutexLocker lock(&m_mutex);
startTimers();
- m_audioThreadState.storeRelaxed(Running);
- AudioOutputUnitStart(m_audioUnit);
+ audioDeviceStart();
}
void QDarwinAudioSink::audioThreadStop()
{
- QMutexLocker lock(&m_mutex);
stopTimers();
- if (m_audioThreadState.testAndSetAcquire(Running, Stopped))
- m_threadFinished.wait(&m_mutex, 500);
+
+ // It's common practice to call AudioOutputUnitStop
+ // from the thread where the audio output was started,
+ // so we don't have to rely on the stops inside renderCallback.
+ audioDeviceStop();
}
void QDarwinAudioSink::audioThreadDrain()
{
- QMutexLocker lock(&m_mutex);
stopTimers();
- if (m_audioThreadState.testAndSetAcquire(Running, Draining))
- m_threadFinished.wait(&m_mutex, 500);
+
+ QMutexLocker lock(&m_mutex);
+
+ if (m_audioThreadState.testAndSetAcquire(Running, Draining)) {
+ constexpr int MaxDrainWaitingTime = 500;
+
+ m_threadFinished.wait(&m_mutex, MaxDrainWaitingTime);
+
+ if (m_audioThreadState.fetchAndStoreRelaxed(Stopped) != Stopped) {
+ qWarning() << "Couldn't wait for draining; force stop";
+
+ AudioOutputUnitStop(m_audioUnit);
+ }
+ }
+}
+
+void QDarwinAudioSink::audioDeviceStart()
+{
+ QMutexLocker lock(&m_mutex);
+
+ const auto state = m_audioThreadState.loadAcquire();
+ if (state == Stopped) {
+ m_audioThreadState.storeRelaxed(Running);
+ AudioOutputUnitStart(m_audioUnit);
+ } else {
+ qWarning() << "Unexpected state on audio device start:" << state;
+ }
}
void QDarwinAudioSink::audioDeviceStop()
{
- AudioOutputUnitStop(m_audioUnit);
- m_audioThreadState.storeRelaxed(Stopped);
+ {
+ QMutexLocker lock(&m_mutex);
+
+ AudioOutputUnitStop(m_audioUnit);
+ m_audioThreadState.storeRelaxed(Stopped);
+ }
+
m_threadFinished.wakeOne();
}
@@ -626,10 +655,11 @@ void QDarwinAudioSink::audioDeviceIdle()
if (m_stateCode != QAudio::ActiveState)
return;
- audioDeviceStop();
-
m_errorCode = QAudio::UnderrunError;
m_stateCode = QAudio::IdleState;
+
+ audioDeviceStop();
+
QMetaObject::invokeMethod(this, "deviceStopped", Qt::QueuedConnection);
}
@@ -638,10 +668,11 @@ void QDarwinAudioSink::audioDeviceError()
if (m_stateCode != QAudio::ActiveState)
return;
- audioDeviceStop();
-
m_errorCode = QAudio::IOError;
m_stateCode = QAudio::StoppedState;
+
+ audioDeviceStop();
+
QMetaObject::invokeMethod(this, "deviceStopped", Qt::QueuedConnection);
}