Flatten TrackSelectionParameters

PiperOrigin-RevId: 428747243
This commit is contained in:
olly 2022-02-15 12:39:30 +00:00 committed by Ian Baker
parent 91d4add082
commit 8b01d07512
9 changed files with 465 additions and 613 deletions

View File

@ -0,0 +1,139 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.media3.common;
import static androidx.media3.common.util.Assertions.checkNotNull;
import static java.util.Collections.max;
import static java.util.Collections.min;
import android.os.Bundle;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import androidx.media3.common.util.UnstableApi;
import com.google.common.collect.ImmutableList;
import com.google.common.primitives.Ints;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
/**
* Forces the selection of {@link #trackIndices} for a {@link TrackGroup}.
*
* <p>If multiple tracks in {@link #trackGroup} are overridden, as many as possible will be selected
* depending on the player capabilities.
*
* <p>If {@link #trackIndices} is empty, no tracks from {@link #trackGroup} will be played. This is
* similar to {@link TrackSelectionParameters#disabledTrackTypes}, except it will only affect the
* playback of the associated {@link TrackGroup}. For example, if the only {@link
* C#TRACK_TYPE_VIDEO} {@link TrackGroup} is associated with no tracks, no video will play until the
* next video starts.
*/
public final class TrackSelectionOverride implements Bundleable {
/** The {@link TrackGroup} whose {@link #trackIndices} are forced to be selected. */
public final TrackGroup trackGroup;
/** The indices of tracks in a {@link TrackGroup} to be selected. */
public final ImmutableList<Integer> trackIndices;
@Documented
@Retention(RetentionPolicy.SOURCE)
@IntDef({
FIELD_TRACK_GROUP,
FIELD_TRACKS,
})
private @interface FieldNumber {}
private static final int FIELD_TRACK_GROUP = 0;
private static final int FIELD_TRACKS = 1;
/** Constructs an instance to force all tracks in {@code trackGroup} to be selected. */
public TrackSelectionOverride(TrackGroup trackGroup) {
this.trackGroup = trackGroup;
ImmutableList.Builder<Integer> builder = new ImmutableList.Builder<>();
for (int i = 0; i < trackGroup.length; i++) {
builder.add(i);
}
this.trackIndices = builder.build();
}
/**
* Constructs an instance to force {@code trackIndices} in {@code trackGroup} to be selected.
*
* @param trackGroup The {@link TrackGroup} for which to override the track selection.
* @param trackIndices The indices of the tracks in the {@link TrackGroup} to select.
*/
public TrackSelectionOverride(TrackGroup trackGroup, List<Integer> trackIndices) {
if (!trackIndices.isEmpty()) {
if (min(trackIndices) < 0 || max(trackIndices) >= trackGroup.length) {
throw new IndexOutOfBoundsException();
}
}
this.trackGroup = trackGroup;
this.trackIndices = ImmutableList.copyOf(trackIndices);
}
/** Returns the {@link C.TrackType} of the overridden track group. */
public @C.TrackType int getTrackType() {
return MimeTypes.getTrackType(trackGroup.getFormat(0).sampleMimeType);
}
@Override
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
TrackSelectionOverride that = (TrackSelectionOverride) obj;
return trackGroup.equals(that.trackGroup) && trackIndices.equals(that.trackIndices);
}
@Override
public int hashCode() {
return trackGroup.hashCode() + 31 * trackIndices.hashCode();
}
// Bundleable implementation
@UnstableApi
@Override
public Bundle toBundle() {
Bundle bundle = new Bundle();
bundle.putBundle(keyForField(FIELD_TRACK_GROUP), trackGroup.toBundle());
bundle.putIntArray(keyForField(FIELD_TRACKS), Ints.toArray(trackIndices));
return bundle;
}
/** Object that can restore {@code TrackSelectionOverride} from a {@link Bundle}. */
@UnstableApi
public static final Creator<TrackSelectionOverride> CREATOR =
bundle -> {
@Nullable Bundle trackGroupBundle = bundle.getBundle(keyForField(FIELD_TRACK_GROUP));
checkNotNull(trackGroupBundle); // Mandatory as there are no reasonable defaults.
TrackGroup trackGroup = TrackGroup.CREATOR.fromBundle(trackGroupBundle);
@Nullable int[] tracks = bundle.getIntArray(keyForField(FIELD_TRACKS));
if (tracks == null) {
return new TrackSelectionOverride(trackGroup);
}
return new TrackSelectionOverride(trackGroup, Ints.asList(tracks));
};
private static String keyForField(@FieldNumber int field) {
return Integer.toString(field, Character.MAX_RADIX);
}
}

View File

