How to reduce max playback speed to avoid AudioTrack OOM
Due to too high max speed, buffer size is too large and AudioTrack creation fails due to out of memory.
11-21 20:13:45.982 11934 18111 E AF::TrackBase: TrackBase(275): not enough memory for AudioTrack size=12583144
11-21 20:13:45.982 11934 18111 E AF::TrackBase: Primary:
11-21 20:13:45.982 11934 18111 E AF::TrackBase: Dedicated Pool Allocator Dump:
11-21 20:13:45.982 11934 18111 E AF::TrackBase: HeapID Size Offset Order Name
11-21 20:13:45.982 11934 18111 E AF::TrackBase: Secondary:
11-21 20:13:45.982 11934 18111 E AF::TrackBase: Primary:
11-21 20:13:45.982 11934 18111 E AF::TrackBase: Large Shared Allocator Dump:
11-21 20:13:45.982 11934 18111 E AF::TrackBase: HeapID Size Offset Order Name
11-21 20:13:45.982 11934 18111 E AF::TrackBase: 3512587008 0 0 Track ID: 272
11-21 20:13:45.982 11934 18111 E AF::TrackBase: Secondary:
11-21 20:13:45.982 11934 18111 E AF::TrackBase: Small Shared Allocator Dump:
11-21 20:13:45.982 11934 18111 E AF::TrackBase: HeapID Size Offset Order Name
11-21 20:13:45.985 11934 18111 E AudioFlinger: createTrack_l() initCheck failed -12; no control block?
ExoPlayer already applies 4x multiplier to PCM for all playbacks: https://github.com/androidx/media/blob/bfe5930f7f29c6492d60e3d01a90abd3c138b615/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/DefaultAudioTrackBufferSizeProvider.java#L48 but due to 12 channel audio file it also applies 6x multiplier compared to stereo due to more channels and audio playback params for speed change applies another 8x multiplier compared to other player with it disabled. https://github.com/androidx/media/blob/04b56d587bf0fa6855c171f0ebc5510329194cbd/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioTrackAudioOutputProvider.java#L290 So we have 6*8=48x the buffer size for speed adjustment enabled 12ch compared to speed adjustment disabled stereo and that leads to buffer out of memory.
In my testing affected device works fine with max speed reduced to 4x (which is already more than enough and also the maximum I expose in UI) and pcm multiplication reduced to 2x. While PCM multiplication is easy to configure (with setPcmBufferMultiplicationFactor), is there a way to change max playback speed? And is it a good idea to apply this on a global level (also to stereo playbacks)?
Hi @nift4,
Did you get a playback failure due to this OOM issue? I'm asking because we do handle this error in DefaultAudioSink, where a AUDIO_TRACK_SMALLER_BUFFER_RETRY_SIZE = 1_000_000 will be used on the second try.
If we enable to set the max playback speed, it will not be that flexible to avoid OOM for all the devices. For example, a device works fine with 4x max speed, but another one may still cannot work. So I think it would be better to utilize our existing retry logic. Probably we should make this retry logic more intelligent (eg. try half of the failed buffer size (if > 1_000_000) first and only use 1_000_000 on the final attempt).
How do you think?
Hi, thanks for the reply. I didn't know about retry logic. However, I am experiencing playback failures. There were two types of failure:
- failure to play anything at all due to very big buffer size
- playback starts but any seek fails as the AudioTrack that was used for playback and is being released asynchronously takes too much of the memory
I will investigate if I can figure out why retry logic doesn't seem to be working for me