summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorChristian Strømme <christian.stromme@theqtcompany.com>2014-10-30 18:29:38 +0100
committerChristian Stromme <christian.stromme@digia.com>2014-11-04 15:09:26 +0100
commite92bcbfa4dc8ea5e78e4c1712fffc9be0104a73e (patch)
tree60093ca4a71ca655724826db6c4a1798635760af /src
parentad929984e3560407cd530d4420bda97e973d5e7d (diff)
OpenSL ES: improve buffer logic
Don't use relaxed load and stores, we need to be stricter to avoid problems with high frequency re-fills of the buffer. If we don't enforce ordering we might end-up spending more time trying to acquire an open slot in the buffer. Updating processes bytes is also moved off the "OpenSL" thread. Added some comments for improved readability. Change-Id: Ie27965fc6bf4b8394081ae6419f4933522ada98e Reviewed-by: Yoann Lopes <yoann.lopes@theqtcompany.com>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/opensles/qopenslesaudiooutput.cpp34
-rw-r--r--src/plugins/opensles/qopenslesaudiooutput.h1
2 files changed, 27 insertions, 8 deletions
diff --git a/src/plugins/opensles/qopenslesaudiooutput.cpp b/src/plugins/opensles/qopenslesaudiooutput.cpp
index c45fbd3c5..b89d8b93c 100644
--- a/src/plugins/opensles/qopenslesaudiooutput.cpp
+++ b/src/plugins/opensles/qopenslesaudiooutput.cpp
@@ -157,7 +157,7 @@ int QOpenSLESAudioOutput::bytesFree() const
if (m_state != QAudio::ActiveState && m_state != QAudio::IdleState)
return 0;
- return m_availableBuffers.load() ? m_bufferSize : 0;
+ return m_availableBuffers.loadAcquire() ? m_bufferSize : 0;
}
int QOpenSLESAudioOutput::periodSize() const
@@ -343,6 +343,11 @@ void QOpenSLESAudioOutput::onEOSEvent()
setError(QAudio::UnderrunError);
}
+void QOpenSLESAudioOutput::onBytesProcessed(qint64 bytes)
+{
+ m_processedBytes += bytes;
+}
+
void QOpenSLESAudioOutput::bufferAvailable(quint32 count, quint32 playIndex)
{
Q_UNUSED(count);
@@ -351,11 +356,13 @@ void QOpenSLESAudioOutput::bufferAvailable(quint32 count, quint32 playIndex)
if (m_state == QAudio::StoppedState)
return;
- if (!m_pullMode) {
- m_availableBuffers.fetchAndAddRelaxed(1);
+ if (!m_pullMode) { // We're in push mode.
+ // Signal that there is a new open slot in the buffer and return
+ m_availableBuffers.fetchAndAddRelease(1);
return;
}
+ // We're in pull mode.
const int index = m_nextBuffer * m_bufferSize;
const qint64 readSize = m_audioSource->read(m_buffers + index, m_bufferSize);
@@ -370,8 +377,8 @@ void QOpenSLESAudioOutput::bufferAvailable(quint32 count, quint32 playIndex)
return;
}
- m_processedBytes += readSize;
m_nextBuffer = (m_nextBuffer + 1) % BUFFER_COUNT;
+ QMetaObject::invokeMethod(this, "onBytesProcessed", Qt::QueuedConnection, Q_ARG(qint64, readSize));
}
void QOpenSLESAudioOutput::playCallback(SLPlayItf player, void *ctx, SLuint32 event)
@@ -570,7 +577,7 @@ void QOpenSLESAudioOutput::destroyPlayer()
m_buffers = Q_NULLPTR;
m_processedBytes = 0;
m_nextBuffer = 0;
- m_availableBuffers = BUFFER_COUNT;
+ m_availableBuffers.storeRelease(BUFFER_COUNT);
m_playItf = Q_NULLPTR;
m_volumeItf = Q_NULLPTR;
m_bufferQueueItf = Q_NULLPTR;
@@ -599,20 +606,32 @@ void QOpenSLESAudioOutput::startPlayer()
qint64 QOpenSLESAudioOutput::writeData(const char *data, qint64 len)
{
- if (!len || !m_availableBuffers.load())
+ if (!len)
return 0;
if (len > m_bufferSize)
len = m_bufferSize;
+ // Acquire one slot in the buffer
+ const int before = m_availableBuffers.fetchAndAddAcquire(-1);
+
+ // If there where no vacant slots, then we just overdrew the buffer account...
+ if (before < 1) {
+ m_availableBuffers.fetchAndAddRelease(1);
+ return 0;
+ }
+
const int index = m_nextBuffer * m_bufferSize;
::memcpy(m_buffers + index, data, len);
const SLuint32 res = (*m_bufferQueueItf)->Enqueue(m_bufferQueueItf,
m_buffers + index,
len);
- if (res == SL_RESULT_BUFFER_INSUFFICIENT)
+ // If we where unable to enqueue a new buffer, give back the acquired slot.
+ if (res == SL_RESULT_BUFFER_INSUFFICIENT) {
+ m_availableBuffers.fetchAndAddRelease(1);
return 0;
+ }
if (res != SL_RESULT_SUCCESS) {
setError(QAudio::FatalError);
@@ -621,7 +640,6 @@ qint64 QOpenSLESAudioOutput::writeData(const char *data, qint64 len)
}
m_processedBytes += len;
- m_availableBuffers.fetchAndAddRelaxed(-1);
setState(QAudio::ActiveState);
setError(QAudio::NoError);
m_nextBuffer = (m_nextBuffer + 1) % BUFFER_COUNT;
diff --git a/src/plugins/opensles/qopenslesaudiooutput.h b/src/plugins/opensles/qopenslesaudiooutput.h
index 200b4a3cc..f36a5bf04 100644
--- a/src/plugins/opensles/qopenslesaudiooutput.h
+++ b/src/plugins/opensles/qopenslesaudiooutput.h
@@ -79,6 +79,7 @@ private:
friend class SLIODevicePrivate;
Q_INVOKABLE void onEOSEvent();
+ Q_INVOKABLE void onBytesProcessed(qint64 bytes);
void bufferAvailable(quint32 count, quint32 playIndex);
static void playCallback(SLPlayItf playItf, void *ctx, SLuint32 event);