Skip to content

How to reduce max playback speed to avoid AudioTrack OOM #2905

Closed

Description

@nift4

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:


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.
usePlaybackParameters ? MAX_PLAYBACK_SPEED : DEFAULT_PLAYBACK_SPEED);

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)?

Activity

  1. changed the title [-]How to reduce max playback speed to avoid AudioTrack[/-] [+]How to reduce max playback speed to avoid AudioTrack OOM[/+] on Nov 21, 2025
  2. self-assigned this
    on Nov 25, 2025
  3. tianyif commented on Nov 27, 2025

    @tianyif
    Contributor

    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?

  4. nift4 commented on Dec 1, 2025

    @nift4
    ContributorAuthor

    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

  5. nift4 commented on Dec 27, 2025

    @nift4
    ContributorAuthor

    Hi @tianyif, sorry for the delay.

    I re-checked and retry failed internal check in platform AudioTrack.java:

            if ((audioBufferSize % frameSizeInBytes != 0) || (audioBufferSize < 1)) {
                throw new IllegalArgumentException("Invalid audio buffer size.");
            }

    With mChannelCount=12 and 4 bytes per sample, frameSizeInBytes is 48 and 1_000_000 % 48 = 16, which is not 0, so AudioTrack cannot be created.

    It seems to be a bug and the retry logic should be adjusted a little to account for this check and modify buffer size. I did it like this just for testing, surely it can be done in a prettier way:

            Configuration retryConfiguration =
                configuration.copyWithBufferSize(AUDIO_TRACK_SMALLER_BUFFER_RETRY_SIZE +
                        configuration.outputPcmFrameSize - (AUDIO_TRACK_SMALLER_BUFFER_RETRY_SIZE % configuration.outputPcmFrameSize));

    and I can confirm playback now always can proceed successfully.

    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).

    Making this retry logic more intelligent would probably also be a good idea, to avoid app using very small buffer because normal buffer was too big. (Generally, I want big buffer to use less battery while playing music)

    Personally however, I think that it would also be good to change the max playback speed anyway though, to avoid the need of using retry when I know I never want to use 8x speed playback. I only want to reduce it to maximum exposed in UI and combine with retry logic when lower playback speed is not enough. Do you think that makes sense?

    Thanks!

  6. nift4 commented on Jan 24, 2026

    @nift4
    ContributorAuthor

    Hi @tianyif, do you think the above change is fine for a temporary solution? Thanks in advance!

  7. tianyif commented on Jan 26, 2026

    @tianyif
    Contributor

    @nift4, thanks for the analysis! The observation of the platform AudioTrack behavior is very helpful. I will take a look on this.

  8. nift4 commented on Jan 29, 2026

    @nift4
    ContributorAuthor

    Thank you @tianyif! I see the commit addresses both the check failed issue and adds smarter retry logic. So this should fully fix the user-visible symptom of playback failure.

    What I am still wondering about is whether there could be a way added to change maximum speed (to less than 8, but more than 1), because my app won't ever need to play this fast. It would basically fix the issue at its root cause, at least for my app.
    (I assume it might be somewhat beneficial to not use big buffers if not needed, even if they don't lead to a playback failure, as they are a shared resource and should be managed carefully.)

  9. nift4 commented on Jan 30, 2026

    @nift4
    ContributorAuthor

    I uploaded a proposal to illustrate what I am talking about: #3040

  10. locked and limited conversation to collaborators on Apr 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions