From daf72f518c5ebfcaf0943ff0585c715188ce7b23 Mon Sep 17 00:00:00 2001 From: olly Date: Tue, 15 Feb 2022 12:39:30 +0000 Subject: [PATCH] Flatten TrackSelectionParameters PiperOrigin-RevId: 428747243 --- RELEASENOTES.md | 3 + docs/track-selection.md | 25 +- .../TrackSelectionOverride.java | 136 ++++++++ .../TrackSelectionOverrides.java | 310 ------------------ .../TrackSelectionParameters.java | 99 ++++-- .../TrackSelectionOverrideTest.java | 73 +++++ .../TrackSelectionOverridesTest.java | 176 ---------- .../TrackSelectionParametersTest.java | 131 +++++++- .../trackselection/DefaultTrackSelector.java | 48 ++- .../DefaultTrackSelectorTest.java | 68 ++-- .../ui/StyledPlayerControlView.java | 34 +- 11 files changed, 476 insertions(+), 627 deletions(-) create mode 100644 library/common/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionOverride.java delete mode 100644 library/common/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionOverrides.java create mode 100644 library/common/src/test/java/com/google/android/exoplayer2/trackselection/TrackSelectionOverrideTest.java delete mode 100644 library/common/src/test/java/com/google/android/exoplayer2/trackselection/TrackSelectionOverridesTest.java diff --git a/RELEASENOTES.md b/RELEASENOTES.md index f3f76c73d6..fd9ccdd063 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -56,6 +56,9 @@ values in `Player.EventFlags`. * Split `AnalyticsCollector` into an interface and default implementation to allow it to be stripped by R8 if an app doesn't need it. +* Track selection + * Flatten `TrackSelectionOverrides` class into `TrackSelectionParameters`, + and promote `TrackSelectionOverride` to a top level class. * Android 12 compatibility: * Upgrade the Cast extension to depend on `com.google.android.gms:play-services-cast-framework:20.1.0`. Earlier diff --git a/docs/track-selection.md b/docs/track-selection.md index 90f1be5f7f..bb9bc8d4fe 100644 --- a/docs/track-selection.md +++ b/docs/track-selection.md @@ -124,13 +124,11 @@ track group to select this audio group and prevent any other audio track groups from being selected: ~~~ -TrackSelectionOverrides overrides = - new TrackSelectionOverrides.Builder() - .setOverrideForType(new TrackSelectionOverride(audioTrackGroup)) - .build(); player.setTrackSelectionParameters( player.getTrackSelectionParameters() - .buildUpon().setTrackSelectionOverrides(overrides).build()); + .buildUpon() + .setOverrideForType(new TrackSelectionOverride(audioTrackGroup)) + .build()); ~~~ {: .language-java} @@ -149,20 +147,17 @@ player.setTrackSelectionParameters( ~~~ {: .language-java} -Alternatively, it's possible to prevent the selection of track groups for the -current playlist item only by specifying empty overrides for these groups: +Alternatively, it's possible to prevent the selection of tracks from a specific +`TrackGroup` only by specifying an empty override for that group: ~~~ -TrackSelectionOverrides overrides = - new TrackSelectionOverrides.Builder() - .addOverride( - new TrackSelectionOverride( - disabledTrackGroup, - /* select no tracks for this group */ ImmutableList.of())) - .build(); player.setTrackSelectionParameters( player.getTrackSelectionParameters() - .buildUpon().setTrackSelectionOverrides(overrides).build()); + .buildUpon() + .addOverride( + new TrackSelectionOverride( + disabledTrackGroup, ImmutableList.of())) + .build()); ~~~ {: .language-java} diff --git a/library/common/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionOverride.java b/library/common/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionOverride.java new file mode 100644 index 0000000000..8f8ce7a4f6 --- /dev/null +++ b/library/common/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionOverride.java @@ -0,0 +1,136 @@ +/* + * 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 com.google.android.exoplayer2.trackselection; + +import static com.google.android.exoplayer2.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 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}. + * + *

