From 0ccf816a5caabb99484cfedc23df9a703edfc68e Mon Sep 17 00:00:00 2001 From: aquilescanta Date: Thu, 14 Dec 2017 06:54:12 -0800 Subject: [PATCH] Add a bitmask for text tracks' selection flags in DefaultTrackSelector ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=179039563 --- RELEASENOTES.md | 2 + .../trackselection/DefaultTrackSelector.java | 128 +++++++++++++----- .../DefaultTrackSelectorTest.java | 128 ++++++++++++++++++ 3 files changed, 226 insertions(+), 32 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 9875333dad..686a6d10ba 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -29,6 +29,8 @@ ([#3149](https://github.com/google/ExoPlayer/issues/3149)). * DefaultTrackSelector: Replace `DefaultTrackSelector.Parameters` copy methods with a builder. +* DefaultTrackSelector: Support disabling of individual text track selection + flags. * New Cast extension: Simplifies toggling between local and Cast playbacks. ### 2.6.1 ### 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 2f0dc8f04e..09bd81416c 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 @@ -82,6 +82,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { private String preferredAudioLanguage; private String preferredTextLanguage; private boolean selectUndeterminedTextLanguage; + private int disabledTextTrackSelectionFlags; private boolean forceLowestBitrate; private boolean allowMixedMimeAdaptiveness; private boolean allowNonSeamlessAdaptiveness; @@ -109,6 +110,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { preferredAudioLanguage = initialValues.preferredAudioLanguage; preferredTextLanguage = initialValues.preferredTextLanguage; selectUndeterminedTextLanguage = initialValues.selectUndeterminedTextLanguage; + disabledTextTrackSelectionFlags = initialValues.disabledTextTrackSelectionFlags; forceLowestBitrate = initialValues.forceLowestBitrate; allowMixedMimeAdaptiveness = initialValues.allowMixedMimeAdaptiveness; allowNonSeamlessAdaptiveness = initialValues.allowNonSeamlessAdaptiveness; @@ -153,6 +155,17 @@ public class DefaultTrackSelector extends MappingTrackSelector { return this; } + /** + * See {@link Parameters#disabledTextTrackSelectionFlags}. + * + * @return This builder. + */ + public ParametersBuilder setDisabledTextTrackSelectionFlags( + int disabledTextTrackSelectionFlags) { + this.disabledTextTrackSelectionFlags = disabledTextTrackSelectionFlags; + return this; + } + /** * See {@link Parameters#forceLowestBitrate}. * @@ -287,11 +300,22 @@ public class DefaultTrackSelector extends MappingTrackSelector { * Builds a {@link Parameters} instance with the selected values. */ public Parameters build() { - return new Parameters(preferredAudioLanguage, preferredTextLanguage, - selectUndeterminedTextLanguage, forceLowestBitrate, allowMixedMimeAdaptiveness, - allowNonSeamlessAdaptiveness, maxVideoWidth, maxVideoHeight, maxVideoBitrate, - exceedVideoConstraintsIfNecessary, exceedRendererCapabilitiesIfNecessary, viewportWidth, - viewportHeight, viewportOrientationMayChange); + return new Parameters( + preferredAudioLanguage, + preferredTextLanguage, + selectUndeterminedTextLanguage, + disabledTextTrackSelectionFlags, + forceLowestBitrate, + allowMixedMimeAdaptiveness, + allowNonSeamlessAdaptiveness, + maxVideoWidth, + maxVideoHeight, + maxVideoBitrate, + exceedVideoConstraintsIfNecessary, + exceedRendererCapabilitiesIfNecessary, + viewportWidth, + viewportHeight, + viewportOrientationMayChange); } } @@ -303,19 +327,21 @@ public class DefaultTrackSelector extends MappingTrackSelector { /** * An instance with default values: + * * */ public static final Parameters DEFAULT = new Parameters(); @@ -338,6 +364,11 @@ public class DefaultTrackSelector extends MappingTrackSelector { * {@link #preferredTextLanguage} is available, or if {@link #preferredTextLanguage} is unset. */ public final boolean selectUndeterminedTextLanguage; + /** + * Bitmask of selection flags that are disabled for text track selections. See {@link + * C.SelectionFlags}. + */ + public final int disabledTextTrackSelectionFlags; // Video /** @@ -392,19 +423,44 @@ public class DefaultTrackSelector extends MappingTrackSelector { public final boolean exceedRendererCapabilitiesIfNecessary; private Parameters() { - this(null, null, false, false, false, true, Integer.MAX_VALUE, Integer.MAX_VALUE, - Integer.MAX_VALUE, true, true, Integer.MAX_VALUE, Integer.MAX_VALUE, true); + this( + null, + null, + false, + 0, + false, + false, + true, + Integer.MAX_VALUE, + Integer.MAX_VALUE, + Integer.MAX_VALUE, + true, + true, + Integer.MAX_VALUE, + Integer.MAX_VALUE, + true); } - private Parameters(String preferredAudioLanguage, String preferredTextLanguage, - boolean selectUndeterminedTextLanguage, boolean forceLowestBitrate, - boolean allowMixedMimeAdaptiveness, boolean allowNonSeamlessAdaptiveness, int maxVideoWidth, - int maxVideoHeight, int maxVideoBitrate, boolean exceedVideoConstraintsIfNecessary, - boolean exceedRendererCapabilitiesIfNecessary, int viewportWidth, int viewportHeight, + private Parameters( + String preferredAudioLanguage, + String preferredTextLanguage, + boolean selectUndeterminedTextLanguage, + int disabledTextTrackSelectionFlags, + boolean forceLowestBitrate, + boolean allowMixedMimeAdaptiveness, + boolean allowNonSeamlessAdaptiveness, + int maxVideoWidth, + int maxVideoHeight, + int maxVideoBitrate, + boolean exceedVideoConstraintsIfNecessary, + boolean exceedRendererCapabilitiesIfNecessary, + int viewportWidth, + int viewportHeight, boolean viewportOrientationMayChange) { this.preferredAudioLanguage = Util.normalizeLanguageCode(preferredAudioLanguage); this.preferredTextLanguage = Util.normalizeLanguageCode(preferredTextLanguage); this.selectUndeterminedTextLanguage = selectUndeterminedTextLanguage; + this.disabledTextTrackSelectionFlags = disabledTextTrackSelectionFlags; this.forceLowestBitrate = forceLowestBitrate; this.allowMixedMimeAdaptiveness = allowMixedMimeAdaptiveness; this.allowNonSeamlessAdaptiveness = allowNonSeamlessAdaptiveness; @@ -434,14 +490,18 @@ public class DefaultTrackSelector extends MappingTrackSelector { return false; } Parameters other = (Parameters) obj; - return forceLowestBitrate == other.forceLowestBitrate + return selectUndeterminedTextLanguage == other.selectUndeterminedTextLanguage + && disabledTextTrackSelectionFlags == other.disabledTextTrackSelectionFlags + && forceLowestBitrate == other.forceLowestBitrate && allowMixedMimeAdaptiveness == other.allowMixedMimeAdaptiveness && allowNonSeamlessAdaptiveness == other.allowNonSeamlessAdaptiveness - && maxVideoWidth == other.maxVideoWidth && maxVideoHeight == other.maxVideoHeight + && maxVideoWidth == other.maxVideoWidth + && maxVideoHeight == other.maxVideoHeight && exceedVideoConstraintsIfNecessary == other.exceedVideoConstraintsIfNecessary && exceedRendererCapabilitiesIfNecessary == other.exceedRendererCapabilitiesIfNecessary && viewportOrientationMayChange == other.viewportOrientationMayChange - && viewportWidth == other.viewportWidth && viewportHeight == other.viewportHeight + && viewportWidth == other.viewportWidth + && viewportHeight == other.viewportHeight && maxVideoBitrate == other.maxVideoBitrate && TextUtils.equals(preferredAudioLanguage, other.preferredAudioLanguage) && TextUtils.equals(preferredTextLanguage, other.preferredTextLanguage); @@ -449,19 +509,21 @@ public class DefaultTrackSelector extends MappingTrackSelector { @Override public int hashCode() { - int result = preferredAudioLanguage.hashCode(); - result = 31 * result + preferredTextLanguage.hashCode(); + int result = selectUndeterminedTextLanguage ? 1 : 0; + result = 31 * result + disabledTextTrackSelectionFlags; result = 31 * result + (forceLowestBitrate ? 1 : 0); result = 31 * result + (allowMixedMimeAdaptiveness ? 1 : 0); result = 31 * result + (allowNonSeamlessAdaptiveness ? 1 : 0); result = 31 * result + maxVideoWidth; result = 31 * result + maxVideoHeight; - result = 31 * result + maxVideoBitrate; result = 31 * result + (exceedVideoConstraintsIfNecessary ? 1 : 0); result = 31 * result + (exceedRendererCapabilitiesIfNecessary ? 1 : 0); result = 31 * result + (viewportOrientationMayChange ? 1 : 0); result = 31 * result + viewportWidth; result = 31 * result + viewportHeight; + result = 31 * result + maxVideoBitrate; + result = 31 * result + preferredAudioLanguage.hashCode(); + result = 31 * result + preferredTextLanguage.hashCode(); return result; } @@ -923,8 +985,10 @@ public class DefaultTrackSelector extends MappingTrackSelector { if (isSupported(trackFormatSupport[trackIndex], params.exceedRendererCapabilitiesIfNecessary)) { Format format = trackGroup.getFormat(trackIndex); - boolean isDefault = (format.selectionFlags & C.SELECTION_FLAG_DEFAULT) != 0; - boolean isForced = (format.selectionFlags & C.SELECTION_FLAG_FORCED) != 0; + int maskedSelectionFlags = + format.selectionFlags & ~params.disabledTextTrackSelectionFlags; + boolean isDefault = (maskedSelectionFlags & C.SELECTION_FLAG_DEFAULT) != 0; + boolean isForced = (maskedSelectionFlags & C.SELECTION_FLAG_FORCED) != 0; int trackScore; boolean preferredLanguageFound = formatHasLanguage(format, params.preferredTextLanguage); if (preferredLanguageFound 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 1eff48b730..24362d1570 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 @@ -529,6 +529,134 @@ public final class DefaultTrackSelectorTest { .isEqualTo(lowerSampleRateHigherBitrateFormat); } + /** Tests text track selection flags. */ + @Test + public void testsTextTrackSelectionFlags() throws ExoPlaybackException { + Format forcedOnly = + Format.createTextContainerFormat( + "forcedOnly", + null, + MimeTypes.TEXT_VTT, + null, + Format.NO_VALUE, + C.SELECTION_FLAG_FORCED, + "eng"); + Format forcedDefault = + Format.createTextContainerFormat( + "forcedDefault", + null, + MimeTypes.TEXT_VTT, + null, + Format.NO_VALUE, + C.SELECTION_FLAG_FORCED | C.SELECTION_FLAG_DEFAULT, + "eng"); + Format defaultOnly = + Format.createTextContainerFormat( + "defaultOnly", + null, + MimeTypes.TEXT_VTT, + null, + Format.NO_VALUE, + C.SELECTION_FLAG_DEFAULT, + "eng"); + Format forcedOnlySpanish = + Format.createTextContainerFormat( + "forcedOnlySpanish", + null, + MimeTypes.TEXT_VTT, + null, + Format.NO_VALUE, + C.SELECTION_FLAG_FORCED, + "spa"); + Format noFlag = + Format.createTextContainerFormat( + "noFlag", null, MimeTypes.TEXT_VTT, null, Format.NO_VALUE, 0, "eng"); + + RendererCapabilities[] textRendererCapabilities = + new RendererCapabilities[] {ALL_TEXT_FORMAT_SUPPORTED_RENDERER_CAPABILITIES}; + + TrackSelectorResult result; + + // There is no text language preference, the first track flagged as default should be selected. + result = + trackSelector.selectTracks( + textRendererCapabilities, wrapFormats(forcedOnly, forcedDefault, defaultOnly, noFlag)); + assertThat(result.selections.get(0).getFormat(0)).isSameAs(forcedDefault); + + // Ditto. + result = + trackSelector.selectTracks( + textRendererCapabilities, wrapFormats(forcedOnly, noFlag, defaultOnly)); + assertThat(result.selections.get(0).getFormat(0)).isSameAs(defaultOnly); + + // With no language preference and no text track flagged as default, the first forced should be + // selected. + result = trackSelector.selectTracks(textRendererCapabilities, wrapFormats(forcedOnly, noFlag)); + assertThat(result.selections.get(0).getFormat(0)).isSameAs(forcedOnly); + + trackSelector.setParameters( + Parameters.DEFAULT + .buildUpon() + .setDisabledTextTrackSelectionFlags(C.SELECTION_FLAG_DEFAULT) + .build()); + + // Default flags are disabled, so the first track flagged as forced should be selected. + result = + trackSelector.selectTracks( + textRendererCapabilities, wrapFormats(defaultOnly, noFlag, forcedOnly, forcedDefault)); + assertThat(result.selections.get(0).getFormat(0)).isSameAs(forcedOnly); + + trackSelector.setParameters( + trackSelector.getParameters().buildUpon().setPreferredAudioLanguage("spa").build()); + + // Default flags are disabled, but there is a text track flagged as forced whose language + // matches the preferred audio language. + result = + trackSelector.selectTracks( + textRendererCapabilities, + wrapFormats(forcedDefault, forcedOnly, defaultOnly, noFlag, forcedOnlySpanish)); + assertThat(result.selections.get(0).getFormat(0)).isSameAs(forcedOnlySpanish); + + trackSelector.setParameters( + trackSelector + .getParameters() + .buildUpon() + .setDisabledTextTrackSelectionFlags(C.SELECTION_FLAG_DEFAULT | C.SELECTION_FLAG_FORCED) + .build()); + + // All selection flags are disabled and there is no language preference, so nothing should be + // selected. + result = + trackSelector.selectTracks( + textRendererCapabilities, wrapFormats(forcedOnly, forcedDefault, defaultOnly, noFlag)); + assertThat(result.selections.get(0)).isNull(); + + trackSelector.setParameters( + Parameters.DEFAULT.buildUpon().setPreferredTextLanguage("eng").build()); + + // There is a preferred language, so the first language-matching track flagged as default should + // be selected. + result = + trackSelector.selectTracks( + textRendererCapabilities, wrapFormats(forcedOnly, forcedDefault, defaultOnly, noFlag)); + assertThat(result.selections.get(0).getFormat(0)).isSameAs(forcedDefault); + + trackSelector.setParameters( + trackSelector + .getParameters() + .buildUpon() + .setDisabledTextTrackSelectionFlags(C.SELECTION_FLAG_DEFAULT) + .build()); + + // Same as above, but the default flag is disabled. If multiple tracks match the preferred + // language, those not flagged as forced are preferred, as they likely include the contents of + // forced subtitles. + result = + trackSelector.selectTracks( + textRendererCapabilities, wrapFormats(noFlag, forcedOnly, forcedDefault, defaultOnly)); + assertThat(result.selections.get(0).getFormat(0)).isSameAs(noFlag); + } + /** * Tests that the default track selector will select a text track with undetermined language if no * text track with the preferred language is available but