aaudio: fix race at start of stream
When an MMAP stream is started, it is possible for the
beginning of the sound to be lost. One reason is because
the written data is placed right in front of the DSP read position.
But the DSP position is not well known when the stream is starting
because we only have a few timestamps.
If the DSP advances before the data is written then the first burst
might be skipped
This CL places the initial write one burst ahead of the estimated DSP
position.
The same code is used to synchronize the read/write counters
when a flush() occurs. In that case the serverMargin is zero.
Bug: 156313728
Bug: 157510931
Bug: 158547650
Test: atest CtsNativeMediaAAudioTestCases
Test: see bugs for other test cases
Change-Id: I96170a924c69eee080a497b52cc6c1f3498c5455
diff --git a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
index 1303daf..6337b53 100644
--- a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
@@ -86,8 +86,13 @@
return mServiceInterface.flushStream(mServiceStreamHandle);
}
-void AudioStreamInternalPlay::advanceClientToMatchServerPosition() {
- int64_t readCounter = mAudioEndpoint->getDataReadCounter();
+void AudioStreamInternalPlay::prepareBuffersForStart() {
+ // Prevent stale data from being played.
+ mAudioEndpoint->eraseDataMemory();
+}
+
+void AudioStreamInternalPlay::advanceClientToMatchServerPosition(int32_t serverMargin) {
+ int64_t readCounter = mAudioEndpoint->getDataReadCounter() + serverMargin;
int64_t writeCounter = mAudioEndpoint->getDataWriteCounter();
// Bump offset so caller does not see the retrograde motion in getFramesRead().
@@ -145,7 +150,9 @@
if (mNeedCatchUp.isRequested()) {
// Catch an MMAP pointer that is already advancing.
// This will avoid initial underruns caused by a slow cold start.
- advanceClientToMatchServerPosition();
+ // We add a one burst margin in case the DSP advances before we can write the data.
+ // This can help prevent the beginning of the stream from being skipped.
+ advanceClientToMatchServerPosition(getFramesPerBurst());
mNeedCatchUp.acknowledge();
}