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; package androidx.media3.common;
import static androidx.media3.common.util.Assertions.checkNotNull; 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 com.google.common.base.MoreObjects.firstNonNull;
import static java.lang.annotation.ElementType.TYPE_USE;
import android.content.Context; import android.content.Context;
import android.graphics.Point; import android.graphics.Point;
@ -31,12 +31,15 @@ import androidx.annotation.RequiresApi;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util; import androidx.media3.common.util.Util;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.primitives.Ints; import com.google.common.primitives.Ints;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; 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.Locale;
import java.util.Set; import java.util.Set;
import org.checkerframework.checker.initialization.qual.UnknownInitialization; import org.checkerframework.checker.initialization.qual.UnknownInitialization;
@ -95,7 +98,7 @@ public class TrackSelectionParameters implements Bundleable {
// General // General
private boolean forceLowestBitrate; private boolean forceLowestBitrate;
private boolean forceHighestSupportedBitrate; private boolean forceHighestSupportedBitrate;
private TrackSelectionOverrides trackSelectionOverrides; private HashMap<TrackGroup, TrackSelectionOverride> overrides;
private ImmutableSet<@C.TrackType Integer> disabledTrackTypes; private ImmutableSet<@C.TrackType Integer> disabledTrackTypes;
/** /**
@ -128,7 +131,7 @@ public class TrackSelectionParameters implements Bundleable {
// General // General
forceLowestBitrate = false; forceLowestBitrate = false;
forceHighestSupportedBitrate = false; forceHighestSupportedBitrate = false;
trackSelectionOverrides = TrackSelectionOverrides.EMPTY; overrides = new HashMap<>();
disabledTrackTypes = ImmutableSet.of(); disabledTrackTypes = ImmutableSet.of();
} }
@ -236,11 +239,16 @@ public class TrackSelectionParameters implements Bundleable {
bundle.getBoolean( bundle.getBoolean(
keyForField(FIELD_FORCE_HIGHEST_SUPPORTED_BITRATE), keyForField(FIELD_FORCE_HIGHEST_SUPPORTED_BITRATE),
DEFAULT_WITHOUT_CONTEXT.forceHighestSupportedBitrate); DEFAULT_WITHOUT_CONTEXT.forceHighestSupportedBitrate);
trackSelectionOverrides = overrides = new HashMap<>();
fromNullableBundle( List<TrackSelectionOverride> overrideList =
TrackSelectionOverrides.CREATOR, fromBundleNullableList(
bundle.getBundle(keyForField(FIELD_SELECTION_OVERRIDE_KEYS)), TrackSelectionOverride.CREATOR,
TrackSelectionOverrides.EMPTY); 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 = disabledTrackTypes =
ImmutableSet.copyOf( ImmutableSet.copyOf(
Ints.asList( Ints.asList(
@ -254,7 +262,7 @@ public class TrackSelectionParameters implements Bundleable {
"preferredAudioLanguages", "preferredAudioLanguages",
"preferredAudioMimeTypes", "preferredAudioMimeTypes",
"preferredTextLanguages", "preferredTextLanguages",
"trackSelectionOverrides", "overrides",
"disabledTrackTypes", "disabledTrackTypes",
}) })
private void init(@UnknownInitialization Builder this, TrackSelectionParameters parameters) { private void init(@UnknownInitialization Builder this, TrackSelectionParameters parameters) {
@ -285,8 +293,8 @@ public class TrackSelectionParameters implements Bundleable {
// General // General
forceLowestBitrate = parameters.forceLowestBitrate; forceLowestBitrate = parameters.forceLowestBitrate;
forceHighestSupportedBitrate = parameters.forceHighestSupportedBitrate; forceHighestSupportedBitrate = parameters.forceHighestSupportedBitrate;
trackSelectionOverrides = parameters.trackSelectionOverrides;
disabledTrackTypes = parameters.disabledTrackTypes; disabledTrackTypes = parameters.disabledTrackTypes;
overrides = new HashMap<>(parameters.overrides);
} }
/** Overrides the value of the builder with the value of {@link TrackSelectionParameters}. */ /** Overrides the value of the builder with the value of {@link TrackSelectionParameters}. */
@ -646,14 +654,42 @@ public class TrackSelectionParameters implements Bundleable {
return this; 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. * Remove any override associated with {@link TrackGroup TrackGroups} of type {@code trackType}.
*
* @param trackSelectionOverrides The track selection overrides.
* @return This builder.
*/ */
public Builder setTrackSelectionOverrides(TrackSelectionOverrides trackSelectionOverrides) { public Builder clearOverridesOfType(@C.TrackType int trackType) {
this.trackSelectionOverrides = trackSelectionOverrides; 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; return this;
} }
@ -860,8 +896,9 @@ public class TrackSelectionParameters implements Bundleable {
*/ */
public final boolean forceHighestSupportedBitrate; public final boolean forceHighestSupportedBitrate;
/** Overrides to force tracks to be selected. */ /** Overrides to force selection of specific tracks. */
public final TrackSelectionOverrides trackSelectionOverrides; public final ImmutableMap<TrackGroup, TrackSelectionOverride> overrides;
/** /**
* The track types that are disabled. No track of a disabled type will be selected, thus no track * 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 * 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 // General
this.forceLowestBitrate = builder.forceLowestBitrate; this.forceLowestBitrate = builder.forceLowestBitrate;
this.forceHighestSupportedBitrate = builder.forceHighestSupportedBitrate; this.forceHighestSupportedBitrate = builder.forceHighestSupportedBitrate;
this.trackSelectionOverrides = builder.trackSelectionOverrides; this.overrides = ImmutableMap.copyOf(builder.overrides);
this.disabledTrackTypes = builder.disabledTrackTypes; this.disabledTrackTypes = builder.disabledTrackTypes;
} }
@ -943,7 +980,7 @@ public class TrackSelectionParameters implements Bundleable {
// General // General
&& forceLowestBitrate == other.forceLowestBitrate && forceLowestBitrate == other.forceLowestBitrate
&& forceHighestSupportedBitrate == other.forceHighestSupportedBitrate && forceHighestSupportedBitrate == other.forceHighestSupportedBitrate
&& trackSelectionOverrides.equals(other.trackSelectionOverrides) && overrides.equals(other.overrides)
&& disabledTrackTypes.equals(other.disabledTrackTypes); && disabledTrackTypes.equals(other.disabledTrackTypes);
} }
@ -977,7 +1014,7 @@ public class TrackSelectionParameters implements Bundleable {
// General // General
result = 31 * result + (forceLowestBitrate ? 1 : 0); result = 31 * result + (forceLowestBitrate ? 1 : 0);
result = 31 * result + (forceHighestSupportedBitrate ? 1 : 0); result = 31 * result + (forceHighestSupportedBitrate ? 1 : 0);
result = 31 * result + trackSelectionOverrides.hashCode(); result = 31 * result + overrides.hashCode();
result = 31 * result + disabledTrackTypes.hashCode(); result = 31 * result + disabledTrackTypes.hashCode();
return result; return result;
} }
@ -986,7 +1023,6 @@ public class TrackSelectionParameters implements Bundleable {
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({ @IntDef({
FIELD_PREFERRED_AUDIO_LANGUAGES, FIELD_PREFERRED_AUDIO_LANGUAGES,
FIELD_PREFERRED_AUDIO_ROLE_FLAGS, FIELD_PREFERRED_AUDIO_ROLE_FLAGS,
@ -1010,8 +1046,7 @@ public class TrackSelectionParameters implements Bundleable {
FIELD_PREFERRED_AUDIO_MIME_TYPES, FIELD_PREFERRED_AUDIO_MIME_TYPES,
FIELD_FORCE_LOWEST_BITRATE, FIELD_FORCE_LOWEST_BITRATE,
FIELD_FORCE_HIGHEST_SUPPORTED_BITRATE, FIELD_FORCE_HIGHEST_SUPPORTED_BITRATE,
FIELD_SELECTION_OVERRIDE_KEYS, FIELD_SELECTION_OVERRIDES,
FIELD_SELECTION_OVERRIDE_VALUES,
FIELD_DISABLED_TRACK_TYPE, FIELD_DISABLED_TRACK_TYPE,
FIELD_PREFERRED_VIDEO_ROLE_FLAGS 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_PREFERRED_AUDIO_MIME_TYPES = 20;
private static final int FIELD_FORCE_LOWEST_BITRATE = 21; private static final int FIELD_FORCE_LOWEST_BITRATE = 21;
private static final int FIELD_FORCE_HIGHEST_SUPPORTED_BITRATE = 22; 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_OVERRIDES = 23;
private static final int FIELD_SELECTION_OVERRIDE_VALUES = 24; private static final int FIELD_DISABLED_TRACK_TYPE = 24;
private static final int FIELD_DISABLED_TRACK_TYPE = 25; private static final int FIELD_PREFERRED_VIDEO_ROLE_FLAGS = 25;
private static final int FIELD_PREFERRED_VIDEO_ROLE_FLAGS = 26;
@UnstableApi @UnstableApi
@Override @Override
@ -1086,8 +1120,8 @@ public class TrackSelectionParameters implements Bundleable {
bundle.putBoolean(keyForField(FIELD_FORCE_LOWEST_BITRATE), forceLowestBitrate); bundle.putBoolean(keyForField(FIELD_FORCE_LOWEST_BITRATE), forceLowestBitrate);
bundle.putBoolean( bundle.putBoolean(
keyForField(FIELD_FORCE_HIGHEST_SUPPORTED_BITRATE), forceHighestSupportedBitrate); keyForField(FIELD_FORCE_HIGHEST_SUPPORTED_BITRATE), forceHighestSupportedBitrate);
bundle.putBundle( bundle.putParcelableArrayList(
keyForField(FIELD_SELECTION_OVERRIDE_KEYS), trackSelectionOverrides.toBundle()); keyForField(FIELD_SELECTION_OVERRIDES), toBundleArrayList(overrides.values()));
bundle.putIntArray(keyForField(FIELD_DISABLED_TRACK_TYPE), Ints.toArray(disabledTrackTypes)); bundle.putIntArray(keyForField(FIELD_DISABLED_TRACK_TYPE), Ints.toArray(disabledTrackTypes));
return bundle; 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 androidx.test.core.app.ApplicationProvider.getApplicationContext;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import androidx.media3.common.TrackSelectionOverrides.TrackSelectionOverride;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
@ -29,6 +28,9 @@ import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
public final class TrackSelectionParametersTest { public final class TrackSelectionParametersTest {
private static final TrackGroup AAC_TRACK_GROUP =
new TrackGroup(new Format.Builder().setSampleMimeType(MimeTypes.AUDIO_AAC).build());
@Test @Test
public void defaultValue_withoutChange_isAsExpected() { public void defaultValue_withoutChange_isAsExpected() {
TrackSelectionParameters parameters = TrackSelectionParameters.DEFAULT_WITHOUT_CONTEXT; TrackSelectionParameters parameters = TrackSelectionParameters.DEFAULT_WITHOUT_CONTEXT;
@ -59,22 +61,19 @@ public final class TrackSelectionParametersTest {
// General // General
assertThat(parameters.forceLowestBitrate).isFalse(); assertThat(parameters.forceLowestBitrate).isFalse();
assertThat(parameters.forceHighestSupportedBitrate).isFalse(); assertThat(parameters.forceHighestSupportedBitrate).isFalse();
assertThat(parameters.trackSelectionOverrides.asList()).isEmpty(); assertThat(parameters.overrides).isEmpty();
assertThat(parameters.disabledTrackTypes).isEmpty(); assertThat(parameters.disabledTrackTypes).isEmpty();
} }
@Test @Test
public void parametersSet_fromDefault_isAsExpected() { public void parametersSet_fromDefault_isAsExpected() {
TrackSelectionOverrides trackSelectionOverrides = TrackSelectionOverride override1 =
new TrackSelectionOverrides.Builder() new TrackSelectionOverride(new TrackGroup(new Format.Builder().build()));
.addOverride(new TrackSelectionOverride(new TrackGroup(new Format.Builder().build()))) TrackSelectionOverride override2 =
.addOverride(
new TrackSelectionOverride( new TrackSelectionOverride(
new TrackGroup( new TrackGroup(
new Format.Builder().setId(4).build(), new Format.Builder().setId(4).build(), new Format.Builder().setId(5).build()),
new Format.Builder().setId(5).build()), /* trackIndices= */ ImmutableList.of(1));
/* trackIndices= */ ImmutableList.of(1)))
.build();
TrackSelectionParameters parameters = TrackSelectionParameters parameters =
TrackSelectionParameters.DEFAULT_WITHOUT_CONTEXT TrackSelectionParameters.DEFAULT_WITHOUT_CONTEXT
.buildUpon() .buildUpon()
@ -103,7 +102,13 @@ public final class TrackSelectionParametersTest {
// General // General
.setForceLowestBitrate(false) .setForceLowestBitrate(false)
.setForceHighestSupportedBitrate(true) .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)) .setDisabledTrackTypes(ImmutableSet.of(C.TRACK_TYPE_AUDIO, C.TRACK_TYPE_TEXT))
.build(); .build();
@ -137,7 +142,8 @@ public final class TrackSelectionParametersTest {
// General // General
assertThat(parameters.forceLowestBitrate).isFalse(); assertThat(parameters.forceLowestBitrate).isFalse();
assertThat(parameters.forceHighestSupportedBitrate).isTrue(); assertThat(parameters.forceHighestSupportedBitrate).isTrue();
assertThat(parameters.trackSelectionOverrides).isEqualTo(trackSelectionOverrides); assertThat(parameters.overrides)
.containsExactly(override1.trackGroup, override1, override2.trackGroup, override2);
assertThat(parameters.disabledTrackTypes) assertThat(parameters.disabledTrackTypes)
.containsExactly(C.TRACK_TYPE_AUDIO, C.TRACK_TYPE_TEXT); .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.viewportHeight).isEqualTo(Integer.MAX_VALUE);
assertThat(parameters.viewportOrientationMayChange).isTrue(); 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.TrackGroup;
import androidx.media3.common.TrackGroupArray; import androidx.media3.common.TrackGroupArray;
import androidx.media3.common.TrackSelection; import androidx.media3.common.TrackSelection;
import androidx.media3.common.TrackSelectionOverrides; import androidx.media3.common.TrackSelectionOverride;
import androidx.media3.common.TrackSelectionOverrides.TrackSelectionOverride;
import androidx.media3.common.TrackSelectionParameters; import androidx.media3.common.TrackSelectionParameters;
import androidx.media3.common.util.Assertions; import androidx.media3.common.util.Assertions;
import androidx.media3.common.util.BundleableUtil; import androidx.media3.common.util.BundleableUtil;
@ -598,9 +597,32 @@ public class DefaultTrackSelector extends MappingTrackSelector {
} }
@Override @Override
public ParametersBuilder setTrackSelectionOverrides( public ParametersBuilder addOverride(TrackSelectionOverride override) {
TrackSelectionOverrides trackSelectionOverrides) { super.addOverride(override);
super.setTrackSelectionOverrides(trackSelectionOverrides); 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; return this;
} }
@ -705,7 +727,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
* @param groups The {@link TrackGroupArray} for which the override should be applied. * @param groups The {@link TrackGroupArray} for which the override should be applied.
* @param override The override. * @param override The override.
* @return This builder. * @return This builder.
* @deprecated Use {@link TrackSelectionParameters.Builder#setTrackSelectionOverrides}. * @deprecated Use {@link TrackSelectionParameters.Builder#addOverride(TrackSelectionOverride)}.
*/ */
@Deprecated @Deprecated
public final ParametersBuilder setSelectionOverride( public final ParametersBuilder setSelectionOverride(
@ -730,7 +752,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
* @param rendererIndex The renderer index. * @param rendererIndex The renderer index.
* @param groups The {@link TrackGroupArray} for which the override should be cleared. * @param groups The {@link TrackGroupArray} for which the override should be cleared.
* @return This builder. * @return This builder.
* @deprecated Use {@link TrackSelectionParameters.Builder#setTrackSelectionOverrides}. * @deprecated Use {@link TrackSelectionParameters.Builder#clearOverride(TrackGroup)}.
*/ */
@Deprecated @Deprecated
public final ParametersBuilder clearSelectionOverride( public final ParametersBuilder clearSelectionOverride(
@ -753,7 +775,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
* *
* @param rendererIndex The renderer index. * @param rendererIndex The renderer index.
* @return This builder. * @return This builder.
* @deprecated Use {@link TrackSelectionParameters.Builder#setTrackSelectionOverrides}. * @deprecated Use {@link TrackSelectionParameters.Builder#clearOverridesOfType(int)}.
*/ */
@Deprecated @Deprecated
public final ParametersBuilder clearSelectionOverrides(int rendererIndex) { public final ParametersBuilder clearSelectionOverrides(int rendererIndex) {
@ -771,7 +793,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
* Clears all track selection overrides for all renderers. * Clears all track selection overrides for all renderers.
* *
* @return This builder. * @return This builder.
* @deprecated Use {@link TrackSelectionParameters.Builder#setTrackSelectionOverrides}. * @deprecated Use {@link TrackSelectionParameters.Builder#clearOverrides()}.
*/ */
@Deprecated @Deprecated
public final ParametersBuilder clearSelectionOverrides() { public final ParametersBuilder clearSelectionOverrides() {
@ -1022,7 +1044,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
* @return Whether there is an override. * @return Whether there is an override.
* @deprecated Only works to retrieve the overrides set with the deprecated {@link * @deprecated Only works to retrieve the overrides set with the deprecated {@link
* ParametersBuilder#setSelectionOverride(int, TrackGroupArray, SelectionOverride)}. Use * ParametersBuilder#setSelectionOverride(int, TrackGroupArray, SelectionOverride)}. Use
* {@link TrackSelectionParameters#trackSelectionOverrides} instead. * {@link TrackSelectionParameters#overrides} instead.
*/ */
@Deprecated @Deprecated
public final boolean hasSelectionOverride(int rendererIndex, TrackGroupArray groups) { 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. * @return The override, or null if no override exists.
* @deprecated Only works to retrieve the overrides set with the deprecated {@link * @deprecated Only works to retrieve the overrides set with the deprecated {@link
* ParametersBuilder#setSelectionOverride(int, TrackGroupArray, SelectionOverride)}. Use * ParametersBuilder#setSelectionOverride(int, TrackGroupArray, SelectionOverride)}. Use
* {@link TrackSelectionParameters#trackSelectionOverrides} instead. * {@link TrackSelectionParameters#overrides} instead.
*/ */
@Deprecated @Deprecated
@Nullable @Nullable
@ -1661,9 +1683,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
TrackGroupArray rendererTrackGroups = mappedTrackInfo.getTrackGroups(rendererIndex); TrackGroupArray rendererTrackGroups = mappedTrackInfo.getTrackGroups(rendererIndex);
for (int j = 0; j < rendererTrackGroups.length; j++) { for (int j = 0; j < rendererTrackGroups.length; j++) {
maybeUpdateApplicableOverrides( maybeUpdateApplicableOverrides(
applicableOverrides, applicableOverrides, params.overrides.get(rendererTrackGroups.get(j)), rendererIndex);
params.trackSelectionOverrides.getOverride(rendererTrackGroups.get(j)),
rendererIndex);
} }
} }
// Also iterate unmapped groups to see if they have overrides. // 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++) { for (int i = 0; i < unmappedGroups.length; i++) {
maybeUpdateApplicableOverrides( maybeUpdateApplicableOverrides(
applicableOverrides, applicableOverrides,
params.trackSelectionOverrides.getOverride(unmappedGroups.get(i)), params.overrides.get(unmappedGroups.get(i)),
/* rendererIndex= */ C.INDEX_UNSET); /* rendererIndex= */ C.INDEX_UNSET);
} }
return applicableOverrides; return applicableOverrides;

View File

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

View File

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