Commit d5ef11aa by krocard Committed by bachinger

Add track selection override to the player API

This moves `SelectionOverride` from `DefaultTrackSelector`
to `TrackSelectionParameters`.

It is then use to allow track selection override per
track selection array.

Note that contrary to
`DefaultTrackSelector.Parameters.selectionOverride`, the renderer
concept is not exposed.

This cl is a part of the bigger track selection change,
splitted for ease of review.
Find all cls with the tag:
#player-track-selection

PiperOrigin-RevId: 399933612
parent ece0cfc9
......@@ -24,6 +24,7 @@ import androidx.annotation.Nullable;
import com.google.android.exoplayer2.Bundleable;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/** Utilities for {@link Bundleable}. */
......@@ -108,14 +109,15 @@ public final class BundleableUtil {
}
/**
* Converts a list of {@link Bundleable} to an {@link ArrayList} of {@link Bundle} so that the
* returned list can be put to {@link Bundle} using {@link Bundle#putParcelableArrayList}
* Converts a collection of {@link Bundleable} to an {@link ArrayList} of {@link Bundle} so that
* the returned list can be put to {@link Bundle} using {@link Bundle#putParcelableArrayList}
* conveniently.
*/
public static <T extends Bundleable> ArrayList<Bundle> toBundleArrayList(List<T> bundleableList) {
ArrayList<Bundle> arrayList = new ArrayList<>(bundleableList.size());
for (int i = 0; i < bundleableList.size(); i++) {
arrayList.add(bundleableList.get(i).toBundle());
public static <T extends Bundleable> ArrayList<Bundle> toBundleArrayList(
Collection<T> bundleables) {
ArrayList<Bundle> arrayList = new ArrayList<>(bundleables.size());
for (T element : bundleables) {
arrayList.add(element.toBundle());
}
return arrayList;
}
......
......@@ -19,8 +19,14 @@ import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
import static com.google.common.truth.Truth.assertThat;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.Bundleable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.SelectionOverride;
import com.google.android.exoplayer2.trackselection.TrackSelectionParameters.TrackSelectionOverride;
import com.google.android.exoplayer2.util.MimeTypes;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import org.junit.Test;
import org.junit.runner.RunWith;
......@@ -58,10 +64,16 @@ public class TrackSelectionParametersTest {
// General
assertThat(parameters.forceLowestBitrate).isFalse();
assertThat(parameters.forceHighestSupportedBitrate).isFalse();
assertThat(parameters.trackSelectionOverrides).isEmpty();
assertThat(parameters.disabledTrackTypes).isEmpty();
}
@Test
public void parametersSet_fromDefault_isAsExpected() {
ImmutableMap<TrackGroup, TrackSelectionOverride> trackSelectionOverrides =
ImmutableMap.of(
new TrackGroup(new Format.Builder().build()),
new TrackSelectionOverride(/* tracks= */ ImmutableSet.of(2, 3)));
TrackSelectionParameters parameters =
TrackSelectionParameters.DEFAULT_WITHOUT_CONTEXT
.buildUpon()
......@@ -90,6 +102,8 @@ public class TrackSelectionParametersTest {
// General
.setForceLowestBitrate(false)
.setForceHighestSupportedBitrate(true)
.setTrackSelectionOverrides(trackSelectionOverrides)
.setDisabledTrackTypes(ImmutableSet.of(C.TRACK_TYPE_AUDIO, C.TRACK_TYPE_TEXT))
.build();
// Video
......@@ -122,6 +136,9 @@ public class TrackSelectionParametersTest {
// General
assertThat(parameters.forceLowestBitrate).isFalse();
assertThat(parameters.forceHighestSupportedBitrate).isTrue();
assertThat(parameters.trackSelectionOverrides).isEqualTo(trackSelectionOverrides);
assertThat(parameters.disabledTrackTypes)
.containsExactly(C.TRACK_TYPE_AUDIO, C.TRACK_TYPE_TEXT);
}
@Test
......@@ -160,4 +177,17 @@ public class TrackSelectionParametersTest {
assertThat(parameters.viewportHeight).isEqualTo(Integer.MAX_VALUE);
assertThat(parameters.viewportOrientationMayChange).isTrue();
}
/** Tests {@link SelectionOverride}'s {@link Bundleable} implementation. */
@Test
public void roundTripViaBundle_ofSelectionOverride_yieldsEqualInstance() {
SelectionOverride selectionOverrideToBundle =
new SelectionOverride(/* groupIndex= */ 1, /* tracks...= */ 2, 3);
SelectionOverride selectionOverrideFromBundle =
DefaultTrackSelector.SelectionOverride.CREATOR.fromBundle(
selectionOverrideToBundle.toBundle());
assertThat(selectionOverrideFromBundle).isEqualTo(selectionOverrideToBundle);
}
}
......@@ -39,6 +39,7 @@ import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.TrackSelectionParameters.TrackSelectionOverride;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.BundleableUtil;
import com.google.android.exoplayer2.util.Util;
......@@ -609,6 +610,13 @@ public class DefaultTrackSelector extends MappingTrackSelector {
}
@Override
public ParametersBuilder setTrackSelectionOverrides(
Map<TrackGroup, TrackSelectionOverride> trackSelectionOverrides) {
super.setTrackSelectionOverrides(trackSelectionOverrides);
return this;
}
@Override
public ParametersBuilder setDisabledTrackTypes(Set<@C.TrackType Integer> disabledTrackTypes) {
super.setDisabledTrackTypes(disabledTrackTypes);
return this;
......@@ -1490,19 +1498,33 @@ public class DefaultTrackSelector extends MappingTrackSelector {
// Apply track disabling and overriding.
for (int i = 0; i < rendererCount; i++) {
// Per renderer and per track type disabling
@C.TrackType int rendererType = mappedTrackInfo.getRendererType(i);
if (params.getRendererDisabled(i) || params.disabledTrackTypes.contains(rendererType)) {
definitions[i] = null;
continue;
}
// Per TrackGroupArray override
TrackGroupArray rendererTrackGroups = mappedTrackInfo.getTrackGroups(i);
if (params.hasSelectionOverride(i, rendererTrackGroups)) {
SelectionOverride override = params.getSelectionOverride(i, rendererTrackGroups);
@Nullable SelectionOverride override = params.getSelectionOverride(i, rendererTrackGroups);
definitions[i] =
override == null
? null
: new ExoTrackSelection.Definition(
rendererTrackGroups.get(override.groupIndex), override.tracks, override.type);
continue;
}
// Per TrackGroup override
for (int j = 0; j < rendererTrackGroups.length; j++) {
TrackGroup trackGroup = rendererTrackGroups.get(j);
@Nullable
TrackSelectionOverride overrideTracks = params.trackSelectionOverrides.get(trackGroup);
if (overrideTracks != null) {
definitions[i] =
new ExoTrackSelection.Definition(trackGroup, Ints.toArray(overrideTracks.tracks));
break;
}
}
}
......
......@@ -45,10 +45,12 @@ import com.google.android.exoplayer2.testutil.FakeTimeline;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.ParametersBuilder;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.SelectionOverride;
import com.google.android.exoplayer2.trackselection.TrackSelectionParameters.TrackSelectionOverride;
import com.google.android.exoplayer2.trackselection.TrackSelector.InvalidationListener;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import java.util.HashMap;
import java.util.Map;
......@@ -152,16 +154,21 @@ public final class DefaultTrackSelectorTest {
assertThat(parametersFromBundle).isEqualTo(parametersToBundle);
}
/** Tests {@link SelectionOverride}'s {@link Bundleable} implementation. */
/** Tests that an empty override clears a track selection. */
@Test
public void roundTripViaBundle_ofSelectionOverride_yieldsEqualInstance() {
SelectionOverride selectionOverrideToBundle =
new SelectionOverride(/* groupIndex= */ 1, /* tracks...= */ 2, 3);
public void selectTracks_withNullOverride_clearsTrackSelection() throws ExoPlaybackException {
trackSelector.setParameters(
trackSelector
.buildUponParameters()
.setTrackSelectionOverrides(
ImmutableMap.of(VIDEO_TRACK_GROUP, new TrackSelectionOverride(ImmutableSet.of()))));
SelectionOverride selectionOverrideFromBundle =
SelectionOverride.CREATOR.fromBundle(selectionOverrideToBundle.toBundle());
TrackSelectorResult result =
trackSelector.selectTracks(RENDERER_CAPABILITIES, TRACK_GROUPS, periodId, TIMELINE);
assertThat(selectionOverrideFromBundle).isEqualTo(selectionOverrideToBundle);
assertSelections(result, new TrackSelection[] {null, TRACK_SELECTIONS[1]});
assertThat(result.rendererConfigurations)
.isEqualTo(new RendererConfiguration[] {null, DEFAULT});
}
/** Tests that a null override clears a track selection. */
......@@ -193,6 +200,29 @@ public final class DefaultTrackSelectorTest {
.isEqualTo(new RendererConfiguration[] {DEFAULT, DEFAULT});
}
/** Tests that an empty override is not applied for a different set of available track groups. */
@Test
public void selectTracks_withEmptyTrackOverrideForDifferentTracks_hasNoEffect()
throws ExoPlaybackException {
trackSelector.setParameters(
trackSelector
.buildUponParameters()
.setTrackSelectionOverrides(
ImmutableMap.of(
new TrackGroup(VIDEO_FORMAT, VIDEO_FORMAT), TrackSelectionOverride.DISABLE)));
TrackSelectorResult result =
trackSelector.selectTracks(
RENDERER_CAPABILITIES,
new TrackGroupArray(VIDEO_TRACK_GROUP, AUDIO_TRACK_GROUP, VIDEO_TRACK_GROUP),
periodId,
TIMELINE);
assertThat(result.selections).asList().containsExactlyElementsIn(TRACK_SELECTIONS).inOrder();
assertThat(result.rendererConfigurations)
.isEqualTo(new RendererConfiguration[] {DEFAULT, DEFAULT});
}
/** Tests that an override is not applied for a different set of available track groups. */
@Test
public void selectTracksWithNullOverrideForDifferentTracks() throws ExoPlaybackException {
......@@ -1815,6 +1845,10 @@ public final class DefaultTrackSelectorTest {
.setRendererDisabled(1, true)
.setRendererDisabled(3, true)
.setRendererDisabled(5, false)
.setTrackSelectionOverrides(
ImmutableMap.of(
AUDIO_TRACK_GROUP,
new TrackSelectionOverride(/* tracks= */ ImmutableSet.of(3, 4, 5))))
.setDisabledTrackTypes(ImmutableSet.of(C.TRACK_TYPE_AUDIO))
.build();
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment