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 new file mode 100644 index 0000000000..bb8fce5fa4 --- /dev/null +++ b/library/common/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionParameters.java @@ -0,0 +1,855 @@ +/* + * Copyright (C) 2019 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 android.content.Context; +import android.graphics.Point; +import android.os.Looper; +import android.os.Parcel; +import android.os.Parcelable; +import android.view.accessibility.CaptioningManager; +import androidx.annotation.Nullable; +import androidx.annotation.RequiresApi; +import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.util.Util; +import com.google.common.collect.ImmutableList; +import java.util.ArrayList; +import java.util.Locale; + +/** Constraint parameters for track selection. */ +public class TrackSelectionParameters implements Parcelable { + + /** + * A builder for {@link TrackSelectionParameters}. See the {@link TrackSelectionParameters} + * documentation for explanations of the parameters that can be configured using this builder. + */ + public static class Builder { + // Video + private int maxVideoWidth; + private int maxVideoHeight; + private int maxVideoFrameRate; + private int maxVideoBitrate; + private int minVideoWidth; + private int minVideoHeight; + private int minVideoFrameRate; + private int minVideoBitrate; + private int viewportWidth; + private int viewportHeight; + private boolean viewportOrientationMayChange; + private ImmutableList preferredVideoMimeTypes; + // Audio + private ImmutableList preferredAudioLanguages; + @C.RoleFlags private int preferredAudioRoleFlags; + private int maxAudioChannelCount; + private int maxAudioBitrate; + private ImmutableList preferredAudioMimeTypes; + // Text + private ImmutableList preferredTextLanguages; + @C.RoleFlags private int preferredTextRoleFlags; + private boolean selectUndeterminedTextLanguage; + // General + private boolean forceLowestBitrate; + private boolean forceHighestSupportedBitrate; + + /** + * @deprecated {@link Context} constraints will not be set using this constructor. Use {@link + * #Builder(Context)} instead. + */ + @Deprecated + public Builder() { + // Video + maxVideoWidth = Integer.MAX_VALUE; + maxVideoHeight = Integer.MAX_VALUE; + maxVideoFrameRate = Integer.MAX_VALUE; + maxVideoBitrate = Integer.MAX_VALUE; + viewportWidth = Integer.MAX_VALUE; + viewportHeight = Integer.MAX_VALUE; + viewportOrientationMayChange = true; + preferredVideoMimeTypes = ImmutableList.of(); + // Audio + preferredAudioLanguages = ImmutableList.of(); + preferredAudioRoleFlags = 0; + maxAudioChannelCount = Integer.MAX_VALUE; + maxAudioBitrate = Integer.MAX_VALUE; + preferredAudioMimeTypes = ImmutableList.of(); + // Text + preferredTextLanguages = ImmutableList.of(); + preferredTextRoleFlags = 0; + selectUndeterminedTextLanguage = false; + // General + forceLowestBitrate = false; + forceHighestSupportedBitrate = false; + } + + /** + * Creates a builder with default initial values. + * + * @param context Any context. + */ + @SuppressWarnings({"deprecation", "method.invocation"}) // Methods invoked are setter only. + public Builder(Context context) { + this(); + setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettings(context); + setViewportSizeToPhysicalDisplaySize(context, /* viewportOrientationMayChange= */ true); + } + + /** + * @param initialValues The {@link TrackSelectionParameters} from which the initial values of + * the builder are obtained. + */ + protected Builder(TrackSelectionParameters initialValues) { + // Video + maxVideoWidth = initialValues.maxVideoWidth; + maxVideoHeight = initialValues.maxVideoHeight; + maxVideoFrameRate = initialValues.maxVideoFrameRate; + maxVideoBitrate = initialValues.maxVideoBitrate; + minVideoWidth = initialValues.minVideoWidth; + minVideoHeight = initialValues.minVideoHeight; + minVideoFrameRate = initialValues.minVideoFrameRate; + minVideoBitrate = initialValues.minVideoBitrate; + viewportWidth = initialValues.viewportWidth; + viewportHeight = initialValues.viewportHeight; + viewportOrientationMayChange = initialValues.viewportOrientationMayChange; + preferredVideoMimeTypes = initialValues.preferredVideoMimeTypes; + // Audio + preferredAudioLanguages = initialValues.preferredAudioLanguages; + preferredAudioRoleFlags = initialValues.preferredAudioRoleFlags; + maxAudioChannelCount = initialValues.maxAudioChannelCount; + maxAudioBitrate = initialValues.maxAudioBitrate; + preferredAudioMimeTypes = initialValues.preferredAudioMimeTypes; + // Text + preferredTextLanguages = initialValues.preferredTextLanguages; + preferredTextRoleFlags = initialValues.preferredTextRoleFlags; + selectUndeterminedTextLanguage = initialValues.selectUndeterminedTextLanguage; + // General + forceLowestBitrate = initialValues.forceLowestBitrate; + forceHighestSupportedBitrate = initialValues.forceHighestSupportedBitrate; + } + + // Video + + /** + * Equivalent to {@link #setMaxVideoSize setMaxVideoSize(1279, 719)}. + * + * @return This builder. + */ + public Builder setMaxVideoSizeSd() { + return setMaxVideoSize(1279, 719); + } + + /** + * Equivalent to {@link #setMaxVideoSize setMaxVideoSize(Integer.MAX_VALUE, Integer.MAX_VALUE)}. + * + * @return This builder. + */ + public Builder clearVideoSizeConstraints() { + return setMaxVideoSize(Integer.MAX_VALUE, Integer.MAX_VALUE); + } + + /** + * Sets the maximum allowed video width and height. + * + * @param maxVideoWidth Maximum allowed video width in pixels. + * @param maxVideoHeight Maximum allowed video height in pixels. + * @return This builder. + */ + public Builder setMaxVideoSize(int maxVideoWidth, int maxVideoHeight) { + this.maxVideoWidth = maxVideoWidth; + this.maxVideoHeight = maxVideoHeight; + return this; + } + + /** + * Sets the maximum allowed video frame rate. + * + * @param maxVideoFrameRate Maximum allowed video frame rate in hertz. + * @return This builder. + */ + public Builder setMaxVideoFrameRate(int maxVideoFrameRate) { + this.maxVideoFrameRate = maxVideoFrameRate; + return this; + } + + /** + * Sets the maximum allowed video bitrate. + * + * @param maxVideoBitrate Maximum allowed video bitrate in bits per second. + * @return This builder. + */ + public Builder setMaxVideoBitrate(int maxVideoBitrate) { + this.maxVideoBitrate = maxVideoBitrate; + return this; + } + + /** + * Sets the minimum allowed video width and height. + * + * @param minVideoWidth Minimum allowed video width in pixels. + * @param minVideoHeight Minimum allowed video height in pixels. + * @return This builder. + */ + public Builder setMinVideoSize(int minVideoWidth, int minVideoHeight) { + this.minVideoWidth = minVideoWidth; + this.minVideoHeight = minVideoHeight; + return this; + } + + /** + * Sets the minimum allowed video frame rate. + * + * @param minVideoFrameRate Minimum allowed video frame rate in hertz. + * @return This builder. + */ + public Builder setMinVideoFrameRate(int minVideoFrameRate) { + this.minVideoFrameRate = minVideoFrameRate; + return this; + } + + /** + * Sets the minimum allowed video bitrate. + * + * @param minVideoBitrate Minimum allowed video bitrate in bits per second. + * @return This builder. + */ + public Builder setMinVideoBitrate(int minVideoBitrate) { + this.minVideoBitrate = minVideoBitrate; + return this; + } + + /** + * Equivalent to calling {@link #setViewportSize(int, int, boolean)} with the viewport size + * obtained from {@link Util#getCurrentDisplayModeSize(Context)}. + * + * @param context Any context. + * @param viewportOrientationMayChange Whether the viewport orientation may change during + * playback. + * @return This builder. + */ + public Builder setViewportSizeToPhysicalDisplaySize( + Context context, boolean viewportOrientationMayChange) { + // Assume the viewport is fullscreen. + Point viewportSize = Util.getCurrentDisplayModeSize(context); + return setViewportSize(viewportSize.x, viewportSize.y, viewportOrientationMayChange); + } + + /** + * Equivalent to {@link #setViewportSize setViewportSize(Integer.MAX_VALUE, Integer.MAX_VALUE, + * true)}. + * + * @return This builder. + */ + public Builder clearViewportSizeConstraints() { + return setViewportSize(Integer.MAX_VALUE, Integer.MAX_VALUE, true); + } + + /** + * Sets the viewport size to constrain adaptive video selections so that only tracks suitable + * for the viewport are selected. + * + * @param viewportWidth Viewport width in pixels. + * @param viewportHeight Viewport height in pixels. + * @param viewportOrientationMayChange Whether the viewport orientation may change during + * playback. + * @return This builder. + */ + public Builder setViewportSize( + int viewportWidth, int viewportHeight, boolean viewportOrientationMayChange) { + this.viewportWidth = viewportWidth; + this.viewportHeight = viewportHeight; + this.viewportOrientationMayChange = viewportOrientationMayChange; + return this; + } + + /** + * Sets the preferred sample MIME type for video tracks. + * + * @param mimeType The preferred MIME type for video tracks, or {@code null} to clear a + * previously set preference. + * @return This builder. + */ + public Builder setPreferredVideoMimeType(@Nullable String mimeType) { + return mimeType == null ? setPreferredVideoMimeTypes() : setPreferredVideoMimeTypes(mimeType); + } + + /** + * Sets the preferred sample MIME types for video tracks. + * + * @param mimeTypes The preferred MIME types for video tracks in order of preference, or an + * empty list for no preference. + * @return This builder. + */ + public Builder setPreferredVideoMimeTypes(String... mimeTypes) { + preferredVideoMimeTypes = ImmutableList.copyOf(mimeTypes); + return this; + } + + // Audio + + /** + * Sets the preferred language for audio and forced text tracks. + * + * @param preferredAudioLanguage Preferred audio language as an IETF BCP 47 conformant tag, or + * {@code null} to select the default track, or the first track if there's no default. + * @return This builder. + */ + public Builder setPreferredAudioLanguage(@Nullable String preferredAudioLanguage) { + return preferredAudioLanguage == null + ? setPreferredAudioLanguages() + : setPreferredAudioLanguages(preferredAudioLanguage); + } + + /** + * Sets the preferred languages for audio and forced text tracks. + * + * @param preferredAudioLanguages Preferred audio languages as IETF BCP 47 conformant tags in + * order of preference, or an empty array to select the default track, or the first track if + * there's no default. + * @return This builder. + */ + public Builder setPreferredAudioLanguages(String... preferredAudioLanguages) { + ImmutableList.Builder listBuilder = ImmutableList.builder(); + for (String language : checkNotNull(preferredAudioLanguages)) { + listBuilder.add(Util.normalizeLanguageCode(checkNotNull(language))); + } + this.preferredAudioLanguages = listBuilder.build(); + return this; + } + + /** + * Sets the preferred {@link C.RoleFlags} for audio tracks. + * + * @param preferredAudioRoleFlags Preferred audio role flags. + * @return This builder. + */ + public Builder setPreferredAudioRoleFlags(@C.RoleFlags int preferredAudioRoleFlags) { + this.preferredAudioRoleFlags = preferredAudioRoleFlags; + return this; + } + + /** + * Sets the maximum allowed audio channel count. + * + * @param maxAudioChannelCount Maximum allowed audio channel count. + * @return This builder. + */ + public Builder setMaxAudioChannelCount(int maxAudioChannelCount) { + this.maxAudioChannelCount = maxAudioChannelCount; + return this; + } + + /** + * Sets the maximum allowed audio bitrate. + * + * @param maxAudioBitrate Maximum allowed audio bitrate in bits per second. + * @return This builder. + */ + public Builder setMaxAudioBitrate(int maxAudioBitrate) { + this.maxAudioBitrate = maxAudioBitrate; + return this; + } + + /** + * Sets the preferred sample MIME type for audio tracks. + * + * @param mimeType The preferred MIME type for audio tracks, or {@code null} to clear a + * previously set preference. + * @return This builder. + */ + public Builder setPreferredAudioMimeType(@Nullable String mimeType) { + return mimeType == null ? setPreferredAudioMimeTypes() : setPreferredAudioMimeTypes(mimeType); + } + + /** + * Sets the preferred sample MIME types for audio tracks. + * + * @param mimeTypes The preferred MIME types for audio tracks in order of preference, or an + * empty list for no preference. + * @return This builder. + */ + public Builder setPreferredAudioMimeTypes(String... mimeTypes) { + preferredAudioMimeTypes = ImmutableList.copyOf(mimeTypes); + return this; + } + + // Text + + /** + * Sets the preferred language and role flags for text tracks based on the accessibility + * settings of {@link CaptioningManager}. + * + *

Does nothing for API levels < 19 or when the {@link CaptioningManager} is disabled. + * + * @param context A {@link Context}. + * @return This builder. + */ + public Builder setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettings( + Context context) { + if (Util.SDK_INT >= 19) { + setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettingsV19(context); + } + return this; + } + + /** + * Sets the preferred language for text tracks. + * + * @param preferredTextLanguage Preferred text language as an IETF BCP 47 conformant tag, or + * {@code null} to select the default track if there is one, or no track otherwise. + * @return This builder. + */ + public Builder setPreferredTextLanguage(@Nullable String preferredTextLanguage) { + return preferredTextLanguage == null + ? setPreferredTextLanguages() + : setPreferredTextLanguages(preferredTextLanguage); + } + + /** + * Sets the preferred languages for text tracks. + * + * @param preferredTextLanguages Preferred text languages as IETF BCP 47 conformant tags in + * order of preference, or an empty array to select the default track if there is one, or no + * track otherwise. + * @return This builder. + */ + public Builder setPreferredTextLanguages(String... preferredTextLanguages) { + ImmutableList.Builder listBuilder = ImmutableList.builder(); + for (String language : checkNotNull(preferredTextLanguages)) { + listBuilder.add(Util.normalizeLanguageCode(checkNotNull(language))); + } + this.preferredTextLanguages = listBuilder.build(); + return this; + } + + /** + * Sets the preferred {@link C.RoleFlags} for text tracks. + * + * @param preferredTextRoleFlags Preferred text role flags. + * @return This builder. + */ + public Builder setPreferredTextRoleFlags(@C.RoleFlags int preferredTextRoleFlags) { + this.preferredTextRoleFlags = preferredTextRoleFlags; + return this; + } + + /** + * Sets whether a text track with undetermined language should be selected if no track with + * {@link #setPreferredTextLanguages(String...) a preferred language} is available, or if the + * preferred language is unset. + * + * @param selectUndeterminedTextLanguage Whether a text track with undetermined language should + * be selected if no preferred language track is available. + * @return This builder. + */ + public Builder setSelectUndeterminedTextLanguage(boolean selectUndeterminedTextLanguage) { + this.selectUndeterminedTextLanguage = selectUndeterminedTextLanguage; + return this; + } + + // General + + /** + * Sets whether to force selection of the single lowest bitrate audio and video tracks that + * comply with all other constraints. + * + * @param forceLowestBitrate Whether to force selection of the single lowest bitrate audio and + * video tracks. + * @return This builder. + */ + public Builder setForceLowestBitrate(boolean forceLowestBitrate) { + this.forceLowestBitrate = forceLowestBitrate; + return this; + } + + /** + * Sets whether to force selection of the highest bitrate audio and video tracks that comply + * with all other constraints. + * + * @param forceHighestSupportedBitrate Whether to force selection of the highest bitrate audio + * and video tracks. + * @return This builder. + */ + public Builder setForceHighestSupportedBitrate(boolean forceHighestSupportedBitrate) { + this.forceHighestSupportedBitrate = forceHighestSupportedBitrate; + return this; + } + + /** Builds a {@link TrackSelectionParameters} instance with the selected values. */ + public TrackSelectionParameters build() { + return new TrackSelectionParameters(this); + } + + @RequiresApi(19) + private void setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettingsV19( + Context context) { + if (Util.SDK_INT < 23 && Looper.myLooper() == null) { + // Android platform bug (pre-Marshmallow) that causes RuntimeExceptions when + // CaptioningService is instantiated from a non-Looper thread. See [internal: b/143779904]. + return; + } + CaptioningManager captioningManager = + (CaptioningManager) context.getSystemService(Context.CAPTIONING_SERVICE); + if (captioningManager == null || !captioningManager.isEnabled()) { + return; + } + preferredTextRoleFlags = C.ROLE_FLAG_CAPTION | C.ROLE_FLAG_DESCRIBES_MUSIC_AND_SOUND; + Locale preferredLocale = captioningManager.getLocale(); + if (preferredLocale != null) { + preferredTextLanguages = ImmutableList.of(Util.getLocaleLanguageTag(preferredLocale)); + } + } + } + + /** + * An instance with default values, except those obtained from the {@link Context}. + * + *

If possible, use {@link #getDefaults(Context)} instead. + * + *

This instance will not have the following settings: + * + *

    + *
  • {@link Builder#setViewportSizeToPhysicalDisplaySize(Context, boolean) Viewport + * constraints} configured for the primary display. + *
  • {@link Builder#setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettings(Context) + * Preferred text language and role flags} configured to the accessibility settings of + * {@link CaptioningManager}. + *
+ */ + @SuppressWarnings("deprecation") + public static final TrackSelectionParameters DEFAULT_WITHOUT_CONTEXT = new Builder().build(); + /** + * @deprecated This instance is not configured using {@link Context} constraints. Use {@link + * #getDefaults(Context)} instead. + */ + @Deprecated public static final TrackSelectionParameters DEFAULT = DEFAULT_WITHOUT_CONTEXT; + + public static final Creator CREATOR = + new Creator() { + + @Override + public TrackSelectionParameters createFromParcel(Parcel in) { + return new TrackSelectionParameters(in); + } + + @Override + public TrackSelectionParameters[] newArray(int size) { + return new TrackSelectionParameters[size]; + } + }; + + /** Returns an instance configured with default values. */ + public static TrackSelectionParameters getDefaults(Context context) { + return new Builder(context).build(); + } + + // Video + /** + * Maximum allowed video width in pixels. The default value is {@link Integer#MAX_VALUE} (i.e. no + * constraint). + * + *

To constrain adaptive video track selections to be suitable for a given viewport (the region + * of the display within which video will be played), use ({@link #viewportWidth}, {@link + * #viewportHeight} and {@link #viewportOrientationMayChange}) instead. + */ + public final int maxVideoWidth; + /** + * Maximum allowed video height in pixels. The default value is {@link Integer#MAX_VALUE} (i.e. no + * constraint). + * + *

To constrain adaptive video track selections to be suitable for a given viewport (the region + * of the display within which video will be played), use ({@link #viewportWidth}, {@link + * #viewportHeight} and {@link #viewportOrientationMayChange}) instead. + */ + public final int maxVideoHeight; + /** + * Maximum allowed video frame rate in hertz. The default value is {@link Integer#MAX_VALUE} (i.e. + * no constraint). + */ + public final int maxVideoFrameRate; + /** + * Maximum allowed video bitrate in bits per second. The default value is {@link + * Integer#MAX_VALUE} (i.e. no constraint). + */ + public final int maxVideoBitrate; + /** Minimum allowed video width in pixels. The default value is 0 (i.e. no constraint). */ + public final int minVideoWidth; + /** Minimum allowed video height in pixels. The default value is 0 (i.e. no constraint). */ + public final int minVideoHeight; + /** Minimum allowed video frame rate in hertz. The default value is 0 (i.e. no constraint). */ + public final int minVideoFrameRate; + /** + * Minimum allowed video bitrate in bits per second. The default value is 0 (i.e. no constraint). + */ + public final int minVideoBitrate; + /** + * Viewport width in pixels. Constrains video track selections for adaptive content so that only + * tracks suitable for the viewport are selected. The default value is the physical width of the + * primary display, in pixels. + */ + public final int viewportWidth; + /** + * Viewport height in pixels. Constrains video track selections for adaptive content so that only + * tracks suitable for the viewport are selected. The default value is the physical height of the + * primary display, in pixels. + */ + public final int viewportHeight; + /** + * Whether the viewport orientation may change during playback. Constrains video track selections + * for adaptive content so that only tracks suitable for the viewport are selected. The default + * value is {@code true}. + */ + public final boolean viewportOrientationMayChange; + /** + * The preferred sample MIME types for video tracks in order of preference, or an empty list for + * no preference. The default is an empty list. + */ + public final ImmutableList preferredVideoMimeTypes; + // Audio + /** + * The preferred languages for audio and forced text tracks as IETF BCP 47 conformant tags in + * order of preference. An empty list selects the default track, or the first track if there's no + * default. The default value is an empty list. + */ + public final ImmutableList preferredAudioLanguages; + /** + * The preferred {@link C.RoleFlags} for audio tracks. {@code 0} selects the default track if + * there is one, or the first track if there's no default. The default value is {@code 0}. + */ + @C.RoleFlags public final int preferredAudioRoleFlags; + /** + * Maximum allowed audio channel count. The default value is {@link Integer#MAX_VALUE} (i.e. no + * constraint). + */ + public final int maxAudioChannelCount; + /** + * Maximum allowed audio bitrate in bits per second. The default value is {@link + * Integer#MAX_VALUE} (i.e. no constraint). + */ + public final int maxAudioBitrate; + /** + * The preferred sample MIME types for audio tracks in order of preference, or an empty list for + * no preference. The default is an empty list. + */ + public final ImmutableList preferredAudioMimeTypes; + // Text + /** + * The preferred languages for text tracks as IETF BCP 47 conformant tags in order of preference. + * An empty list selects the default track if there is one, or no track otherwise. The default + * value is an empty list, or the language of the accessibility {@link CaptioningManager} if + * enabled. + */ + public final ImmutableList preferredTextLanguages; + /** + * The preferred {@link C.RoleFlags} for text tracks. {@code 0} selects the default track if there + * is one, or no track otherwise. The default value is {@code 0}, or {@link C#ROLE_FLAG_SUBTITLE} + * | {@link C#ROLE_FLAG_DESCRIBES_MUSIC_AND_SOUND} if the accessibility {@link CaptioningManager} + * is enabled. + */ + @C.RoleFlags public final int preferredTextRoleFlags; + /** + * Whether a text track with undetermined language should be selected if no track with {@link + * #preferredTextLanguages} is available, or if {@link #preferredTextLanguages} is unset. The + * default value is {@code false}. + */ + public final boolean selectUndeterminedTextLanguage; + // General + /** + * Whether to force selection of the single lowest bitrate audio and video tracks that comply with + * all other constraints. The default value is {@code false}. + */ + public final boolean forceLowestBitrate; + /** + * Whether to force selection of the highest bitrate audio and video tracks that comply with all + * other constraints. The default value is {@code false}. + */ + public final boolean forceHighestSupportedBitrate; + + protected TrackSelectionParameters(Builder builder) { + // Video + this.maxVideoWidth = builder.maxVideoWidth; + this.maxVideoHeight = builder.maxVideoHeight; + this.maxVideoFrameRate = builder.maxVideoFrameRate; + this.maxVideoBitrate = builder.maxVideoBitrate; + this.minVideoWidth = builder.minVideoWidth; + this.minVideoHeight = builder.minVideoHeight; + this.minVideoFrameRate = builder.minVideoFrameRate; + this.minVideoBitrate = builder.minVideoBitrate; + this.viewportWidth = builder.viewportWidth; + this.viewportHeight = builder.viewportHeight; + this.viewportOrientationMayChange = builder.viewportOrientationMayChange; + this.preferredVideoMimeTypes = builder.preferredVideoMimeTypes; + // Audio + this.preferredAudioLanguages = builder.preferredAudioLanguages; + this.preferredAudioRoleFlags = builder.preferredAudioRoleFlags; + this.maxAudioChannelCount = builder.maxAudioChannelCount; + this.maxAudioBitrate = builder.maxAudioBitrate; + this.preferredAudioMimeTypes = builder.preferredAudioMimeTypes; + // Text + this.preferredTextLanguages = builder.preferredTextLanguages; + this.preferredTextRoleFlags = builder.preferredTextRoleFlags; + this.selectUndeterminedTextLanguage = builder.selectUndeterminedTextLanguage; + // General + this.forceLowestBitrate = builder.forceLowestBitrate; + this.forceHighestSupportedBitrate = builder.forceHighestSupportedBitrate; + } + + /* package */ TrackSelectionParameters(Parcel in) { + ArrayList preferredAudioLanguages = new ArrayList<>(); + in.readList(preferredAudioLanguages, /* loader= */ null); + this.preferredAudioLanguages = ImmutableList.copyOf(preferredAudioLanguages); + this.preferredAudioRoleFlags = in.readInt(); + ArrayList preferredTextLanguages1 = new ArrayList<>(); + in.readList(preferredTextLanguages1, /* loader= */ null); + this.preferredTextLanguages = ImmutableList.copyOf(preferredTextLanguages1); + this.preferredTextRoleFlags = in.readInt(); + this.selectUndeterminedTextLanguage = Util.readBoolean(in); + // Video + this.maxVideoWidth = in.readInt(); + this.maxVideoHeight = in.readInt(); + this.maxVideoFrameRate = in.readInt(); + this.maxVideoBitrate = in.readInt(); + this.minVideoWidth = in.readInt(); + this.minVideoHeight = in.readInt(); + this.minVideoFrameRate = in.readInt(); + this.minVideoBitrate = in.readInt(); + this.viewportWidth = in.readInt(); + this.viewportHeight = in.readInt(); + this.viewportOrientationMayChange = Util.readBoolean(in); + ArrayList preferredVideoMimeTypes = new ArrayList<>(); + in.readList(preferredVideoMimeTypes, /* loader= */ null); + this.preferredVideoMimeTypes = ImmutableList.copyOf(preferredVideoMimeTypes); + // Audio + this.maxAudioChannelCount = in.readInt(); + this.maxAudioBitrate = in.readInt(); + ArrayList preferredAudioMimeTypes = new ArrayList<>(); + in.readList(preferredAudioMimeTypes, /* loader= */ null); + this.preferredAudioMimeTypes = ImmutableList.copyOf(preferredAudioMimeTypes); + // General + this.forceLowestBitrate = Util.readBoolean(in); + this.forceHighestSupportedBitrate = Util.readBoolean(in); + } + + /** Creates a new {@link Builder}, copying the initial values from this instance. */ + public Builder buildUpon() { + return new Builder(this); + } + + @Override + @SuppressWarnings("EqualsGetClass") + public boolean equals(@Nullable Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + TrackSelectionParameters other = (TrackSelectionParameters) obj; + // Video + return maxVideoWidth == other.maxVideoWidth + && maxVideoHeight == other.maxVideoHeight + && maxVideoFrameRate == other.maxVideoFrameRate + && maxVideoBitrate == other.maxVideoBitrate + && minVideoWidth == other.minVideoWidth + && minVideoHeight == other.minVideoHeight + && minVideoFrameRate == other.minVideoFrameRate + && minVideoBitrate == other.minVideoBitrate + && viewportOrientationMayChange == other.viewportOrientationMayChange + && viewportWidth == other.viewportWidth + && viewportHeight == other.viewportHeight + && preferredVideoMimeTypes.equals(other.preferredVideoMimeTypes) + // Audio + && preferredAudioLanguages.equals(other.preferredAudioLanguages) + && preferredAudioRoleFlags == other.preferredAudioRoleFlags + && maxAudioChannelCount == other.maxAudioChannelCount + && maxAudioBitrate == other.maxAudioBitrate + && preferredAudioMimeTypes.equals(other.preferredAudioMimeTypes) + && preferredTextLanguages.equals(other.preferredTextLanguages) + && preferredTextRoleFlags == other.preferredTextRoleFlags + && selectUndeterminedTextLanguage == other.selectUndeterminedTextLanguage + // General + && forceLowestBitrate == other.forceLowestBitrate + && forceHighestSupportedBitrate == other.forceHighestSupportedBitrate; + } + + @Override + public int hashCode() { + int result = 1; + // Video + result = 31 * result + maxVideoWidth; + result = 31 * result + maxVideoHeight; + result = 31 * result + maxVideoFrameRate; + result = 31 * result + maxVideoBitrate; + result = 31 * result + minVideoWidth; + result = 31 * result + minVideoHeight; + result = 31 * result + minVideoFrameRate; + result = 31 * result + minVideoBitrate; + result = 31 * result + (viewportOrientationMayChange ? 1 : 0); + result = 31 * result + viewportWidth; + result = 31 * result + viewportHeight; + result = 31 * result + preferredVideoMimeTypes.hashCode(); + // Audio + result = 31 * result + preferredAudioLanguages.hashCode(); + result = 31 * result + preferredAudioRoleFlags; + result = 31 * result + maxAudioChannelCount; + result = 31 * result + maxAudioBitrate; + result = 31 * result + preferredAudioMimeTypes.hashCode(); + // Text + result = 31 * result + preferredTextLanguages.hashCode(); + result = 31 * result + preferredTextRoleFlags; + result = 31 * result + (selectUndeterminedTextLanguage ? 1 : 0); + // General + result = 31 * result + (forceLowestBitrate ? 1 : 0); + result = 31 * result + (forceHighestSupportedBitrate ? 1 : 0); + return result; + } + + // Parcelable implementation. + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeList(preferredAudioLanguages); + dest.writeInt(preferredAudioRoleFlags); + dest.writeList(preferredTextLanguages); + dest.writeInt(preferredTextRoleFlags); + Util.writeBoolean(dest, selectUndeterminedTextLanguage); + // Video + dest.writeInt(maxVideoWidth); + dest.writeInt(maxVideoHeight); + dest.writeInt(maxVideoFrameRate); + dest.writeInt(maxVideoBitrate); + dest.writeInt(minVideoWidth); + dest.writeInt(minVideoHeight); + dest.writeInt(minVideoFrameRate); + dest.writeInt(minVideoBitrate); + dest.writeInt(viewportWidth); + dest.writeInt(viewportHeight); + Util.writeBoolean(dest, viewportOrientationMayChange); + dest.writeList(preferredVideoMimeTypes); + // Audio + dest.writeInt(maxAudioChannelCount); + dest.writeInt(maxAudioBitrate); + dest.writeList(preferredAudioMimeTypes); + // General + Util.writeBoolean(dest, forceLowestBitrate); + Util.writeBoolean(dest, forceHighestSupportedBitrate); + } +} 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 new file mode 100644 index 0000000000..69743bb609 --- /dev/null +++ b/library/common/src/test/java/com/google/android/exoplayer2/trackselection/TrackSelectionParametersTest.java @@ -0,0 +1,163 @@ +/* + * 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 androidx.test.core.app.ApplicationProvider.getApplicationContext; +import static com.google.common.truth.Truth.assertThat; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.util.MimeTypes; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** Tests for {@link TrackSelectionParameters}. */ +@RunWith(AndroidJUnit4.class) +public class TrackSelectionParametersTest { + + @Test + public void defaultValue_withoutChange_isAsExpected() { + TrackSelectionParameters parameters = TrackSelectionParameters.DEFAULT_WITHOUT_CONTEXT; + + // Video + assertThat(parameters.maxVideoWidth).isEqualTo(Integer.MAX_VALUE); + assertThat(parameters.maxVideoHeight).isEqualTo(Integer.MAX_VALUE); + assertThat(parameters.maxVideoFrameRate).isEqualTo(Integer.MAX_VALUE); + assertThat(parameters.maxVideoBitrate).isEqualTo(Integer.MAX_VALUE); + assertThat(parameters.minVideoWidth).isEqualTo(0); + assertThat(parameters.minVideoHeight).isEqualTo(0); + assertThat(parameters.minVideoFrameRate).isEqualTo(0); + assertThat(parameters.minVideoBitrate).isEqualTo(0); + assertThat(parameters.viewportWidth).isEqualTo(Integer.MAX_VALUE); + assertThat(parameters.viewportHeight).isEqualTo(Integer.MAX_VALUE); + assertThat(parameters.viewportOrientationMayChange).isTrue(); + assertThat(parameters.preferredVideoMimeTypes).isEmpty(); + // Audio + assertThat(parameters.preferredAudioLanguages).isEmpty(); + assertThat(parameters.preferredAudioRoleFlags).isEqualTo(0); + assertThat(parameters.maxAudioChannelCount).isEqualTo(Integer.MAX_VALUE); + assertThat(parameters.maxAudioBitrate).isEqualTo(Integer.MAX_VALUE); + // Text + assertThat(parameters.preferredAudioMimeTypes).isEmpty(); + assertThat(parameters.preferredTextLanguages).isEmpty(); + assertThat(parameters.preferredTextRoleFlags).isEqualTo(0); + assertThat(parameters.selectUndeterminedTextLanguage).isFalse(); + // General + assertThat(parameters.forceLowestBitrate).isFalse(); + assertThat(parameters.forceHighestSupportedBitrate).isFalse(); + } + + @Test + public void parametersSet_fromDefault_isAsExpected() { + TrackSelectionParameters parameters = + TrackSelectionParameters.DEFAULT_WITHOUT_CONTEXT + .buildUpon() + // Video + .setMaxVideoSize(/* maxVideoWidth= */ 0, /* maxVideoHeight= */ 1) + .setMaxVideoFrameRate(2) + .setMaxVideoBitrate(3) + .setMinVideoSize(/* minVideoWidth= */ 4, /* minVideoHeight= */ 5) + .setMinVideoFrameRate(6) + .setMinVideoBitrate(7) + .setViewportSize( + /* viewportWidth= */ 8, + /* viewportHeight= */ 9, + /* viewportOrientationMayChange= */ true) + .setPreferredVideoMimeTypes(MimeTypes.VIDEO_AV1, MimeTypes.VIDEO_H264) + // Audio + .setPreferredAudioLanguages("zh", "jp") + .setPreferredAudioRoleFlags(C.ROLE_FLAG_COMMENTARY) + .setMaxAudioChannelCount(10) + .setMaxAudioBitrate(11) + .setPreferredAudioMimeTypes(MimeTypes.AUDIO_AC3, MimeTypes.AUDIO_E_AC3) + // Text + .setPreferredTextLanguages("de", "en") + .setPreferredTextRoleFlags(C.ROLE_FLAG_CAPTION) + .setSelectUndeterminedTextLanguage(true) + // General + .setForceLowestBitrate(false) + .setForceHighestSupportedBitrate(true) + .build(); + + // Video + assertThat(parameters.maxVideoWidth).isEqualTo(0); + assertThat(parameters.maxVideoHeight).isEqualTo(1); + assertThat(parameters.maxVideoFrameRate).isEqualTo(2); + assertThat(parameters.maxVideoBitrate).isEqualTo(3); + assertThat(parameters.minVideoWidth).isEqualTo(4); + assertThat(parameters.minVideoHeight).isEqualTo(5); + assertThat(parameters.minVideoFrameRate).isEqualTo(6); + assertThat(parameters.minVideoBitrate).isEqualTo(7); + assertThat(parameters.viewportWidth).isEqualTo(8); + assertThat(parameters.viewportHeight).isEqualTo(9); + assertThat(parameters.viewportOrientationMayChange).isTrue(); + assertThat(parameters.preferredVideoMimeTypes) + .containsExactly(MimeTypes.VIDEO_AV1, MimeTypes.VIDEO_H264) + .inOrder(); + // Audio + assertThat(parameters.preferredAudioLanguages).containsExactly("zh", "jp").inOrder(); + assertThat(parameters.preferredAudioRoleFlags).isEqualTo(C.ROLE_FLAG_COMMENTARY); + assertThat(parameters.maxAudioChannelCount).isEqualTo(10); + assertThat(parameters.maxAudioBitrate).isEqualTo(11); + assertThat(parameters.preferredAudioMimeTypes) + .containsExactly(MimeTypes.AUDIO_AC3, MimeTypes.AUDIO_E_AC3) + .inOrder(); + // Text + assertThat(parameters.preferredTextLanguages).containsExactly("de", "en").inOrder(); + assertThat(parameters.preferredTextRoleFlags).isEqualTo(C.ROLE_FLAG_CAPTION); + assertThat(parameters.selectUndeterminedTextLanguage).isTrue(); + // General + assertThat(parameters.forceLowestBitrate).isFalse(); + assertThat(parameters.forceHighestSupportedBitrate).isTrue(); + } + + @Test + public void setMaxVideoSizeSd_defaultBuilder_parametersVideoSizeAreSd() { + TrackSelectionParameters parameters = + new TrackSelectionParameters.Builder(getApplicationContext()).setMaxVideoSizeSd().build(); + + assertThat(parameters.maxVideoWidth).isEqualTo(1279); + assertThat(parameters.maxVideoHeight).isEqualTo(719); + } + + @Test + public void clearVideoSizeConstraints_withSdConstrains_clearConstrains() { + TrackSelectionParameters parameters = + new TrackSelectionParameters.Builder(getApplicationContext()) + .setMaxVideoSizeSd() + .clearVideoSizeConstraints() + .build(); + + assertThat(parameters.maxVideoWidth).isEqualTo(Integer.MAX_VALUE); + assertThat(parameters.maxVideoHeight).isEqualTo(Integer.MAX_VALUE); + } + + @Test + public void clearViewPortConstraints_withConstrains_clearConstrains() { + TrackSelectionParameters parameters = + new TrackSelectionParameters.Builder(getApplicationContext()) + .setViewportSize( + /*viewportWidth=*/ 1, + /*viewportHeight=*/ 2, + /*viewportOrientationMayChange=*/ false) + .clearViewportSizeConstraints() + .build(); + + assertThat(parameters.viewportWidth).isEqualTo(Integer.MAX_VALUE); + assertThat(parameters.viewportHeight).isEqualTo(Integer.MAX_VALUE); + assertThat(parameters.viewportOrientationMayChange).isTrue(); + } +} 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 e2858b79c3..91c4a79d3a 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 @@ -51,9 +51,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; -import org.checkerframework.checker.initialization.qual.UnderInitialization; import org.checkerframework.checker.nullness.compatqual.NullableType; -import org.checkerframework.checker.nullness.qual.EnsuresNonNull; /** * A default {@link TrackSelector} suitable for most use cases. Track selections are made according @@ -170,32 +168,17 @@ public class DefaultTrackSelector extends MappingTrackSelector { public static final class ParametersBuilder extends TrackSelectionParameters.Builder { // Video - private int maxVideoWidth; - private int maxVideoHeight; - private int maxVideoFrameRate; - private int maxVideoBitrate; - private int minVideoWidth; - private int minVideoHeight; - private int minVideoFrameRate; - private int minVideoBitrate; private boolean exceedVideoConstraintsIfNecessary; private boolean allowVideoMixedMimeTypeAdaptiveness; private boolean allowVideoNonSeamlessAdaptiveness; - private int viewportWidth; - private int viewportHeight; - private boolean viewportOrientationMayChange; - private ImmutableList preferredVideoMimeTypes; // Audio - private int maxAudioChannelCount; - private int maxAudioBitrate; private boolean exceedAudioConstraintsIfNecessary; private boolean allowAudioMixedMimeTypeAdaptiveness; private boolean allowAudioMixedSampleRateAdaptiveness; private boolean allowAudioMixedChannelCountAdaptiveness; - private ImmutableList preferredAudioMimeTypes; + // Text + @C.SelectionFlags private int disabledTextTrackSelectionFlags; // General - private boolean forceLowestBitrate; - private boolean forceHighestSupportedBitrate; private boolean exceedRendererCapabilitiesIfNecessary; private boolean tunnelingEnabled; private boolean allowMultipleAdaptiveSelections; @@ -212,9 +195,9 @@ public class DefaultTrackSelector extends MappingTrackSelector { @SuppressWarnings({"deprecation"}) public ParametersBuilder() { super(); - setInitialValuesWithoutContext(); selectionOverrides = new SparseArray<>(); rendererDisabledFlags = new SparseBooleanArray(); + init(); } /** @@ -224,10 +207,9 @@ public class DefaultTrackSelector extends MappingTrackSelector { */ public ParametersBuilder(Context context) { super(context); - setInitialValuesWithoutContext(); selectionOverrides = new SparseArray<>(); rendererDisabledFlags = new SparseBooleanArray(); - setViewportSizeToPhysicalDisplaySize(context, /* viewportOrientationMayChange= */ true); + init(); } /** @@ -236,34 +218,19 @@ public class DefaultTrackSelector extends MappingTrackSelector { */ private ParametersBuilder(Parameters initialValues) { super(initialValues); + // Text + disabledTextTrackSelectionFlags = initialValues.disabledTextTrackSelectionFlags; // Video - maxVideoWidth = initialValues.maxVideoWidth; - maxVideoHeight = initialValues.maxVideoHeight; - maxVideoFrameRate = initialValues.maxVideoFrameRate; - maxVideoBitrate = initialValues.maxVideoBitrate; - minVideoWidth = initialValues.minVideoWidth; - minVideoHeight = initialValues.minVideoHeight; - minVideoFrameRate = initialValues.minVideoFrameRate; - minVideoBitrate = initialValues.minVideoBitrate; exceedVideoConstraintsIfNecessary = initialValues.exceedVideoConstraintsIfNecessary; allowVideoMixedMimeTypeAdaptiveness = initialValues.allowVideoMixedMimeTypeAdaptiveness; allowVideoNonSeamlessAdaptiveness = initialValues.allowVideoNonSeamlessAdaptiveness; - viewportWidth = initialValues.viewportWidth; - viewportHeight = initialValues.viewportHeight; - viewportOrientationMayChange = initialValues.viewportOrientationMayChange; - preferredVideoMimeTypes = initialValues.preferredVideoMimeTypes; // Audio - maxAudioChannelCount = initialValues.maxAudioChannelCount; - maxAudioBitrate = initialValues.maxAudioBitrate; exceedAudioConstraintsIfNecessary = initialValues.exceedAudioConstraintsIfNecessary; allowAudioMixedMimeTypeAdaptiveness = initialValues.allowAudioMixedMimeTypeAdaptiveness; allowAudioMixedSampleRateAdaptiveness = initialValues.allowAudioMixedSampleRateAdaptiveness; allowAudioMixedChannelCountAdaptiveness = initialValues.allowAudioMixedChannelCountAdaptiveness; - preferredAudioMimeTypes = initialValues.preferredAudioMimeTypes; // General - forceLowestBitrate = initialValues.forceLowestBitrate; - forceHighestSupportedBitrate = initialValues.forceHighestSupportedBitrate; exceedRendererCapabilitiesIfNecessary = initialValues.exceedRendererCapabilitiesIfNecessary; tunnelingEnabled = initialValues.tunnelingEnabled; allowMultipleAdaptiveSelections = initialValues.allowMultipleAdaptiveSelections; @@ -274,91 +241,53 @@ public class DefaultTrackSelector extends MappingTrackSelector { // Video - /** - * Equivalent to {@link #setMaxVideoSize setMaxVideoSize(1279, 719)}. - * - * @return This builder. - */ - public ParametersBuilder setMaxVideoSizeSd() { - return setMaxVideoSize(1279, 719); - } - - /** - * Equivalent to {@link #setMaxVideoSize setMaxVideoSize(Integer.MAX_VALUE, Integer.MAX_VALUE)}. - * - * @return This builder. - */ - public ParametersBuilder clearVideoSizeConstraints() { - return setMaxVideoSize(Integer.MAX_VALUE, Integer.MAX_VALUE); - } - - /** - * Sets the maximum allowed video width and height. - * - * @param maxVideoWidth Maximum allowed video width in pixels. - * @param maxVideoHeight Maximum allowed video height in pixels. - * @return This builder. - */ - public ParametersBuilder setMaxVideoSize(int maxVideoWidth, int maxVideoHeight) { - this.maxVideoWidth = maxVideoWidth; - this.maxVideoHeight = maxVideoHeight; + @Override + public DefaultTrackSelector.ParametersBuilder setMaxVideoSizeSd() { + super.setMaxVideoSizeSd(); return this; } - /** - * Sets the maximum allowed video frame rate. - * - * @param maxVideoFrameRate Maximum allowed video frame rate in hertz. - * @return This builder. - */ - public ParametersBuilder setMaxVideoFrameRate(int maxVideoFrameRate) { - this.maxVideoFrameRate = maxVideoFrameRate; + @Override + public DefaultTrackSelector.ParametersBuilder clearVideoSizeConstraints() { + super.clearVideoSizeConstraints(); return this; } - /** - * Sets the maximum allowed video bitrate. - * - * @param maxVideoBitrate Maximum allowed video bitrate in bits per second. - * @return This builder. - */ - public ParametersBuilder setMaxVideoBitrate(int maxVideoBitrate) { - this.maxVideoBitrate = maxVideoBitrate; + @Override + public DefaultTrackSelector.ParametersBuilder setMaxVideoSize( + int maxVideoWidth, int maxVideoHeight) { + super.setMaxVideoSize(maxVideoWidth, maxVideoHeight); return this; } - /** - * Sets the minimum allowed video width and height. - * - * @param minVideoWidth Minimum allowed video width in pixels. - * @param minVideoHeight Minimum allowed video height in pixels. - * @return This builder. - */ - public ParametersBuilder setMinVideoSize(int minVideoWidth, int minVideoHeight) { - this.minVideoWidth = minVideoWidth; - this.minVideoHeight = minVideoHeight; + @Override + public DefaultTrackSelector.ParametersBuilder setMaxVideoFrameRate(int maxVideoFrameRate) { + super.setMaxVideoFrameRate(maxVideoFrameRate); return this; } - /** - * Sets the minimum allowed video frame rate. - * - * @param minVideoFrameRate Minimum allowed video frame rate in hertz. - * @return This builder. - */ - public ParametersBuilder setMinVideoFrameRate(int minVideoFrameRate) { - this.minVideoFrameRate = minVideoFrameRate; + @Override + public DefaultTrackSelector.ParametersBuilder setMaxVideoBitrate(int maxVideoBitrate) { + super.setMaxVideoBitrate(maxVideoBitrate); return this; } - /** - * Sets the minimum allowed video bitrate. - * - * @param minVideoBitrate Minimum allowed video bitrate in bits per second. - * @return This builder. - */ - public ParametersBuilder setMinVideoBitrate(int minVideoBitrate) { - this.minVideoBitrate = minVideoBitrate; + @Override + public DefaultTrackSelector.ParametersBuilder setMinVideoSize( + int minVideoWidth, int minVideoHeight) { + super.setMinVideoSize(minVideoWidth, minVideoHeight); + return this; + } + + @Override + public DefaultTrackSelector.ParametersBuilder setMinVideoFrameRate(int minVideoFrameRate) { + super.setMinVideoFrameRate(minVideoFrameRate); + return this; + } + + @Override + public DefaultTrackSelector.ParametersBuilder setMinVideoBitrate(int minVideoBitrate) { + super.setMinVideoBitrate(minVideoBitrate); return this; } @@ -407,70 +336,35 @@ public class DefaultTrackSelector extends MappingTrackSelector { return this; } - /** - * Equivalent to calling {@link #setViewportSize(int, int, boolean)} with the viewport size - * obtained from {@link Util#getCurrentDisplayModeSize(Context)}. - * - * @param context Any context. - * @param viewportOrientationMayChange Whether the viewport orientation may change during - * playback. - * @return This builder. - */ + @Override public ParametersBuilder setViewportSizeToPhysicalDisplaySize( Context context, boolean viewportOrientationMayChange) { - // Assume the viewport is fullscreen. - Point viewportSize = Util.getCurrentDisplayModeSize(context); - return setViewportSize(viewportSize.x, viewportSize.y, viewportOrientationMayChange); - } - - /** - * Equivalent to {@link #setViewportSize setViewportSize(Integer.MAX_VALUE, Integer.MAX_VALUE, - * true)}. - * - * @return This builder. - */ - public ParametersBuilder clearViewportSizeConstraints() { - return setViewportSize(Integer.MAX_VALUE, Integer.MAX_VALUE, true); - } - - /** - * Sets the viewport size to constrain adaptive video selections so that only tracks suitable - * for the viewport are selected. - * - * @param viewportWidth Viewport width in pixels. - * @param viewportHeight Viewport height in pixels. - * @param viewportOrientationMayChange Whether the viewport orientation may change during - * playback. - * @return This builder. - */ - public ParametersBuilder setViewportSize( - int viewportWidth, int viewportHeight, boolean viewportOrientationMayChange) { - this.viewportWidth = viewportWidth; - this.viewportHeight = viewportHeight; - this.viewportOrientationMayChange = viewportOrientationMayChange; + super.setViewportSizeToPhysicalDisplaySize(context, viewportOrientationMayChange); return this; } - /** - * Sets the preferred sample MIME type for video tracks. - * - * @param mimeType The preferred MIME type for video tracks, or {@code null} to clear a - * previously set preference. - * @return This builder. - */ - public ParametersBuilder setPreferredVideoMimeType(@Nullable String mimeType) { - return mimeType == null ? setPreferredVideoMimeTypes() : setPreferredVideoMimeTypes(mimeType); + @Override + public ParametersBuilder clearViewportSizeConstraints() { + super.clearViewportSizeConstraints(); + return this; } - /** - * Sets the preferred sample MIME types for video tracks. - * - * @param mimeTypes The preferred MIME types for video tracks in order of preference, or an - * empty list for no preference. - * @return This builder. - */ + @Override + public ParametersBuilder setViewportSize( + int viewportWidth, int viewportHeight, boolean viewportOrientationMayChange) { + super.setViewportSize(viewportWidth, viewportHeight, viewportOrientationMayChange); + return this; + } + + @Override + public ParametersBuilder setPreferredVideoMimeType(@Nullable String mimeType) { + super.setPreferredVideoMimeType(mimeType); + return this; + } + + @Override public ParametersBuilder setPreferredVideoMimeTypes(String... mimeTypes) { - preferredVideoMimeTypes = ImmutableList.copyOf(mimeTypes); + super.setPreferredVideoMimeTypes(mimeTypes); return this; } @@ -494,25 +388,15 @@ public class DefaultTrackSelector extends MappingTrackSelector { return this; } - /** - * Sets the maximum allowed audio channel count. - * - * @param maxAudioChannelCount Maximum allowed audio channel count. - * @return This builder. - */ + @Override public ParametersBuilder setMaxAudioChannelCount(int maxAudioChannelCount) { - this.maxAudioChannelCount = maxAudioChannelCount; + super.setMaxAudioChannelCount(maxAudioChannelCount); return this; } - /** - * Sets the maximum allowed audio bitrate. - * - * @param maxAudioBitrate Maximum allowed audio bitrate in bits per second. - * @return This builder. - */ + @Override public ParametersBuilder setMaxAudioBitrate(int maxAudioBitrate) { - this.maxAudioBitrate = maxAudioBitrate; + super.setMaxAudioBitrate(maxAudioBitrate); return this; } @@ -575,26 +459,15 @@ public class DefaultTrackSelector extends MappingTrackSelector { return this; } - /** - * Sets the preferred sample MIME type for audio tracks. - * - * @param mimeType The preferred MIME type for audio tracks, or {@code null} to clear a - * previously set preference. - * @return This builder. - */ + @Override public ParametersBuilder setPreferredAudioMimeType(@Nullable String mimeType) { - return mimeType == null ? setPreferredAudioMimeTypes() : setPreferredAudioMimeTypes(mimeType); + super.setPreferredAudioMimeType(mimeType); + return this; } - /** - * Sets the preferred sample MIME types for audio tracks. - * - * @param mimeTypes The preferred MIME types for audio tracks in order of preference, or an - * empty list for no preference. - * @return This builder. - */ + @Override public ParametersBuilder setPreferredAudioMimeTypes(String... mimeTypes) { - preferredAudioMimeTypes = ImmutableList.copyOf(mimeTypes); + super.setPreferredAudioMimeTypes(mimeTypes); return this; } @@ -632,38 +505,30 @@ public class DefaultTrackSelector extends MappingTrackSelector { return this; } - @Override + /** + * Sets a bitmask of selection flags that are disabled for text track selections. + * + * @param disabledTextTrackSelectionFlags A bitmask of {@link C.SelectionFlags} that are + * disabled for text track selections. + * @return This builder. + */ public ParametersBuilder setDisabledTextTrackSelectionFlags( @C.SelectionFlags int disabledTextTrackSelectionFlags) { - super.setDisabledTextTrackSelectionFlags(disabledTextTrackSelectionFlags); + this.disabledTextTrackSelectionFlags = disabledTextTrackSelectionFlags; return this; } // General - /** - * Sets whether to force selection of the single lowest bitrate audio and video tracks that - * comply with all other constraints. - * - * @param forceLowestBitrate Whether to force selection of the single lowest bitrate audio and - * video tracks. - * @return This builder. - */ + @Override public ParametersBuilder setForceLowestBitrate(boolean forceLowestBitrate) { - this.forceLowestBitrate = forceLowestBitrate; + super.setForceLowestBitrate(forceLowestBitrate); return this; } - /** - * Sets whether to force selection of the highest bitrate audio and video tracks that comply - * with all other constraints. - * - * @param forceHighestSupportedBitrate Whether to force selection of the highest bitrate audio - * and video tracks. - * @return This builder. - */ + @Override public ParametersBuilder setForceHighestSupportedBitrate(boolean forceHighestSupportedBitrate) { - this.forceHighestSupportedBitrate = forceHighestSupportedBitrate; + super.setForceHighestSupportedBitrate(forceHighestSupportedBitrate); return this; } @@ -826,74 +691,24 @@ public class DefaultTrackSelector extends MappingTrackSelector { } /** Builds a {@link Parameters} instance with the selected values. */ + @Override public Parameters build() { - return new Parameters( - // Video - maxVideoWidth, - maxVideoHeight, - maxVideoFrameRate, - maxVideoBitrate, - minVideoWidth, - minVideoHeight, - minVideoFrameRate, - minVideoBitrate, - exceedVideoConstraintsIfNecessary, - allowVideoMixedMimeTypeAdaptiveness, - allowVideoNonSeamlessAdaptiveness, - viewportWidth, - viewportHeight, - viewportOrientationMayChange, - preferredVideoMimeTypes, - // Audio - preferredAudioLanguages, - preferredAudioRoleFlags, - maxAudioChannelCount, - maxAudioBitrate, - exceedAudioConstraintsIfNecessary, - allowAudioMixedMimeTypeAdaptiveness, - allowAudioMixedSampleRateAdaptiveness, - allowAudioMixedChannelCountAdaptiveness, - preferredAudioMimeTypes, - // Text - preferredTextLanguages, - preferredTextRoleFlags, - selectUndeterminedTextLanguage, - disabledTextTrackSelectionFlags, - // General - forceLowestBitrate, - forceHighestSupportedBitrate, - exceedRendererCapabilitiesIfNecessary, - tunnelingEnabled, - allowMultipleAdaptiveSelections, - selectionOverrides, - rendererDisabledFlags); + return new Parameters(this); } - @EnsuresNonNull({"preferredVideoMimeTypes", "preferredAudioMimeTypes"}) - private void setInitialValuesWithoutContext(@UnderInitialization ParametersBuilder this) { + private void init(ParametersBuilder this) { // Video - maxVideoWidth = Integer.MAX_VALUE; - maxVideoHeight = Integer.MAX_VALUE; - maxVideoFrameRate = Integer.MAX_VALUE; - maxVideoBitrate = Integer.MAX_VALUE; exceedVideoConstraintsIfNecessary = true; allowVideoMixedMimeTypeAdaptiveness = false; allowVideoNonSeamlessAdaptiveness = true; - viewportWidth = Integer.MAX_VALUE; - viewportHeight = Integer.MAX_VALUE; - viewportOrientationMayChange = true; - preferredVideoMimeTypes = ImmutableList.of(); // Audio - maxAudioChannelCount = Integer.MAX_VALUE; - maxAudioBitrate = Integer.MAX_VALUE; exceedAudioConstraintsIfNecessary = true; allowAudioMixedMimeTypeAdaptiveness = false; allowAudioMixedSampleRateAdaptiveness = false; allowAudioMixedChannelCountAdaptiveness = false; - preferredAudioMimeTypes = ImmutableList.of(); + // Text + disabledTextTrackSelectionFlags = 0; // General - forceLowestBitrate = false; - forceHighestSupportedBitrate = false; exceedRendererCapabilitiesIfNecessary = true; tunnelingEnabled = false; allowMultipleAdaptiveSelections = true; @@ -912,10 +727,9 @@ public class DefaultTrackSelector extends MappingTrackSelector { } /** - * Extends {@link TrackSelectionParameters} by adding fields that are specific to {@link - * DefaultTrackSelector}. + * Extends {@link Parameters} by adding fields that are specific to {@link DefaultTrackSelector}. */ - public static final class Parameters extends TrackSelectionParameters { + public static final class Parameters extends TrackSelectionParameters implements Parcelable { /** * An instance with default values, except those obtained from the {@link Context}. @@ -935,6 +749,30 @@ public class DefaultTrackSelector extends MappingTrackSelector { */ @SuppressWarnings("deprecation") public static final Parameters DEFAULT_WITHOUT_CONTEXT = new ParametersBuilder().build(); + /** + * @deprecated This instance is not configured using {@link Context} constraints. Use {@link + * #getDefaults(Context)} instead. + */ + @Deprecated public static final Parameters DEFAULT = DEFAULT_WITHOUT_CONTEXT; + + public static final Creator CREATOR = + new Creator() { + + @Override + public Parameters createFromParcel(Parcel in) { + return new Parameters(in); + } + + @Override + public Parameters[] newArray(int size) { + return new Parameters[size]; + } + }; + /** + * Bitmask of selection flags that are disabled for text track selections. See {@link + * C.SelectionFlags}. The default value is {@code 0} (i.e. no flags). + */ + @C.SelectionFlags public final int disabledTextTrackSelectionFlags; /** Returns an instance configured with default values. */ public static Parameters getDefaults(Context context) { @@ -942,45 +780,6 @@ public class DefaultTrackSelector extends MappingTrackSelector { } // Video - /** - * Maximum allowed video width in pixels. The default value is {@link Integer#MAX_VALUE} (i.e. - * no constraint). - * - *

To constrain adaptive video track selections to be suitable for a given viewport (the - * region of the display within which video will be played), use ({@link #viewportWidth}, {@link - * #viewportHeight} and {@link #viewportOrientationMayChange}) instead. - */ - public final int maxVideoWidth; - /** - * Maximum allowed video height in pixels. The default value is {@link Integer#MAX_VALUE} (i.e. - * no constraint). - * - *

To constrain adaptive video track selections to be suitable for a given viewport (the - * region of the display within which video will be played), use ({@link #viewportWidth}, {@link - * #viewportHeight} and {@link #viewportOrientationMayChange}) instead. - */ - public final int maxVideoHeight; - /** - * Maximum allowed video frame rate in hertz. The default value is {@link Integer#MAX_VALUE} - * (i.e. no constraint). - */ - public final int maxVideoFrameRate; - /** - * Maximum allowed video bitrate in bits per second. The default value is {@link - * Integer#MAX_VALUE} (i.e. no constraint). - */ - public final int maxVideoBitrate; - /** Minimum allowed video width in pixels. The default value is 0 (i.e. no constraint). */ - public final int minVideoWidth; - /** Minimum allowed video height in pixels. The default value is 0 (i.e. no constraint). */ - public final int minVideoHeight; - /** Minimum allowed video frame rate in hertz. The default value is 0 (i.e. no constraint). */ - public final int minVideoFrameRate; - /** - * Minimum allowed video bitrate in bits per second. The default value is 0 (i.e. no - * constraint). - */ - public final int minVideoBitrate; /** * Whether to exceed the {@link #maxVideoWidth}, {@link #maxVideoHeight} and {@link * #maxVideoBitrate} constraints when no selection can be made otherwise. The default value is @@ -999,40 +798,6 @@ public class DefaultTrackSelector extends MappingTrackSelector { * The default value is {@code true}. */ public final boolean allowVideoNonSeamlessAdaptiveness; - /** - * Viewport width in pixels. Constrains video track selections for adaptive content so that only - * tracks suitable for the viewport are selected. The default value is the physical width of the - * primary display, in pixels. - */ - public final int viewportWidth; - /** - * Viewport height in pixels. Constrains video track selections for adaptive content so that - * only tracks suitable for the viewport are selected. The default value is the physical height - * of the primary display, in pixels. - */ - public final int viewportHeight; - /** - * Whether the viewport orientation may change during playback. Constrains video track - * selections for adaptive content so that only tracks suitable for the viewport are selected. - * The default value is {@code true}. - */ - public final boolean viewportOrientationMayChange; - /** - * The preferred sample MIME types for video tracks in order of preference, or an empty list for - * no preference. The default is an empty list. - */ - public final ImmutableList preferredVideoMimeTypes; - // Audio - /** - * Maximum allowed audio channel count. The default value is {@link Integer#MAX_VALUE} (i.e. no - * constraint). - */ - public final int maxAudioChannelCount; - /** - * Maximum allowed audio bitrate in bits per second. The default value is {@link - * Integer#MAX_VALUE} (i.e. no constraint). - */ - public final int maxAudioBitrate; /** * Whether to exceed the {@link #maxAudioChannelCount} and {@link #maxAudioBitrate} constraints * when no selection can be made otherwise. The default value is {@code true}. @@ -1054,22 +819,6 @@ public class DefaultTrackSelector extends MappingTrackSelector { * false}. */ public final boolean allowAudioMixedChannelCountAdaptiveness; - /** - * The preferred sample MIME types for audio tracks in order of preference, or an empty list for - * no preference. The default is an empty list. - */ - public final ImmutableList preferredAudioMimeTypes; - // General - /** - * Whether to force selection of the single lowest bitrate audio and video tracks that comply - * with all other constraints. The default value is {@code false}. - */ - public final boolean forceLowestBitrate; - /** - * Whether to force selection of the highest bitrate audio and video tracks that comply with all - * other constraints. The default value is {@code false}. - */ - public final boolean forceHighestSupportedBitrate; /** * Whether to exceed renderer capabilities when no selection can be made otherwise. * @@ -1097,122 +846,42 @@ public class DefaultTrackSelector extends MappingTrackSelector { selectionOverrides; private final SparseBooleanArray rendererDisabledFlags; - /* package */ Parameters( - // Video - int maxVideoWidth, - int maxVideoHeight, - int maxVideoFrameRate, - int maxVideoBitrate, - int minVideoWidth, - int minVideoHeight, - int minVideoFrameRate, - int minVideoBitrate, - boolean exceedVideoConstraintsIfNecessary, - boolean allowVideoMixedMimeTypeAdaptiveness, - boolean allowVideoNonSeamlessAdaptiveness, - int viewportWidth, - int viewportHeight, - boolean viewportOrientationMayChange, - ImmutableList preferredVideoMimeTypes, - // Audio - ImmutableList preferredAudioLanguages, - @C.RoleFlags int preferredAudioRoleFlags, - int maxAudioChannelCount, - int maxAudioBitrate, - boolean exceedAudioConstraintsIfNecessary, - boolean allowAudioMixedMimeTypeAdaptiveness, - boolean allowAudioMixedSampleRateAdaptiveness, - boolean allowAudioMixedChannelCountAdaptiveness, - ImmutableList preferredAudioMimeTypes, - // Text - ImmutableList preferredTextLanguages, - @C.RoleFlags int preferredTextRoleFlags, - boolean selectUndeterminedTextLanguage, - @C.SelectionFlags int disabledTextTrackSelectionFlags, - // General - boolean forceLowestBitrate, - boolean forceHighestSupportedBitrate, - boolean exceedRendererCapabilitiesIfNecessary, - boolean tunnelingEnabled, - boolean allowMultipleAdaptiveSelections, - // Overrides - SparseArray> selectionOverrides, - SparseBooleanArray rendererDisabledFlags) { - super( - preferredAudioLanguages, - preferredAudioRoleFlags, - preferredTextLanguages, - preferredTextRoleFlags, - selectUndeterminedTextLanguage, - disabledTextTrackSelectionFlags); + private Parameters(ParametersBuilder builder) { + super(builder); // Video - this.maxVideoWidth = maxVideoWidth; - this.maxVideoHeight = maxVideoHeight; - this.maxVideoFrameRate = maxVideoFrameRate; - this.maxVideoBitrate = maxVideoBitrate; - this.minVideoWidth = minVideoWidth; - this.minVideoHeight = minVideoHeight; - this.minVideoFrameRate = minVideoFrameRate; - this.minVideoBitrate = minVideoBitrate; - this.exceedVideoConstraintsIfNecessary = exceedVideoConstraintsIfNecessary; - this.allowVideoMixedMimeTypeAdaptiveness = allowVideoMixedMimeTypeAdaptiveness; - this.allowVideoNonSeamlessAdaptiveness = allowVideoNonSeamlessAdaptiveness; - this.viewportWidth = viewportWidth; - this.viewportHeight = viewportHeight; - this.viewportOrientationMayChange = viewportOrientationMayChange; - this.preferredVideoMimeTypes = preferredVideoMimeTypes; + exceedVideoConstraintsIfNecessary = builder.exceedVideoConstraintsIfNecessary; + allowVideoMixedMimeTypeAdaptiveness = builder.allowVideoMixedMimeTypeAdaptiveness; + allowVideoNonSeamlessAdaptiveness = builder.allowVideoNonSeamlessAdaptiveness; // Audio - this.maxAudioChannelCount = maxAudioChannelCount; - this.maxAudioBitrate = maxAudioBitrate; - this.exceedAudioConstraintsIfNecessary = exceedAudioConstraintsIfNecessary; - this.allowAudioMixedMimeTypeAdaptiveness = allowAudioMixedMimeTypeAdaptiveness; - this.allowAudioMixedSampleRateAdaptiveness = allowAudioMixedSampleRateAdaptiveness; - this.allowAudioMixedChannelCountAdaptiveness = allowAudioMixedChannelCountAdaptiveness; - this.preferredAudioMimeTypes = preferredAudioMimeTypes; + exceedAudioConstraintsIfNecessary = builder.exceedAudioConstraintsIfNecessary; + allowAudioMixedMimeTypeAdaptiveness = builder.allowAudioMixedMimeTypeAdaptiveness; + allowAudioMixedSampleRateAdaptiveness = builder.allowAudioMixedSampleRateAdaptiveness; + allowAudioMixedChannelCountAdaptiveness = builder.allowAudioMixedChannelCountAdaptiveness; + // Text + disabledTextTrackSelectionFlags = builder.disabledTextTrackSelectionFlags; // General - this.forceLowestBitrate = forceLowestBitrate; - this.forceHighestSupportedBitrate = forceHighestSupportedBitrate; - this.exceedRendererCapabilitiesIfNecessary = exceedRendererCapabilitiesIfNecessary; - this.tunnelingEnabled = tunnelingEnabled; - this.allowMultipleAdaptiveSelections = allowMultipleAdaptiveSelections; + exceedRendererCapabilitiesIfNecessary = builder.exceedRendererCapabilitiesIfNecessary; + tunnelingEnabled = builder.tunnelingEnabled; + allowMultipleAdaptiveSelections = builder.allowMultipleAdaptiveSelections; // Overrides - this.selectionOverrides = selectionOverrides; - this.rendererDisabledFlags = rendererDisabledFlags; + selectionOverrides = builder.selectionOverrides; + rendererDisabledFlags = builder.rendererDisabledFlags; } /* package */ Parameters(Parcel in) { super(in); // Video - this.maxVideoWidth = in.readInt(); - this.maxVideoHeight = in.readInt(); - this.maxVideoFrameRate = in.readInt(); - this.maxVideoBitrate = in.readInt(); - this.minVideoWidth = in.readInt(); - this.minVideoHeight = in.readInt(); - this.minVideoFrameRate = in.readInt(); - this.minVideoBitrate = in.readInt(); this.exceedVideoConstraintsIfNecessary = Util.readBoolean(in); this.allowVideoMixedMimeTypeAdaptiveness = Util.readBoolean(in); this.allowVideoNonSeamlessAdaptiveness = Util.readBoolean(in); - this.viewportWidth = in.readInt(); - this.viewportHeight = in.readInt(); - this.viewportOrientationMayChange = Util.readBoolean(in); - ArrayList preferredVideoMimeTypes = new ArrayList<>(); - in.readList(preferredVideoMimeTypes, /* loader= */ null); - this.preferredVideoMimeTypes = ImmutableList.copyOf(preferredVideoMimeTypes); // Audio - this.maxAudioChannelCount = in.readInt(); - this.maxAudioBitrate = in.readInt(); this.exceedAudioConstraintsIfNecessary = Util.readBoolean(in); this.allowAudioMixedMimeTypeAdaptiveness = Util.readBoolean(in); this.allowAudioMixedSampleRateAdaptiveness = Util.readBoolean(in); this.allowAudioMixedChannelCountAdaptiveness = Util.readBoolean(in); - ArrayList preferredAudioMimeTypes = new ArrayList<>(); - in.readList(preferredAudioMimeTypes, /* loader= */ null); - this.preferredAudioMimeTypes = ImmutableList.copyOf(preferredAudioMimeTypes); + // Text + this.disabledTextTrackSelectionFlags = in.readInt(); // General - this.forceLowestBitrate = Util.readBoolean(in); - this.forceHighestSupportedBitrate = Util.readBoolean(in); this.exceedRendererCapabilitiesIfNecessary = Util.readBoolean(in); this.tunnelingEnabled = Util.readBoolean(in); this.allowMultipleAdaptiveSelections = Util.readBoolean(in); @@ -1259,11 +928,11 @@ public class DefaultTrackSelector extends MappingTrackSelector { } /** Creates a new {@link ParametersBuilder}, copying the initial values from this instance. */ - @Override public ParametersBuilder buildUpon() { return new ParametersBuilder(this); } + @SuppressWarnings("EqualsGetClass") // Class is not final for backward-compatibility reason. @Override public boolean equals(@Nullable Object obj) { if (this == obj) { @@ -1273,35 +942,20 @@ public class DefaultTrackSelector extends MappingTrackSelector { return false; } Parameters other = (Parameters) obj; - return super.equals(obj) + return super.equals(other) // Video - && maxVideoWidth == other.maxVideoWidth - && maxVideoHeight == other.maxVideoHeight - && maxVideoFrameRate == other.maxVideoFrameRate - && maxVideoBitrate == other.maxVideoBitrate - && minVideoWidth == other.minVideoWidth - && minVideoHeight == other.minVideoHeight - && minVideoFrameRate == other.minVideoFrameRate - && minVideoBitrate == other.minVideoBitrate && exceedVideoConstraintsIfNecessary == other.exceedVideoConstraintsIfNecessary && allowVideoMixedMimeTypeAdaptiveness == other.allowVideoMixedMimeTypeAdaptiveness && allowVideoNonSeamlessAdaptiveness == other.allowVideoNonSeamlessAdaptiveness - && viewportOrientationMayChange == other.viewportOrientationMayChange - && viewportWidth == other.viewportWidth - && viewportHeight == other.viewportHeight - && preferredVideoMimeTypes.equals(other.preferredVideoMimeTypes) // Audio - && maxAudioChannelCount == other.maxAudioChannelCount - && maxAudioBitrate == other.maxAudioBitrate && exceedAudioConstraintsIfNecessary == other.exceedAudioConstraintsIfNecessary && allowAudioMixedMimeTypeAdaptiveness == other.allowAudioMixedMimeTypeAdaptiveness && allowAudioMixedSampleRateAdaptiveness == other.allowAudioMixedSampleRateAdaptiveness && allowAudioMixedChannelCountAdaptiveness == other.allowAudioMixedChannelCountAdaptiveness - && preferredAudioMimeTypes.equals(other.preferredAudioMimeTypes) + // Text + && disabledTextTrackSelectionFlags == other.disabledTextTrackSelectionFlags // General - && forceLowestBitrate == other.forceLowestBitrate - && forceHighestSupportedBitrate == other.forceHighestSupportedBitrate && exceedRendererCapabilitiesIfNecessary == other.exceedRendererCapabilitiesIfNecessary && tunnelingEnabled == other.tunnelingEnabled && allowMultipleAdaptiveSelections == other.allowMultipleAdaptiveSelections @@ -1312,34 +966,20 @@ public class DefaultTrackSelector extends MappingTrackSelector { @Override public int hashCode() { - int result = super.hashCode(); + int result = 1; + result = 31 * result + super.hashCode(); // Video - result = 31 * result + maxVideoWidth; - result = 31 * result + maxVideoHeight; - result = 31 * result + maxVideoFrameRate; - result = 31 * result + maxVideoBitrate; - result = 31 * result + minVideoWidth; - result = 31 * result + minVideoHeight; - result = 31 * result + minVideoFrameRate; - result = 31 * result + minVideoBitrate; result = 31 * result + (exceedVideoConstraintsIfNecessary ? 1 : 0); result = 31 * result + (allowVideoMixedMimeTypeAdaptiveness ? 1 : 0); result = 31 * result + (allowVideoNonSeamlessAdaptiveness ? 1 : 0); - result = 31 * result + (viewportOrientationMayChange ? 1 : 0); - result = 31 * result + viewportWidth; - result = 31 * result + viewportHeight; - result = 31 * result + preferredVideoMimeTypes.hashCode(); // Audio - result = 31 * result + maxAudioChannelCount; - result = 31 * result + maxAudioBitrate; result = 31 * result + (exceedAudioConstraintsIfNecessary ? 1 : 0); result = 31 * result + (allowAudioMixedMimeTypeAdaptiveness ? 1 : 0); result = 31 * result + (allowAudioMixedSampleRateAdaptiveness ? 1 : 0); result = 31 * result + (allowAudioMixedChannelCountAdaptiveness ? 1 : 0); - result = 31 * result + preferredAudioMimeTypes.hashCode(); + // Text + result = 31 * result + disabledTextTrackSelectionFlags; // General - result = 31 * result + (forceLowestBitrate ? 1 : 0); - result = 31 * result + (forceHighestSupportedBitrate ? 1 : 0); result = 31 * result + (exceedRendererCapabilitiesIfNecessary ? 1 : 0); result = 31 * result + (tunnelingEnabled ? 1 : 0); result = 31 * result + (allowMultipleAdaptiveSelections ? 1 : 0); @@ -1358,32 +998,17 @@ public class DefaultTrackSelector extends MappingTrackSelector { public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); // Video - dest.writeInt(maxVideoWidth); - dest.writeInt(maxVideoHeight); - dest.writeInt(maxVideoFrameRate); - dest.writeInt(maxVideoBitrate); - dest.writeInt(minVideoWidth); - dest.writeInt(minVideoHeight); - dest.writeInt(minVideoFrameRate); - dest.writeInt(minVideoBitrate); Util.writeBoolean(dest, exceedVideoConstraintsIfNecessary); Util.writeBoolean(dest, allowVideoMixedMimeTypeAdaptiveness); Util.writeBoolean(dest, allowVideoNonSeamlessAdaptiveness); - dest.writeInt(viewportWidth); - dest.writeInt(viewportHeight); - Util.writeBoolean(dest, viewportOrientationMayChange); - dest.writeList(preferredVideoMimeTypes); // Audio - dest.writeInt(maxAudioChannelCount); - dest.writeInt(maxAudioBitrate); Util.writeBoolean(dest, exceedAudioConstraintsIfNecessary); Util.writeBoolean(dest, allowAudioMixedMimeTypeAdaptiveness); Util.writeBoolean(dest, allowAudioMixedSampleRateAdaptiveness); Util.writeBoolean(dest, allowAudioMixedChannelCountAdaptiveness); - dest.writeList(preferredAudioMimeTypes); + // Text + dest.writeInt(disabledTextTrackSelectionFlags); // General - Util.writeBoolean(dest, forceLowestBitrate); - Util.writeBoolean(dest, forceHighestSupportedBitrate); Util.writeBoolean(dest, exceedRendererCapabilitiesIfNecessary); Util.writeBoolean(dest, tunnelingEnabled); Util.writeBoolean(dest, allowMultipleAdaptiveSelections); @@ -1392,20 +1017,6 @@ public class DefaultTrackSelector extends MappingTrackSelector { dest.writeSparseBooleanArray(rendererDisabledFlags); } - public static final Parcelable.Creator CREATOR = - new Parcelable.Creator() { - - @Override - public Parameters createFromParcel(Parcel in) { - return new Parameters(in); - } - - @Override - public Parameters[] newArray(int size) { - return new Parameters[size]; - } - }; - // Static utility methods. private static SparseArray> diff --git a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionParameters.java b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionParameters.java deleted file mode 100644 index a9a2c30d84..0000000000 --- a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelectionParameters.java +++ /dev/null @@ -1,406 +0,0 @@ -/* - * Copyright (C) 2019 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 android.content.Context; -import android.os.Looper; -import android.os.Parcel; -import android.os.Parcelable; -import android.view.accessibility.CaptioningManager; -import androidx.annotation.Nullable; -import androidx.annotation.RequiresApi; -import com.google.android.exoplayer2.C; -import com.google.android.exoplayer2.util.Util; -import com.google.common.collect.ImmutableList; -import java.util.ArrayList; -import java.util.Locale; - -/** Constraint parameters for track selection. */ -public class TrackSelectionParameters implements Parcelable { - - /** - * A builder for {@link TrackSelectionParameters}. See the {@link TrackSelectionParameters} - * documentation for explanations of the parameters that can be configured using this builder. - */ - public static class Builder { - - /* package */ ImmutableList preferredAudioLanguages; - @C.RoleFlags /* package */ int preferredAudioRoleFlags; - /* package */ ImmutableList preferredTextLanguages; - @C.RoleFlags /* package */ int preferredTextRoleFlags; - /* package */ boolean selectUndeterminedTextLanguage; - @C.SelectionFlags /* package */ int disabledTextTrackSelectionFlags; - - /** - * Creates a builder with default initial values. - * - * @param context Any context. - */ - @SuppressWarnings({"deprecation", "nullness:method.invocation"}) - public Builder(Context context) { - this(); - setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettings(context); - } - - /** - * @deprecated {@link Context} constraints will not be set when using this constructor. Use - * {@link #Builder(Context)} instead. - */ - @Deprecated - public Builder() { - preferredAudioLanguages = ImmutableList.of(); - preferredAudioRoleFlags = 0; - preferredTextLanguages = ImmutableList.of(); - preferredTextRoleFlags = 0; - selectUndeterminedTextLanguage = false; - disabledTextTrackSelectionFlags = 0; - } - - /** - * @param initialValues The {@link TrackSelectionParameters} from which the initial values of - * the builder are obtained. - */ - /* package */ Builder(TrackSelectionParameters initialValues) { - preferredAudioLanguages = initialValues.preferredAudioLanguages; - preferredAudioRoleFlags = initialValues.preferredAudioRoleFlags; - preferredTextLanguages = initialValues.preferredTextLanguages; - preferredTextRoleFlags = initialValues.preferredTextRoleFlags; - selectUndeterminedTextLanguage = initialValues.selectUndeterminedTextLanguage; - disabledTextTrackSelectionFlags = initialValues.disabledTextTrackSelectionFlags; - } - - /** - * Sets the preferred language for audio and forced text tracks. - * - * @param preferredAudioLanguage Preferred audio language as an IETF BCP 47 conformant tag, or - * {@code null} to select the default track, or the first track if there's no default. - * @return This builder. - */ - public Builder setPreferredAudioLanguage(@Nullable String preferredAudioLanguage) { - return preferredAudioLanguage == null - ? setPreferredAudioLanguages() - : setPreferredAudioLanguages(preferredAudioLanguage); - } - - /** - * Sets the preferred languages for audio and forced text tracks. - * - * @param preferredAudioLanguages Preferred audio languages as IETF BCP 47 conformant tags in - * order of preference, or an empty array to select the default track, or the first track if - * there's no default. - * @return This builder. - */ - public Builder setPreferredAudioLanguages(String... preferredAudioLanguages) { - ImmutableList.Builder listBuilder = ImmutableList.builder(); - for (String language : checkNotNull(preferredAudioLanguages)) { - listBuilder.add(Util.normalizeLanguageCode(checkNotNull(language))); - } - this.preferredAudioLanguages = listBuilder.build(); - return this; - } - - /** - * Sets the preferred {@link C.RoleFlags} for audio tracks. - * - * @param preferredAudioRoleFlags Preferred audio role flags. - * @return This builder. - */ - public Builder setPreferredAudioRoleFlags(@C.RoleFlags int preferredAudioRoleFlags) { - this.preferredAudioRoleFlags = preferredAudioRoleFlags; - return this; - } - - /** - * Sets the preferred language and role flags for text tracks based on the accessibility - * settings of {@link CaptioningManager}. - * - *

Does nothing for API levels < 19 or when the {@link CaptioningManager} is disabled. - * - * @param context A {@link Context}. - * @return This builder. - */ - public Builder setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettings( - Context context) { - if (Util.SDK_INT >= 19) { - setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettingsV19(context); - } - return this; - } - - /** - * Sets the preferred language for text tracks. - * - * @param preferredTextLanguage Preferred text language as an IETF BCP 47 conformant tag, or - * {@code null} to select the default track if there is one, or no track otherwise. - * @return This builder. - */ - public Builder setPreferredTextLanguage(@Nullable String preferredTextLanguage) { - return preferredTextLanguage == null - ? setPreferredTextLanguages() - : setPreferredTextLanguages(preferredTextLanguage); - } - - /** - * Sets the preferred languages for text tracks. - * - * @param preferredTextLanguages Preferred text languages as IETF BCP 47 conformant tags in - * order of preference, or an empty array to select the default track if there is one, or no - * track otherwise. - * @return This builder. - */ - public Builder setPreferredTextLanguages(String... preferredTextLanguages) { - ImmutableList.Builder listBuilder = ImmutableList.builder(); - for (String language : checkNotNull(preferredTextLanguages)) { - listBuilder.add(Util.normalizeLanguageCode(checkNotNull(language))); - } - this.preferredTextLanguages = listBuilder.build(); - return this; - } - - /** - * Sets the preferred {@link C.RoleFlags} for text tracks. - * - * @param preferredTextRoleFlags Preferred text role flags. - * @return This builder. - */ - public Builder setPreferredTextRoleFlags(@C.RoleFlags int preferredTextRoleFlags) { - this.preferredTextRoleFlags = preferredTextRoleFlags; - return this; - } - - /** - * Sets whether a text track with undetermined language should be selected if no track with - * {@link #setPreferredTextLanguages(String...) a preferred language} is available, or if the - * preferred language is unset. - * - * @param selectUndeterminedTextLanguage Whether a text track with undetermined language should - * be selected if no preferred language track is available. - * @return This builder. - */ - public Builder setSelectUndeterminedTextLanguage(boolean selectUndeterminedTextLanguage) { - this.selectUndeterminedTextLanguage = selectUndeterminedTextLanguage; - return this; - } - - /** - * Sets a bitmask of selection flags that are disabled for text track selections. - * - * @param disabledTextTrackSelectionFlags A bitmask of {@link C.SelectionFlags} that are - * disabled for text track selections. - * @return This builder. - */ - public Builder setDisabledTextTrackSelectionFlags( - @C.SelectionFlags int disabledTextTrackSelectionFlags) { - this.disabledTextTrackSelectionFlags = disabledTextTrackSelectionFlags; - return this; - } - - /** Builds a {@link TrackSelectionParameters} instance with the selected values. */ - public TrackSelectionParameters build() { - return new TrackSelectionParameters( - // Audio - preferredAudioLanguages, - preferredAudioRoleFlags, - // Text - preferredTextLanguages, - preferredTextRoleFlags, - selectUndeterminedTextLanguage, - disabledTextTrackSelectionFlags); - } - - @RequiresApi(19) - private void setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettingsV19( - Context context) { - if (Util.SDK_INT < 23 && Looper.myLooper() == null) { - // Android platform bug (pre-Marshmallow) that causes RuntimeExceptions when - // CaptioningService is instantiated from a non-Looper thread. See [internal: b/143779904]. - return; - } - CaptioningManager captioningManager = - (CaptioningManager) context.getSystemService(Context.CAPTIONING_SERVICE); - if (captioningManager == null || !captioningManager.isEnabled()) { - return; - } - preferredTextRoleFlags = C.ROLE_FLAG_CAPTION | C.ROLE_FLAG_DESCRIBES_MUSIC_AND_SOUND; - Locale preferredLocale = captioningManager.getLocale(); - if (preferredLocale != null) { - preferredTextLanguages = ImmutableList.of(Util.getLocaleLanguageTag(preferredLocale)); - } - } - } - - /** - * An instance with default values, except those obtained from the {@link Context}. - * - *

If possible, use {@link #getDefaults(Context)} instead. - * - *

This instance will not have the following settings: - * - *

    - *
  • {@link Builder#setPreferredTextLanguageAndRoleFlagsToCaptioningManagerSettings(Context) - * Preferred text language and role flags} configured to the accessibility settings of - * {@link CaptioningManager}. - *
- */ - @SuppressWarnings("deprecation") - public static final TrackSelectionParameters DEFAULT_WITHOUT_CONTEXT = new Builder().build(); - - /** - * @deprecated This instance is not configured using {@link Context} constraints. Use {@link - * #getDefaults(Context)} instead. - */ - @Deprecated public static final TrackSelectionParameters DEFAULT = DEFAULT_WITHOUT_CONTEXT; - - /** Returns an instance configured with default values. */ - public static TrackSelectionParameters getDefaults(Context context) { - return new Builder(context).build(); - } - - /** - * The preferred languages for audio and forced text tracks as IETF BCP 47 conformant tags in - * order of preference. An empty list selects the default track, or the first track if there's no - * default. The default value is an empty list. - */ - public final ImmutableList preferredAudioLanguages; - /** - * The preferred {@link C.RoleFlags} for audio tracks. {@code 0} selects the default track if - * there is one, or the first track if there's no default. The default value is {@code 0}. - */ - @C.RoleFlags public final int preferredAudioRoleFlags; - /** - * The preferred languages for text tracks as IETF BCP 47 conformant tags in order of preference. - * An empty list selects the default track if there is one, or no track otherwise. The default - * value is an empty list, or the language of the accessibility {@link CaptioningManager} if - * enabled. - */ - public final ImmutableList preferredTextLanguages; - /** - * The preferred {@link C.RoleFlags} for text tracks. {@code 0} selects the default track if there - * is one, or no track otherwise. The default value is {@code 0}, or {@link C#ROLE_FLAG_SUBTITLE} - * | {@link C#ROLE_FLAG_DESCRIBES_MUSIC_AND_SOUND} if the accessibility {@link CaptioningManager} - * is enabled. - */ - @C.RoleFlags public final int preferredTextRoleFlags; - /** - * Whether a text track with undetermined language should be selected if no track with {@link - * #preferredTextLanguages} is available, or if {@link #preferredTextLanguages} is unset. The - * default value is {@code false}. - */ - public final boolean selectUndeterminedTextLanguage; - /** - * Bitmask of selection flags that are disabled for text track selections. See {@link - * C.SelectionFlags}. The default value is {@code 0} (i.e. no flags). - */ - @C.SelectionFlags public final int disabledTextTrackSelectionFlags; - - /* package */ TrackSelectionParameters( - ImmutableList preferredAudioLanguages, - @C.RoleFlags int preferredAudioRoleFlags, - ImmutableList preferredTextLanguages, - @C.RoleFlags int preferredTextRoleFlags, - boolean selectUndeterminedTextLanguage, - @C.SelectionFlags int disabledTextTrackSelectionFlags) { - // Audio - this.preferredAudioLanguages = preferredAudioLanguages; - this.preferredAudioRoleFlags = preferredAudioRoleFlags; - // Text - this.preferredTextLanguages = preferredTextLanguages; - this.preferredTextRoleFlags = preferredTextRoleFlags; - this.selectUndeterminedTextLanguage = selectUndeterminedTextLanguage; - this.disabledTextTrackSelectionFlags = disabledTextTrackSelectionFlags; - } - - /* package */ TrackSelectionParameters(Parcel in) { - ArrayList preferredAudioLanguages = new ArrayList<>(); - in.readList(preferredAudioLanguages, /* loader= */ null); - this.preferredAudioLanguages = ImmutableList.copyOf(preferredAudioLanguages); - this.preferredAudioRoleFlags = in.readInt(); - ArrayList preferredTextLanguages = new ArrayList<>(); - in.readList(preferredTextLanguages, /* loader= */ null); - this.preferredTextLanguages = ImmutableList.copyOf(preferredTextLanguages); - this.preferredTextRoleFlags = in.readInt(); - this.selectUndeterminedTextLanguage = Util.readBoolean(in); - this.disabledTextTrackSelectionFlags = in.readInt(); - } - - /** Creates a new {@link Builder}, copying the initial values from this instance. */ - public Builder buildUpon() { - return new Builder(this); - } - - @Override - @SuppressWarnings("EqualsGetClass") - public boolean equals(@Nullable Object obj) { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass()) { - return false; - } - TrackSelectionParameters other = (TrackSelectionParameters) obj; - return preferredAudioLanguages.equals(other.preferredAudioLanguages) - && preferredAudioRoleFlags == other.preferredAudioRoleFlags - && preferredTextLanguages.equals(other.preferredTextLanguages) - && preferredTextRoleFlags == other.preferredTextRoleFlags - && selectUndeterminedTextLanguage == other.selectUndeterminedTextLanguage - && disabledTextTrackSelectionFlags == other.disabledTextTrackSelectionFlags; - } - - @Override - public int hashCode() { - int result = 1; - result = 31 * result + preferredAudioLanguages.hashCode(); - result = 31 * result + preferredAudioRoleFlags; - result = 31 * result + preferredTextLanguages.hashCode(); - result = 31 * result + preferredTextRoleFlags; - result = 31 * result + (selectUndeterminedTextLanguage ? 1 : 0); - result = 31 * result + disabledTextTrackSelectionFlags; - return result; - } - - // Parcelable implementation. - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeList(preferredAudioLanguages); - dest.writeInt(preferredAudioRoleFlags); - dest.writeList(preferredTextLanguages); - dest.writeInt(preferredTextRoleFlags); - Util.writeBoolean(dest, selectUndeterminedTextLanguage); - dest.writeInt(disabledTextTrackSelectionFlags); - } - - public static final Creator CREATOR = - new Creator() { - - @Override - public TrackSelectionParameters createFromParcel(Parcel in) { - return new TrackSelectionParameters(in); - } - - @Override - public TrackSelectionParameters[] newArray(int size) { - return new TrackSelectionParameters[size]; - } - }; -} 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 29f3e69001..81959d35d8 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 @@ -30,8 +30,6 @@ import static org.mockito.MockitoAnnotations.initMocks; import android.content.Context; import android.os.Parcel; -import android.util.SparseArray; -import android.util.SparseBooleanArray; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.C; @@ -51,7 +49,6 @@ import com.google.android.exoplayer2.trackselection.TrackSelector.InvalidationLi import com.google.android.exoplayer2.upstream.BandwidthMeter; import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.Util; -import com.google.common.collect.ImmutableList; import java.util.HashMap; import java.util.Map; import org.junit.Before; @@ -1725,55 +1722,50 @@ public final class DefaultTrackSelectorTest { * variables. */ private static Parameters buildParametersForEqualsTest() { - SparseArray> selectionOverrides = new SparseArray<>(); - Map videoOverrides = new HashMap<>(); - videoOverrides.put(new TrackGroupArray(VIDEO_TRACK_GROUP), new SelectionOverride(0, 1)); - selectionOverrides.put(2, videoOverrides); - - SparseBooleanArray rendererDisabledFlags = new SparseBooleanArray(); - rendererDisabledFlags.put(3, true); - - return new Parameters( + return Parameters.DEFAULT_WITHOUT_CONTEXT + .buildUpon() // Video - /* maxVideoWidth= */ 0, - /* maxVideoHeight= */ 1, - /* maxVideoFrameRate= */ 2, - /* maxVideoBitrate= */ 3, - /* minVideoWidth= */ 4, - /* minVideoHeight= */ 5, - /* minVideoFrameRate= */ 6, - /* minVideoBitrate= */ 7, - /* exceedVideoConstraintsIfNecessary= */ false, - /* allowVideoMixedMimeTypeAdaptiveness= */ true, - /* allowVideoNonSeamlessAdaptiveness= */ false, - /* viewportWidth= */ 8, - /* viewportHeight= */ 9, - /* viewportOrientationMayChange= */ true, - /* preferredVideoMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_AV1, MimeTypes.VIDEO_H264), + .setMaxVideoSize(/* maxVideoWidth= */ 0, /* maxVideoHeight= */ 1) + .setMaxVideoFrameRate(2) + .setMaxVideoBitrate(3) + .setMinVideoSize(/* minVideoWidth= */ 4, /* minVideoHeight= */ 5) + .setMinVideoFrameRate(6) + .setMinVideoBitrate(7) + .setExceedVideoConstraintsIfNecessary(false) + .setAllowVideoMixedMimeTypeAdaptiveness(true) + .setAllowVideoNonSeamlessAdaptiveness(false) + .setViewportSize( + /* viewportWidth= */ 8, + /* viewportHeight= */ 9, + /* viewportOrientationMayChange= */ true) + .setPreferredVideoMimeTypes(MimeTypes.VIDEO_AV1, MimeTypes.VIDEO_H264) // Audio - /* preferredAudioLanguages= */ ImmutableList.of("zh", "jp"), - /* preferredAudioRoleFlags= */ C.ROLE_FLAG_COMMENTARY, - /* maxAudioChannelCount= */ 10, - /* maxAudioBitrate= */ 11, - /* exceedAudioConstraintsIfNecessary= */ false, - /* allowAudioMixedMimeTypeAdaptiveness= */ true, - /* allowAudioMixedSampleRateAdaptiveness= */ false, - /* allowAudioMixedChannelCountAdaptiveness= */ true, - /* preferredAudioMimeTypes= */ ImmutableList.of(MimeTypes.AUDIO_AC3, MimeTypes.AUDIO_E_AC3), + .setPreferredAudioLanguages("zh", "jp") + .setPreferredAudioRoleFlags(C.ROLE_FLAG_COMMENTARY) + .setMaxAudioChannelCount(10) + .setMaxAudioBitrate(11) + .setExceedAudioConstraintsIfNecessary(false) + .setAllowAudioMixedMimeTypeAdaptiveness(true) + .setAllowAudioMixedSampleRateAdaptiveness(false) + .setAllowAudioMixedChannelCountAdaptiveness(true) + .setPreferredAudioMimeTypes(MimeTypes.AUDIO_AC3, MimeTypes.AUDIO_E_AC3) // Text - /* preferredTextLanguages= */ ImmutableList.of("de", "en"), - /* preferredTextRoleFlags= */ C.ROLE_FLAG_CAPTION, - /* selectUndeterminedTextLanguage= */ true, - /* disabledTextTrackSelectionFlags= */ C.SELECTION_FLAG_AUTOSELECT, + .setPreferredTextLanguages("de", "en") + .setPreferredTextRoleFlags(C.ROLE_FLAG_CAPTION) + .setSelectUndeterminedTextLanguage(true) + .setDisabledTextTrackSelectionFlags(C.SELECTION_FLAG_AUTOSELECT) // General - /* forceLowestBitrate= */ false, - /* forceHighestSupportedBitrate= */ true, - /* exceedRendererCapabilitiesIfNecessary= */ false, - /* tunnelingEnabled= */ true, - /* allowMultipleAdaptiveSelections= */ true, - // Overrides - selectionOverrides, - rendererDisabledFlags); + .setForceLowestBitrate(false) + .setForceHighestSupportedBitrate(true) + .setExceedRendererCapabilitiesIfNecessary(false) + .setTunnelingEnabled(true) + .setAllowMultipleAdaptiveSelections(true) + .setSelectionOverride( + /* rendererIndex= */ 2, + new TrackGroupArray(VIDEO_TRACK_GROUP), + new SelectionOverride(0, 1)) + .setRendererDisabled(3, true) + .build(); } /**