Skip to content

Dynamically allocate metadata renderers before track group selection #2911

@benlancaster

Description

@benlancaster

Use case description

ExoPlayer defaults to two MetadataRenderer instances:

protected void buildMetadataRenderers(
Context context,
MetadataOutput output,
Looper outputLooper,
@ExtensionRendererMode int extensionRendererMode,
ArrayList<Renderer> out) {
out.add(new MetadataRenderer(output, outputLooper));
out.add(new MetadataRenderer(output, outputLooper));
}

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?

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions