Version
Media3 main branch
More version details
Hi team,
I'm looking for guidance on a rebuffering regression I observed after upgrading from Media3 1.5.0 to 1.9.2, and I want to confirm whether my interpretation of the 1.8 changelog is correct before I commit to the workaround long term.
What I'm seeing
After the upgrade, a cluster of low-end Android devices started reporting roughly 4× the rebuffer frequency they had on 1.5.0 (MUX rebuffer events per minute of watch time). Logs on a representative device (OPPO A40 / CPH2669) show frequent AudioTrack underruns followed by MediaCodecAudioRenderer.isReady() returning false, which transitions the player to STATE_BUFFERING. The source buffer is healthy at the time (tens of seconds buffered), so this is not a network/load-control issue.
My reading of the 1.8.0 changelog is that AudioTrackPositionTracker now consults AudioTrack#getUnderrunCount(), which means real PCM underruns that were previously invisible to the player now propagate into renderer-not-ready and surface as buffering. Is that an accurate characterization?
Playback profile
- DASH, AVC video, AAC audio, ~2–4 Mbps
- Standard DefaultRenderersFactory + DefaultAudioSink (no custom audio pipeline before the fix)
- DefaultLoadControl with a 30s minimum buffer
Workaround I'm testing
I subclassed DefaultRenderersFactory and overrode buildAudioSink to install a DefaultAudioTrackBufferSizeProvider with larger PCM minimum/maximum durations and a higher multiplication factor, wired through AudioTrackAudioOutputProvider.Builder.setAudioTrackBufferSizeProvider(...) and DefaultAudioSink.Builder.setAudioOutputProvider(...). This is the approach suggested in #718.
Test results (OPPO A40 / CPH2669, ~22 min video)
| Build |
AudioTrack underruns |
STATE_BUFFERING events |
| Media3 1.5.x baseline |
~50 |
7 (all seek-induced) |
| Media3 1.9.2, no fix |
249 |
64 |
| Media3 1.9.2 + larger PCM buffer (5s min / 8s max, ×8 multiplier) |
0 |
6 (all seek-induced) |
Questions
- Is my reading of the 1.8 getUnderrunCount() change correct as the mechanism here?
- Is overriding buildAudioSink with a larger DefaultAudioTrackBufferSizeProvider still the recommended path for devices whose default AudioTrack buffer is too small for sustained PCM playback, or is there a newer/preferred API I should be using in 1.9?
- Are there any signals exposed by Media3 (beyond AnalyticsListener.onAudioUnderrun) that would let me detect at runtime when a device is undersized, so I don't have to maintain a static device allow-list?
Thanks for any pointers.
Devices that reproduce the issue
- CPH2669
- CPH2727
- CPH2711
- CPH2641
- CPH3669
- moto g23
- moto g13
Devices that do not reproduce the issue
No response
Reproducible in the demo app?
Not tested
Reproduction steps
- OPPO A40 (CPH2669) running a build with ExoPlayer / Media3 1.9.2.
- Start playing a video.
- Start playing an episode and let it run. The buffering spinner appears periodically on its own, even with no user interaction.
- Seek forward and backward a few times, and rotate the screen between portrait and landscape. Rotation in particular triggers the buffering quickly.
- The player shows a buffering spinner repeatedly, even though playback has been running long enough that the buffer should be full.
- Repeat the same steps on a build with Media3 1.5.0. The buffering spinner does not appear under the same interactions.
Expected result
Playback runs smoothly without buffering interruptions once the source buffer is full, matching the behavior on Media3 1.5.0.
Actual result
The player transitions to STATE_BUFFERING repeatedly even though player.totalBufferedDuration is tens of seconds. Logs show each buffering event is preceded by AnalyticsListener.onAudioUnderrun calls, and MediaCodecAudioRenderer.isReady() returns false at those moments.
Media
Not applicable to a specific stream. The issue is reproducible with any DASH stream containing AAC audio when played on a device with a small default AudioTrack PCM buffer (e.g. OPPO A40 / CPH2669). I have not tried to reproduce in the Media3 demo app yet, but I expect any of its DASH + AAC samples to surface it on that device class.
Bug Report
Version
Media3 main branch
More version details
Hi team,
I'm looking for guidance on a rebuffering regression I observed after upgrading from Media3 1.5.0 to 1.9.2, and I want to confirm whether my interpretation of the 1.8 changelog is correct before I commit to the workaround long term.
What I'm seeing
After the upgrade, a cluster of low-end Android devices started reporting roughly 4× the rebuffer frequency they had on 1.5.0 (MUX rebuffer events per minute of watch time). Logs on a representative device (OPPO A40 / CPH2669) show frequent AudioTrack underruns followed by MediaCodecAudioRenderer.isReady() returning false, which transitions the player to STATE_BUFFERING. The source buffer is healthy at the time (tens of seconds buffered), so this is not a network/load-control issue.
My reading of the 1.8.0 changelog is that AudioTrackPositionTracker now consults AudioTrack#getUnderrunCount(), which means real PCM underruns that were previously invisible to the player now propagate into renderer-not-ready and surface as buffering. Is that an accurate characterization?
Playback profile
Workaround I'm testing
I subclassed DefaultRenderersFactory and overrode buildAudioSink to install a DefaultAudioTrackBufferSizeProvider with larger PCM minimum/maximum durations and a higher multiplication factor, wired through AudioTrackAudioOutputProvider.Builder.setAudioTrackBufferSizeProvider(...) and DefaultAudioSink.Builder.setAudioOutputProvider(...). This is the approach suggested in #718.
Test results (OPPO A40 / CPH2669, ~22 min video)
Questions
Thanks for any pointers.
Devices that reproduce the issue
Devices that do not reproduce the issue
No response
Reproducible in the demo app?
Not tested
Reproduction steps
Expected result
Playback runs smoothly without buffering interruptions once the source buffer is full, matching the behavior on Media3 1.5.0.
Actual result
The player transitions to STATE_BUFFERING repeatedly even though player.totalBufferedDuration is tens of seconds. Logs show each buffering event is preceded by AnalyticsListener.onAudioUnderrun calls, and MediaCodecAudioRenderer.isReady() returns false at those moments.
Media
Not applicable to a specific stream. The issue is reproducible with any DASH stream containing AAC audio when played on a device with a small default AudioTrack PCM buffer (e.g. OPPO A40 / CPH2669). I have not tried to reproduce in the Media3 demo app yet, but I expect any of its DASH + AAC samples to surface it on that device class.
Bug Report
adb bugreportto [email protected] after filing this issue.