If multiple tracks in {@link #trackGroup} are overridden, as many as possible will be selected + * depending on the player capabilities. + * + *

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 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 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 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 + + @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}. */ + public static final Creator 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); + } +} diff --git a/library/common/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionOverrides.java b/library/common/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionOverrides.java deleted file mode 100644 index 20baeb466e..0000000000 --- a/library/common/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionOverrides.java +++ /dev/null @@ -1,310 +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 com.google.android.exoplayer2.trackselection; - -import static com.google.android.exoplayer2.util.Assertions.checkNotNull; -import static com.google.android.exoplayer2.util.BundleableUtil.fromBundleNullableList; -import static com.google.android.exoplayer2.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 com.google.android.exoplayer2.Bundleable; -import com.google.android.exoplayer2.C; -import com.google.android.exoplayer2.MediaItem; -import com.google.android.exoplayer2.source.TrackGroup; -import com.google.android.exoplayer2.util.MimeTypes; -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}. - * - *

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. - * - *

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}. - * - *

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 overrides; - - /** Creates an builder with no {@link TrackSelectionOverride}. */ - public Builder() { - overrides = new HashMap<>(); - } - - private Builder(Map overrides) { - this.overrides = new HashMap<>(overrides); - } - - /** 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; - } - - /** - * Remove any override associated with {@link TrackGroup TrackGroups} of type {@code trackType}. - */ - public Builder clearOverridesOfType(@C.TrackType int trackType) { - for (Iterator 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}. - * - *

If multiple tracks in {@link #trackGroup} are overridden, as many as possible will be - * selected depending on the player capabilities. - * - *

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 trackIndices; - - /** Constructs an instance to force all tracks in {@code trackGroup} to be selected. */ - public TrackSelectionOverride(TrackGroup trackGroup) { - this.trackGroup = trackGroup; - ImmutableList.Builder 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 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; - - @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}. */ - public static final Creator 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 overrides; - - private TrackSelectionOverrides(Map 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}. */ - public ImmutableList 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; - - @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}. */ - public static final Creator CREATOR = - bundle -> { - List trackSelectionOverrides = - fromBundleNullableList( - TrackSelectionOverride.CREATOR, - bundle.getParcelableArrayList(keyForField(FIELD_OVERRIDES)), - ImmutableList.of()); - ImmutableMap.Builder 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); - } -} diff --git a/library/common/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionParameters.java b/library/common/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionParameters.java index a3b22b4a3b..ad83f1a6fe 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionParameters.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionParameters.java @@ -16,9 +16,9 @@ package com.google.android.exoplayer2.trackselection; import static com.google.android.exoplayer2.util.Assertions.checkNotNull; -import static com.google.android.exoplayer2.util.BundleableUtil.fromNullableBundle; +import static com.google.android.exoplayer2.util.BundleableUtil.fromBundleNullableList; +import static com.google.android.exoplayer2.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; @@ -30,14 +30,18 @@ import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import com.google.android.exoplayer2.Bundleable; import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.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; @@ -96,7 +100,7 @@ public class TrackSelectionParameters implements Bundleable { // General private boolean forceLowestBitrate; private boolean forceHighestSupportedBitrate; - private TrackSelectionOverrides trackSelectionOverrides; + private HashMap overrides; private ImmutableSet<@C.TrackType Integer> disabledTrackTypes; /** @@ -128,7 +132,7 @@ public class TrackSelectionParameters implements Bundleable { // General forceLowestBitrate = false; forceHighestSupportedBitrate = false; - trackSelectionOverrides = TrackSelectionOverrides.EMPTY; + overrides = new HashMap<>(); disabledTrackTypes = ImmutableSet.of(); } @@ -234,11 +238,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 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( @@ -252,7 +261,7 @@ public class TrackSelectionParameters implements Bundleable { "preferredAudioLanguages", "preferredAudioMimeTypes", "preferredTextLanguages", - "trackSelectionOverrides", + "overrides", "disabledTrackTypes", }) private void init(@UnknownInitialization Builder this, TrackSelectionParameters parameters) { @@ -283,8 +292,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}. */ @@ -643,14 +652,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 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; } @@ -855,8 +892,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 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 @@ -892,7 +930,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; } @@ -937,7 +975,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); } @@ -971,7 +1009,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; } @@ -980,7 +1018,6 @@ public class TrackSelectionParameters implements Bundleable { @Documented @Retention(RetentionPolicy.SOURCE) - @Target(TYPE_USE) @IntDef({ FIELD_PREFERRED_AUDIO_LANGUAGES, FIELD_PREFERRED_AUDIO_ROLE_FLAGS, @@ -1004,8 +1041,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 }) @@ -1033,10 +1069,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; @Override public Bundle toBundle() { @@ -1079,8 +1114,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; diff --git a/library/common/src/test/java/com/google/android/exoplayer2/trackselection/TrackSelectionOverrideTest.java b/library/common/src/test/java/com/google/android/exoplayer2/trackselection/TrackSelectionOverrideTest.java new file mode 100644 index 0000000000..7034903c47 --- /dev/null +++ b/library/common/src/test/java/com/google/android/exoplayer2/trackselection/TrackSelectionOverrideTest.java @@ -0,0 +1,73 @@ +/* + * 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 com.google.android.exoplayer2.trackselection; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertThrows; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.android.exoplayer2.Format; +import com.google.android.exoplayer2.source.TrackGroup; +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)); + } +} diff --git a/library/common/src/test/java/com/google/android/exoplayer2/trackselection/TrackSelectionOverridesTest.java b/library/common/src/test/java/com/google/android/exoplayer2/trackselection/TrackSelectionOverridesTest.java deleted file mode 100644 index 5fe642ac48..0000000000 --- a/library/common/src/test/java/com/google/android/exoplayer2/trackselection/TrackSelectionOverridesTest.java +++ /dev/null @@ -1,176 +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 com.google.android.exoplayer2.trackselection; - -import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.assertThrows; - -import androidx.test.ext.junit.runners.AndroidJUnit4; -import com.google.android.exoplayer2.C; -import com.google.android.exoplayer2.Format; -import com.google.android.exoplayer2.source.TrackGroup; -import com.google.android.exoplayer2.trackselection.TrackSelectionOverrides.TrackSelectionOverride; -import com.google.android.exoplayer2.util.MimeTypes; -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); - } -} diff --git a/library/common/src/test/java/com/google/android/exoplayer2/trackselection/TrackSelectionParametersTest.java b/library/common/src/test/java/com/google/android/exoplayer2/trackselection/TrackSelectionParametersTest.java index 519b1d4bed..c65ec2f966 100644 --- a/library/common/src/test/java/com/google/android/exoplayer2/trackselection/TrackSelectionParametersTest.java +++ b/library/common/src/test/java/com/google/android/exoplayer2/trackselection/TrackSelectionParametersTest.java @@ -22,7 +22,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.source.TrackGroup; -import com.google.android.exoplayer2.trackselection.TrackSelectionOverrides.TrackSelectionOverride; import com.google.android.exoplayer2.util.MimeTypes; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; @@ -33,6 +32,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; @@ -63,22 +65,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() @@ -107,7 +106,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(); @@ -141,7 +146,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); } @@ -182,4 +188,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); + } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java index ac2b6cbb25..ea3c00efab 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java @@ -43,7 +43,6 @@ import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.TrackGroupArray; -import com.google.android.exoplayer2.trackselection.TrackSelectionOverrides.TrackSelectionOverride; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.BundleableUtil; import com.google.android.exoplayer2.util.MimeTypes; @@ -593,9 +592,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; } @@ -700,7 +722,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( @@ -725,7 +747,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( @@ -748,7 +770,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) { @@ -766,7 +788,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() { @@ -1017,7 +1039,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) { @@ -1034,7 +1056,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 @@ -1653,9 +1675,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. @@ -1663,7 +1683,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; diff --git a/library/core/src/test/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelectorTest.java b/library/core/src/test/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelectorTest.java index e56d4bfb49..f9affe7b98 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelectorTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelectorTest.java @@ -52,7 +52,6 @@ import com.google.android.exoplayer2.testutil.FakeTimeline; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.ParametersBuilder; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.SelectionOverride; -import com.google.android.exoplayer2.trackselection.TrackSelectionOverrides.TrackSelectionOverride; import com.google.android.exoplayer2.trackselection.TrackSelector.InvalidationListener; import com.google.android.exoplayer2.upstream.BandwidthMeter; import com.google.android.exoplayer2.util.MimeTypes; @@ -169,10 +168,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); @@ -223,18 +220,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( @@ -258,12 +253,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( @@ -307,10 +300,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}, @@ -326,10 +317,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}, @@ -359,10 +348,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}, @@ -2395,13 +2382,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(); } diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerControlView.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerControlView.java index 82715eddf7..4efcc9db85 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerControlView.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/StyledPlayerControlView.java @@ -67,8 +67,7 @@ import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.TracksInfo; import com.google.android.exoplayer2.TracksInfo.TrackGroupInfo; import com.google.android.exoplayer2.source.TrackGroup; -import com.google.android.exoplayer2.trackselection.TrackSelectionOverrides; -import com.google.android.exoplayer2.trackselection.TrackSelectionOverrides.TrackSelectionOverride; +import com.google.android.exoplayer2.trackselection.TrackSelectionOverride; import com.google.android.exoplayer2.trackselection.TrackSelectionParameters; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.RepeatModeUtil; @@ -1908,7 +1907,7 @@ public class StyledPlayerControlView 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 -> { @@ -1917,12 +1916,6 @@ public class StyledPlayerControlView 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); @@ -1930,7 +1923,7 @@ public class StyledPlayerControlView extends FrameLayout { .setTrackSelectionParameters( trackSelectionParameters .buildUpon() - .setTrackSelectionOverrides(trackSelectionOverrides) + .clearOverridesOfType(C.TRACK_TYPE_AUDIO) .setDisabledTrackTypes(disabledTrackTypes) .build()); settingsAdapter.setSubTextAtPosition( @@ -1940,10 +1933,10 @@ public class StyledPlayerControlView 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; } } @@ -1966,7 +1959,7 @@ public class StyledPlayerControlView 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)); @@ -2017,8 +2010,7 @@ public class StyledPlayerControlView 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( @@ -2028,14 +2020,6 @@ public class StyledPlayerControlView 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()); @@ -2043,7 +2027,9 @@ public class StyledPlayerControlView extends FrameLayout { .setTrackSelectionParameters( trackSelectionParameters .buildUpon() - .setTrackSelectionOverrides(overrides) + .setOverrideForType( + new TrackSelectionOverride( + trackGroup, ImmutableList.of(track.trackIndex))) .setDisabledTrackTypes(disabledTrackTypes) .build()); onTrackSelection(track.trackName);