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?
Use case description
ExoPlayer defaults to two
MetadataRendererinstances:media/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/DefaultRenderersFactory.java
Lines 756 to 764 in bfe5930
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
RenderersCoordinatorClasswithLock()methodemptyTrackSelectorResult(moved fromExoPlayerImpl)2.
ExoPlayerImpl.javaChangesRenderer[]array withRenderersCoordinatorsetVideoOutputInternal,sendRendererMessage)renderersCoordinator.renderers3.
ExoPlayerImplInternal.javaChangesRenderer[]andRendererCapabilities[]withRenderersCoordinatorrenderersCoordinator.withLock()for thread safety:doSomeWork()handlePeriodPrepared()reselectTracksInternal()attemptRendererErrorRecovery()renderersCoordinator.renderers4.
MediaPeriodHolder.javaChangesRenderersCoordinator.OnRenderersReevaluatedinterfaceRenderersCoordinatorinstead ofRendererCapabilities[]sampleStreamsandmayRetainStreamFlagsarrays when renderers are reevaluated5.
RenderersFactory.javaInterface EnhancementreevaluateRenderers()method with default implementationPurpose:
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?