diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 7daa5c9da5..e8efde7f4f 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -6,6 +6,8 @@ * Add `SampleQueue.discardUpstreamFrom` so upstream samples can be discarded by timestamp. * Add `SampleQueue.getLargestReadTimestampUs`. +* Track selection: + * Add option to specify multiple preferred audio or text languages. ### 2.12.0 (not yet released - targeted for 2020-09-03) ### 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 f61c0b14d4..c9f0e290c9 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 @@ -39,6 +39,7 @@ import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Util; import com.google.common.collect.ComparisonChain; +import com.google.common.collect.ImmutableList; import com.google.common.collect.Ordering; import com.google.common.primitives.Ints; import java.util.ArrayList; @@ -450,6 +451,12 @@ public class DefaultTrackSelector extends MappingTrackSelector { return this; } + @Override + public ParametersBuilder setPreferredAudioLanguages(String... preferredAudioLanguages) { + super.setPreferredAudioLanguages(preferredAudioLanguages); + return this; + } + /** * Sets the maximum allowed audio channel count. * @@ -546,6 +553,12 @@ public class DefaultTrackSelector extends MappingTrackSelector { return this; } + @Override + public ParametersBuilder setPreferredTextLanguages(String... preferredTextLanguages) { + super.setPreferredTextLanguages(preferredTextLanguages); + return this; + } + @Override public ParametersBuilder setPreferredTextRoleFlags(@C.RoleFlags int preferredTextRoleFlags) { super.setPreferredTextRoleFlags(preferredTextRoleFlags); @@ -767,7 +780,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { viewportHeight, viewportOrientationMayChange, // Audio - preferredAudioLanguage, + preferredAudioLanguages, maxAudioChannelCount, maxAudioBitrate, exceedAudioConstraintsIfNecessary, @@ -775,7 +788,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { allowAudioMixedSampleRateAdaptiveness, allowAudioMixedChannelCountAdaptiveness, // Text - preferredTextLanguage, + preferredTextLanguages, preferredTextRoleFlags, selectUndeterminedTextLanguage, disabledTextTrackSelectionFlags, @@ -1015,7 +1028,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { int viewportHeight, boolean viewportOrientationMayChange, // Audio - @Nullable String preferredAudioLanguage, + ImmutableList preferredAudioLanguages, int maxAudioChannelCount, int maxAudioBitrate, boolean exceedAudioConstraintsIfNecessary, @@ -1023,7 +1036,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { boolean allowAudioMixedSampleRateAdaptiveness, boolean allowAudioMixedChannelCountAdaptiveness, // Text - @Nullable String preferredTextLanguage, + ImmutableList preferredTextLanguages, @C.RoleFlags int preferredTextRoleFlags, boolean selectUndeterminedTextLanguage, @C.SelectionFlags int disabledTextTrackSelectionFlags, @@ -1036,8 +1049,8 @@ public class DefaultTrackSelector extends MappingTrackSelector { SparseArray> selectionOverrides, SparseBooleanArray rendererDisabledFlags) { super( - preferredAudioLanguage, - preferredTextLanguage, + preferredAudioLanguages, + preferredTextLanguages, preferredTextRoleFlags, selectUndeterminedTextLanguage, disabledTextTrackSelectionFlags); @@ -2607,6 +2620,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { private final Parameters parameters; private final boolean isWithinRendererCapabilities; private final int preferredLanguageScore; + private final int preferredLanguageIndex; private final int localeLanguageMatchIndex; private final int localeLanguageScore; private final boolean isDefaultSelectionFlag; @@ -2619,11 +2633,22 @@ public class DefaultTrackSelector extends MappingTrackSelector { this.language = normalizeUndeterminedLanguageToNull(format.language); isWithinRendererCapabilities = isSupported(formatSupport, /* allowExceedsCapabilities= */ false); - preferredLanguageScore = - getFormatLanguageScore( - format, - parameters.preferredAudioLanguage, - /* allowUndeterminedFormatLanguage= */ false); + int bestLanguageScore = 0; + int bestLanguageIndex = Integer.MAX_VALUE; + for (int i = 0; i < parameters.preferredAudioLanguages.size(); i++) { + int score = + getFormatLanguageScore( + format, + parameters.preferredAudioLanguages.get(i), + /* allowUndeterminedFormatLanguage= */ false); + if (score > 0) { + bestLanguageIndex = i; + bestLanguageScore = score; + break; + } + } + preferredLanguageIndex = bestLanguageIndex; + preferredLanguageScore = bestLanguageScore; isDefaultSelectionFlag = (format.selectionFlags & C.SELECTION_FLAG_DEFAULT) != 0; channelCount = format.channelCount; sampleRate = format.sampleRate; @@ -2666,6 +2691,10 @@ public class DefaultTrackSelector extends MappingTrackSelector { : FORMAT_VALUE_ORDERING.reverse(); return ComparisonChain.start() .compareFalseFirst(this.isWithinRendererCapabilities, other.isWithinRendererCapabilities) + .compare( + this.preferredLanguageIndex, + other.preferredLanguageIndex, + Ordering.natural().reverse()) .compare(this.preferredLanguageScore, other.preferredLanguageScore) .compareFalseFirst(this.isWithinConstraints, other.isWithinConstraints) .compare( @@ -2701,6 +2730,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { private final boolean isWithinRendererCapabilities; private final boolean isDefault; private final boolean isForced; + private final int preferredLanguageIndex; private final int preferredLanguageScore; private final int preferredRoleFlagsScore; private final int selectedAudioLanguageScore; @@ -2717,9 +2747,26 @@ public class DefaultTrackSelector extends MappingTrackSelector { format.selectionFlags & ~parameters.disabledTextTrackSelectionFlags; isDefault = (maskedSelectionFlags & C.SELECTION_FLAG_DEFAULT) != 0; isForced = (maskedSelectionFlags & C.SELECTION_FLAG_FORCED) != 0; - preferredLanguageScore = - getFormatLanguageScore( - format, parameters.preferredTextLanguage, parameters.selectUndeterminedTextLanguage); + int bestLanguageIndex = Integer.MAX_VALUE; + int bestLanguageScore = 0; + // Compare against empty (unset) language if no preference is given to allow the selection of + // a text track with undetermined language. + ImmutableList preferredLanguages = + parameters.preferredTextLanguages.isEmpty() + ? ImmutableList.of("") + : parameters.preferredTextLanguages; + for (int i = 0; i < preferredLanguages.size(); i++) { + int score = + getFormatLanguageScore( + format, preferredLanguages.get(i), parameters.selectUndeterminedTextLanguage); + if (score > 0) { + bestLanguageIndex = i; + bestLanguageScore = score; + break; + } + } + preferredLanguageIndex = bestLanguageIndex; + preferredLanguageScore = bestLanguageScore; preferredRoleFlagsScore = Integer.bitCount(format.roleFlags & parameters.preferredTextRoleFlags); hasCaptionRoleFlags = @@ -2730,7 +2777,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { getFormatLanguageScore(format, selectedAudioLanguage, selectedAudioLanguageUndetermined); isWithinConstraints = preferredLanguageScore > 0 - || (parameters.preferredTextLanguage == null && preferredRoleFlagsScore > 0) + || (parameters.preferredTextLanguages.isEmpty() && preferredRoleFlagsScore > 0) || isDefault || (isForced && selectedAudioLanguageScore > 0); } @@ -2748,6 +2795,10 @@ public class DefaultTrackSelector extends MappingTrackSelector { ComparisonChain.start() .compareFalseFirst( this.isWithinRendererCapabilities, other.isWithinRendererCapabilities) + .compare( + this.preferredLanguageIndex, + other.preferredLanguageIndex, + Ordering.natural().reverse()) .compare(this.preferredLanguageScore, other.preferredLanguageScore) .compare(this.preferredRoleFlagsScore, other.preferredRoleFlagsScore) .compareFalseFirst(this.isDefault, other.isDefault) 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 index 3871a31a3b..be1f8f6733 100644 --- 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 @@ -15,16 +15,19 @@ */ 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.text.TextUtils; 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. */ @@ -36,8 +39,8 @@ public class TrackSelectionParameters implements Parcelable { */ public static class Builder { - @Nullable /* package */ String preferredAudioLanguage; - @Nullable /* package */ String preferredTextLanguage; + /* package */ ImmutableList preferredAudioLanguages; + /* package */ ImmutableList preferredTextLanguages; @C.RoleFlags /* package */ int preferredTextRoleFlags; /* package */ boolean selectUndeterminedTextLanguage; @C.SelectionFlags /* package */ int disabledTextTrackSelectionFlags; @@ -59,8 +62,8 @@ public class TrackSelectionParameters implements Parcelable { */ @Deprecated public Builder() { - preferredAudioLanguage = null; - preferredTextLanguage = null; + preferredAudioLanguages = ImmutableList.of(); + preferredTextLanguages = ImmutableList.of(); preferredTextRoleFlags = 0; selectUndeterminedTextLanguage = false; disabledTextTrackSelectionFlags = 0; @@ -71,8 +74,8 @@ public class TrackSelectionParameters implements Parcelable { * the builder are obtained. */ /* package */ Builder(TrackSelectionParameters initialValues) { - preferredAudioLanguage = initialValues.preferredAudioLanguage; - preferredTextLanguage = initialValues.preferredTextLanguage; + preferredAudioLanguages = initialValues.preferredAudioLanguages; + preferredTextLanguages = initialValues.preferredTextLanguages; preferredTextRoleFlags = initialValues.preferredTextRoleFlags; selectUndeterminedTextLanguage = initialValues.selectUndeterminedTextLanguage; disabledTextTrackSelectionFlags = initialValues.disabledTextTrackSelectionFlags; @@ -86,7 +89,25 @@ public class TrackSelectionParameters implements Parcelable { * @return This builder. */ public Builder setPreferredAudioLanguage(@Nullable String preferredAudioLanguage) { - this.preferredAudioLanguage = 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; } @@ -115,7 +136,25 @@ public class TrackSelectionParameters implements Parcelable { * @return This builder. */ public Builder setPreferredTextLanguage(@Nullable String preferredTextLanguage) { - this.preferredTextLanguage = 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; } @@ -132,8 +171,8 @@ public class TrackSelectionParameters implements Parcelable { /** * Sets whether a text track with undetermined language should be selected if no track with - * {@link #setPreferredTextLanguage(String)} is available, or if the preferred language is - * unset. + * {@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. @@ -161,9 +200,9 @@ public class TrackSelectionParameters implements Parcelable { public TrackSelectionParameters build() { return new TrackSelectionParameters( // Audio - preferredAudioLanguage, + preferredAudioLanguages, // Text - preferredTextLanguage, + preferredTextLanguages, preferredTextRoleFlags, selectUndeterminedTextLanguage, disabledTextTrackSelectionFlags); @@ -185,7 +224,7 @@ public class TrackSelectionParameters implements Parcelable { preferredTextRoleFlags = C.ROLE_FLAG_CAPTION | C.ROLE_FLAG_DESCRIBES_MUSIC_AND_SOUND; Locale preferredLocale = captioningManager.getLocale(); if (preferredLocale != null) { - preferredTextLanguage = Util.getLocaleLanguageTag(preferredLocale); + preferredTextLanguages = ImmutableList.of(Util.getLocaleLanguageTag(preferredLocale)); } } } @@ -218,17 +257,18 @@ public class TrackSelectionParameters implements Parcelable { } /** - * The preferred language for audio and forced text tracks as an IETF BCP 47 conformant tag. - * {@code null} selects the default track, or the first track if there's no default. The default - * value is {@code null}. + * 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. */ - @Nullable public final String preferredAudioLanguage; + public final ImmutableList preferredAudioLanguages; /** - * The preferred language for text tracks as an IETF BCP 47 conformant tag. {@code null} selects - * the default track if there is one, or no track otherwise. The default value is {@code null}, or - * the language of the accessibility {@link CaptioningManager} if enabled. + * 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. */ - @Nullable public final String preferredTextLanguage; + 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} @@ -238,7 +278,7 @@ public class TrackSelectionParameters implements Parcelable { @C.RoleFlags public final int preferredTextRoleFlags; /** * Whether a text track with undetermined language should be selected if no track with {@link - * #preferredTextLanguage} is available, or if {@link #preferredTextLanguage} is unset. The + * #preferredTextLanguages} is available, or if {@link #preferredTextLanguages} is unset. The * default value is {@code false}. */ public final boolean selectUndeterminedTextLanguage; @@ -249,23 +289,27 @@ public class TrackSelectionParameters implements Parcelable { @C.SelectionFlags public final int disabledTextTrackSelectionFlags; /* package */ TrackSelectionParameters( - @Nullable String preferredAudioLanguage, - @Nullable String preferredTextLanguage, + ImmutableList preferredAudioLanguages, + ImmutableList preferredTextLanguages, @C.RoleFlags int preferredTextRoleFlags, boolean selectUndeterminedTextLanguage, @C.SelectionFlags int disabledTextTrackSelectionFlags) { // Audio - this.preferredAudioLanguage = Util.normalizeLanguageCode(preferredAudioLanguage); + this.preferredAudioLanguages = preferredAudioLanguages; // Text - this.preferredTextLanguage = Util.normalizeLanguageCode(preferredTextLanguage); + this.preferredTextLanguages = preferredTextLanguages; this.preferredTextRoleFlags = preferredTextRoleFlags; this.selectUndeterminedTextLanguage = selectUndeterminedTextLanguage; this.disabledTextTrackSelectionFlags = disabledTextTrackSelectionFlags; } /* package */ TrackSelectionParameters(Parcel in) { - this.preferredAudioLanguage = in.readString(); - this.preferredTextLanguage = in.readString(); + ArrayList preferredAudioLanguages = new ArrayList<>(); + in.readList(preferredAudioLanguages, /* loader= */ null); + this.preferredAudioLanguages = ImmutableList.copyOf(preferredAudioLanguages); + 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(); @@ -286,8 +330,8 @@ public class TrackSelectionParameters implements Parcelable { return false; } TrackSelectionParameters other = (TrackSelectionParameters) obj; - return TextUtils.equals(preferredAudioLanguage, other.preferredAudioLanguage) - && TextUtils.equals(preferredTextLanguage, other.preferredTextLanguage) + return preferredAudioLanguages.equals(other.preferredAudioLanguages) + && preferredTextLanguages.equals(other.preferredTextLanguages) && preferredTextRoleFlags == other.preferredTextRoleFlags && selectUndeterminedTextLanguage == other.selectUndeterminedTextLanguage && disabledTextTrackSelectionFlags == other.disabledTextTrackSelectionFlags; @@ -296,8 +340,8 @@ public class TrackSelectionParameters implements Parcelable { @Override public int hashCode() { int result = 1; - result = 31 * result + (preferredAudioLanguage == null ? 0 : preferredAudioLanguage.hashCode()); - result = 31 * result + (preferredTextLanguage == null ? 0 : preferredTextLanguage.hashCode()); + result = 31 * result + preferredAudioLanguages.hashCode(); + result = 31 * result + preferredTextLanguages.hashCode(); result = 31 * result + preferredTextRoleFlags; result = 31 * result + (selectUndeterminedTextLanguage ? 1 : 0); result = 31 * result + disabledTextTrackSelectionFlags; @@ -313,8 +357,8 @@ public class TrackSelectionParameters implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(preferredAudioLanguage); - dest.writeString(preferredTextLanguage); + dest.writeList(preferredAudioLanguages); + dest.writeList(preferredTextLanguages); dest.writeInt(preferredTextRoleFlags); Util.writeBoolean(dest, selectUndeterminedTextLanguage); dest.writeInt(disabledTextTrackSelectionFlags); 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 89dd62e9a6..ef58cb2801 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 @@ -19,6 +19,7 @@ import static com.google.android.exoplayer2.RendererCapabilities.ADAPTIVE_NOT_SE import static com.google.android.exoplayer2.RendererCapabilities.FORMAT_EXCEEDS_CAPABILITIES; import static com.google.android.exoplayer2.RendererCapabilities.FORMAT_HANDLED; import static com.google.android.exoplayer2.RendererCapabilities.FORMAT_UNSUPPORTED_SUBTYPE; +import static com.google.android.exoplayer2.RendererCapabilities.TUNNELING_NOT_SUPPORTED; import static com.google.android.exoplayer2.RendererConfiguration.DEFAULT; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.never; @@ -37,6 +38,7 @@ import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.RendererCapabilities; +import com.google.android.exoplayer2.RendererCapabilities.Capabilities; import com.google.android.exoplayer2.RendererConfiguration; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; @@ -50,6 +52,7 @@ 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; @@ -67,7 +70,8 @@ public final class DefaultTrackSelectorTest { private static final RendererCapabilities ALL_TEXT_FORMAT_SUPPORTED_RENDERER_CAPABILITIES = new FakeRendererCapabilities(C.TRACK_TYPE_TEXT); private static final RendererCapabilities ALL_AUDIO_FORMAT_EXCEEDED_RENDERER_CAPABILITIES = - new FakeRendererCapabilities(C.TRACK_TYPE_AUDIO, FORMAT_EXCEEDS_CAPABILITIES); + new FakeRendererCapabilities( + C.TRACK_TYPE_AUDIO, RendererCapabilities.create(FORMAT_EXCEEDS_CAPABILITIES)); private static final RendererCapabilities VIDEO_CAPABILITIES = new FakeRendererCapabilities(C.TRACK_TYPE_VIDEO); @@ -1318,7 +1322,10 @@ public final class DefaultTrackSelectorTest { @Test public void selectTracksWithMultipleVideoTracksWithNonSeamlessAdaptiveness() throws Exception { FakeRendererCapabilities nonSeamlessVideoCapabilities = - new FakeRendererCapabilities(C.TRACK_TYPE_VIDEO, FORMAT_HANDLED | ADAPTIVE_NOT_SEAMLESS); + new FakeRendererCapabilities( + C.TRACK_TYPE_VIDEO, + RendererCapabilities.create( + FORMAT_HANDLED, ADAPTIVE_NOT_SEAMLESS, TUNNELING_NOT_SUPPORTED)); // Should do non-seamless adaptiveness by default, so expect an adaptive selection. Format.Builder formatBuilder = VIDEO_FORMAT.buildUpon(); @@ -1508,7 +1515,7 @@ public final class DefaultTrackSelectorTest { /* viewportHeight= */ 9, /* viewportOrientationMayChange= */ true, // Audio - /* preferredAudioLanguage= */ "en", + /* preferredAudioLanguages= */ ImmutableList.of("zh", "jp"), /* maxAudioChannelCount= */ 10, /* maxAudioBitrate= */ 11, /* exceedAudioConstraintsIfNecessary= */ false, @@ -1516,10 +1523,10 @@ public final class DefaultTrackSelectorTest { /* allowAudioMixedSampleRateAdaptiveness= */ false, /* allowAudioMixedChannelCountAdaptiveness= */ true, // Text - /* preferredTextLanguage= */ "de", + /* preferredTextLanguages= */ ImmutableList.of("de", "en"), /* preferredTextRoleFlags= */ C.ROLE_FLAG_CAPTION, /* selectUndeterminedTextLanguage= */ true, - /* disabledTextTrackSelectionFlags= */ 12, + /* disabledTextTrackSelectionFlags= */ C.SELECTION_FLAG_AUTOSELECT, // General /* forceLowestBitrate= */ false, /* forceHighestSupportedBitrate= */ true,