From 73d6a0f2bdd48b8a335b485511bc088ad748e158 Mon Sep 17 00:00:00 2001 From: Yannick RUI Date: Thu, 8 Aug 2019 09:17:55 +0200 Subject: [PATCH 1/3] Automatically show closed captioning/hearing impaired text track --- .../trackselection/DefaultTrackSelector.java | 17 +++++++++++- .../TrackSelectionParameters.java | 26 +++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) 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 cc1742bb31..e20daeebad 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 @@ -432,6 +432,12 @@ public class DefaultTrackSelector extends MappingTrackSelector { return this; } + @Override + public ParametersBuilder setPreferredRoleFlags(int preferredRoleFlags) { + super.setPreferredRoleFlags(preferredRoleFlags); + return this; + } + @Override public ParametersBuilder setSelectUndeterminedTextLanguage( boolean selectUndeterminedTextLanguage) { @@ -642,6 +648,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { allowAudioMixedSampleRateAdaptiveness, // Text preferredTextLanguage, + preferredRoleFlags, selectUndeterminedTextLanguage, disabledTextTrackSelectionFlags, // General @@ -837,6 +844,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { /* allowAudioMixedSampleRateAdaptiveness= */ false, // Text TrackSelectionParameters.DEFAULT.preferredTextLanguage, + TrackSelectionParameters.DEFAULT.preferredRoleFlags, TrackSelectionParameters.DEFAULT.selectUndeterminedTextLanguage, TrackSelectionParameters.DEFAULT.disabledTextTrackSelectionFlags, // General @@ -869,6 +877,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { boolean allowAudioMixedSampleRateAdaptiveness, // Text @Nullable String preferredTextLanguage, + int preferredRoleFlags, boolean selectUndeterminedTextLanguage, @C.SelectionFlags int disabledTextTrackSelectionFlags, // General @@ -882,6 +891,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { super( preferredAudioLanguage, preferredTextLanguage, + preferredRoleFlags, selectUndeterminedTextLanguage, disabledTextTrackSelectionFlags); // Video @@ -2590,6 +2600,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { private final boolean isDefault; private final boolean hasPreferredIsForcedFlag; private final int preferredLanguageScore; + private final int preferredRoleFlagsScore; private final int selectedAudioLanguageScore; public TextTrackScore( @@ -2606,6 +2617,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { preferredLanguageScore = getFormatLanguageScore( format, parameters.preferredTextLanguage, parameters.selectUndeterminedTextLanguage); + preferredRoleFlagsScore = format.roleFlags & parameters.preferredRoleFlags; // Prefer non-forced to forced if a preferred text language has been matched. Where both are // provided the non-forced track will usually contain the forced subtitles as a subset. // Otherwise, prefer a forced track. @@ -2616,7 +2628,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { selectedAudioLanguageScore = getFormatLanguageScore(format, selectedAudioLanguage, selectedAudioLanguageUndetermined); isWithinConstraints = - preferredLanguageScore > 0 || isDefault || (isForced && selectedAudioLanguageScore > 0); + (preferredLanguageScore > 0 || (parameters.preferredTextLanguage == null && selectedAudioLanguageScore > 0 && preferredRoleFlagsScore > 0)) || isDefault || (isForced && selectedAudioLanguageScore > 0); } /** @@ -2634,6 +2646,9 @@ public class DefaultTrackSelector extends MappingTrackSelector { if (this.preferredLanguageScore != other.preferredLanguageScore) { return compareInts(this.preferredLanguageScore, other.preferredLanguageScore); } + if (this.preferredRoleFlagsScore != other.preferredRoleFlagsScore) { + return compareInts(this.preferredRoleFlagsScore, other.preferredRoleFlagsScore); + } if (this.isDefault != other.isDefault) { return this.isDefault ? 1 : -1; } 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 81af551b68..2edbbc8bd4 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 @@ -33,6 +33,7 @@ public class TrackSelectionParameters implements Parcelable { @Nullable /* package */ String preferredAudioLanguage; @Nullable /* package */ String preferredTextLanguage; + @C.RoleFlags /* package */ int preferredRoleFlags; /* package */ boolean selectUndeterminedTextLanguage; @C.SelectionFlags /* package */ int disabledTextTrackSelectionFlags; @@ -48,6 +49,7 @@ public class TrackSelectionParameters implements Parcelable { /* package */ Builder(TrackSelectionParameters initialValues) { preferredAudioLanguage = initialValues.preferredAudioLanguage; preferredTextLanguage = initialValues.preferredTextLanguage; + preferredRoleFlags = initialValues.preferredRoleFlags; selectUndeterminedTextLanguage = initialValues.selectUndeterminedTextLanguage; disabledTextTrackSelectionFlags = initialValues.disabledTextTrackSelectionFlags; } @@ -74,6 +76,17 @@ public class TrackSelectionParameters implements Parcelable { return this; } + /** + * See {@link TrackSelectionParameters#preferredRoleFlags}. + * + * @param preferredRoleFlags Preferred role flags. + * @return This builder. + */ + public Builder setPreferredRoleFlags(int preferredRoleFlags) { + this.preferredRoleFlags = preferredRoleFlags; + return this; + } + /** * See {@link TrackSelectionParameters#selectUndeterminedTextLanguage}. * @@ -102,6 +115,7 @@ public class TrackSelectionParameters implements Parcelable { preferredAudioLanguage, // Text preferredTextLanguage, + preferredRoleFlags, selectUndeterminedTextLanguage, disabledTextTrackSelectionFlags); } @@ -121,6 +135,11 @@ public class TrackSelectionParameters implements Parcelable { * the default track if there is one, or no track otherwise. The default value is {@code null}. */ @Nullable public final String preferredTextLanguage; + /** + * The preferred role flags for text tracks. {@code 0} selects + * the default track if there is one, or no track otherwise. The default value is {@code 0}. + */ + @Nullable public final int preferredRoleFlags; /** * 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 @@ -138,6 +157,7 @@ public class TrackSelectionParameters implements Parcelable { /* preferredAudioLanguage= */ null, // Text /* preferredTextLanguage= */ null, + /* preferredRoleFlags= */ 0, /* selectUndeterminedTextLanguage= */ false, /* disabledTextTrackSelectionFlags= */ 0); } @@ -145,12 +165,14 @@ public class TrackSelectionParameters implements Parcelable { /* package */ TrackSelectionParameters( @Nullable String preferredAudioLanguage, @Nullable String preferredTextLanguage, + int preferredRoleFlags, boolean selectUndeterminedTextLanguage, @C.SelectionFlags int disabledTextTrackSelectionFlags) { // Audio this.preferredAudioLanguage = Util.normalizeLanguageCode(preferredAudioLanguage); // Text this.preferredTextLanguage = Util.normalizeLanguageCode(preferredTextLanguage); + this.preferredRoleFlags = preferredRoleFlags; this.selectUndeterminedTextLanguage = selectUndeterminedTextLanguage; this.disabledTextTrackSelectionFlags = disabledTextTrackSelectionFlags; } @@ -158,6 +180,7 @@ public class TrackSelectionParameters implements Parcelable { /* package */ TrackSelectionParameters(Parcel in) { this.preferredAudioLanguage = in.readString(); this.preferredTextLanguage = in.readString(); + this.preferredRoleFlags = in.readInt(); this.selectUndeterminedTextLanguage = Util.readBoolean(in); this.disabledTextTrackSelectionFlags = in.readInt(); } @@ -179,6 +202,7 @@ public class TrackSelectionParameters implements Parcelable { TrackSelectionParameters other = (TrackSelectionParameters) obj; return TextUtils.equals(preferredAudioLanguage, other.preferredAudioLanguage) && TextUtils.equals(preferredTextLanguage, other.preferredTextLanguage) + && preferredRoleFlags == other.preferredRoleFlags && selectUndeterminedTextLanguage == other.selectUndeterminedTextLanguage && disabledTextTrackSelectionFlags == other.disabledTextTrackSelectionFlags; } @@ -188,6 +212,7 @@ public class TrackSelectionParameters implements Parcelable { int result = 1; result = 31 * result + (preferredAudioLanguage == null ? 0 : preferredAudioLanguage.hashCode()); result = 31 * result + (preferredTextLanguage == null ? 0 : preferredTextLanguage.hashCode()); + result = 31 * result + (preferredRoleFlags); result = 31 * result + (selectUndeterminedTextLanguage ? 1 : 0); result = 31 * result + disabledTextTrackSelectionFlags; return result; @@ -204,6 +229,7 @@ public class TrackSelectionParameters implements Parcelable { public void writeToParcel(Parcel dest, int flags) { dest.writeString(preferredAudioLanguage); dest.writeString(preferredTextLanguage); + dest.writeInt(preferredRoleFlags); Util.writeBoolean(dest, selectUndeterminedTextLanguage); dest.writeInt(disabledTextTrackSelectionFlags); } From 831de75f89f2c3230323277d3899def6b1306788 Mon Sep 17 00:00:00 2001 From: Yannick RUI Date: Fri, 9 Aug 2019 10:42:12 +0200 Subject: [PATCH 2/3] Missing documentation link --- .../android/exoplayer2/trackselection/DefaultTrackSelector.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 e20daeebad..d07682f3b9 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 @@ -877,7 +877,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { boolean allowAudioMixedSampleRateAdaptiveness, // Text @Nullable String preferredTextLanguage, - int preferredRoleFlags, + @C.RoleFlags int preferredRoleFlags, boolean selectUndeterminedTextLanguage, @C.SelectionFlags int disabledTextTrackSelectionFlags, // General From 5f4887173143bc53d069f7e61165141b7d206ea2 Mon Sep 17 00:00:00 2001 From: Yannick RUI Date: Thu, 5 Sep 2019 17:31:24 +0200 Subject: [PATCH 3/3] Count the number of matches for role flags. Select a track with matching role flags even if someone specifies a preferred role flgs without providing a preferred language Prefer track without captions or describing music and sound flag when no role flag preference is provided. --- .../trackselection/DefaultTrackSelector.java | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 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 0c96309fdc..f0b6f7e69b 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 @@ -2695,6 +2695,8 @@ public class DefaultTrackSelector extends MappingTrackSelector { private final boolean isWithinRendererCapabilities; private final boolean isDefault; private final boolean hasPreferredIsForcedFlag; + private final boolean hasPreferredRoleFlags; + private final int hasCaptionRoleFlags; private final int preferredLanguageScore; private final int preferredRoleFlagsScore; private final int selectedAudioLanguageScore; @@ -2713,18 +2715,21 @@ public class DefaultTrackSelector extends MappingTrackSelector { preferredLanguageScore = getFormatLanguageScore( format, parameters.preferredTextLanguage, parameters.selectUndeterminedTextLanguage); - preferredRoleFlagsScore = format.roleFlags & parameters.preferredRoleFlags; + preferredRoleFlagsScore = Integer.bitCount(format.roleFlags & parameters.preferredRoleFlags); // Prefer non-forced to forced if a preferred text language has been matched. Where both are // provided the non-forced track will usually contain the forced subtitles as a subset. // Otherwise, prefer a forced track. hasPreferredIsForcedFlag = (preferredLanguageScore > 0 && !isForced) || (preferredLanguageScore == 0 && isForced); + hasPreferredRoleFlags = parameters.preferredRoleFlags > 0; + hasCaptionRoleFlags = Integer.bitCount(format.roleFlags + & (C.ROLE_FLAG_CAPTION | C.ROLE_FLAG_DESCRIBES_MUSIC_AND_SOUND)); boolean selectedAudioLanguageUndetermined = normalizeUndeterminedLanguageToNull(selectedAudioLanguage) == null; selectedAudioLanguageScore = getFormatLanguageScore(format, selectedAudioLanguage, selectedAudioLanguageUndetermined); isWithinConstraints = - (preferredLanguageScore > 0 || (parameters.preferredTextLanguage == null && selectedAudioLanguageScore > 0 && preferredRoleFlagsScore > 0)) || isDefault || (isForced && selectedAudioLanguageScore > 0); + (preferredLanguageScore > 0 || (parameters.preferredTextLanguage == null && preferredRoleFlagsScore > 0)) || isDefault || (isForced && selectedAudioLanguageScore > 0); } /** @@ -2742,16 +2747,23 @@ public class DefaultTrackSelector extends MappingTrackSelector { if (this.preferredLanguageScore != other.preferredLanguageScore) { return compareInts(this.preferredLanguageScore, other.preferredLanguageScore); } - if (this.preferredRoleFlagsScore != other.preferredRoleFlagsScore) { - return compareInts(this.preferredRoleFlagsScore, other.preferredRoleFlagsScore); - } if (this.isDefault != other.isDefault) { return this.isDefault ? 1 : -1; } if (this.hasPreferredIsForcedFlag != other.hasPreferredIsForcedFlag) { return this.hasPreferredIsForcedFlag ? 1 : -1; } - return compareInts(this.selectedAudioLanguageScore, other.selectedAudioLanguageScore); + if (this.selectedAudioLanguageScore != other.selectedAudioLanguageScore) { + return compareInts(this.selectedAudioLanguageScore, other.selectedAudioLanguageScore); + } + + // If no role flag preference is provided in the parameters, prefer tracks + // without C.ROLE_FLAG_CAPTION or C.ROLE_FLAG_DESCRIBES_MUSIC_AND_SOUND + // No specification means that non-captioning text tracks are preferred. + if (!this.hasPreferredRoleFlags) { + return compareInts(other.hasCaptionRoleFlags, this.hasCaptionRoleFlags); + } + return compareInts(this.preferredRoleFlagsScore, other.preferredRoleFlagsScore); } } }