@ -1,313 +0,0 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.media3.common;
import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.common.util.BundleableUtil.fromBundleNullableList;
import static androidx.media3.common.util.BundleableUtil.toBundleArrayList;
import static java.lang.annotation.ElementType.TYPE_USE;
import static java.util.Collections.max;
import static java.util.Collections.min;
import android.os.Bundle;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import androidx.media3.common.util.UnstableApi;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.primitives.Ints;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Forces the selection of the specified tracks in {@link TrackGroup TrackGroups}.
*
* <p>Each {@link TrackSelectionOverride override} only affects the selection of tracks of that
* {@link C.TrackType type}. For example overriding the selection of an {@link C#TRACK_TYPE_AUDIO
* audio} {@link TrackGroup} will not affect the selection of {@link C#TRACK_TYPE_VIDEO video} or
* {@link C#TRACK_TYPE_TEXT text} tracks.
*
* <p>If multiple {@link TrackGroup TrackGroups} of the same {@link C.TrackType} are overridden,
* which tracks will be selected depend on the player capabilities. For example, by default {@code
* ExoPlayer} doesn't support selecting more than one {@link TrackGroup} per {@link C.TrackType}.
*
* <p>Overrides of {@link TrackGroup} that are not currently available are ignored. For example,
* when the player transitions to the next {@link MediaItem} in a playlist, any overrides of the
* previous {@link MediaItem} are ignored.
*
* @see TrackSelectionParameters#trackSelectionOverrides
*/
public final class TrackSelectionOverrides implements Bundleable {
/** Builder for {@link TrackSelectionOverrides}. */
public static final class Builder {
// Cannot use ImmutableMap.Builder as it doesn't support removing entries.
private final HashMap<TrackGroup, TrackSelectionOverride> overrides;
/** Creates an builder with no {@link TrackSelectionOverride}. */
public Builder() {
overrides = new HashMap<>();
}
private Builder(Map<TrackGroup, TrackSelectionOverride> overrides) {
this.overrides = new HashMap<>(overrides);
}
/** Adds an override for the provided {@link TrackGroup}. */
@UnstableApi
public Builder addOverride(TrackSelectionOverride override) {
overrides.put(override.trackGroup, override);
return this;
}
/** Removes the override associated with the provided {@link TrackGroup} if present. */
@UnstableApi
public Builder clearOverride(TrackGroup trackGroup) {
overrides.remove(trackGroup);
return this;
}
/** Set the override for the type of the provided {@link TrackGroup}. */
public Builder setOverrideForType(TrackSelectionOverride override) {
clearOverridesOfType(override.getTrackType());
overrides.put(override.trackGroup, override);
return this;
}
/**
* Remove any override associated with {@link TrackGroup TrackGroups} of type {@code trackType}.
*/
public Builder clearOverridesOfType(@C.TrackType int trackType) {
for (Iterator<TrackSelectionOverride> it = overrides.values().iterator(); it.hasNext(); ) {
TrackSelectionOverride trackSelectionOverride = it.next();
if (trackSelectionOverride.getTrackType() == trackType) {
it.remove();
}
}
return this;
}
/** Returns a new {@link TrackSelectionOverrides} instance with the current builder values. */
public TrackSelectionOverrides build() {
return new TrackSelectionOverrides(overrides);
}
}
/**
* Forces the selection of {@link #trackIndices} for a {@link TrackGroup}.
*
* <p>If multiple tracks in {@link #trackGroup} are overridden, as many as possible will be
* selected depending on the player capabilities.
*
* <p>If {@link #trackIndices} is empty, no tracks from {@link #trackGroup} will be played. This
* is similar to {@link TrackSelectionParameters#disabledTrackTypes}, except it will only affect
* the playback of the associated {@link TrackGroup}. For example, if the only {@link
* C#TRACK_TYPE_VIDEO} {@link TrackGroup} is associated with no tracks, no video will play until
* the next video starts.
*/
public static final class TrackSelectionOverride implements Bundleable {
/** The {@link TrackGroup} whose {@link #trackIndices} are forced to be selected. */
public final TrackGroup trackGroup;
/** The indices of tracks in a {@link TrackGroup} to be selected. */
public final ImmutableList<Integer> trackIndices;
/** Constructs an instance to force all tracks in {@code trackGroup} to be selected. */
public TrackSelectionOverride(TrackGroup trackGroup) {
this.trackGroup = trackGroup;
ImmutableList.Builder<Integer> builder = new ImmutableList.Builder<>();
for (int i = 0; i < trackGroup.length; i++) {
builder.add(i);
}
this.trackIndices = builder.build();
}
/**
* Constructs an instance to force {@code trackIndices} in {@code trackGroup} to be selected.
*
* @param trackGroup The {@link TrackGroup} for which to override the track selection.
* @param trackIndices The indices of the tracks in the {@link TrackGroup} to select.
*/
public TrackSelectionOverride(TrackGroup trackGroup, List<Integer> trackIndices) {
if (!trackIndices.isEmpty()) {
if (min(trackIndices) < 0 || max(trackIndices) >= trackGroup.length) {
throw new IndexOutOfBoundsException();
}
}
this.trackGroup = trackGroup;
this.trackIndices = ImmutableList.copyOf(trackIndices);
}
@Override
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
TrackSelectionOverride that = (TrackSelectionOverride) obj;
return trackGroup.equals(that.trackGroup) && trackIndices.equals(that.trackIndices);
}
@Override
public int hashCode() {
return trackGroup.hashCode() + 31 * trackIndices.hashCode();
}
/** Returns the {@link C.TrackType} of the overriden track group. */
public @C.TrackType int getTrackType() {
return MimeTypes.getTrackType(trackGroup.getFormat(0).sampleMimeType);
}
// Bundleable implementation
@Documented
@Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({
FIELD_TRACK_GROUP,
FIELD_TRACKS,
})
private @interface FieldNumber {}
private static final int FIELD_TRACK_GROUP = 0;
private static final int FIELD_TRACKS = 1;
@UnstableApi
@Override
public Bundle toBundle() {
Bundle bundle = new Bundle();
bundle.putBundle(keyForField(FIELD_TRACK_GROUP), trackGroup.toBundle());
bundle.putIntArray(keyForField(FIELD_TRACKS), Ints.toArray(trackIndices));
return bundle;
}
/** Object that can restore {@code TrackSelectionOverride} from a {@link Bundle}. */
@UnstableApi
public static final Creator<TrackSelectionOverride> CREATOR =
bundle -> {
@Nullable Bundle trackGroupBundle = bundle.getBundle(keyForField(FIELD_TRACK_GROUP));
checkNotNull(trackGroupBundle); // Mandatory as there are no reasonable defaults.
TrackGroup trackGroup = TrackGroup.CREATOR.fromBundle(trackGroupBundle);
@Nullable int[] tracks = bundle.getIntArray(keyForField(FIELD_TRACKS));
if (tracks == null) {
return new TrackSelectionOverride(trackGroup);
}
return new TrackSelectionOverride(trackGroup, Ints.asList(tracks));
};
private static String keyForField(@FieldNumber int field) {
return Integer.toString(field, Character.MAX_RADIX);
}
}
/** Empty {@code TrackSelectionOverrides}, where no track selection is overridden. */
public static final TrackSelectionOverrides EMPTY =
new TrackSelectionOverrides(ImmutableMap.of());
private final ImmutableMap<TrackGroup, TrackSelectionOverride> overrides;
private TrackSelectionOverrides(Map<TrackGroup, TrackSelectionOverride> overrides) {
this.overrides = ImmutableMap.copyOf(overrides);
}
/** Returns a {@link Builder} initialized with the values of this instance. */
public Builder buildUpon() {
return new Builder(overrides);
}
/** Returns a list of the {@link TrackSelectionOverride overrides}. */
@UnstableApi
public ImmutableList<TrackSelectionOverride> asList() {
return ImmutableList.copyOf(overrides.values());
}
/**
* Returns the {@link TrackSelectionOverride} of the provided {@link TrackGroup} or {@code null}
* if there is none.
*/
@Nullable
public TrackSelectionOverride getOverride(TrackGroup trackGroup) {
return overrides.get(trackGroup);
}
@Override
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
TrackSelectionOverrides that = (TrackSelectionOverrides) obj;
return overrides.equals(that.overrides);
}
@Override
public int hashCode() {
return overrides.hashCode();
}
// Bundleable implementation
@Documented
@Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({
FIELD_OVERRIDES,
})
private @interface FieldNumber {}
private static final int FIELD_OVERRIDES = 0;
@UnstableApi
@Override
public Bundle toBundle() {
Bundle bundle = new Bundle();
bundle.putParcelableArrayList(
keyForField(FIELD_OVERRIDES), toBundleArrayList(overrides.values()));
return bundle;
}
/** Object that can restore {@code TrackSelectionOverrides} from a {@link Bundle}. */
@UnstableApi
public static final Creator<TrackSelectionOverrides> CREATOR =
bundle -> {
List<TrackSelectionOverride> trackSelectionOverrides =
fromBundleNullableList(
TrackSelectionOverride.CREATOR,
bundle.getParcelableArrayList(keyForField(FIELD_OVERRIDES)),
ImmutableList.of());
ImmutableMap.Builder<TrackGroup, TrackSelectionOverride> builder =
new ImmutableMap.Builder<>();
for (int i = 0; i < trackSelectionOverrides.size(); i++) {
TrackSelectionOverride trackSelectionOverride = trackSelectionOverrides.get(i);
builder.put(trackSelectionOverride.trackGroup, trackSelectionOverride);
}
return new TrackSelectionOverrides(builder.buildOrThrow());
};
private static String keyForField(@FieldNumber int field) {
return Integer.toString(field, Character.MAX_RADIX);
}
}

