Select adaptive audio tracks based on the best track in the group.

Currently, the subset of audio tracks for adaptation is selected
purely based on the size of the subset in the track group, completely
ignoring the previously selected best individual track.

This change ignores all tracks with a different configuration than the
previously selected best track.

PiperOrigin-RevId: 294231806
This commit is contained in:
tonihei 2020-02-10 17:03:06 +00:00 committed by kim-vde
parent 0eb0267131
commit 66aa35f581
2 changed files with 64 additions and 106 deletions

View file

@ -2133,11 +2133,12 @@ public class DefaultTrackSelector extends MappingTrackSelector {
getAdaptiveAudioTracks(
selectedGroup,
formatSupports[selectedGroupIndex],
selectedTrackIndex,
params.maxAudioBitrate,
params.allowAudioMixedMimeTypeAdaptiveness,
params.allowAudioMixedSampleRateAdaptiveness,
params.allowAudioMixedChannelCountAdaptiveness);
if (adaptiveTracks.length > 0) {
if (adaptiveTracks.length > 1) {
definition = new TrackSelection.Definition(selectedGroup, adaptiveTracks);
}
}
@ -2152,100 +2153,49 @@ public class DefaultTrackSelector extends MappingTrackSelector {
private static int[] getAdaptiveAudioTracks(
TrackGroup group,
@Capabilities int[] formatSupport,
int primaryTrackIndex,
int maxAudioBitrate,
boolean allowMixedMimeTypeAdaptiveness,
boolean allowMixedSampleRateAdaptiveness,
boolean allowAudioMixedChannelCountAdaptiveness) {
int selectedConfigurationTrackCount = 0;
AudioConfigurationTuple selectedConfiguration = null;
HashSet<AudioConfigurationTuple> seenConfigurationTuples = new HashSet<>();
for (int i = 0; i < group.length; i++) {
Format format = group.getFormat(i);
AudioConfigurationTuple configuration =
new AudioConfigurationTuple(
format.channelCount, format.sampleRate, format.sampleMimeType);
if (seenConfigurationTuples.add(configuration)) {
int configurationCount =
getAdaptiveAudioTrackCount(
group,
formatSupport,
configuration,
maxAudioBitrate,
allowMixedMimeTypeAdaptiveness,
allowMixedSampleRateAdaptiveness,
allowAudioMixedChannelCountAdaptiveness);
if (configurationCount > selectedConfigurationTrackCount) {
selectedConfiguration = configuration;
selectedConfigurationTrackCount = configurationCount;
}
}
}
if (selectedConfigurationTrackCount > 1) {
Assertions.checkNotNull(selectedConfiguration);
int[] adaptiveIndices = new int[selectedConfigurationTrackCount];
int index = 0;
for (int i = 0; i < group.length; i++) {
Format format = group.getFormat(i);
if (isSupportedAdaptiveAudioTrack(
format,
formatSupport[i],
selectedConfiguration,
maxAudioBitrate,
allowMixedMimeTypeAdaptiveness,
allowMixedSampleRateAdaptiveness,
allowAudioMixedChannelCountAdaptiveness)) {
adaptiveIndices[index++] = i;
}
}
return adaptiveIndices;
}
return NO_TRACKS;
}
private static int getAdaptiveAudioTrackCount(
TrackGroup group,
@Capabilities int[] formatSupport,
AudioConfigurationTuple configuration,
int maxAudioBitrate,
boolean allowMixedMimeTypeAdaptiveness,
boolean allowMixedSampleRateAdaptiveness,
boolean allowAudioMixedChannelCountAdaptiveness) {
Format primaryFormat = group.getFormat(primaryTrackIndex);
int[] adaptiveIndices = new int[group.length];
int count = 0;
for (int i = 0; i < group.length; i++) {
if (isSupportedAdaptiveAudioTrack(
group.getFormat(i),
formatSupport[i],
configuration,
maxAudioBitrate,
allowMixedMimeTypeAdaptiveness,
allowMixedSampleRateAdaptiveness,
allowAudioMixedChannelCountAdaptiveness)) {
count++;
if (i == primaryTrackIndex
|| isSupportedAdaptiveAudioTrack(
group.getFormat(i),
formatSupport[i],
primaryFormat,
maxAudioBitrate,
allowMixedMimeTypeAdaptiveness,
allowMixedSampleRateAdaptiveness,
allowAudioMixedChannelCountAdaptiveness)) {
adaptiveIndices[count++] = i;
}
}
return count;
return Arrays.copyOf(adaptiveIndices, count);
}
private static boolean isSupportedAdaptiveAudioTrack(
Format format,
@Capabilities int formatSupport,
AudioConfigurationTuple configuration,
Format primaryFormat,
int maxAudioBitrate,
boolean allowMixedMimeTypeAdaptiveness,
boolean allowMixedSampleRateAdaptiveness,
boolean allowAudioMixedChannelCountAdaptiveness) {
return isSupported(formatSupport, false)
return isSupported(formatSupport, /* allowExceedsCapabilities= */ false)
&& (format.bitrate == Format.NO_VALUE || format.bitrate <= maxAudioBitrate)
&& (allowAudioMixedChannelCountAdaptiveness
|| (format.channelCount != Format.NO_VALUE
&& format.channelCount == configuration.channelCount))
&& format.channelCount == primaryFormat.channelCount))
&& (allowMixedMimeTypeAdaptiveness
|| (format.sampleMimeType != null
&& TextUtils.equals(format.sampleMimeType, configuration.mimeType)))
&& TextUtils.equals(format.sampleMimeType, primaryFormat.sampleMimeType)))
&& (allowMixedSampleRateAdaptiveness
|| (format.sampleRate != Format.NO_VALUE
&& format.sampleRate == configuration.sampleRate));
&& format.sampleRate == primaryFormat.sampleRate));
}
// Text track selection implementation.
@ -2705,41 +2655,6 @@ public class DefaultTrackSelector extends MappingTrackSelector {
}
}
private static final class AudioConfigurationTuple {
public final int channelCount;
public final int sampleRate;
@Nullable public final String mimeType;
public AudioConfigurationTuple(int channelCount, int sampleRate, @Nullable String mimeType) {
this.channelCount = channelCount;
this.sampleRate = sampleRate;
this.mimeType = mimeType;
}
@Override
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
AudioConfigurationTuple other = (AudioConfigurationTuple) obj;
return channelCount == other.channelCount && sampleRate == other.sampleRate
&& TextUtils.equals(mimeType, other.mimeType);
}
@Override
public int hashCode() {
int result = channelCount;
result = 31 * result + sampleRate;
result = 31 * result + (mimeType != null ? mimeType.hashCode() : 0);
return result;
}
}
/** Represents how well a text track matches the selection {@link Parameters}. */
protected static final class TextTrackScore implements Comparable<TextTrackScore> {

View file

@ -1282,6 +1282,37 @@ public final class DefaultTrackSelectorTest {
assertAdaptiveSelection(result.selections.get(0), trackGroups.get(0), 0, 1);
}
@Test
public void selectTracks_multipleAudioTracks_selectsAllTracksInBestConfigurationOnly()
throws Exception {
TrackGroupArray trackGroups =
singleTrackGroup(
buildAudioFormatWithConfiguration(
/* id= */ "0", /* channelCount= */ 6, MimeTypes.AUDIO_AAC, /* sampleRate= */ 44100),
buildAudioFormatWithConfiguration(
/* id= */ "1", /* channelCount= */ 2, MimeTypes.AUDIO_AAC, /* sampleRate= */ 44100),
buildAudioFormatWithConfiguration(
/* id= */ "2", /* channelCount= */ 6, MimeTypes.AUDIO_AC3, /* sampleRate= */ 44100),
buildAudioFormatWithConfiguration(
/* id= */ "3", /* channelCount= */ 6, MimeTypes.AUDIO_AAC, /* sampleRate= */ 22050),
buildAudioFormatWithConfiguration(
/* id= */ "4", /* channelCount= */ 6, MimeTypes.AUDIO_AAC, /* sampleRate= */ 22050),
buildAudioFormatWithConfiguration(
/* id= */ "5", /* channelCount= */ 6, MimeTypes.AUDIO_AAC, /* sampleRate= */ 22050),
buildAudioFormatWithConfiguration(
/* id= */ "6",
/* channelCount= */ 6,
MimeTypes.AUDIO_AAC,
/* sampleRate= */ 44100));
TrackSelectorResult result =
trackSelector.selectTracks(
new RendererCapabilities[] {AUDIO_CAPABILITIES}, trackGroups, periodId, TIMELINE);
assertThat(result.length).isEqualTo(1);
assertAdaptiveSelection(result.selections.get(0), trackGroups.get(0), 0, 6);
}
@Test
public void testSelectTracksWithMultipleAudioTracksWithMixedSampleRates() throws Exception {
Format highSampleRateAudioFormat =
@ -1709,6 +1740,18 @@ public final class DefaultTrackSelectorTest {
/* sampleRate= */ 44100);
}
private static Format buildAudioFormatWithConfiguration(
String id, int channelCount, String mimeType, int sampleRate) {
return buildAudioFormat(
id,
mimeType,
/* bitrate= */ Format.NO_VALUE,
/* language= */ null,
/* selectionFlags= */ 0,
channelCount,
sampleRate);
}
private static Format buildAudioFormat(String id) {
return buildAudioFormat(
id,