Details
-
Bug
-
Resolution: Done
-
P2: Important
-
5.3.0 RC1
-
None
-
Android 4.4
Samsung galaxy note 3
-
5a0e49369da7ac04c9bd9eb089a4b001f6a13278
Description
QAudioOutput may output corrupted sound under opensl es backend when using push mode.
The problem is triggered in QOpenSLESAudioOutput::writeData()
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) return 0; if (res != SL_RESULT_SUCCESS) { setError(QAudio::FatalError); destroyPlayer(); return -1; } m_processedBytes += len; m_availableBuffers.fetchAndAddRelaxed(-1); setState(QAudio::ActiveState); setError(QAudio::NoError); m_nextBuffer = (m_nextBuffer + 1) % BUFFER_COUNT;
As we can see, if opensl es can't enqueue more buffer, it will return SL_RESULT_BUFFER_INSUFFICIENT, and QOpenSLESAudioOutput::writeData() will return 0 to notify user nothing has been written to QAudioOutput object, but the problem is m_buffers has been written with data user provided and the old content may not been playback yet! that will cause corrupted sound. I think we should check m_availableBuffers before memcpy the data.
As a workaround one can check QAudioOutput::bytesFree() before calling QIODevice::write() in push mode to avoid this problem.