From 50582417cb6755b73d6dd0262e5ce38b4e6f2460 Mon Sep 17 00:00:00 2001 From: Corentin Zuber Date: Fri, 31 Jul 2020 07:55:22 +0200 Subject: [PATCH 1/2] Authorize multiple preffered language and text --- .../trackselection/DefaultTrackSelector.java | 38 +++++++--- .../TrackSelectionParameters.java | 76 ++++++++++++++----- 2 files changed, 83 insertions(+), 31 deletions(-) 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..9933a2b023 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 @@ -450,6 +450,12 @@ public class DefaultTrackSelector extends MappingTrackSelector { return this; } + @Override + public ParametersBuilder setPreferredAudioLanguage(String[] preferredAudioLanguage) { + super.setPreferredAudioLanguage(preferredAudioLanguage); + return this; + } + /** * Sets the maximum allowed audio channel count. * @@ -1015,7 +1021,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { int viewportHeight, boolean viewportOrientationMayChange, // Audio - @Nullable String preferredAudioLanguage, + String[] preferredAudioLanguage, int maxAudioChannelCount, int maxAudioBitrate, boolean exceedAudioConstraintsIfNecessary, @@ -1023,7 +1029,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { boolean allowAudioMixedSampleRateAdaptiveness, boolean allowAudioMixedChannelCountAdaptiveness, // Text - @Nullable String preferredTextLanguage, + String[] preferredTextLanguage, @C.RoleFlags int preferredTextRoleFlags, boolean selectUndeterminedTextLanguage, @C.SelectionFlags int disabledTextTrackSelectionFlags, @@ -2619,11 +2625,16 @@ 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; + for (int i = 0; i < parameters.preferredAudioLanguage.length; i++) { + int score = getFormatLanguageScore( + format, + parameters.preferredAudioLanguage[i], + /* allowUndeterminedFormatLanguage= */ false); + score = 1000 * score + parameters.preferredAudioLanguage.length - i; // Priorise the first items in array + bestLanguageScore = Math.max(bestLanguageScore, score); + } + preferredLanguageScore = bestLanguageScore; isDefaultSelectionFlag = (format.selectionFlags & C.SELECTION_FLAG_DEFAULT) != 0; channelCount = format.channelCount; sampleRate = format.sampleRate; @@ -2717,9 +2728,14 @@ 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 bestLanguageScore = 0; + for (int i = 0; i < parameters.preferredTextLanguage.length; i++) { + int score = getFormatLanguageScore( + format, parameters.preferredTextLanguage[i], parameters.selectUndeterminedTextLanguage); + score = 1000 * score + parameters.preferredTextLanguage.length - i; // Priorise the first items in array + bestLanguageScore = Math.max(bestLanguageScore, score); + } + preferredLanguageScore = bestLanguageScore; preferredRoleFlagsScore = Integer.bitCount(format.roleFlags & parameters.preferredTextRoleFlags); hasCaptionRoleFlags = @@ -2730,7 +2746,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { getFormatLanguageScore(format, selectedAudioLanguage, selectedAudioLanguageUndetermined); isWithinConstraints = preferredLanguageScore > 0 - || (parameters.preferredTextLanguage == null && preferredRoleFlagsScore > 0) + || (parameters.preferredTextLanguage.length == 0 && preferredRoleFlagsScore > 0) || isDefault || (isForced && selectedAudioLanguageScore > 0); } 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..ac8a84dbf5 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 @@ -19,12 +19,12 @@ 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 java.util.Arrays; import java.util.Locale; /** Constraint parameters for track selection. */ @@ -36,8 +36,8 @@ public class TrackSelectionParameters implements Parcelable { */ public static class Builder { - @Nullable /* package */ String preferredAudioLanguage; - @Nullable /* package */ String preferredTextLanguage; + /* package */ String[] preferredAudioLanguage; + /* package */ String[] preferredTextLanguage; @C.RoleFlags /* package */ int preferredTextRoleFlags; /* package */ boolean selectUndeterminedTextLanguage; @C.SelectionFlags /* package */ int disabledTextTrackSelectionFlags; @@ -59,8 +59,8 @@ public class TrackSelectionParameters implements Parcelable { */ @Deprecated public Builder() { - preferredAudioLanguage = null; - preferredTextLanguage = null; + preferredAudioLanguage = new String[0]; + preferredTextLanguage = new String[0]; preferredTextRoleFlags = 0; selectUndeterminedTextLanguage = false; disabledTextTrackSelectionFlags = 0; @@ -86,6 +86,14 @@ public class TrackSelectionParameters implements Parcelable { * @return This builder. */ public Builder setPreferredAudioLanguage(@Nullable String preferredAudioLanguage) { + if (preferredAudioLanguage == null) { + return setPreferredAudioLanguage(new String[0]); + } else { + return setPreferredAudioLanguage(new String[] { preferredAudioLanguage }); + } + } + + public Builder setPreferredAudioLanguage(String[] preferredAudioLanguage) { this.preferredAudioLanguage = preferredAudioLanguage; return this; } @@ -115,6 +123,14 @@ public class TrackSelectionParameters implements Parcelable { * @return This builder. */ public Builder setPreferredTextLanguage(@Nullable String preferredTextLanguage) { + if (preferredTextLanguage == null) { + return setPreferredTextLanguage(new String[0]); + } else { + return setPreferredTextLanguage(new String[]{preferredTextLanguage}); + } + } + + public Builder setPreferredTextLanguage(String[] preferredTextLanguage) { this.preferredTextLanguage = preferredTextLanguage; return this; } @@ -185,7 +201,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); + preferredTextLanguage = new String[] { Util.getLocaleLanguageTag(preferredLocale) }; } } } @@ -222,13 +238,13 @@ public class TrackSelectionParameters implements Parcelable { * {@code null} selects the default track, or the first track if there's no default. The default * value is {@code null}. */ - @Nullable public final String preferredAudioLanguage; + public final String[] preferredAudioLanguage; /** * 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. */ - @Nullable public final String preferredTextLanguage; + public final String[] preferredTextLanguage; /** * 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} @@ -249,23 +265,37 @@ public class TrackSelectionParameters implements Parcelable { @C.SelectionFlags public final int disabledTextTrackSelectionFlags; /* package */ TrackSelectionParameters( - @Nullable String preferredAudioLanguage, - @Nullable String preferredTextLanguage, + String[] preferredAudioLanguage, + String[] preferredTextLanguage, @C.RoleFlags int preferredTextRoleFlags, boolean selectUndeterminedTextLanguage, @C.SelectionFlags int disabledTextTrackSelectionFlags) { // Audio - this.preferredAudioLanguage = Util.normalizeLanguageCode(preferredAudioLanguage); + this.preferredAudioLanguage = new String[preferredAudioLanguage.length]; + for (int i = 0; i < preferredAudioLanguage.length; i++) { + this.preferredAudioLanguage[i] = Util.normalizeLanguageCode(preferredAudioLanguage[i]); + } // Text - this.preferredTextLanguage = Util.normalizeLanguageCode(preferredTextLanguage); + this.preferredTextLanguage = new String[preferredAudioLanguage.length]; + for (int i = 0; i < preferredTextLanguage.length; i++) { + this.preferredTextLanguage[i] = Util.normalizeLanguageCode(preferredTextLanguage[i]); + } this.preferredTextRoleFlags = preferredTextRoleFlags; this.selectUndeterminedTextLanguage = selectUndeterminedTextLanguage; this.disabledTextTrackSelectionFlags = disabledTextTrackSelectionFlags; } /* package */ TrackSelectionParameters(Parcel in) { - this.preferredAudioLanguage = in.readString(); - this.preferredTextLanguage = in.readString(); + int preferredAudioLanguageSize = in.readInt(); + this.preferredAudioLanguage = new String[preferredAudioLanguageSize]; + for (int i = 0; i < preferredAudioLanguageSize; i++) { + preferredAudioLanguage[i] = in.readString(); + } + int preferredTextLanguageSize = in.readInt(); + this.preferredTextLanguage = new String[preferredTextLanguageSize]; + for (int i = 0; i < preferredTextLanguageSize; i++) { + preferredTextLanguage[i] = in.readString(); + } this.preferredTextRoleFlags = in.readInt(); this.selectUndeterminedTextLanguage = Util.readBoolean(in); this.disabledTextTrackSelectionFlags = in.readInt(); @@ -286,8 +316,8 @@ public class TrackSelectionParameters implements Parcelable { return false; } TrackSelectionParameters other = (TrackSelectionParameters) obj; - return TextUtils.equals(preferredAudioLanguage, other.preferredAudioLanguage) - && TextUtils.equals(preferredTextLanguage, other.preferredTextLanguage) + return Arrays.equals(preferredAudioLanguage, other.preferredAudioLanguage) + && Arrays.equals(preferredTextLanguage, other.preferredTextLanguage) && preferredTextRoleFlags == other.preferredTextRoleFlags && selectUndeterminedTextLanguage == other.selectUndeterminedTextLanguage && disabledTextTrackSelectionFlags == other.disabledTextTrackSelectionFlags; @@ -296,8 +326,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 + Arrays.hashCode(preferredAudioLanguage); + result = 31 * result + Arrays.hashCode(preferredTextLanguage); result = 31 * result + preferredTextRoleFlags; result = 31 * result + (selectUndeterminedTextLanguage ? 1 : 0); result = 31 * result + disabledTextTrackSelectionFlags; @@ -313,8 +343,14 @@ public class TrackSelectionParameters implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(preferredAudioLanguage); - dest.writeString(preferredTextLanguage); + dest.writeInt(preferredAudioLanguage.length); + for (String s : preferredAudioLanguage) { + dest.writeString(s); + } + dest.writeInt(preferredTextLanguage.length); + for (String s : preferredTextLanguage) { + dest.writeString(s); + } dest.writeInt(preferredTextRoleFlags); Util.writeBoolean(dest, selectUndeterminedTextLanguage); dest.writeInt(disabledTextTrackSelectionFlags); From 7bfde6a5ea5402a11640087dc44cbec77aefe217 Mon Sep 17 00:00:00 2001 From: Corentin Zuber Date: Thu, 3 Sep 2020 10:19:55 +0200 Subject: [PATCH 2/2] Fix comments --- .../exoplayer2/offline/DownloadHelper.java | 4 +- .../trackselection/DefaultTrackSelector.java | 48 +++++----- .../TrackSelectionParameters.java | 96 +++++++++---------- .../offline/DownloadHelperTest.java | 12 +-- .../DefaultTrackSelectorTest.java | 24 ++--- 5 files changed, 89 insertions(+), 95 deletions(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadHelper.java b/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadHelper.java index 8cb619f2a2..e944e173b9 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadHelper.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/offline/DownloadHelper.java @@ -654,7 +654,7 @@ public final class DownloadHelper { } } for (String language : languages) { - parametersBuilder.setPreferredAudioLanguage(language); + parametersBuilder.setPreferredAudioLanguages(language); addTrackSelection(periodIndex, parametersBuilder.build()); } } @@ -685,7 +685,7 @@ public final class DownloadHelper { } parametersBuilder.setSelectUndeterminedTextLanguage(selectUndeterminedTextLanguage); for (String language : languages) { - parametersBuilder.setPreferredTextLanguage(language); + parametersBuilder.setPreferredTextLanguages(language); addTrackSelection(periodIndex, parametersBuilder.build()); } } 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 9933a2b023..8abc9b42f0 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; @@ -445,14 +446,8 @@ public class DefaultTrackSelector extends MappingTrackSelector { // Audio @Override - public ParametersBuilder setPreferredAudioLanguage(@Nullable String preferredAudioLanguage) { - super.setPreferredAudioLanguage(preferredAudioLanguage); - return this; - } - - @Override - public ParametersBuilder setPreferredAudioLanguage(String[] preferredAudioLanguage) { - super.setPreferredAudioLanguage(preferredAudioLanguage); + public ParametersBuilder setPreferredAudioLanguages(@Nullable String... preferredAudioLanguages) { + super.setPreferredAudioLanguages(preferredAudioLanguages); return this; } @@ -547,8 +542,8 @@ public class DefaultTrackSelector extends MappingTrackSelector { } @Override - public ParametersBuilder setPreferredTextLanguage(@Nullable String preferredTextLanguage) { - super.setPreferredTextLanguage(preferredTextLanguage); + public ParametersBuilder setPreferredTextLanguages(@Nullable String... preferredTextLanguages) { + super.setPreferredTextLanguages(preferredTextLanguages); return this; } @@ -773,7 +768,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { viewportHeight, viewportOrientationMayChange, // Audio - preferredAudioLanguage, + preferredAudioLanguages, maxAudioChannelCount, maxAudioBitrate, exceedAudioConstraintsIfNecessary, @@ -781,7 +776,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { allowAudioMixedSampleRateAdaptiveness, allowAudioMixedChannelCountAdaptiveness, // Text - preferredTextLanguage, + preferredTextLanguages, preferredTextRoleFlags, selectUndeterminedTextLanguage, disabledTextTrackSelectionFlags, @@ -1021,7 +1016,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { int viewportHeight, boolean viewportOrientationMayChange, // Audio - String[] preferredAudioLanguage, + ImmutableList preferredAudioLanguage, int maxAudioChannelCount, int maxAudioBitrate, boolean exceedAudioConstraintsIfNecessary, @@ -1029,7 +1024,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { boolean allowAudioMixedSampleRateAdaptiveness, boolean allowAudioMixedChannelCountAdaptiveness, // Text - String[] preferredTextLanguage, + ImmutableList preferredTextLanguage, @C.RoleFlags int preferredTextRoleFlags, boolean selectUndeterminedTextLanguage, @C.SelectionFlags int disabledTextTrackSelectionFlags, @@ -2613,6 +2608,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; @@ -2626,14 +2622,18 @@ public class DefaultTrackSelector extends MappingTrackSelector { isWithinRendererCapabilities = isSupported(formatSupport, /* allowExceedsCapabilities= */ false); int bestLanguageScore = 0; - for (int i = 0; i < parameters.preferredAudioLanguage.length; i++) { + int bestLanguageIndex = 0; + for (int i = 0; i < parameters.preferredAudioLanguages.size(); i++) { int score = getFormatLanguageScore( format, - parameters.preferredAudioLanguage[i], + parameters.preferredAudioLanguages.get(i), /* allowUndeterminedFormatLanguage= */ false); - score = 1000 * score + parameters.preferredAudioLanguage.length - i; // Priorise the first items in array - bestLanguageScore = Math.max(bestLanguageScore, score); + if (score > 0) { + bestLanguageIndex = i; + bestLanguageScore = score; + } } + preferredLanguageIndex = bestLanguageIndex; preferredLanguageScore = bestLanguageScore; isDefaultSelectionFlag = (format.selectionFlags & C.SELECTION_FLAG_DEFAULT) != 0; channelCount = format.channelCount; @@ -2677,6 +2677,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( @@ -2729,10 +2733,10 @@ public class DefaultTrackSelector extends MappingTrackSelector { isDefault = (maskedSelectionFlags & C.SELECTION_FLAG_DEFAULT) != 0; isForced = (maskedSelectionFlags & C.SELECTION_FLAG_FORCED) != 0; int bestLanguageScore = 0; - for (int i = 0; i < parameters.preferredTextLanguage.length; i++) { + for (int i = 0; i < parameters.preferredTextLanguages.size(); i++) { int score = getFormatLanguageScore( - format, parameters.preferredTextLanguage[i], parameters.selectUndeterminedTextLanguage); - score = 1000 * score + parameters.preferredTextLanguage.length - i; // Priorise the first items in array + format, parameters.preferredTextLanguages.get(i), parameters.selectUndeterminedTextLanguage); + score = 1000 * score + parameters.preferredTextLanguages.size() - i; // Priorise the first items in array bestLanguageScore = Math.max(bestLanguageScore, score); } preferredLanguageScore = bestLanguageScore; @@ -2746,7 +2750,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { getFormatLanguageScore(format, selectedAudioLanguage, selectedAudioLanguageUndetermined); isWithinConstraints = preferredLanguageScore > 0 - || (parameters.preferredTextLanguage.length == 0 && preferredRoleFlagsScore > 0) + || (parameters.preferredTextLanguages.size() == 0 && preferredRoleFlagsScore > 0) || isDefault || (isForced && selectedAudioLanguageScore > 0); } 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 ac8a84dbf5..b4d54aba38 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 @@ -24,6 +24,8 @@ 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 com.google.common.collect.Lists; import java.util.Arrays; import java.util.Locale; @@ -36,8 +38,8 @@ public class TrackSelectionParameters implements Parcelable { */ public static class Builder { - /* package */ String[] preferredAudioLanguage; - /* package */ String[] preferredTextLanguage; + /* package */ ImmutableList preferredAudioLanguages; + /* package */ ImmutableList preferredTextLanguages; @C.RoleFlags /* package */ int preferredTextRoleFlags; /* package */ boolean selectUndeterminedTextLanguage; @C.SelectionFlags /* package */ int disabledTextTrackSelectionFlags; @@ -59,8 +61,8 @@ public class TrackSelectionParameters implements Parcelable { */ @Deprecated public Builder() { - preferredAudioLanguage = new String[0]; - preferredTextLanguage = new String[0]; + preferredAudioLanguages = ImmutableList.of(); + preferredTextLanguages = ImmutableList.of(); preferredTextRoleFlags = 0; selectUndeterminedTextLanguage = false; disabledTextTrackSelectionFlags = 0; @@ -71,8 +73,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; @@ -81,20 +83,16 @@ public class TrackSelectionParameters implements Parcelable { /** * Sets the preferred language for audio and forced text tracks. * - * @param preferredAudioLanguage Preferred audio language as an IETF BCP 47 conformant tag, or + * @param preferredAudioLanguages 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) { - if (preferredAudioLanguage == null) { - return setPreferredAudioLanguage(new String[0]); + public Builder setPreferredAudioLanguages(@Nullable String... preferredAudioLanguages) { + if (preferredAudioLanguages == null) { + this.preferredAudioLanguages = ImmutableList.of(); } else { - return setPreferredAudioLanguage(new String[] { preferredAudioLanguage }); + this.preferredAudioLanguages = ImmutableList.copyOf(preferredAudioLanguages); } - } - - public Builder setPreferredAudioLanguage(String[] preferredAudioLanguage) { - this.preferredAudioLanguage = preferredAudioLanguage; return this; } @@ -118,20 +116,16 @@ public class TrackSelectionParameters implements Parcelable { /** * Sets the preferred language for text tracks. * - * @param preferredTextLanguage Preferred text language as an IETF BCP 47 conformant tag, or + * @param preferredTextLanguages 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) { - if (preferredTextLanguage == null) { - return setPreferredTextLanguage(new String[0]); + public Builder setPreferredTextLanguages(@Nullable String... preferredTextLanguages) { + if (preferredTextLanguages == null) { + this.preferredTextLanguages = ImmutableList.of(); } else { - return setPreferredTextLanguage(new String[]{preferredTextLanguage}); + this.preferredTextLanguages = ImmutableList.copyOf(preferredTextLanguages); } - } - - public Builder setPreferredTextLanguage(String[] preferredTextLanguage) { - this.preferredTextLanguage = preferredTextLanguage; return this; } @@ -148,7 +142,7 @@ 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 + * {@link #setPreferredTextLanguages(String...)} is available, or if the preferred language is * unset. * * @param selectUndeterminedTextLanguage Whether a text track with undetermined language should @@ -177,9 +171,9 @@ public class TrackSelectionParameters implements Parcelable { public TrackSelectionParameters build() { return new TrackSelectionParameters( // Audio - preferredAudioLanguage, + preferredAudioLanguages, // Text - preferredTextLanguage, + preferredTextLanguages, preferredTextRoleFlags, selectUndeterminedTextLanguage, disabledTextTrackSelectionFlags); @@ -201,7 +195,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 = new String[] { Util.getLocaleLanguageTag(preferredLocale) }; + preferredTextLanguages = ImmutableList.of(Util.getLocaleLanguageTag(preferredLocale)); } } } @@ -238,13 +232,13 @@ public class TrackSelectionParameters implements Parcelable { * {@code null} selects the default track, or the first track if there's no default. The default * value is {@code null}. */ - 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. */ - 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} @@ -254,7 +248,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; @@ -265,21 +259,15 @@ public class TrackSelectionParameters implements Parcelable { @C.SelectionFlags public final int disabledTextTrackSelectionFlags; /* package */ TrackSelectionParameters( - String[] preferredAudioLanguage, - String[] preferredTextLanguage, + ImmutableList preferredAudioLanguages, + ImmutableList preferredTextLanguages, @C.RoleFlags int preferredTextRoleFlags, boolean selectUndeterminedTextLanguage, @C.SelectionFlags int disabledTextTrackSelectionFlags) { // Audio - this.preferredAudioLanguage = new String[preferredAudioLanguage.length]; - for (int i = 0; i < preferredAudioLanguage.length; i++) { - this.preferredAudioLanguage[i] = Util.normalizeLanguageCode(preferredAudioLanguage[i]); - } + this.preferredAudioLanguages = preferredAudioLanguages; // Text - this.preferredTextLanguage = new String[preferredAudioLanguage.length]; - for (int i = 0; i < preferredTextLanguage.length; i++) { - this.preferredTextLanguage[i] = Util.normalizeLanguageCode(preferredTextLanguage[i]); - } + this.preferredTextLanguages = preferredTextLanguages; this.preferredTextRoleFlags = preferredTextRoleFlags; this.selectUndeterminedTextLanguage = selectUndeterminedTextLanguage; this.disabledTextTrackSelectionFlags = disabledTextTrackSelectionFlags; @@ -287,15 +275,17 @@ public class TrackSelectionParameters implements Parcelable { /* package */ TrackSelectionParameters(Parcel in) { int preferredAudioLanguageSize = in.readInt(); - this.preferredAudioLanguage = new String[preferredAudioLanguageSize]; + String[] preferredAudioLanguages = new String[preferredAudioLanguageSize]; for (int i = 0; i < preferredAudioLanguageSize; i++) { - preferredAudioLanguage[i] = in.readString(); + preferredAudioLanguages[i] = in.readString(); } + this.preferredAudioLanguages = ImmutableList.copyOf(preferredAudioLanguages); int preferredTextLanguageSize = in.readInt(); - this.preferredTextLanguage = new String[preferredTextLanguageSize]; + String[] preferredTextLanguages = new String[preferredTextLanguageSize]; for (int i = 0; i < preferredTextLanguageSize; i++) { - preferredTextLanguage[i] = in.readString(); + preferredTextLanguages[i] = in.readString(); } + this.preferredTextLanguages = ImmutableList.copyOf(preferredTextLanguages); this.preferredTextRoleFlags = in.readInt(); this.selectUndeterminedTextLanguage = Util.readBoolean(in); this.disabledTextTrackSelectionFlags = in.readInt(); @@ -316,8 +306,8 @@ public class TrackSelectionParameters implements Parcelable { return false; } TrackSelectionParameters other = (TrackSelectionParameters) obj; - return Arrays.equals(preferredAudioLanguage, other.preferredAudioLanguage) - && Arrays.equals(preferredTextLanguage, other.preferredTextLanguage) + return preferredAudioLanguages.equals(other.preferredAudioLanguages) + && preferredTextLanguages.equals(other.preferredTextLanguages) && preferredTextRoleFlags == other.preferredTextRoleFlags && selectUndeterminedTextLanguage == other.selectUndeterminedTextLanguage && disabledTextTrackSelectionFlags == other.disabledTextTrackSelectionFlags; @@ -326,8 +316,8 @@ public class TrackSelectionParameters implements Parcelable { @Override public int hashCode() { int result = 1; - result = 31 * result + Arrays.hashCode(preferredAudioLanguage); - result = 31 * result + Arrays.hashCode(preferredTextLanguage); + result = 31 * result + preferredAudioLanguages.hashCode(); + result = 31 * result + preferredTextLanguages.hashCode(); result = 31 * result + preferredTextRoleFlags; result = 31 * result + (selectUndeterminedTextLanguage ? 1 : 0); result = 31 * result + disabledTextTrackSelectionFlags; @@ -343,12 +333,12 @@ public class TrackSelectionParameters implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(preferredAudioLanguage.length); - for (String s : preferredAudioLanguage) { + dest.writeInt(preferredAudioLanguages.size()); + for (String s : preferredAudioLanguages) { dest.writeString(s); } - dest.writeInt(preferredTextLanguage.length); - for (String s : preferredTextLanguage) { + dest.writeInt(preferredTextLanguages.size()); + for (String s : preferredTextLanguages) { dest.writeString(s); } dest.writeInt(preferredTextRoleFlags); diff --git a/library/core/src/test/java/com/google/android/exoplayer2/offline/DownloadHelperTest.java b/library/core/src/test/java/com/google/android/exoplayer2/offline/DownloadHelperTest.java index 76f9267430..b974fdca62 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/offline/DownloadHelperTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/offline/DownloadHelperTest.java @@ -251,8 +251,8 @@ public class DownloadHelperTest { prepareDownloadHelper(downloadHelper); DefaultTrackSelector.Parameters parameters = new DefaultTrackSelector.ParametersBuilder(ApplicationProvider.getApplicationContext()) - .setPreferredAudioLanguage("ZH") - .setPreferredTextLanguage("ZH") + .setPreferredAudioLanguages("ZH") + .setPreferredTextLanguages("ZH") .setRendererDisabled(/* rendererIndex= */ 2, true) .build(); @@ -288,8 +288,8 @@ public class DownloadHelperTest { // all video tracks to initial video single track selection. DefaultTrackSelector.Parameters parameters = new DefaultTrackSelector.ParametersBuilder(ApplicationProvider.getApplicationContext()) - .setPreferredAudioLanguage("ZH") - .setPreferredTextLanguage("US") + .setPreferredAudioLanguages("ZH") + .setPreferredTextLanguages("US") .build(); // Add only to one period selection to verify second period selection is untouched. @@ -392,8 +392,8 @@ public class DownloadHelperTest { // also renderers without any track groups. DefaultTrackSelector.Parameters parameters = new DefaultTrackSelector.ParametersBuilder(ApplicationProvider.getApplicationContext()) - .setPreferredAudioLanguage("ZH") - .setPreferredTextLanguage("US") + .setPreferredAudioLanguages("ZH") + .setPreferredTextLanguages("US") .build(); downloadHelper.addTrackSelection(/* periodIndex= */ 0, parameters); byte[] data = new byte[10]; 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..165aefe1f0 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 @@ -283,7 +283,7 @@ public final class DefaultTrackSelectorTest { */ @Test public void setParameterWithNonDefaultParameterNotifyInvalidationListener() { - ParametersBuilder builder = defaultParameters.buildUpon().setPreferredAudioLanguage("eng"); + ParametersBuilder builder = defaultParameters.buildUpon().setPreferredAudioLanguages("eng"); trackSelector.setParameters(builder); verify(invalidationListener).onTrackSelectionsInvalidated(); } @@ -295,7 +295,7 @@ public final class DefaultTrackSelectorTest { */ @Test public void setParameterWithSameParametersDoesNotNotifyInvalidationListenerAgain() { - ParametersBuilder builder = defaultParameters.buildUpon().setPreferredAudioLanguage("eng"); + ParametersBuilder builder = defaultParameters.buildUpon().setPreferredAudioLanguages("eng"); trackSelector.setParameters(builder); trackSelector.setParameters(builder); verify(invalidationListener, times(1)).onTrackSelectionsInvalidated(); @@ -369,7 +369,7 @@ public final class DefaultTrackSelectorTest { Format enAudioFormat = formatBuilder.setLanguage("eng").build(); TrackGroupArray trackGroups = wrapFormats(frAudioFormat, enAudioFormat); - trackSelector.setParameters(defaultParameters.buildUpon().setPreferredAudioLanguage("eng")); + trackSelector.setParameters(defaultParameters.buildUpon().setPreferredAudioLanguages("eng")); TrackSelectorResult result = trackSelector.selectTracks( new RendererCapabilities[] {ALL_AUDIO_FORMAT_SUPPORTED_RENDERER_CAPABILITIES}, @@ -391,7 +391,7 @@ public final class DefaultTrackSelectorTest { Format enNonDefaultFormat = formatBuilder.setLanguage("eng").setSelectionFlags(0).build(); TrackGroupArray trackGroups = wrapFormats(frDefaultFormat, enNonDefaultFormat); - trackSelector.setParameters(defaultParameters.buildUpon().setPreferredAudioLanguage("eng")); + trackSelector.setParameters(defaultParameters.buildUpon().setPreferredAudioLanguages("eng")); TrackSelectorResult result = trackSelector.selectTracks( new RendererCapabilities[] {ALL_AUDIO_FORMAT_SUPPORTED_RENDERER_CAPABILITIES}, @@ -511,7 +511,7 @@ public final class DefaultTrackSelectorTest { RendererCapabilities mappedAudioRendererCapabilities = new FakeMappedRendererCapabilities(C.TRACK_TYPE_AUDIO, mappedCapabilities); - trackSelector.setParameters(defaultParameters.buildUpon().setPreferredAudioLanguage("eng")); + trackSelector.setParameters(defaultParameters.buildUpon().setPreferredAudioLanguages("eng")); TrackSelectorResult result = trackSelector.selectTracks( new RendererCapabilities[] {mappedAudioRendererCapabilities}, @@ -546,7 +546,7 @@ public final class DefaultTrackSelectorTest { RendererCapabilities mappedAudioRendererCapabilities = new FakeMappedRendererCapabilities(C.TRACK_TYPE_AUDIO, mappedCapabilities); - trackSelector.setParameters(defaultParameters.buildUpon().setPreferredAudioLanguage("eng")); + trackSelector.setParameters(defaultParameters.buildUpon().setPreferredAudioLanguages("eng")); TrackSelectorResult result = trackSelector.selectTracks( new RendererCapabilities[] {mappedAudioRendererCapabilities}, @@ -841,7 +841,7 @@ public final class DefaultTrackSelectorTest { // There is a preferred language, so a language-matching track flagged as default should // be selected, and the one without forced flag should be preferred. - trackSelector.setParameters(defaultParameters.buildUpon().setPreferredTextLanguage("eng")); + trackSelector.setParameters(defaultParameters.buildUpon().setPreferredTextLanguages("eng")); result = trackSelector.selectTracks(textRendererCapabilities, trackGroups, periodId, TIMELINE); assertFixedSelection(result.selections.get(0), trackGroups, defaultOnly); @@ -929,7 +929,7 @@ public final class DefaultTrackSelectorTest { result = trackSelector.selectTracks(textRendererCapabilites, trackGroups, periodId, TIMELINE); assertFixedSelection(result.selections.get(0), trackGroups, undeterminedUnd); - ParametersBuilder builder = defaultParameters.buildUpon().setPreferredTextLanguage("spa"); + ParametersBuilder builder = defaultParameters.buildUpon().setPreferredTextLanguages("spa"); trackSelector.setParameters(builder); result = trackSelector.selectTracks(textRendererCapabilites, trackGroups, periodId, TIMELINE); assertFixedSelection(result.selections.get(0), trackGroups, spanish); @@ -984,13 +984,13 @@ public final class DefaultTrackSelectorTest { assertNoSelection(result.selections.get(1)); // Explicit language preference for english. First renderer should be used. - trackSelector.setParameters(defaultParameters.buildUpon().setPreferredTextLanguage("en")); + trackSelector.setParameters(defaultParameters.buildUpon().setPreferredTextLanguages("en")); result = trackSelector.selectTracks(rendererCapabilities, trackGroups, periodId, TIMELINE); assertFixedSelection(result.selections.get(0), trackGroups, english); assertNoSelection(result.selections.get(1)); // Explicit language preference for German. Second renderer should be used. - trackSelector.setParameters(defaultParameters.buildUpon().setPreferredTextLanguage("de")); + trackSelector.setParameters(defaultParameters.buildUpon().setPreferredTextLanguages("de")); result = trackSelector.selectTracks(rendererCapabilities, trackGroups, periodId, TIMELINE); assertNoSelection(result.selections.get(0)); assertFixedSelection(result.selections.get(1), trackGroups, german); @@ -1290,13 +1290,13 @@ public final class DefaultTrackSelectorTest { assertNoSelection(result.selections.get(1)); // Explicit language preference for english. First renderer should be used. - trackSelector.setParameters(defaultParameters.buildUpon().setPreferredAudioLanguage("en")); + trackSelector.setParameters(defaultParameters.buildUpon().setPreferredAudioLanguages("en")); result = trackSelector.selectTracks(rendererCapabilities, trackGroups, periodId, TIMELINE); assertFixedSelection(result.selections.get(0), trackGroups, english); assertNoSelection(result.selections.get(1)); // Explicit language preference for German. Second renderer should be used. - trackSelector.setParameters(defaultParameters.buildUpon().setPreferredAudioLanguage("de")); + trackSelector.setParameters(defaultParameters.buildUpon().setPreferredAudioLanguages("de")); result = trackSelector.selectTracks(rendererCapabilities, trackGroups, periodId, TIMELINE); assertNoSelection(result.selections.get(0)); assertFixedSelection(result.selections.get(1), trackGroups, german);