diff options
author | Christian Strømme <christian.stromme@digia.com> | 2014-09-10 11:52:28 +0200 |
---|---|---|
committer | Christian Stromme <christian.stromme@digia.com> | 2014-09-12 14:04:08 +0200 |
commit | 65d44edd3d06674ec7a0014d7ecabc4f1d0854e1 (patch) | |
tree | eaba71e1a296132531fafbf6a38dd5a58d1a97a5 | |
parent | 8d5114a63051128992291356440ecff9ab2ef6b6 (diff) | |
download | qtmultimedia-65d44edd3d06674ec7a0014d7ecabc4f1d0854e1.tar.gz |
OpenSL ES: Be less rigid about tearing down the output device.
We where very strict about tearing down the audio device. While this is
a good strategy to avoid unnecessary resource usage, it also causes
excessive re-allocations, e.g., when transiting from start to stop and
back again. This can increase latency, especially in case where a short
clip is re-played at a high frequency.
This change also decrease the chance of the player ending up in some
unknown state where it drops audio clips without any warning.
Task-number: QTBUG-40864
Change-Id: I1afad4af0622983f0f0c221d91cf794585d8cad2
Reviewed-by: Yoann Lopes <yoann.lopes@digia.com>
-rw-r--r-- | src/plugins/opensles/qopenslesaudiooutput.cpp | 65 | ||||
-rw-r--r-- | src/plugins/opensles/qopenslesaudiooutput.h | 3 |
2 files changed, 42 insertions, 26 deletions
diff --git a/src/plugins/opensles/qopenslesaudiooutput.cpp b/src/plugins/opensles/qopenslesaudiooutput.cpp index f6583e542..06f2261df 100644 --- a/src/plugins/opensles/qopenslesaudiooutput.cpp +++ b/src/plugins/opensles/qopenslesaudiooutput.cpp @@ -71,7 +71,8 @@ QOpenSLESAudioOutput::QOpenSLESAudioOutput(const QByteArray &device) m_elapsedTime(0), m_processedBytes(0), m_availableBuffers(BUFFER_COUNT), - m_eventMask(SL_PLAYEVENT_HEADATEND) + m_eventMask(SL_PLAYEVENT_HEADATEND), + m_startRequiresInit(true) { #ifndef ANDROID m_streamType = -1; @@ -99,13 +100,10 @@ QAudio::State QOpenSLESAudioOutput::state() const void QOpenSLESAudioOutput::start(QIODevice *device) { Q_ASSERT(device); - destroyPlayer(); - - m_pullMode = true; - if (!preparePlayer()) return; + m_pullMode = true; m_audioSource = device; setState(QAudio::ActiveState); setError(QAudio::NoError); @@ -126,29 +124,20 @@ void QOpenSLESAudioOutput::start(QIODevice *device) // Change the state to playing. // We need to do this after filling the buffers or processedBytes might get corrupted. - if (SL_RESULT_SUCCESS != (*m_playItf)->SetPlayState(m_playItf, SL_PLAYSTATE_PLAYING)) { - setError(QAudio::FatalError); - destroyPlayer(); - } + startPlayer(); } QIODevice *QOpenSLESAudioOutput::start() { - destroyPlayer(); - - m_pullMode = false; - if (!preparePlayer()) return Q_NULLPTR; + m_pullMode = false; m_audioSource = new SLIODevicePrivate(this); m_audioSource->open(QIODevice::WriteOnly | QIODevice::Unbuffered); // Change the state to playing - if (SL_RESULT_SUCCESS != (*m_playItf)->SetPlayState(m_playItf, SL_PLAYSTATE_PLAYING)) { - setError(QAudio::FatalError); - destroyPlayer(); - } + startPlayer(); setState(QAudio::IdleState); return m_audioSource; @@ -159,7 +148,7 @@ void QOpenSLESAudioOutput::stop() if (m_state == QAudio::StoppedState) return; - destroyPlayer(); + stopPlayer(); setError(QAudio::NoError); } @@ -181,6 +170,7 @@ void QOpenSLESAudioOutput::setBufferSize(int value) if (m_state != QAudio::StoppedState) return; + m_startRequiresInit = true; m_bufferSize = value; } @@ -254,6 +244,7 @@ void QOpenSLESAudioOutput::resume() void QOpenSLESAudioOutput::setFormat(const QAudioFormat &format) { + m_startRequiresInit = true; m_format = format; } @@ -325,6 +316,7 @@ void QOpenSLESAudioOutput::setCategory(const QString &category) return; } + m_startRequiresInit = true; m_streamType = streamType; m_category = category; #endif // ANDROID @@ -403,6 +395,11 @@ void QOpenSLESAudioOutput::bufferQueueCallback(SLBufferQueueItf bufferQueue, voi bool QOpenSLESAudioOutput::preparePlayer() { + if (m_startRequiresInit) + destroyPlayer(); + else + return true; + SLEngineItf engine = QOpenSLESEngine::instance()->slEngine(); if (!engine) { qWarning() << "No engine"; @@ -543,20 +540,15 @@ bool QOpenSLESAudioOutput::preparePlayer() m_clockStamp.restart(); setError(QAudio::NoError); + m_startRequiresInit = false; return true; } void QOpenSLESAudioOutput::destroyPlayer() { - setState(QAudio::StoppedState); - - // We need to change the state manually... - if (m_playItf) - (*m_playItf)->SetPlayState(m_playItf, SL_PLAYSTATE_STOPPED); - - if (m_bufferQueueItf && SL_RESULT_SUCCESS != (*m_bufferQueueItf)->Clear(m_bufferQueueItf)) - qWarning() << "Unable to clear buffer"; + if (m_state != QAudio::StoppedState) + stopPlayer(); if (m_playerObject) { (*m_playerObject)->Destroy(m_playerObject); @@ -582,6 +574,27 @@ void QOpenSLESAudioOutput::destroyPlayer() m_playItf = Q_NULLPTR; m_volumeItf = Q_NULLPTR; m_bufferQueueItf = Q_NULLPTR; + m_startRequiresInit = true; +} + +void QOpenSLESAudioOutput::stopPlayer() +{ + setState(QAudio::StoppedState); + + // We need to change the state manually... + if (m_playItf) + (*m_playItf)->SetPlayState(m_playItf, SL_PLAYSTATE_STOPPED); + + if (m_bufferQueueItf && SL_RESULT_SUCCESS != (*m_bufferQueueItf)->Clear(m_bufferQueueItf)) + qWarning() << "Unable to clear buffer"; +} + +void QOpenSLESAudioOutput::startPlayer() +{ + if (SL_RESULT_SUCCESS != (*m_playItf)->SetPlayState(m_playItf, SL_PLAYSTATE_PLAYING)) { + setError(QAudio::FatalError); + destroyPlayer(); + } } qint64 QOpenSLESAudioOutput::writeData(const char *data, qint64 len) diff --git a/src/plugins/opensles/qopenslesaudiooutput.h b/src/plugins/opensles/qopenslesaudiooutput.h index d466ea64b..200b4a3cc 100644 --- a/src/plugins/opensles/qopenslesaudiooutput.h +++ b/src/plugins/opensles/qopenslesaudiooutput.h @@ -86,6 +86,8 @@ private: bool preparePlayer(); void destroyPlayer(); + void stopPlayer(); + void startPlayer(); qint64 writeData(const char *data, qint64 len); void setState(QAudio::State state); @@ -113,6 +115,7 @@ private: qint64 m_processedBytes; QAtomicInt m_availableBuffers; SLuint32 m_eventMask; + bool m_startRequiresInit; qint32 m_streamType; QTime m_clockStamp; |