androidx / androidx/media

Dynamically allocate metadata renderers before track group selection

Open
#2,911 2 comments 0 reactions 1 assignee View on GitHub

@microkatz is already working on this.

Since Nov 24, 2025.

enhancement
Dominant language
Java
Stars
3k
Forks
955
Avg merge
12d 14h
Merged PRs (30d)
2

Description

Use case description

ExoPlayer defaults to two MetadataRenderer instances:

https://github.com/androidx/media/blob/bfe5930f7f29c6492d60e3d01a90abd3c138b615/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/DefaultRenderersFactory.java#L756-L764

This isn't always enough for streams with multiple audio tracks if the audio tracks are carrying pertinent ID3 data. This can be overloaded externally for setting a higher value, but a better approach would be to dynamically allocate these instead.

Proposed solution

If this is of interest we can package up the change in a Pull Request. It's proving quite difficult to maintain with the recent pre-warming stuff that was added

✨ AI summary of the change we have made:

Key Changes:

1. New RenderersCoordinator Class

  • Introduces a new coordinator class to manage renderer lifecycle and dynamic allocation
  • Provides thread-safe access to renderers via a withLock() method
  • Supports reevaluating and potentially adding new renderers when track groups change
  • Maintains an emptyTrackSelectorResult (moved from ExoPlayerImpl)

2. ExoPlayerImpl.java Changes

  • Replaces direct Renderer[] array with RenderersCoordinator
  • Moves renderer initialization logic into the coordinator
  • Adds thread-safe access patterns when interacting with renderers (e.g., setVideoOutputInternal, sendRendererMessage)
  • All renderer access now goes through renderersCoordinator.renderers

3. ExoPlayerImplInternal.java Changes

  • Replaces Renderer[] and RendererCapabilities[] with RenderersCoordinator
  • Wraps critical operations in renderersCoordinator.withLock() for thread safety:
    • doSomeWork()
    • handlePeriodPrepared()
    • reselectTracksInternal()
    • attemptRendererErrorRecovery()
  • All renderer array access updated to use renderersCoordinator.renderers

4. MediaPeriodHolder.java Changes

  • Now implements RenderersCoordinator.OnRenderersReevaluated interface
  • Receives RenderersCoordinator instead of RendererCapabilities[]
  • Dynamically resizes sampleStreams and mayRetainStreamFlags arrays when renderers are reevaluated
  • Registers/unregisters as a listener to the coordinator

5. RenderersFactory.java Interface Enhancement

  • Adds new reevaluateRenderers() method with default implementation
  • Allows factories to provide additional renderers based on new track groups
  • Important constraint: Previous renderers must be preserved in the same order
Purpose:

This change enables ExoPlayer to dynamically adjust its renderer allocation when new track groups are discovered during playback, rather than being locked into a fixed set of renderers at initialization time. This is particularly useful for adaptive streaming scenarios where new track types might become available.

Alternatives considered

Setting a higher value for the default - wasteful in some cases if one/none , and how high is high enough?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.