Add allowAudioMixedChannelCountAdaptiveness parameter to DefaultTrackSelector.

We already allow mixed mime type and mixed sample rate adaptation on request,
so for completeness, we can also allow mixed channel count adaptation.

Issue:#6257
PiperOrigin-RevId: 261930046
This commit is contained in:
tonihei 2019-08-06 17:28:15 +01:00 committed by Oliver Woodman
parent 9f486336be
commit c4ac166f2f
3 changed files with 54 additions and 9 deletions

View file

@ -1,5 +1,12 @@
# Release notes # # Release notes #
### 2.10.5 ###
* Add `allowAudioMixedChannelCountAdaptiveness` parameter to
`DefaultTrackSelector` to allow adaptive selections of audio tracks with
different channel counts
([#6257](https://github.com/google/ExoPlayer/issues/6257)).
### 2.10.4 ### ### 2.10.4 ###
* Offline: Add `Scheduler` implementation that uses `WorkManager`. * Offline: Add `Scheduler` implementation that uses `WorkManager`.

View file

@ -178,6 +178,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
private boolean exceedAudioConstraintsIfNecessary; private boolean exceedAudioConstraintsIfNecessary;
private boolean allowAudioMixedMimeTypeAdaptiveness; private boolean allowAudioMixedMimeTypeAdaptiveness;
private boolean allowAudioMixedSampleRateAdaptiveness; private boolean allowAudioMixedSampleRateAdaptiveness;
private boolean allowAudioMixedChannelCountAdaptiveness;
// General // General
private boolean forceLowestBitrate; private boolean forceLowestBitrate;
private boolean forceHighestSupportedBitrate; private boolean forceHighestSupportedBitrate;
@ -215,6 +216,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
exceedAudioConstraintsIfNecessary = initialValues.exceedAudioConstraintsIfNecessary; exceedAudioConstraintsIfNecessary = initialValues.exceedAudioConstraintsIfNecessary;
allowAudioMixedMimeTypeAdaptiveness = initialValues.allowAudioMixedMimeTypeAdaptiveness; allowAudioMixedMimeTypeAdaptiveness = initialValues.allowAudioMixedMimeTypeAdaptiveness;
allowAudioMixedSampleRateAdaptiveness = initialValues.allowAudioMixedSampleRateAdaptiveness; allowAudioMixedSampleRateAdaptiveness = initialValues.allowAudioMixedSampleRateAdaptiveness;
allowAudioMixedChannelCountAdaptiveness =
initialValues.allowAudioMixedChannelCountAdaptiveness;
// General // General
forceLowestBitrate = initialValues.forceLowestBitrate; forceLowestBitrate = initialValues.forceLowestBitrate;
forceHighestSupportedBitrate = initialValues.forceHighestSupportedBitrate; forceHighestSupportedBitrate = initialValues.forceHighestSupportedBitrate;
@ -412,6 +415,17 @@ public class DefaultTrackSelector extends MappingTrackSelector {
return this; return this;
} }
/**
* See {@link Parameters#allowAudioMixedChannelCountAdaptiveness}.
*
* @return This builder.
*/
public ParametersBuilder setAllowAudioMixedChannelCountAdaptiveness(
boolean allowAudioMixedChannelCountAdaptiveness) {
this.allowAudioMixedChannelCountAdaptiveness = allowAudioMixedChannelCountAdaptiveness;
return this;
}
// Text // Text
@Override @Override
@ -628,6 +642,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
exceedAudioConstraintsIfNecessary, exceedAudioConstraintsIfNecessary,
allowAudioMixedMimeTypeAdaptiveness, allowAudioMixedMimeTypeAdaptiveness,
allowAudioMixedSampleRateAdaptiveness, allowAudioMixedSampleRateAdaptiveness,
allowAudioMixedChannelCountAdaptiveness,
// Text // Text
preferredTextLanguage, preferredTextLanguage,
selectUndeterminedTextLanguage, selectUndeterminedTextLanguage,
@ -749,6 +764,12 @@ public class DefaultTrackSelector extends MappingTrackSelector {
* different sample rates may not be completely seamless. The default value is {@code false}. * different sample rates may not be completely seamless. The default value is {@code false}.
*/ */
public final boolean allowAudioMixedSampleRateAdaptiveness; public final boolean allowAudioMixedSampleRateAdaptiveness;
/**
* Whether to allow adaptive audio selections containing mixed channel counts. Adaptations
* between different channel counts may not be completely seamless. The default value is {@code
* false}.
*/
public final boolean allowAudioMixedChannelCountAdaptiveness;
// General // General
/** /**
@ -809,6 +830,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
/* exceedAudioConstraintsIfNecessary= */ true, /* exceedAudioConstraintsIfNecessary= */ true,
/* allowAudioMixedMimeTypeAdaptiveness= */ false, /* allowAudioMixedMimeTypeAdaptiveness= */ false,
/* allowAudioMixedSampleRateAdaptiveness= */ false, /* allowAudioMixedSampleRateAdaptiveness= */ false,
/* allowAudioMixedChannelCountAdaptiveness= */ false,
// Text // Text
TrackSelectionParameters.DEFAULT.preferredTextLanguage, TrackSelectionParameters.DEFAULT.preferredTextLanguage,
TrackSelectionParameters.DEFAULT.selectUndeterminedTextLanguage, TrackSelectionParameters.DEFAULT.selectUndeterminedTextLanguage,
@ -841,6 +863,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
boolean exceedAudioConstraintsIfNecessary, boolean exceedAudioConstraintsIfNecessary,
boolean allowAudioMixedMimeTypeAdaptiveness, boolean allowAudioMixedMimeTypeAdaptiveness,
boolean allowAudioMixedSampleRateAdaptiveness, boolean allowAudioMixedSampleRateAdaptiveness,
boolean allowAudioMixedChannelCountAdaptiveness,
// Text // Text
@Nullable String preferredTextLanguage, @Nullable String preferredTextLanguage,
boolean selectUndeterminedTextLanguage, boolean selectUndeterminedTextLanguage,
@ -875,6 +898,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
this.exceedAudioConstraintsIfNecessary = exceedAudioConstraintsIfNecessary; this.exceedAudioConstraintsIfNecessary = exceedAudioConstraintsIfNecessary;
this.allowAudioMixedMimeTypeAdaptiveness = allowAudioMixedMimeTypeAdaptiveness; this.allowAudioMixedMimeTypeAdaptiveness = allowAudioMixedMimeTypeAdaptiveness;
this.allowAudioMixedSampleRateAdaptiveness = allowAudioMixedSampleRateAdaptiveness; this.allowAudioMixedSampleRateAdaptiveness = allowAudioMixedSampleRateAdaptiveness;
this.allowAudioMixedChannelCountAdaptiveness = allowAudioMixedChannelCountAdaptiveness;
// General // General
this.forceLowestBitrate = forceLowestBitrate; this.forceLowestBitrate = forceLowestBitrate;
this.forceHighestSupportedBitrate = forceHighestSupportedBitrate; this.forceHighestSupportedBitrate = forceHighestSupportedBitrate;
@ -908,6 +932,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
this.exceedAudioConstraintsIfNecessary = Util.readBoolean(in); this.exceedAudioConstraintsIfNecessary = Util.readBoolean(in);
this.allowAudioMixedMimeTypeAdaptiveness = Util.readBoolean(in); this.allowAudioMixedMimeTypeAdaptiveness = Util.readBoolean(in);
this.allowAudioMixedSampleRateAdaptiveness = Util.readBoolean(in); this.allowAudioMixedSampleRateAdaptiveness = Util.readBoolean(in);
this.allowAudioMixedChannelCountAdaptiveness = Util.readBoolean(in);
// General // General
this.forceLowestBitrate = Util.readBoolean(in); this.forceLowestBitrate = Util.readBoolean(in);
this.forceHighestSupportedBitrate = Util.readBoolean(in); this.forceHighestSupportedBitrate = Util.readBoolean(in);
@ -989,6 +1014,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
&& exceedAudioConstraintsIfNecessary == other.exceedAudioConstraintsIfNecessary && exceedAudioConstraintsIfNecessary == other.exceedAudioConstraintsIfNecessary
&& allowAudioMixedMimeTypeAdaptiveness == other.allowAudioMixedMimeTypeAdaptiveness && allowAudioMixedMimeTypeAdaptiveness == other.allowAudioMixedMimeTypeAdaptiveness
&& allowAudioMixedSampleRateAdaptiveness == other.allowAudioMixedSampleRateAdaptiveness && allowAudioMixedSampleRateAdaptiveness == other.allowAudioMixedSampleRateAdaptiveness
&& allowAudioMixedChannelCountAdaptiveness
== other.allowAudioMixedChannelCountAdaptiveness
// General // General
&& forceLowestBitrate == other.forceLowestBitrate && forceLowestBitrate == other.forceLowestBitrate
&& forceHighestSupportedBitrate == other.forceHighestSupportedBitrate && forceHighestSupportedBitrate == other.forceHighestSupportedBitrate
@ -1019,6 +1046,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
result = 31 * result + (exceedAudioConstraintsIfNecessary ? 1 : 0); result = 31 * result + (exceedAudioConstraintsIfNecessary ? 1 : 0);
result = 31 * result + (allowAudioMixedMimeTypeAdaptiveness ? 1 : 0); result = 31 * result + (allowAudioMixedMimeTypeAdaptiveness ? 1 : 0);
result = 31 * result + (allowAudioMixedSampleRateAdaptiveness ? 1 : 0); result = 31 * result + (allowAudioMixedSampleRateAdaptiveness ? 1 : 0);
result = 31 * result + (allowAudioMixedChannelCountAdaptiveness ? 1 : 0);
// General // General
result = 31 * result + (forceLowestBitrate ? 1 : 0); result = 31 * result + (forceLowestBitrate ? 1 : 0);
result = 31 * result + (forceHighestSupportedBitrate ? 1 : 0); result = 31 * result + (forceHighestSupportedBitrate ? 1 : 0);
@ -1055,6 +1083,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
Util.writeBoolean(dest, exceedAudioConstraintsIfNecessary); Util.writeBoolean(dest, exceedAudioConstraintsIfNecessary);
Util.writeBoolean(dest, allowAudioMixedMimeTypeAdaptiveness); Util.writeBoolean(dest, allowAudioMixedMimeTypeAdaptiveness);
Util.writeBoolean(dest, allowAudioMixedSampleRateAdaptiveness); Util.writeBoolean(dest, allowAudioMixedSampleRateAdaptiveness);
Util.writeBoolean(dest, allowAudioMixedChannelCountAdaptiveness);
// General // General
Util.writeBoolean(dest, forceLowestBitrate); Util.writeBoolean(dest, forceLowestBitrate);
Util.writeBoolean(dest, forceHighestSupportedBitrate); Util.writeBoolean(dest, forceHighestSupportedBitrate);
@ -1936,7 +1965,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
formatSupports[selectedGroupIndex], formatSupports[selectedGroupIndex],
params.maxAudioBitrate, params.maxAudioBitrate,
params.allowAudioMixedMimeTypeAdaptiveness, params.allowAudioMixedMimeTypeAdaptiveness,
params.allowAudioMixedSampleRateAdaptiveness); params.allowAudioMixedSampleRateAdaptiveness,
params.allowAudioMixedChannelCountAdaptiveness);
if (adaptiveTracks.length > 0) { if (adaptiveTracks.length > 0) {
definition = new TrackSelection.Definition(selectedGroup, adaptiveTracks); definition = new TrackSelection.Definition(selectedGroup, adaptiveTracks);
} }
@ -1954,7 +1984,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
int[] formatSupport, int[] formatSupport,
int maxAudioBitrate, int maxAudioBitrate,
boolean allowMixedMimeTypeAdaptiveness, boolean allowMixedMimeTypeAdaptiveness,
boolean allowMixedSampleRateAdaptiveness) { boolean allowMixedSampleRateAdaptiveness,
boolean allowAudioMixedChannelCountAdaptiveness) {
int selectedConfigurationTrackCount = 0; int selectedConfigurationTrackCount = 0;
AudioConfigurationTuple selectedConfiguration = null; AudioConfigurationTuple selectedConfiguration = null;
HashSet<AudioConfigurationTuple> seenConfigurationTuples = new HashSet<>(); HashSet<AudioConfigurationTuple> seenConfigurationTuples = new HashSet<>();
@ -1971,7 +2002,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
configuration, configuration,
maxAudioBitrate, maxAudioBitrate,
allowMixedMimeTypeAdaptiveness, allowMixedMimeTypeAdaptiveness,
allowMixedSampleRateAdaptiveness); allowMixedSampleRateAdaptiveness,
allowAudioMixedChannelCountAdaptiveness);
if (configurationCount > selectedConfigurationTrackCount) { if (configurationCount > selectedConfigurationTrackCount) {
selectedConfiguration = configuration; selectedConfiguration = configuration;
selectedConfigurationTrackCount = configurationCount; selectedConfigurationTrackCount = configurationCount;
@ -1991,7 +2023,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
selectedConfiguration, selectedConfiguration,
maxAudioBitrate, maxAudioBitrate,
allowMixedMimeTypeAdaptiveness, allowMixedMimeTypeAdaptiveness,
allowMixedSampleRateAdaptiveness)) { allowMixedSampleRateAdaptiveness,
allowAudioMixedChannelCountAdaptiveness)) {
adaptiveIndices[index++] = i; adaptiveIndices[index++] = i;
} }
} }
@ -2006,7 +2039,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
AudioConfigurationTuple configuration, AudioConfigurationTuple configuration,
int maxAudioBitrate, int maxAudioBitrate,
boolean allowMixedMimeTypeAdaptiveness, boolean allowMixedMimeTypeAdaptiveness,
boolean allowMixedSampleRateAdaptiveness) { boolean allowMixedSampleRateAdaptiveness,
boolean allowAudioMixedChannelCountAdaptiveness) {
int count = 0; int count = 0;
for (int i = 0; i < group.length; i++) { for (int i = 0; i < group.length; i++) {
if (isSupportedAdaptiveAudioTrack( if (isSupportedAdaptiveAudioTrack(
@ -2015,7 +2049,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
configuration, configuration,
maxAudioBitrate, maxAudioBitrate,
allowMixedMimeTypeAdaptiveness, allowMixedMimeTypeAdaptiveness,
allowMixedSampleRateAdaptiveness)) { allowMixedSampleRateAdaptiveness,
allowAudioMixedChannelCountAdaptiveness)) {
count++; count++;
} }
} }
@ -2028,11 +2063,13 @@ public class DefaultTrackSelector extends MappingTrackSelector {
AudioConfigurationTuple configuration, AudioConfigurationTuple configuration,
int maxAudioBitrate, int maxAudioBitrate,
boolean allowMixedMimeTypeAdaptiveness, boolean allowMixedMimeTypeAdaptiveness,
boolean allowMixedSampleRateAdaptiveness) { boolean allowMixedSampleRateAdaptiveness,
boolean allowAudioMixedChannelCountAdaptiveness) {
return isSupported(formatSupport, false) return isSupported(formatSupport, false)
&& (format.bitrate == Format.NO_VALUE || format.bitrate <= maxAudioBitrate) && (format.bitrate == Format.NO_VALUE || format.bitrate <= maxAudioBitrate)
&& (format.channelCount != Format.NO_VALUE && (allowAudioMixedChannelCountAdaptiveness
&& format.channelCount == configuration.channelCount) || (format.channelCount != Format.NO_VALUE
&& format.channelCount == configuration.channelCount))
&& (allowMixedMimeTypeAdaptiveness && (allowMixedMimeTypeAdaptiveness
|| (format.sampleMimeType != null || (format.sampleMimeType != null
&& TextUtils.equals(format.sampleMimeType, configuration.mimeType))) && TextUtils.equals(format.sampleMimeType, configuration.mimeType)))

View file

@ -143,6 +143,7 @@ public final class DefaultTrackSelectorTest {
/* exceedAudioConstraintsIfNecessary= */ false, /* exceedAudioConstraintsIfNecessary= */ false,
/* allowAudioMixedMimeTypeAdaptiveness= */ true, /* allowAudioMixedMimeTypeAdaptiveness= */ true,
/* allowAudioMixedSampleRateAdaptiveness= */ false, /* allowAudioMixedSampleRateAdaptiveness= */ false,
/* allowAudioMixedChannelCountAdaptiveness= */ true,
// Text // Text
/* preferredTextLanguage= */ "de", /* preferredTextLanguage= */ "de",
/* selectUndeterminedTextLanguage= */ true, /* selectUndeterminedTextLanguage= */ true,