From 66aa35f581c4f74c6fc75586126c0554530dbd34 Mon Sep 17 00:00:00 2001 From: tonihei Date: Mon, 10 Feb 2020 17:03:06 +0000 Subject: [PATCH] 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 --- .../trackselection/DefaultTrackSelector.java | 127 +++--------------- .../DefaultTrackSelectorTest.java | 43 ++++++ 2 files changed, 64 insertions(+), 106 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 822fd03fdf..70c4ad14a5 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 @@ -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 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 { 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 62d38187c4..6cd56924ef 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 @@ -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,