View File

@ -16,9 +16,9 @@
package androidx.media3.common;
import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.common.util.BundleableUtil.fromNullableBundle;
import static androidx.media3.common.util.BundleableUtil.fromBundleNullableList;
import static androidx.media3.common.util.BundleableUtil.toBundleArrayList;
import static com.google.common.base.MoreObjects.firstNonNull;
import static java.lang.annotation.ElementType.TYPE_USE;
import android.content.Context;
import android.graphics.Point;
@ -31,12 +31,15 @@ import androidx.annotation.RequiresApi;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.primitives.Ints;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import org.checkerframework.checker.initialization.qual.UnknownInitialization;
@ -95,7 +98,7 @@ public class TrackSelectionParameters implements Bundleable {
// General
private boolean forceLowestBitrate;
private boolean forceHighestSupportedBitrate;
private TrackSelectionOverrides trackSelectionOverrides;
private HashMap<TrackGroup, TrackSelectionOverride> overrides;
private ImmutableSet<@C.TrackType Integer> disabledTrackTypes;
/**
@ -128,7 +131,7 @@ public class TrackSelectionParameters implements Bundleable {
// General
forceLowestBitrate = false;
forceHighestSupportedBitrate = false;
trackSelectionOverrides = TrackSelectionOverrides.EMPTY;
overrides = new HashMap<>();
disabledTrackTypes = ImmutableSet.of();
}
@ -236,11 +239,16 @@ public class TrackSelectionParameters implements Bundleable {
bundle.getBoolean(
keyForField(FIELD_FORCE_HIGHEST_SUPPORTED_BITRATE),
DEFAULT_WITHOUT_CONTEXT.forceHighestSupportedBitrate);
trackSelectionOverrides =
fromNullableBundle(
TrackSelectionOverrides.CREATOR,
bundle.getBundle(keyForField(FIELD_SELECTION_OVERRIDE_KEYS)),
TrackSelectionOverrides.EMPTY);
overrides = new HashMap<>();
List<TrackSelectionOverride> overrideList =
fromBundleNullableList(
TrackSelectionOverride.CREATOR,
bundle.getParcelableArrayList(keyForField(FIELD_SELECTION_OVERRIDES)),
ImmutableList.of());
for (int i = 0; i < overrideList.size(); i++) {
TrackSelectionOverride override = overrideList.get(i);
overrides.put(override.trackGroup, override);
}
disabledTrackTypes =
ImmutableSet.copyOf(
Ints.asList(
@ -254,7 +262,7 @@ public class TrackSelectionParameters implements Bundleable {
"preferredAudioLanguages",
"preferredAudioMimeTypes",
"preferredTextLanguages",
"trackSelectionOverrides",
"overrides",
"disabledTrackTypes",
})
private void init(@UnknownInitialization Builder this, TrackSelectionParameters parameters) {
@ -285,8 +293,8 @@ public class TrackSelectionParameters implements Bundleable {
// General
forceLowestBitrate = parameters.forceLowestBitrate;
forceHighestSupportedBitrate = parameters.forceHighestSupportedBitrate;
trackSelectionOverrides = parameters.trackSelectionOverrides;
disabledTrackTypes = parameters.disabledTrackTypes;
overrides = new HashMap<>(parameters.overrides);
}
/** Overrides the value of the builder with the value of {@link TrackSelectionParameters}. */
@ -646,14 +654,42 @@ public class TrackSelectionParameters implements Bundleable {
return this;
}
/** Adds an override for the provided {@link TrackGroup}. */
public Builder addOverride(TrackSelectionOverride override) {
overrides.put(override.trackGroup, override);
return this;
}
/** Removes the override associated with the provided {@link TrackGroup} if present. */
public Builder clearOverride(TrackGroup trackGroup) {
overrides.remove(trackGroup);
return this;
}
/** Set the override for the type of the provided {@link TrackGroup}. */
public Builder setOverrideForType(TrackSelectionOverride override) {
clearOverridesOfType(override.getTrackType());
overrides.put(override.trackGroup, override);
return this;
}
/**
* Sets the selection overrides.
*
* @param trackSelectionOverrides The track selection overrides.
* @return This builder.
* Remove any override associated with {@link TrackGroup TrackGroups} of type {@code trackType}.
*/
public Builder setTrackSelectionOverrides(TrackSelectionOverrides trackSelectionOverrides) {
this.trackSelectionOverrides = trackSelectionOverrides;
public Builder clearOverridesOfType(@C.TrackType int trackType) {
Iterator<TrackSelectionOverride> it = overrides.values().iterator();
while (it.hasNext()) {
TrackSelectionOverride override = it.next();
if (override.getTrackType() == trackType) {
it.remove();
}
}
return this;
}
/** Removes all track overrides. */
public Builder clearOverrides() {
overrides.clear();
return this;
}
@ -860,8 +896,9 @@ public class TrackSelectionParameters implements Bundleable {
*/
public final boolean forceHighestSupportedBitrate;
/** Overrides to force tracks to be selected. */
public final TrackSelectionOverrides trackSelectionOverrides;
/** Overrides to force selection of specific tracks. */
public final ImmutableMap<TrackGroup, TrackSelectionOverride> overrides;
/**
* The track types that are disabled. No track of a disabled type will be selected, thus no track
* type contained in the set will be played. The default value is that no track type is disabled
@ -898,7 +935,7 @@ public class TrackSelectionParameters implements Bundleable {
// General
this.forceLowestBitrate = builder.forceLowestBitrate;
this.forceHighestSupportedBitrate = builder.forceHighestSupportedBitrate;
this.trackSelectionOverrides = builder.trackSelectionOverrides;
this.overrides = ImmutableMap.copyOf(builder.overrides);
this.disabledTrackTypes = builder.disabledTrackTypes;
}
@ -943,7 +980,7 @@ public class TrackSelectionParameters implements Bundleable {
// General
&& forceLowestBitrate == other.forceLowestBitrate
&& forceHighestSupportedBitrate == other.forceHighestSupportedBitrate
&& trackSelectionOverrides.equals(other.trackSelectionOverrides)
&& overrides.equals(other.overrides)
&& disabledTrackTypes.equals(other.disabledTrackTypes);
}
@ -977,7 +1014,7 @@ public class TrackSelectionParameters implements Bundleable {
// General
result = 31 * result + (forceLowestBitrate ? 1 : 0);
result = 31 * result + (forceHighestSupportedBitrate ? 1 : 0);
result = 31 * result + trackSelectionOverrides.hashCode();
result = 31 * result + overrides.hashCode();
result = 31 * result + disabledTrackTypes.hashCode();
return result;
}
@ -986,7 +1023,6 @@ public class TrackSelectionParameters implements Bundleable {
@Documented
@Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({
FIELD_PREFERRED_AUDIO_LANGUAGES,
FIELD_PREFERRED_AUDIO_ROLE_FLAGS,
@ -1010,8 +1046,7 @@ public class TrackSelectionParameters implements Bundleable {
FIELD_PREFERRED_AUDIO_MIME_TYPES,
FIELD_FORCE_LOWEST_BITRATE,
FIELD_FORCE_HIGHEST_SUPPORTED_BITRATE,
FIELD_SELECTION_OVERRIDE_KEYS,
FIELD_SELECTION_OVERRIDE_VALUES,
FIELD_SELECTION_OVERRIDES,
FIELD_DISABLED_TRACK_TYPE,
FIELD_PREFERRED_VIDEO_ROLE_FLAGS
})
@ -1039,10 +1074,9 @@ public class TrackSelectionParameters implements Bundleable {
private static final int FIELD_PREFERRED_AUDIO_MIME_TYPES = 20;
private static final int FIELD_FORCE_LOWEST_BITRATE = 21;
private static final int FIELD_FORCE_HIGHEST_SUPPORTED_BITRATE = 22;
private static final int FIELD_SELECTION_OVERRIDE_KEYS = 23;
private static final int FIELD_SELECTION_OVERRIDE_VALUES = 24;
private static final int FIELD_DISABLED_TRACK_TYPE = 25;
private static final int FIELD_PREFERRED_VIDEO_ROLE_FLAGS = 26;
private static final int FIELD_SELECTION_OVERRIDES = 23;
private static final int FIELD_DISABLED_TRACK_TYPE = 24;
private static final int FIELD_PREFERRED_VIDEO_ROLE_FLAGS = 25;
@UnstableApi
@Override
@ -1086,8 +1120,8 @@ public class TrackSelectionParameters implements Bundleable {
bundle.putBoolean(keyForField(FIELD_FORCE_LOWEST_BITRATE), forceLowestBitrate);
bundle.putBoolean(
keyForField(FIELD_FORCE_HIGHEST_SUPPORTED_BITRATE), forceHighestSupportedBitrate);
bundle.putBundle(
keyForField(FIELD_SELECTION_OVERRIDE_KEYS), trackSelectionOverrides.toBundle());
bundle.putParcelableArrayList(
keyForField(FIELD_SELECTION_OVERRIDES), toBundleArrayList(overrides.values()));
bundle.putIntArray(keyForField(FIELD_DISABLED_TRACK_TYPE), Ints.toArray(disabledTrackTypes));
return bundle;

View File

@ -0,0 +1,71 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.media3.common;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.common.collect.ImmutableList;
import java.util.Arrays;
import org.junit.Test;
import org.junit.runner.RunWith;
/** Unit tests for {@link TrackSelectionOverride}. */
@RunWith(AndroidJUnit4.class)
public final class TrackSelectionOverrideTest {
@Test
public void newTrackSelectionOverride_withJustTrackGroup_selectsAllTracks() {
TrackSelectionOverride trackSelectionOverride =
new TrackSelectionOverride(newTrackGroupWithIds(1, 2));
assertThat(trackSelectionOverride.trackGroup).isEqualTo(newTrackGroupWithIds(1, 2));
assertThat(trackSelectionOverride.trackIndices).containsExactly(0, 1).inOrder();
}
@Test
public void newTrackSelectionOverride_withTracks_selectsOnlySpecifiedTracks() {
TrackSelectionOverride trackSelectionOverride =
new TrackSelectionOverride(newTrackGroupWithIds(1, 2), ImmutableList.of(1));
assertThat(trackSelectionOverride.trackGroup).isEqualTo(newTrackGroupWithIds(1, 2));
assertThat(trackSelectionOverride.trackIndices).containsExactly(1);
}
@Test
public void newTrackSelectionOverride_with0Tracks_selectsAllSpecifiedTracks() {
TrackSelectionOverride trackSelectionOverride =
new TrackSelectionOverride(newTrackGroupWithIds(1, 2), ImmutableList.of());
assertThat(trackSelectionOverride.trackGroup).isEqualTo(newTrackGroupWithIds(1, 2));
assertThat(trackSelectionOverride.trackIndices).isEmpty();
}
@Test
public void newTrackSelectionOverride_withInvalidIndex_throws() {
assertThrows(
IndexOutOfBoundsException.class,
() -> new TrackSelectionOverride(newTrackGroupWithIds(1, 2), ImmutableList.of(2)));
}
private static TrackGroup newTrackGroupWithIds(int... ids) {
return new TrackGroup(
Arrays.stream(ids)
.mapToObj(id -> new Format.Builder().setId(id).build())
.toArray(Format[]::new));
}
}

View File

@ -1,172 +0,0 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.media3.common;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
import androidx.media3.common.TrackSelectionOverrides.TrackSelectionOverride;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.common.collect.ImmutableList;
import java.util.Arrays;
import org.junit.Test;
import org.junit.runner.RunWith;
/** Unit tests for {@link TrackSelectionOverrides}. */
@RunWith(AndroidJUnit4.class)
public final class TrackSelectionOverridesTest {
public static final TrackGroup AAC_TRACK_GROUP =
new TrackGroup(new Format.Builder().setSampleMimeType(MimeTypes.AUDIO_AAC).build());
private static TrackGroup newTrackGroupWithIds(int... ids) {
return new TrackGroup(
Arrays.stream(ids)
.mapToObj(id -> new Format.Builder().setId(id).build())
.toArray(Format[]::new));
}
@Test
public void newTrackSelectionOverride_withJustTrackGroup_selectsAllTracks() {
TrackSelectionOverride trackSelectionOverride =
new TrackSelectionOverride(newTrackGroupWithIds(1, 2));
assertThat(trackSelectionOverride.trackGroup).isEqualTo(newTrackGroupWithIds(1, 2));
assertThat(trackSelectionOverride.trackIndices).containsExactly(0, 1).inOrder();
}
@Test
public void newTrackSelectionOverride_withTracks_selectsOnlySpecifiedTracks() {
TrackSelectionOverride trackSelectionOverride =
new TrackSelectionOverride(newTrackGroupWithIds(1, 2), ImmutableList.of(1));
assertThat(trackSelectionOverride.trackGroup).isEqualTo(newTrackGroupWithIds(1, 2));
assertThat(trackSelectionOverride.trackIndices).containsExactly(1);
}
@Test
public void newTrackSelectionOverride_with0Tracks_selectsAllSpecifiedTracks() {
TrackSelectionOverride trackSelectionOverride =
new TrackSelectionOverride(newTrackGroupWithIds(1, 2), ImmutableList.of());
assertThat(trackSelectionOverride.trackGroup).isEqualTo(newTrackGroupWithIds(1, 2));
assertThat(trackSelectionOverride.trackIndices).isEmpty();
}
@Test
public void newTrackSelectionOverride_withInvalidIndex_throws() {
assertThrows(
IndexOutOfBoundsException.class,
() -> new TrackSelectionOverride(newTrackGroupWithIds(1, 2), ImmutableList.of(2)));
}
@Test
public void roundTripViaBundle_withOverrides_yieldsEqualInstance() {
TrackSelectionOverrides trackSelectionOverrides =
new TrackSelectionOverrides.Builder()
.setOverrideForType(
new TrackSelectionOverride(newTrackGroupWithIds(3, 4), ImmutableList.of(1)))
.addOverride(new TrackSelectionOverride(newTrackGroupWithIds(5, 6)))
.build();
TrackSelectionOverrides fromBundle =
TrackSelectionOverrides.CREATOR.fromBundle(trackSelectionOverrides.toBundle());
assertThat(fromBundle).isEqualTo(trackSelectionOverrides);
assertThat(fromBundle.asList()).isEqualTo(trackSelectionOverrides.asList());
}
@Test
public void builder_byDefault_isEmpty() {
TrackSelectionOverrides trackSelectionOverrides = new TrackSelectionOverrides.Builder().build();
assertThat(trackSelectionOverrides.asList()).isEmpty();
assertThat(trackSelectionOverrides).isEqualTo(TrackSelectionOverrides.EMPTY);
}
@Test
public void addOverride_onDifferentGroups_addsOverride() {
TrackSelectionOverride override1 = new TrackSelectionOverride(newTrackGroupWithIds(1));
TrackSelectionOverride override2 = new TrackSelectionOverride(newTrackGroupWithIds(2));
TrackSelectionOverrides trackSelectionOverrides =
new TrackSelectionOverrides.Builder().addOverride(override1).addOverride(override2).build();
assertThat(trackSelectionOverrides.asList()).containsExactly(override1, override2);
assertThat(trackSelectionOverrides.getOverride(override1.trackGroup)).isEqualTo(override1);
assertThat(trackSelectionOverrides.getOverride(override2.trackGroup)).isEqualTo(override2);
}
@Test
public void addOverride_onSameGroup_replacesOverride() {
TrackGroup trackGroup = newTrackGroupWithIds(1, 2, 3);
TrackSelectionOverride override1 =
new TrackSelectionOverride(trackGroup, /* trackIndices= */ ImmutableList.of(0));
TrackSelectionOverride override2 =
new TrackSelectionOverride(trackGroup, /* trackIndices= */ ImmutableList.of(1));
TrackSelectionOverrides trackSelectionOverrides =
new TrackSelectionOverrides.Builder().addOverride(override1).addOverride(override2).build();
assertThat(trackSelectionOverrides.asList()).containsExactly(override2);
assertThat(trackSelectionOverrides.getOverride(override2.trackGroup)).isEqualTo(override2);
}
@Test
public void setOverrideForType_onSameType_replacesOverride() {
TrackSelectionOverride override1 = new TrackSelectionOverride(newTrackGroupWithIds(1));
TrackSelectionOverride override2 = new TrackSelectionOverride(newTrackGroupWithIds(2));
TrackSelectionOverrides trackSelectionOverrides =
new TrackSelectionOverrides.Builder()
.setOverrideForType(override1)
.setOverrideForType(override2)
.build();
assertThat(trackSelectionOverrides.asList()).containsExactly(override2);
assertThat(trackSelectionOverrides.getOverride(override2.trackGroup)).isEqualTo(override2);
}
@Test
public void clearOverridesOfType_ofTypeAudio_removesAudioOverride() {
TrackSelectionOverride override1 = new TrackSelectionOverride(AAC_TRACK_GROUP);
TrackSelectionOverride override2 = new TrackSelectionOverride(newTrackGroupWithIds(1));
TrackSelectionOverrides trackSelectionOverrides =
new TrackSelectionOverrides.Builder()
.addOverride(override1)
.addOverride(override2)
.clearOverridesOfType(C.TRACK_TYPE_AUDIO)
.build();
assertThat(trackSelectionOverrides.asList()).containsExactly(override2);
assertThat(trackSelectionOverrides.getOverride(override2.trackGroup)).isEqualTo(override2);
}
@Test
public void clearOverride_ofTypeGroup_removesOverride() {
TrackSelectionOverride override1 = new TrackSelectionOverride(AAC_TRACK_GROUP);
TrackSelectionOverride override2 = new TrackSelectionOverride(newTrackGroupWithIds(1));
TrackSelectionOverrides trackSelectionOverrides =
new TrackSelectionOverrides.Builder()
.addOverride(override1)
.addOverride(override2)
.clearOverride(override2.trackGroup)
.build();
assertThat(trackSelectionOverrides.asList()).containsExactly(override1);
assertThat(trackSelectionOverrides.getOverride(override1.trackGroup)).isEqualTo(override1);
}
}

View File

@ -18,7 +18,6 @@ package androidx.media3.common;
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
import static com.google.common.truth.Truth.assertThat;
import androidx.media3.common.TrackSelectionOverrides.TrackSelectionOverride;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@ -29,6 +28,9 @@ import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
public final class TrackSelectionParametersTest {
private static final TrackGroup AAC_TRACK_GROUP =
new TrackGroup(new Format.Builder().setSampleMimeType(MimeTypes.AUDIO_AAC).build());
@Test
public void defaultValue_withoutChange_isAsExpected() {
TrackSelectionParameters parameters = TrackSelectionParameters.DEFAULT_WITHOUT_CONTEXT;
@ -59,22 +61,19 @@ public final class TrackSelectionParametersTest {
// General
assertThat(parameters.forceLowestBitrate).isFalse();
assertThat(parameters.forceHighestSupportedBitrate).isFalse();
assertThat(parameters.trackSelectionOverrides.asList()).isEmpty();
assertThat(parameters.overrides).isEmpty();
assertThat(parameters.disabledTrackTypes).isEmpty();
}
@Test
public void parametersSet_fromDefault_isAsExpected() {
TrackSelectionOverrides trackSelectionOverrides =
new TrackSelectionOverrides.Builder()
.addOverride(new TrackSelectionOverride(new TrackGroup(new Format.Builder().build())))
.addOverride(
new TrackSelectionOverride(
new TrackGroup(
new Format.Builder().setId(4).build(),
new Format.Builder().setId(5).build()),
/* trackIndices= */ ImmutableList.of(1)))
.build();
TrackSelectionOverride override1 =
new TrackSelectionOverride(new TrackGroup(new Format.Builder().build()));
TrackSelectionOverride override2 =
new TrackSelectionOverride(
new TrackGroup(
new Format.Builder().setId(4).build(), new Format.Builder().setId(5).build()),
/* trackIndices= */ ImmutableList.of(1));
TrackSelectionParameters parameters =
TrackSelectionParameters.DEFAULT_WITHOUT_CONTEXT
.buildUpon()
@ -103,7 +102,13 @@ public final class TrackSelectionParametersTest {
// General
.setForceLowestBitrate(false)
.setForceHighestSupportedBitrate(true)
.setTrackSelectionOverrides(trackSelectionOverrides)
.addOverride(new TrackSelectionOverride(new TrackGroup(new Format.Builder().build())))
.addOverride(
new TrackSelectionOverride(
new TrackGroup(
new Format.Builder().setId(4).build(),
new Format.Builder().setId(5).build()),
/* trackIndices= */ ImmutableList.of(1)))
.setDisabledTrackTypes(ImmutableSet.of(C.TRACK_TYPE_AUDIO, C.TRACK_TYPE_TEXT))
.build();
@ -137,7 +142,8 @@ public final class TrackSelectionParametersTest {
// General
assertThat(parameters.forceLowestBitrate).isFalse();
assertThat(parameters.forceHighestSupportedBitrate).isTrue();
assertThat(parameters.trackSelectionOverrides).isEqualTo(trackSelectionOverrides);
assertThat(parameters.overrides)
.containsExactly(override1.trackGroup, override1, override2.trackGroup, override2);
assertThat(parameters.disabledTrackTypes)
.containsExactly(C.TRACK_TYPE_AUDIO, C.TRACK_TYPE_TEXT);
}
@ -178,4 +184,101 @@ public final class TrackSelectionParametersTest {
assertThat(parameters.viewportHeight).isEqualTo(Integer.MAX_VALUE);
assertThat(parameters.viewportOrientationMayChange).isTrue();
}
@Test
public void roundTripViaBundle_withOverride_yieldsEqualInstance() {
TrackSelectionOverride override =
new TrackSelectionOverride(
newTrackGroupWithIds(3, 4), /* trackIndices= */ ImmutableList.of(1));
TrackSelectionParameters trackSelectionParameters =
new TrackSelectionParameters.Builder(getApplicationContext()).addOverride(override).build();
TrackSelectionParameters fromBundle =
TrackSelectionParameters.CREATOR.fromBundle(trackSelectionParameters.toBundle());
assertThat(fromBundle).isEqualTo(trackSelectionParameters);
assertThat(trackSelectionParameters.overrides).containsExactly(override.trackGroup, override);
}
@Test
public void addOverride_onDifferentGroups_addsOverride() {
TrackSelectionOverride override1 = new TrackSelectionOverride(newTrackGroupWithIds(1));
TrackSelectionOverride override2 = new TrackSelectionOverride(newTrackGroupWithIds(2));
TrackSelectionParameters trackSelectionParameters =
new TrackSelectionParameters.Builder(getApplicationContext())
.addOverride(override1)
.addOverride(override2)
.build();
assertThat(trackSelectionParameters.overrides)
.containsExactly(override1.trackGroup, override1, override2.trackGroup, override2);
}
@Test
public void addOverride_onSameGroup_replacesOverride() {
TrackGroup trackGroup = newTrackGroupWithIds(1, 2, 3);
TrackSelectionOverride override1 =
new TrackSelectionOverride(trackGroup, /* trackIndices= */ ImmutableList.of(0));
TrackSelectionOverride override2 =
new TrackSelectionOverride(trackGroup, /* trackIndices= */ ImmutableList.of(1));
TrackSelectionParameters trackSelectionParameters =
new TrackSelectionParameters.Builder(getApplicationContext())
.addOverride(override1)
.addOverride(override2)
.build();
assertThat(trackSelectionParameters.overrides).containsExactly(override2.trackGroup, override2);
}
@Test
public void setOverrideForType_onSameType_replacesOverride() {
TrackSelectionOverride override1 = new TrackSelectionOverride(newTrackGroupWithIds(1));
TrackSelectionOverride override2 = new TrackSelectionOverride(newTrackGroupWithIds(2));
TrackSelectionParameters trackSelectionParameters =
new TrackSelectionParameters.Builder(getApplicationContext())
.setOverrideForType(override1)
.setOverrideForType(override2)
.build();
assertThat(trackSelectionParameters.overrides).containsExactly(override2.trackGroup, override2);
}
@Test
public void clearOverridesOfType_ofTypeAudio_removesAudioOverride() {
TrackSelectionOverride override1 = new TrackSelectionOverride(AAC_TRACK_GROUP);
TrackSelectionOverride override2 = new TrackSelectionOverride(newTrackGroupWithIds(1));
TrackSelectionParameters trackSelectionParameters =
new TrackSelectionParameters.Builder(getApplicationContext())
.addOverride(override1)
.addOverride(override2)
.clearOverridesOfType(C.TRACK_TYPE_AUDIO)
.build();
assertThat(trackSelectionParameters.overrides).containsExactly(override2.trackGroup, override2);
}
@Test
public void clearOverride_ofTypeGroup_removesOverride() {
TrackSelectionOverride override1 = new TrackSelectionOverride(AAC_TRACK_GROUP);
TrackSelectionOverride override2 = new TrackSelectionOverride(newTrackGroupWithIds(1));
TrackSelectionParameters trackSelectionParameters =
new TrackSelectionParameters.Builder(getApplicationContext())
.addOverride(override1)
.addOverride(override2)
.clearOverride(override2.trackGroup)
.build();
assertThat(trackSelectionParameters.overrides).containsExactly(override1.trackGroup, override1);
}
private static TrackGroup newTrackGroupWithIds(int... ids) {
Format[] formats = new Format[ids.length];
for (int i = 0; i < ids.length; i++) {
formats[i] = new Format.Builder().setId(ids[i]).build();
}
return new TrackGroup(formats);
}
}

View File

@ -38,8 +38,7 @@ import androidx.media3.common.Timeline;
import androidx.media3.common.TrackGroup;
import androidx.media3.common.TrackGroupArray;
import androidx.media3.common.TrackSelection;
import androidx.media3.common.TrackSelectionOverrides;
import androidx.media3.common.TrackSelectionOverrides.TrackSelectionOverride;
import androidx.media3.common.TrackSelectionOverride;
import androidx.media3.common.TrackSelectionParameters;
import androidx.media3.common.util.Assertions;
import androidx.media3.common.util.BundleableUtil;
@ -598,9 +597,32 @@ public class DefaultTrackSelector extends MappingTrackSelector {
}
@Override
public ParametersBuilder setTrackSelectionOverrides(
TrackSelectionOverrides trackSelectionOverrides) {
super.setTrackSelectionOverrides(trackSelectionOverrides);
public ParametersBuilder addOverride(TrackSelectionOverride override) {
super.addOverride(override);
return this;
}
@Override
public ParametersBuilder clearOverride(TrackGroup trackGroup) {
super.clearOverride(trackGroup);
return this;
}
@Override
public ParametersBuilder setOverrideForType(TrackSelectionOverride override) {
super.setOverrideForType(override);
return this;
}
@Override
public ParametersBuilder clearOverridesOfType(@C.TrackType int trackType) {
super.clearOverridesOfType(trackType);
return this;
}
@Override
public ParametersBuilder clearOverrides() {
super.clearOverrides();
return this;
}
@ -705,7 +727,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
* @param groups The {@link TrackGroupArray} for which the override should be applied.
* @param override The override.
* @return This builder.
* @deprecated Use {@link TrackSelectionParameters.Builder#setTrackSelectionOverrides}.
* @deprecated Use {@link TrackSelectionParameters.Builder#addOverride(TrackSelectionOverride)}.
*/
@Deprecated
public final ParametersBuilder setSelectionOverride(
@ -730,7 +752,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
* @param rendererIndex The renderer index.
* @param groups The {@link TrackGroupArray} for which the override should be cleared.
* @return This builder.
* @deprecated Use {@link TrackSelectionParameters.Builder#setTrackSelectionOverrides}.
* @deprecated Use {@link TrackSelectionParameters.Builder#clearOverride(TrackGroup)}.
*/
@Deprecated
public final ParametersBuilder clearSelectionOverride(
@ -753,7 +775,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
*
* @param rendererIndex The renderer index.
* @return This builder.
* @deprecated Use {@link TrackSelectionParameters.Builder#setTrackSelectionOverrides}.
* @deprecated Use {@link TrackSelectionParameters.Builder#clearOverridesOfType(int)}.
*/
@Deprecated
public final ParametersBuilder clearSelectionOverrides(int rendererIndex) {
@ -771,7 +793,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
* Clears all track selection overrides for all renderers.
*
* @return This builder.
* @deprecated Use {@link TrackSelectionParameters.Builder#setTrackSelectionOverrides}.
* @deprecated Use {@link TrackSelectionParameters.Builder#clearOverrides()}.
*/
@Deprecated
public final ParametersBuilder clearSelectionOverrides() {
@ -1022,7 +1044,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
* @return Whether there is an override.
* @deprecated Only works to retrieve the overrides set with the deprecated {@link
* ParametersBuilder#setSelectionOverride(int, TrackGroupArray, SelectionOverride)}. Use
* {@link TrackSelectionParameters#trackSelectionOverrides} instead.
* {@link TrackSelectionParameters#overrides} instead.
*/
@Deprecated
public final boolean hasSelectionOverride(int rendererIndex, TrackGroupArray groups) {
@ -1039,7 +1061,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
* @return The override, or null if no override exists.
* @deprecated Only works to retrieve the overrides set with the deprecated {@link
* ParametersBuilder#setSelectionOverride(int, TrackGroupArray, SelectionOverride)}. Use
* {@link TrackSelectionParameters#trackSelectionOverrides} instead.
* {@link TrackSelectionParameters#overrides} instead.
*/
@Deprecated
@Nullable
@ -1661,9 +1683,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
TrackGroupArray rendererTrackGroups = mappedTrackInfo.getTrackGroups(rendererIndex);
for (int j = 0; j < rendererTrackGroups.length; j++) {
maybeUpdateApplicableOverrides(
applicableOverrides,
params.trackSelectionOverrides.getOverride(rendererTrackGroups.get(j)),
rendererIndex);
applicableOverrides, params.overrides.get(rendererTrackGroups.get(j)), rendererIndex);
}
}
// Also iterate unmapped groups to see if they have overrides.
@ -1671,7 +1691,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
for (int i = 0; i < unmappedGroups.length; i++) {
maybeUpdateApplicableOverrides(
applicableOverrides,
params.trackSelectionOverrides.getOverride(unmappedGroups.get(i)),
params.overrides.get(unmappedGroups.get(i)),
/* rendererIndex= */ C.INDEX_UNSET);
}
return applicableOverrides;

View File

@ -42,8 +42,7 @@ import androidx.media3.common.Timeline;
import androidx.media3.common.TrackGroup;
import androidx.media3.common.TrackGroupArray;
import androidx.media3.common.TrackSelection;
import androidx.media3.common.TrackSelectionOverrides;
import androidx.media3.common.TrackSelectionOverrides.TrackSelectionOverride;
import androidx.media3.common.TrackSelectionOverride;
import androidx.media3.common.TracksInfo;
import androidx.media3.common.util.Util;
import androidx.media3.exoplayer.ExoPlaybackException;
@ -171,10 +170,8 @@ public final class DefaultTrackSelectorTest {
trackSelector.setParameters(
trackSelector
.buildUponParameters()
.setTrackSelectionOverrides(
new TrackSelectionOverrides.Builder()
.addOverride(new TrackSelectionOverride(VIDEO_TRACK_GROUP, ImmutableList.of()))
.build()));
.addOverride(new TrackSelectionOverride(VIDEO_TRACK_GROUP, ImmutableList.of()))
.build());
TrackSelectorResult result =
trackSelector.selectTracks(RENDERER_CAPABILITIES, TRACK_GROUPS, periodId, TIMELINE);
@ -225,18 +222,16 @@ public final class DefaultTrackSelectorTest {
trackSelector.setParameters(
trackSelector
.buildUponParameters()
.setTrackSelectionOverrides(
new TrackSelectionOverrides.Builder()
.addOverride(
new TrackSelectionOverride(
videoGroupHighBitrate, /* trackIndices= */ ImmutableList.of()))
.addOverride(
new TrackSelectionOverride(
videoGroupMidBitrate, /* trackIndices= */ ImmutableList.of(0)))
.addOverride(
new TrackSelectionOverride(
videoGroupLowBitrate, /* trackIndices= */ ImmutableList.of()))
.build()));
.addOverride(
new TrackSelectionOverride(
videoGroupHighBitrate, /* trackIndices= */ ImmutableList.of()))
.addOverride(
new TrackSelectionOverride(
videoGroupMidBitrate, /* trackIndices= */ ImmutableList.of(0)))
.addOverride(
new TrackSelectionOverride(
videoGroupLowBitrate, /* trackIndices= */ ImmutableList.of()))
.build());
TrackSelectorResult result =
trackSelector.selectTracks(
@ -260,12 +255,10 @@ public final class DefaultTrackSelectorTest {
trackSelector.setParameters(
trackSelector
.buildUponParameters()
.setTrackSelectionOverrides(
new TrackSelectionOverrides.Builder()
.setOverrideForType(
new TrackSelectionOverride(
new TrackGroup(VIDEO_FORMAT, VIDEO_FORMAT), ImmutableList.of()))
.build()));
.setOverrideForType(
new TrackSelectionOverride(
new TrackGroup(VIDEO_FORMAT, VIDEO_FORMAT), ImmutableList.of()))
.build());
TrackSelectorResult result =
trackSelector.selectTracks(
@ -309,10 +302,8 @@ public final class DefaultTrackSelectorTest {
trackSelector.setParameters(
trackSelector
.buildUponParameters()
.setTrackSelectionOverrides(
new TrackSelectionOverrides.Builder()
.setOverrideForType(new TrackSelectionOverride(videoGroupH264))
.build()));
.setOverrideForType(new TrackSelectionOverride(videoGroupH264))
.build());
TrackSelectorResult result =
trackSelector.selectTracks(
new RendererCapabilities[] {rendererCapabilitiesH264, rendererCapabilitiesAv1},
@ -328,10 +319,8 @@ public final class DefaultTrackSelectorTest {
trackSelector.setParameters(
trackSelector
.buildUponParameters()
.setTrackSelectionOverrides(
new TrackSelectionOverrides.Builder()
.setOverrideForType(new TrackSelectionOverride(videoGroupAv1))
.build()));
.setOverrideForType(new TrackSelectionOverride(videoGroupAv1))
.build());
result =
trackSelector.selectTracks(
new RendererCapabilities[] {rendererCapabilitiesH264, rendererCapabilitiesAv1},
@ -361,10 +350,8 @@ public final class DefaultTrackSelectorTest {
trackSelector.setParameters(
trackSelector
.buildUponParameters()
.setTrackSelectionOverrides(
new TrackSelectionOverrides.Builder()
.setOverrideForType(new TrackSelectionOverride(audioGroupUnsupported))
.build()));
.setOverrideForType(new TrackSelectionOverride(audioGroupUnsupported))
.build());
TrackSelectorResult result =
trackSelector.selectTracks(
new RendererCapabilities[] {VIDEO_CAPABILITIES, audioRendererCapabilties},
@ -2397,13 +2384,10 @@ public final class DefaultTrackSelectorTest {
.setRendererDisabled(1, true)
.setRendererDisabled(3, true)
.setRendererDisabled(5, false)
.setTrackSelectionOverrides(
new TrackSelectionOverrides.Builder()
.setOverrideForType(
new TrackSelectionOverride(
new TrackGroup(AUDIO_FORMAT, AUDIO_FORMAT, AUDIO_FORMAT, AUDIO_FORMAT),
/* trackIndices= */ ImmutableList.of(0, 2, 3)))
.build())
.setOverrideForType(
new TrackSelectionOverride(
new TrackGroup(AUDIO_FORMAT, AUDIO_FORMAT, AUDIO_FORMAT, AUDIO_FORMAT),
/* trackIndices= */ ImmutableList.of(0, 2, 3)))
.setDisabledTrackTypes(ImmutableSet.of(C.TRACK_TYPE_AUDIO))
.build();
}

View File

@ -63,8 +63,7 @@ import androidx.media3.common.Player.Events;
import androidx.media3.common.Player.State;
import androidx.media3.common.Timeline;
import androidx.media3.common.TrackGroup;
import androidx.media3.common.TrackSelectionOverrides;
import androidx.media3.common.TrackSelectionOverrides.TrackSelectionOverride;
import androidx.media3.common.TrackSelectionOverride;
import androidx.media3.common.TrackSelectionParameters;
import androidx.media3.common.TracksInfo;
import androidx.media3.common.TracksInfo.TrackGroupInfo;
@ -1902,7 +1901,7 @@ public class PlayerControlView extends FrameLayout {
holder.textView.setText(R.string.exo_track_selection_auto);
// hasSelectionOverride is true means there is an explicit track selection, not "Auto".
TrackSelectionParameters parameters = checkNotNull(player).getTrackSelectionParameters();
boolean hasSelectionOverride = hasSelectionOverride(parameters.trackSelectionOverrides);
boolean hasSelectionOverride = hasSelectionOverride(parameters);
holder.checkView.setVisibility(hasSelectionOverride ? INVISIBLE : VISIBLE);
holder.itemView.setOnClickListener(
v -> {
@ -1911,12 +1910,6 @@ public class PlayerControlView extends FrameLayout {
}
TrackSelectionParameters trackSelectionParameters =
player.getTrackSelectionParameters();
TrackSelectionOverrides trackSelectionOverrides =
trackSelectionParameters
.trackSelectionOverrides
.buildUpon()
.clearOverridesOfType(C.TRACK_TYPE_AUDIO)
.build();
Set<@C.TrackType Integer> disabledTrackTypes =
new HashSet<>(trackSelectionParameters.disabledTrackTypes);
disabledTrackTypes.remove(C.TRACK_TYPE_AUDIO);
@ -1924,7 +1917,7 @@ public class PlayerControlView extends FrameLayout {
.setTrackSelectionParameters(
trackSelectionParameters
.buildUpon()
.setTrackSelectionOverrides(trackSelectionOverrides)
.clearOverridesOfType(C.TRACK_TYPE_AUDIO)
.setDisabledTrackTypes(disabledTrackTypes)
.build());
settingsAdapter.setSubTextAtPosition(
@ -1934,10 +1927,10 @@ public class PlayerControlView extends FrameLayout {
});
}
private boolean hasSelectionOverride(TrackSelectionOverrides trackSelectionOverrides) {
private boolean hasSelectionOverride(TrackSelectionParameters trackSelectionParameters) {
for (int i = 0; i < tracks.size(); i++) {
TrackGroup trackGroup = tracks.get(i).trackGroupInfo.getTrackGroup();
if (trackSelectionOverrides.getOverride(trackGroup) != null) {
if (trackSelectionParameters.overrides.containsKey(trackGroup)) {
return true;
}
}
@ -1960,7 +1953,7 @@ public class PlayerControlView extends FrameLayout {
getResources().getString(R.string.exo_track_selection_none));
// TODO(insun) : Make the audio item in main settings (settingsAdapater)
// to be non-clickable.
} else if (!hasSelectionOverride(params.trackSelectionOverrides)) {
} else if (!hasSelectionOverride(params)) {
settingsAdapter.setSubTextAtPosition(
SETTINGS_AUDIO_TRACK_SELECTION_POSITION,
getResources().getString(R.string.exo_track_selection_auto));
@ -2011,8 +2004,7 @@ public class PlayerControlView extends FrameLayout {
TrackInformation track = tracks.get(position - 1);
TrackGroup trackGroup = track.trackGroupInfo.getTrackGroup();
TrackSelectionParameters params = checkNotNull(player).getTrackSelectionParameters();
boolean explicitlySelected =
params.trackSelectionOverrides.getOverride(trackGroup) != null && track.isSelected();
boolean explicitlySelected = params.overrides.get(trackGroup) != null && track.isSelected();
holder.textView.setText(track.trackName);
holder.checkView.setVisibility(explicitlySelected ? VISIBLE : INVISIBLE);
holder.itemView.setOnClickListener(
@ -2022,14 +2014,6 @@ public class PlayerControlView extends FrameLayout {
}
TrackSelectionParameters trackSelectionParameters =
player.getTrackSelectionParameters();
TrackSelectionOverrides overrides =
trackSelectionParameters
.trackSelectionOverrides
.buildUpon()
.setOverrideForType(
new TrackSelectionOverride(
trackGroup, ImmutableList.of(track.trackIndex)))
.build();
Set<@C.TrackType Integer> disabledTrackTypes =
new HashSet<>(trackSelectionParameters.disabledTrackTypes);
disabledTrackTypes.remove(track.trackGroupInfo.getTrackType());
@ -2037,7 +2021,9 @@ public class PlayerControlView extends FrameLayout {
.setTrackSelectionParameters(
trackSelectionParameters
.buildUpon()
.setTrackSelectionOverrides(overrides)
.setOverrideForType(
new TrackSelectionOverride(
trackGroup, ImmutableList.of(track.trackIndex)))
.setDisabledTrackTypes(disabledTrackTypes)
.build());
onTrackSelection(track.trackName);