From 46bf710cb34a5c4491ca4d8578cdc2915813df67 Mon Sep 17 00:00:00 2001 From: tonihei Date: Fri, 23 Aug 2019 16:57:14 +0100 Subject: [PATCH] Do not compare bitrates of audio tracks with different languages. The last selection criteria is the audio bitrate to prefer higher-quality streams. We shouldn't apply this criterium though if the languages of the tracks are different. Issue:#6335 PiperOrigin-RevId: 265064756 --- RELEASENOTES.md | 2 + .../trackselection/DefaultTrackSelector.java | 8 +- .../DefaultTrackSelectorTest.java | 91 ++++++++++++++----- 3 files changed, 77 insertions(+), 24 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 61d0c94344..17664dbe53 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -9,6 +9,8 @@ * Reset `DefaultBandwidthMeter` to initial values on network change. * Increase maximum buffer size for video in `DefaultLoadControl` to ensure high quality video can be loaded up to the full default buffer duration. +* Fix audio selection issue where languages are compared by bit rate + ([#6335](https://github.com/google/ExoPlayer/issues/6335)). ### 2.10.4 ### 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 762e0a98b4..de4415ce39 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 @@ -2501,6 +2501,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { public final boolean isWithinConstraints; + @Nullable private final String language; private final Parameters parameters; private final boolean isWithinRendererCapabilities; private final int preferredLanguageScore; @@ -2513,6 +2514,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { public AudioTrackScore(Format format, Parameters parameters, int formatSupport) { this.parameters = parameters; + this.language = normalizeUndeterminedLanguageToNull(format.language); isWithinRendererCapabilities = isSupported(formatSupport, false); preferredLanguageScore = getFormatLanguageScore(format, parameters.preferredAudioLanguage); isDefaultSelectionFlag = (format.selectionFlags & C.SELECTION_FLAG_DEFAULT) != 0; @@ -2580,7 +2582,11 @@ public class DefaultTrackSelector extends MappingTrackSelector { if (this.sampleRate != other.sampleRate) { return resultSign * compareInts(this.sampleRate, other.sampleRate); } - return resultSign * compareInts(this.bitrate, other.bitrate); + if (Util.areEqual(this.language, other.language)) { + // Only compare bit rates of tracks with the same or unknown language. + return resultSign * compareInts(this.bitrate, other.bitrate); + } + return 0; } } 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 9941ae1098..92c4628fa0 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 @@ -719,37 +719,38 @@ public final class DefaultTrackSelectorTest { } /** - * Tests that track selector will select audio tracks with higher bit-rate when other factors are - * the same, and tracks are within renderer's capabilities. + * Tests that track selector will select audio tracks with higher bit rate when other factors are + * the same, and tracks are within renderer's capabilities, and have the same language. */ @Test - public void testSelectTracksWithinCapabilitiesSelectHigherBitrate() throws Exception { + public void selectAudioTracks_withinCapabilities_andSameLanguage_selectsHigherBitrate() + throws Exception { Format lowerBitrateFormat = Format.createAudioSampleFormat( "audioFormat", MimeTypes.AUDIO_AAC, - null, - 15000, - Format.NO_VALUE, - 2, - 44100, - null, - null, - 0, - null); + /* codecs= */ null, + /* bitrate= */ 15000, + /* maxInputSize= */ Format.NO_VALUE, + /* channelCount= */ 2, + /* sampleRate= */ 44100, + /* initializationData= */ null, + /* drmInitData= */ null, + /* selectionFlags= */ 0, + /* language= */ "hi"); Format higherBitrateFormat = Format.createAudioSampleFormat( "audioFormat", MimeTypes.AUDIO_AAC, - null, - 30000, - Format.NO_VALUE, - 2, - 44100, - null, - null, - 0, - null); + /* codecs= */ null, + /* bitrate= */ 30000, + /* maxInputSize= */ Format.NO_VALUE, + /* channelCount= */ 2, + /* sampleRate= */ 44100, + /* initializationData= */ null, + /* drmInitData= */ null, + /* selectionFlags= */ 0, + /* language= */ "hi"); TrackGroupArray trackGroups = wrapFormats(lowerBitrateFormat, higherBitrateFormat); TrackSelectorResult result = @@ -761,14 +762,58 @@ public final class DefaultTrackSelectorTest { assertFixedSelection(result.selections.get(0), trackGroups, higherBitrateFormat); } + /** + * Tests that track selector will select the first audio track even if other tracks with a + * different language have higher bit rates, all other factors are the same, and tracks are within + * renderer's capabilities. + */ + @Test + public void selectAudioTracks_withinCapabilities_andDifferentLanguage_selectsFirstTrack() + throws Exception { + Format firstLanguageFormat = + Format.createAudioSampleFormat( + "audioFormat", + MimeTypes.AUDIO_AAC, + /* codecs= */ null, + /* bitrate= */ 15000, + /* maxInputSize= */ Format.NO_VALUE, + /* channelCount= */ 2, + /* sampleRate= */ 44100, + /* initializationData= */ null, + /* drmInitData= */ null, + /* selectionFlags= */ 0, + /* language= */ "hi"); + Format higherBitrateFormat = + Format.createAudioSampleFormat( + "audioFormat", + MimeTypes.AUDIO_AAC, + /* codecs= */ null, + /* bitrate= */ 30000, + /* maxInputSize= */ Format.NO_VALUE, + /* channelCount= */ 2, + /* sampleRate= */ 44100, + /* initializationData= */ null, + /* drmInitData= */ null, + /* selectionFlags= */ 0, + /* language= */ "te"); + TrackGroupArray trackGroups = wrapFormats(firstLanguageFormat, higherBitrateFormat); + + TrackSelectorResult result = + trackSelector.selectTracks( + new RendererCapabilities[] {ALL_AUDIO_FORMAT_SUPPORTED_RENDERER_CAPABILITIES}, + trackGroups, + periodId, + TIMELINE); + assertFixedSelection(result.selections.get(0), trackGroups, firstLanguageFormat); + } + /** * Tests that track selector will prefer audio tracks with higher channel count over tracks with * higher sample rate when other factors are the same, and tracks are within renderer's * capabilities. */ @Test - public void testSelectTracksPreferHigherNumChannelBeforeSampleRate() - throws Exception { + public void testSelectTracksPreferHigherNumChannelBeforeSampleRate() throws Exception { Format higherChannelLowerSampleRateFormat = Format.createAudioSampleFormat( "audioFormat",