Merge pull request #7814 from zubcoco:dev-v2

PiperOrigin-RevId: 330366909
This commit is contained in:
Oliver Woodman 2020-09-07 20:43:30 +01:00
commit 442aa78196
4 changed files with 159 additions and 55 deletions

View File

@ -6,6 +6,8 @@
* Add `SampleQueue.discardUpstreamFrom` so upstream samples can be * Add `SampleQueue.discardUpstreamFrom` so upstream samples can be
discarded by timestamp. discarded by timestamp.
* Add `SampleQueue.getLargestReadTimestampUs`. * 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) ### ### 2.12.0 (not yet released - targeted for 2020-09-03) ###

View File

@ -39,6 +39,7 @@ import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.common.collect.ComparisonChain; import com.google.common.collect.ComparisonChain;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Ordering; import com.google.common.collect.Ordering;
import com.google.common.primitives.Ints; import com.google.common.primitives.Ints;
import java.util.ArrayList; import java.util.ArrayList;
@ -450,6 +451,12 @@ public class DefaultTrackSelector extends MappingTrackSelector {
return this; return this;
} }
@Override
public ParametersBuilder setPreferredAudioLanguages(String... preferredAudioLanguages) {
super.setPreferredAudioLanguages(preferredAudioLanguages);
return this;
}
/** /**
* Sets the maximum allowed audio channel count. * Sets the maximum allowed audio channel count.
* *
@ -546,6 +553,12 @@ public class DefaultTrackSelector extends MappingTrackSelector {
return this; return this;
} }
@Override
public ParametersBuilder setPreferredTextLanguages(String... preferredTextLanguages) {
super.setPreferredTextLanguages(preferredTextLanguages);
return this;
}
@Override @Override
public ParametersBuilder setPreferredTextRoleFlags(@C.RoleFlags int preferredTextRoleFlags) { public ParametersBuilder setPreferredTextRoleFlags(@C.RoleFlags int preferredTextRoleFlags) {
super.setPreferredTextRoleFlags(preferredTextRoleFlags); super.setPreferredTextRoleFlags(preferredTextRoleFlags);
@ -767,7 +780,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
viewportHeight, viewportHeight,
viewportOrientationMayChange, viewportOrientationMayChange,
// Audio // Audio
preferredAudioLanguage, preferredAudioLanguages,
maxAudioChannelCount, maxAudioChannelCount,
maxAudioBitrate, maxAudioBitrate,
exceedAudioConstraintsIfNecessary, exceedAudioConstraintsIfNecessary,
@ -775,7 +788,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
allowAudioMixedSampleRateAdaptiveness, allowAudioMixedSampleRateAdaptiveness,
allowAudioMixedChannelCountAdaptiveness, allowAudioMixedChannelCountAdaptiveness,
// Text // Text
preferredTextLanguage, preferredTextLanguages,
preferredTextRoleFlags, preferredTextRoleFlags,
selectUndeterminedTextLanguage, selectUndeterminedTextLanguage,
disabledTextTrackSelectionFlags, disabledTextTrackSelectionFlags,
@ -1015,7 +1028,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
int viewportHeight, int viewportHeight,
boolean viewportOrientationMayChange, boolean viewportOrientationMayChange,
// Audio // Audio
@Nullable String preferredAudioLanguage, ImmutableList<String> preferredAudioLanguages,
int maxAudioChannelCount, int maxAudioChannelCount,
int maxAudioBitrate, int maxAudioBitrate,
boolean exceedAudioConstraintsIfNecessary, boolean exceedAudioConstraintsIfNecessary,
@ -1023,7 +1036,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
boolean allowAudioMixedSampleRateAdaptiveness, boolean allowAudioMixedSampleRateAdaptiveness,
boolean allowAudioMixedChannelCountAdaptiveness, boolean allowAudioMixedChannelCountAdaptiveness,
// Text // Text
@Nullable String preferredTextLanguage, ImmutableList<String> preferredTextLanguages,
@C.RoleFlags int preferredTextRoleFlags, @C.RoleFlags int preferredTextRoleFlags,
boolean selectUndeterminedTextLanguage, boolean selectUndeterminedTextLanguage,
@C.SelectionFlags int disabledTextTrackSelectionFlags, @C.SelectionFlags int disabledTextTrackSelectionFlags,
@ -1036,8 +1049,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
SparseArray<Map<TrackGroupArray, @NullableType SelectionOverride>> selectionOverrides, SparseArray<Map<TrackGroupArray, @NullableType SelectionOverride>> selectionOverrides,
SparseBooleanArray rendererDisabledFlags) { SparseBooleanArray rendererDisabledFlags) {
super( super(
preferredAudioLanguage, preferredAudioLanguages,
preferredTextLanguage, preferredTextLanguages,
preferredTextRoleFlags, preferredTextRoleFlags,
selectUndeterminedTextLanguage, selectUndeterminedTextLanguage,
disabledTextTrackSelectionFlags); disabledTextTrackSelectionFlags);
@ -2607,6 +2620,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
private final Parameters parameters; private final Parameters parameters;
private final boolean isWithinRendererCapabilities; private final boolean isWithinRendererCapabilities;
private final int preferredLanguageScore; private final int preferredLanguageScore;
private final int preferredLanguageIndex;
private final int localeLanguageMatchIndex; private final int localeLanguageMatchIndex;
private final int localeLanguageScore; private final int localeLanguageScore;
private final boolean isDefaultSelectionFlag; private final boolean isDefaultSelectionFlag;
@ -2619,11 +2633,22 @@ public class DefaultTrackSelector extends MappingTrackSelector {
this.language = normalizeUndeterminedLanguageToNull(format.language); this.language = normalizeUndeterminedLanguageToNull(format.language);
isWithinRendererCapabilities = isWithinRendererCapabilities =
isSupported(formatSupport, /* allowExceedsCapabilities= */ false); isSupported(formatSupport, /* allowExceedsCapabilities= */ false);
preferredLanguageScore = int bestLanguageScore = 0;
getFormatLanguageScore( int bestLanguageIndex = Integer.MAX_VALUE;
format, for (int i = 0; i < parameters.preferredAudioLanguages.size(); i++) {
parameters.preferredAudioLanguage, int score =
/* allowUndeterminedFormatLanguage= */ false); 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; isDefaultSelectionFlag = (format.selectionFlags & C.SELECTION_FLAG_DEFAULT) != 0;
channelCount = format.channelCount; channelCount = format.channelCount;
sampleRate = format.sampleRate; sampleRate = format.sampleRate;
@ -2666,6 +2691,10 @@ public class DefaultTrackSelector extends MappingTrackSelector {
: FORMAT_VALUE_ORDERING.reverse(); : FORMAT_VALUE_ORDERING.reverse();
return ComparisonChain.start() return ComparisonChain.start()
.compareFalseFirst(this.isWithinRendererCapabilities, other.isWithinRendererCapabilities) .compareFalseFirst(this.isWithinRendererCapabilities, other.isWithinRendererCapabilities)
.compare(
this.preferredLanguageIndex,
other.preferredLanguageIndex,
Ordering.natural().reverse())
.compare(this.preferredLanguageScore, other.preferredLanguageScore) .compare(this.preferredLanguageScore, other.preferredLanguageScore)
.compareFalseFirst(this.isWithinConstraints, other.isWithinConstraints) .compareFalseFirst(this.isWithinConstraints, other.isWithinConstraints)
.compare( .compare(
@ -2701,6 +2730,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
private final boolean isWithinRendererCapabilities; private final boolean isWithinRendererCapabilities;
private final boolean isDefault; private final boolean isDefault;
private final boolean isForced; private final boolean isForced;
private final int preferredLanguageIndex;
private final int preferredLanguageScore; private final int preferredLanguageScore;
private final int preferredRoleFlagsScore; private final int preferredRoleFlagsScore;
private final int selectedAudioLanguageScore; private final int selectedAudioLanguageScore;
@ -2717,9 +2747,26 @@ public class DefaultTrackSelector extends MappingTrackSelector {
format.selectionFlags & ~parameters.disabledTextTrackSelectionFlags; format.selectionFlags & ~parameters.disabledTextTrackSelectionFlags;
isDefault = (maskedSelectionFlags & C.SELECTION_FLAG_DEFAULT) != 0; isDefault = (maskedSelectionFlags & C.SELECTION_FLAG_DEFAULT) != 0;
isForced = (maskedSelectionFlags & C.SELECTION_FLAG_FORCED) != 0; isForced = (maskedSelectionFlags & C.SELECTION_FLAG_FORCED) != 0;
preferredLanguageScore = int bestLanguageIndex = Integer.MAX_VALUE;
getFormatLanguageScore( int bestLanguageScore = 0;
format, parameters.preferredTextLanguage, parameters.selectUndeterminedTextLanguage); // Compare against empty (unset) language if no preference is given to allow the selection of
// a text track with undetermined language.
ImmutableList<String> 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 = preferredRoleFlagsScore =
Integer.bitCount(format.roleFlags & parameters.preferredTextRoleFlags); Integer.bitCount(format.roleFlags & parameters.preferredTextRoleFlags);
hasCaptionRoleFlags = hasCaptionRoleFlags =
@ -2730,7 +2777,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
getFormatLanguageScore(format, selectedAudioLanguage, selectedAudioLanguageUndetermined); getFormatLanguageScore(format, selectedAudioLanguage, selectedAudioLanguageUndetermined);
isWithinConstraints = isWithinConstraints =
preferredLanguageScore > 0 preferredLanguageScore > 0
|| (parameters.preferredTextLanguage == null && preferredRoleFlagsScore > 0) || (parameters.preferredTextLanguages.isEmpty() && preferredRoleFlagsScore > 0)
|| isDefault || isDefault
|| (isForced && selectedAudioLanguageScore > 0); || (isForced && selectedAudioLanguageScore > 0);
} }
@ -2748,6 +2795,10 @@ public class DefaultTrackSelector extends MappingTrackSelector {
ComparisonChain.start() ComparisonChain.start()
.compareFalseFirst( .compareFalseFirst(
this.isWithinRendererCapabilities, other.isWithinRendererCapabilities) this.isWithinRendererCapabilities, other.isWithinRendererCapabilities)
.compare(
this.preferredLanguageIndex,
other.preferredLanguageIndex,
Ordering.natural().reverse())
.compare(this.preferredLanguageScore, other.preferredLanguageScore) .compare(this.preferredLanguageScore, other.preferredLanguageScore)
.compare(this.preferredRoleFlagsScore, other.preferredRoleFlagsScore) .compare(this.preferredRoleFlagsScore, other.preferredRoleFlagsScore)
.compareFalseFirst(this.isDefault, other.isDefault) .compareFalseFirst(this.isDefault, other.isDefault)

View File

@ -15,16 +15,19 @@
*/ */
package com.google.android.exoplayer2.trackselection; package com.google.android.exoplayer2.trackselection;
import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
import android.content.Context; import android.content.Context;
import android.os.Looper; import android.os.Looper;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import android.text.TextUtils;
import android.view.accessibility.CaptioningManager; import android.view.accessibility.CaptioningManager;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.Locale; import java.util.Locale;
/** Constraint parameters for track selection. */ /** Constraint parameters for track selection. */
@ -36,8 +39,8 @@ public class TrackSelectionParameters implements Parcelable {
*/ */
public static class Builder { public static class Builder {
@Nullable /* package */ String preferredAudioLanguage; /* package */ ImmutableList<String> preferredAudioLanguages;
@Nullable /* package */ String preferredTextLanguage; /* package */ ImmutableList<String> preferredTextLanguages;
@C.RoleFlags /* package */ int preferredTextRoleFlags; @C.RoleFlags /* package */ int preferredTextRoleFlags;
/* package */ boolean selectUndeterminedTextLanguage; /* package */ boolean selectUndeterminedTextLanguage;
@C.SelectionFlags /* package */ int disabledTextTrackSelectionFlags; @C.SelectionFlags /* package */ int disabledTextTrackSelectionFlags;
@ -59,8 +62,8 @@ public class TrackSelectionParameters implements Parcelable {
*/ */
@Deprecated @Deprecated
public Builder() { public Builder() {
preferredAudioLanguage = null; preferredAudioLanguages = ImmutableList.of();
preferredTextLanguage = null; preferredTextLanguages = ImmutableList.of();
preferredTextRoleFlags = 0; preferredTextRoleFlags = 0;
selectUndeterminedTextLanguage = false; selectUndeterminedTextLanguage = false;
disabledTextTrackSelectionFlags = 0; disabledTextTrackSelectionFlags = 0;
@ -71,8 +74,8 @@ public class TrackSelectionParameters implements Parcelable {
* the builder are obtained. * the builder are obtained.
*/ */
/* package */ Builder(TrackSelectionParameters initialValues) { /* package */ Builder(TrackSelectionParameters initialValues) {
preferredAudioLanguage = initialValues.preferredAudioLanguage; preferredAudioLanguages = initialValues.preferredAudioLanguages;
preferredTextLanguage = initialValues.preferredTextLanguage; preferredTextLanguages = initialValues.preferredTextLanguages;
preferredTextRoleFlags = initialValues.preferredTextRoleFlags; preferredTextRoleFlags = initialValues.preferredTextRoleFlags;
selectUndeterminedTextLanguage = initialValues.selectUndeterminedTextLanguage; selectUndeterminedTextLanguage = initialValues.selectUndeterminedTextLanguage;
disabledTextTrackSelectionFlags = initialValues.disabledTextTrackSelectionFlags; disabledTextTrackSelectionFlags = initialValues.disabledTextTrackSelectionFlags;
@ -86,7 +89,25 @@ public class TrackSelectionParameters implements Parcelable {
* @return This builder. * @return This builder.
*/ */
public Builder setPreferredAudioLanguage(@Nullable String preferredAudioLanguage) { 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<String> listBuilder = ImmutableList.builder();
for (String language : checkNotNull(preferredAudioLanguages)) {
listBuilder.add(Util.normalizeLanguageCode(checkNotNull(language)));
}
this.preferredAudioLanguages = listBuilder.build();
return this; return this;
} }
@ -115,7 +136,25 @@ public class TrackSelectionParameters implements Parcelable {
* @return This builder. * @return This builder.
*/ */
public Builder setPreferredTextLanguage(@Nullable String preferredTextLanguage) { 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<String> listBuilder = ImmutableList.builder();
for (String language : checkNotNull(preferredTextLanguages)) {
listBuilder.add(Util.normalizeLanguageCode(checkNotNull(language)));
}
this.preferredTextLanguages = listBuilder.build();
return this; 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 * 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...) a preferred language} is available, or if the
* unset. * preferred language is unset.
* *
* @param selectUndeterminedTextLanguage Whether a text track with undetermined language should * @param selectUndeterminedTextLanguage Whether a text track with undetermined language should
* be selected if no preferred language track is available. * be selected if no preferred language track is available.
@ -161,9 +200,9 @@ public class TrackSelectionParameters implements Parcelable {
public TrackSelectionParameters build() { public TrackSelectionParameters build() {
return new TrackSelectionParameters( return new TrackSelectionParameters(
// Audio // Audio
preferredAudioLanguage, preferredAudioLanguages,
// Text // Text
preferredTextLanguage, preferredTextLanguages,
preferredTextRoleFlags, preferredTextRoleFlags,
selectUndeterminedTextLanguage, selectUndeterminedTextLanguage,
disabledTextTrackSelectionFlags); disabledTextTrackSelectionFlags);
@ -185,7 +224,7 @@ public class TrackSelectionParameters implements Parcelable {
preferredTextRoleFlags = C.ROLE_FLAG_CAPTION | C.ROLE_FLAG_DESCRIBES_MUSIC_AND_SOUND; preferredTextRoleFlags = C.ROLE_FLAG_CAPTION | C.ROLE_FLAG_DESCRIBES_MUSIC_AND_SOUND;
Locale preferredLocale = captioningManager.getLocale(); Locale preferredLocale = captioningManager.getLocale();
if (preferredLocale != null) { 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. * The preferred languages for audio and forced text tracks as IETF BCP 47 conformant tags in
* {@code null} selects the default track, or the first track if there's no default. The default * order of preference. An empty list selects the default track, or the first track if there's no
* value is {@code null}. * default. The default value is an empty list.
*/ */
@Nullable public final String preferredAudioLanguage; public final ImmutableList<String> preferredAudioLanguages;
/** /**
* The preferred language for text tracks as an IETF BCP 47 conformant tag. {@code null} selects * The preferred languages for text tracks as IETF BCP 47 conformant tags in order of preference.
* the default track if there is one, or no track otherwise. The default value is {@code null}, or * An empty list selects the default track if there is one, or no track otherwise. The default
* the language of the accessibility {@link CaptioningManager} if enabled. * value is an empty list, or the language of the accessibility {@link CaptioningManager} if
* enabled.
*/ */
@Nullable public final String preferredTextLanguage; public final ImmutableList<String> preferredTextLanguages;
/** /**
* The preferred {@link C.RoleFlags} for text tracks. {@code 0} selects the default track if there * 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} * 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; @C.RoleFlags public final int preferredTextRoleFlags;
/** /**
* Whether a text track with undetermined language should be selected if no track with {@link * 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}. * default value is {@code false}.
*/ */
public final boolean selectUndeterminedTextLanguage; public final boolean selectUndeterminedTextLanguage;
@ -249,23 +289,27 @@ public class TrackSelectionParameters implements Parcelable {
@C.SelectionFlags public final int disabledTextTrackSelectionFlags; @C.SelectionFlags public final int disabledTextTrackSelectionFlags;
/* package */ TrackSelectionParameters( /* package */ TrackSelectionParameters(
@Nullable String preferredAudioLanguage, ImmutableList<String> preferredAudioLanguages,
@Nullable String preferredTextLanguage, ImmutableList<String> preferredTextLanguages,
@C.RoleFlags int preferredTextRoleFlags, @C.RoleFlags int preferredTextRoleFlags,
boolean selectUndeterminedTextLanguage, boolean selectUndeterminedTextLanguage,
@C.SelectionFlags int disabledTextTrackSelectionFlags) { @C.SelectionFlags int disabledTextTrackSelectionFlags) {
// Audio // Audio
this.preferredAudioLanguage = Util.normalizeLanguageCode(preferredAudioLanguage); this.preferredAudioLanguages = preferredAudioLanguages;
// Text // Text
this.preferredTextLanguage = Util.normalizeLanguageCode(preferredTextLanguage); this.preferredTextLanguages = preferredTextLanguages;
this.preferredTextRoleFlags = preferredTextRoleFlags; this.preferredTextRoleFlags = preferredTextRoleFlags;
this.selectUndeterminedTextLanguage = selectUndeterminedTextLanguage; this.selectUndeterminedTextLanguage = selectUndeterminedTextLanguage;
this.disabledTextTrackSelectionFlags = disabledTextTrackSelectionFlags; this.disabledTextTrackSelectionFlags = disabledTextTrackSelectionFlags;
} }
/* package */ TrackSelectionParameters(Parcel in) { /* package */ TrackSelectionParameters(Parcel in) {
this.preferredAudioLanguage = in.readString(); ArrayList<String> preferredAudioLanguages = new ArrayList<>();
this.preferredTextLanguage = in.readString(); in.readList(preferredAudioLanguages, /* loader= */ null);
this.preferredAudioLanguages = ImmutableList.copyOf(preferredAudioLanguages);
ArrayList<String> preferredTextLanguages = new ArrayList<>();
in.readList(preferredTextLanguages, /* loader= */ null);
this.preferredTextLanguages = ImmutableList.copyOf(preferredTextLanguages);
this.preferredTextRoleFlags = in.readInt(); this.preferredTextRoleFlags = in.readInt();
this.selectUndeterminedTextLanguage = Util.readBoolean(in); this.selectUndeterminedTextLanguage = Util.readBoolean(in);
this.disabledTextTrackSelectionFlags = in.readInt(); this.disabledTextTrackSelectionFlags = in.readInt();
@ -286,8 +330,8 @@ public class TrackSelectionParameters implements Parcelable {
return false; return false;
} }
TrackSelectionParameters other = (TrackSelectionParameters) obj; TrackSelectionParameters other = (TrackSelectionParameters) obj;
return TextUtils.equals(preferredAudioLanguage, other.preferredAudioLanguage) return preferredAudioLanguages.equals(other.preferredAudioLanguages)
&& TextUtils.equals(preferredTextLanguage, other.preferredTextLanguage) && preferredTextLanguages.equals(other.preferredTextLanguages)
&& preferredTextRoleFlags == other.preferredTextRoleFlags && preferredTextRoleFlags == other.preferredTextRoleFlags
&& selectUndeterminedTextLanguage == other.selectUndeterminedTextLanguage && selectUndeterminedTextLanguage == other.selectUndeterminedTextLanguage
&& disabledTextTrackSelectionFlags == other.disabledTextTrackSelectionFlags; && disabledTextTrackSelectionFlags == other.disabledTextTrackSelectionFlags;
@ -296,8 +340,8 @@ public class TrackSelectionParameters implements Parcelable {
@Override @Override
public int hashCode() { public int hashCode() {
int result = 1; int result = 1;
result = 31 * result + (preferredAudioLanguage == null ? 0 : preferredAudioLanguage.hashCode()); result = 31 * result + preferredAudioLanguages.hashCode();
result = 31 * result + (preferredTextLanguage == null ? 0 : preferredTextLanguage.hashCode()); result = 31 * result + preferredTextLanguages.hashCode();
result = 31 * result + preferredTextRoleFlags; result = 31 * result + preferredTextRoleFlags;
result = 31 * result + (selectUndeterminedTextLanguage ? 1 : 0); result = 31 * result + (selectUndeterminedTextLanguage ? 1 : 0);
result = 31 * result + disabledTextTrackSelectionFlags; result = 31 * result + disabledTextTrackSelectionFlags;
@ -313,8 +357,8 @@ public class TrackSelectionParameters implements Parcelable {
@Override @Override
public void writeToParcel(Parcel dest, int flags) { public void writeToParcel(Parcel dest, int flags) {
dest.writeString(preferredAudioLanguage); dest.writeList(preferredAudioLanguages);
dest.writeString(preferredTextLanguage); dest.writeList(preferredTextLanguages);
dest.writeInt(preferredTextRoleFlags); dest.writeInt(preferredTextRoleFlags);
Util.writeBoolean(dest, selectUndeterminedTextLanguage); Util.writeBoolean(dest, selectUndeterminedTextLanguage);
dest.writeInt(disabledTextTrackSelectionFlags); dest.writeInt(disabledTextTrackSelectionFlags);

View File

@ -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_EXCEEDS_CAPABILITIES;
import static com.google.android.exoplayer2.RendererCapabilities.FORMAT_HANDLED; 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.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.android.exoplayer2.RendererConfiguration.DEFAULT;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.never; 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.ExoPlaybackException;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.RendererCapabilities; import com.google.android.exoplayer2.RendererCapabilities;
import com.google.android.exoplayer2.RendererCapabilities.Capabilities;
import com.google.android.exoplayer2.RendererConfiguration; import com.google.android.exoplayer2.RendererConfiguration;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; 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.upstream.BandwidthMeter;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.common.collect.ImmutableList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.junit.Before; import org.junit.Before;
@ -67,7 +70,8 @@ public final class DefaultTrackSelectorTest {
private static final RendererCapabilities ALL_TEXT_FORMAT_SUPPORTED_RENDERER_CAPABILITIES = private static final RendererCapabilities ALL_TEXT_FORMAT_SUPPORTED_RENDERER_CAPABILITIES =
new FakeRendererCapabilities(C.TRACK_TYPE_TEXT); new FakeRendererCapabilities(C.TRACK_TYPE_TEXT);
private static final RendererCapabilities ALL_AUDIO_FORMAT_EXCEEDED_RENDERER_CAPABILITIES = 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 = private static final RendererCapabilities VIDEO_CAPABILITIES =
new FakeRendererCapabilities(C.TRACK_TYPE_VIDEO); new FakeRendererCapabilities(C.TRACK_TYPE_VIDEO);
@ -1318,7 +1322,10 @@ public final class DefaultTrackSelectorTest {
@Test @Test
public void selectTracksWithMultipleVideoTracksWithNonSeamlessAdaptiveness() throws Exception { public void selectTracksWithMultipleVideoTracksWithNonSeamlessAdaptiveness() throws Exception {
FakeRendererCapabilities nonSeamlessVideoCapabilities = 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. // Should do non-seamless adaptiveness by default, so expect an adaptive selection.
Format.Builder formatBuilder = VIDEO_FORMAT.buildUpon(); Format.Builder formatBuilder = VIDEO_FORMAT.buildUpon();
@ -1508,7 +1515,7 @@ public final class DefaultTrackSelectorTest {
/* viewportHeight= */ 9, /* viewportHeight= */ 9,
/* viewportOrientationMayChange= */ true, /* viewportOrientationMayChange= */ true,
// Audio // Audio
/* preferredAudioLanguage= */ "en", /* preferredAudioLanguages= */ ImmutableList.of("zh", "jp"),
/* maxAudioChannelCount= */ 10, /* maxAudioChannelCount= */ 10,
/* maxAudioBitrate= */ 11, /* maxAudioBitrate= */ 11,
/* exceedAudioConstraintsIfNecessary= */ false, /* exceedAudioConstraintsIfNecessary= */ false,
@ -1516,10 +1523,10 @@ public final class DefaultTrackSelectorTest {
/* allowAudioMixedSampleRateAdaptiveness= */ false, /* allowAudioMixedSampleRateAdaptiveness= */ false,
/* allowAudioMixedChannelCountAdaptiveness= */ true, /* allowAudioMixedChannelCountAdaptiveness= */ true,
// Text // Text
/* preferredTextLanguage= */ "de", /* preferredTextLanguages= */ ImmutableList.of("de", "en"),
/* preferredTextRoleFlags= */ C.ROLE_FLAG_CAPTION, /* preferredTextRoleFlags= */ C.ROLE_FLAG_CAPTION,
/* selectUndeterminedTextLanguage= */ true, /* selectUndeterminedTextLanguage= */ true,
/* disabledTextTrackSelectionFlags= */ 12, /* disabledTextTrackSelectionFlags= */ C.SELECTION_FLAG_AUTOSELECT,
// General // General
/* forceLowestBitrate= */ false, /* forceLowestBitrate= */ false,
/* forceHighestSupportedBitrate= */ true, /* forceHighestSupportedBitrate= */ true,