diff --git a/RELEASENOTES.md b/RELEASENOTES.md index b53b2f6226..7c278fa114 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -3,6 +3,9 @@ ### dev-v2 (not yet released) * Core Library: + * Fix track selection issue where a mixture of non-empty and empty track + overrides is not applied correctly + ([#9649](https://github.com/google/ExoPlayer/issues/9649). * Add protected method `DefaultRenderersFactory.getCodecAdapterFactory()` so that subclasses of `DefaultRenderersFactory` that override `buildVideoRenderers()` or `buildAudioRenderers()` can access the codec diff --git a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java index 3e0ed7e887..600a387796 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java @@ -1553,7 +1553,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { || params.disabledTrackTypes.contains(rendererType)) { return null; } - // Per TrackGroupArray override + // Per TrackGroupArray overrides. TrackGroupArray rendererTrackGroups = mappedTrackInfo.getTrackGroups(rendererIndex); if (params.hasSelectionOverride(rendererIndex, rendererTrackGroups)) { @Nullable @@ -1564,18 +1564,27 @@ public class DefaultTrackSelector extends MappingTrackSelector { return new ExoTrackSelection.Definition( rendererTrackGroups.get(override.groupIndex), override.tracks, override.type); } - // Per TrackGroup override + // Per TrackGroup overrides. for (int j = 0; j < rendererTrackGroups.length; j++) { TrackGroup trackGroup = rendererTrackGroups.get(j); @Nullable TrackSelectionOverride overrideTracks = params.trackSelectionOverrides.getOverride(trackGroup); if (overrideTracks != null) { - return new ExoTrackSelection.Definition( - trackGroup, Ints.toArray(overrideTracks.trackIndexes)); + if (overrideTracks.trackIndexes.isEmpty()) { + // TrackGroup is disabled. Deselect the currentDefinition if applicable. Otherwise ignore. + if (currentDefinition != null && currentDefinition.group.equals(trackGroup)) { + currentDefinition = null; + } + } else { + // Override current definition with new selection. + currentDefinition = + new ExoTrackSelection.Definition( + trackGroup, Ints.toArray(overrideTracks.trackIndexes)); + } } } - return currentDefinition; // No override + return currentDefinition; } // Track selection prior to overrides and disabled flags being applied. diff --git a/library/core/src/test/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelectorTest.java b/library/core/src/test/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelectorTest.java index c2eaf5ddaf..dcec44bc26 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelectorTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelectorTest.java @@ -204,6 +204,43 @@ public final class DefaultTrackSelectorTest { .isEqualTo(new RendererConfiguration[] {DEFAULT, DEFAULT}); } + @Test + public void selectTrack_withMixedEmptyAndNonEmptyTrackOverrides_appliesNonEmptyOverride() + throws Exception { + TrackGroup videoGroupHighBitrate = + new TrackGroup(VIDEO_FORMAT.buildUpon().setAverageBitrate(1_000_000).build()); + TrackGroup videoGroupMidBitrate = + new TrackGroup(VIDEO_FORMAT.buildUpon().setAverageBitrate(500_000).build()); + TrackGroup videoGroupLowBitrate = + new TrackGroup(VIDEO_FORMAT.buildUpon().setAverageBitrate(100_000).build()); + trackSelector.setParameters( + trackSelector + .buildUponParameters() + .setTrackSelectionOverrides( + new TrackSelectionOverrides.Builder() + .addOverride( + new TrackSelectionOverride( + videoGroupHighBitrate, /* trackIndexes= */ ImmutableList.of())) + .addOverride( + new TrackSelectionOverride( + videoGroupMidBitrate, /* trackIndexes= */ ImmutableList.of(0))) + .addOverride( + new TrackSelectionOverride( + videoGroupLowBitrate, /* trackIndexes= */ ImmutableList.of())) + .build())); + + TrackSelectorResult result = + trackSelector.selectTracks( + RENDERER_CAPABILITIES, + new TrackGroupArray(videoGroupHighBitrate, videoGroupMidBitrate, videoGroupLowBitrate), + periodId, + TIMELINE); + + assertThat(result.selections) + .asList() + .containsExactly(new FixedTrackSelection(videoGroupMidBitrate, /* track= */ 0), null); + } + /** Tests that an empty override is not applied for a different set of available track groups. */ @Test public void selectTracks_withEmptyTrackOverrideForDifferentTracks_hasNoEffect()