-
Notifications
You must be signed in to change notification settings - Fork 572
TechNote_ReleaseBuffer
There is a bug that can sometimes cause an assert in ClientProxy or AudioTrackShared::releaseBuffer() when headsets are connected or disconnected. The bug was originally reported at: https://github.com/google/oboe/issues/535
You will see signatures like this in the logcat:
F AudioTrackShared: releaseBuffer: mUnreleased out of range, !(stepCount:96 <= mUnreleased:0 <= mFrameCount:480), BufferSizeInFrames:480
Android version 10 (Q) or earlier.
Oboe version 1.4.0 or earlier when using OpenSLES with an OUTPUT stream callback.
OR any version of Oboe if:
- Oboe is using using OpenSL ES or a non-MMAP Legacy AAudio stream
- AND you call stream->getFramesRead() or stream->getTimestamp(...) from inside an OUTPUT stream callback,
It does not happen when Oboe uses AAudio MMAP because it does not call releaseBuffer().
- Use Oboe 1.4.1 or later.
- Do not call stream->getFramesRead() or stream->getTimestamp() from inside the callback of an OUTPUT stream. If you absolutely must, then call them at the beginning of your callback to reduce the probability of a crash.
Here is a fix in Oboe 1.4.1 that removed a call to getPosition().
The sequence of events is:
- AudioFlinger AudioTrack obtains a buffer from the audio device
- user plugs in headphones, which invalidates the audio device
- app is called (callback) to render audio using the buffer
- the app or Oboe calls getFramesRead() or getTimestamp(), which calls down to AudioTrack::getPosition() or AudioTrack::getTimestamp()
- device routing change occurs because the audio device is invalid
- callback ends by releasing the buffer back to a different device
- AudioTrackShared::releaseBuffer() checks to make sure the device matches the one in ObtainBuffer() and asserts if they do not match.
Oboe, before V1.4.1, would update the server position in its callback. This called getPosition() in OpenSL ES, which called AudioTrack::getPosition().
The probability of the assert() is proportional to the time that the CPU spends between obtaining a buffer and calling restoreTrack_l().
This bug is tracked internally at: b/136268149
These steps will trigger the bug most of the time:
- Install OboeTester 1.5.22 or later, with Oboe < 1.4.1
- Enter in a Terminal window: adb logcat | grep releaseBuffer
- Launch OboeTester
- Click TEST OUTPUT
- Select API: OpenSL ES
- Click OPEN
- Click START, you should hear a tone
- Slide "Workload" fader slowly up until you hear bad glitches.
- Plug in headphones.
You may see a message like this in the logcat:
AudioTrackShared: releaseBuffer: mUnreleased out of range, !(stepCount:96 <= mUnreleased:0 <= mFrameCount:480), BufferSizeInFrames:480
These patches are available in Q AOSP:
- Apps Using Oboe or AAudio
- Tech Notes
- OboeTester Instructions
- Quirks and Bugs
- Developer Notes