Commit 6f6f381b by olly Committed by Oliver Woodman

Fix audio and text track selection in the multi-renderer case

If we can select a track that has a strictly higher score than a
selection already made for a renderer of the same type, we should
prefer it.

Issue: #4711

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=212835895
parent 3e4115ff
...@@ -124,6 +124,9 @@ ...@@ -124,6 +124,9 @@
* Fix bugs reporting events for multi-period media sources * Fix bugs reporting events for multi-period media sources
([#4492](https://github.com/google/ExoPlayer/issues/4492) and ([#4492](https://github.com/google/ExoPlayer/issues/4492) and
[#4634](https://github.com/google/ExoPlayer/issues/4634)). [#4634](https://github.com/google/ExoPlayer/issues/4634)).
* Fix issue where the preferred audio or text track would not be selected if
mapped onto a secondary renderer of the corresponding type
([#4711](http://github.com/google/ExoPlayer/issues/4711)).
* Fix issue where errors of upcoming playlist items are thrown too early * Fix issue where errors of upcoming playlist items are thrown too early
([#4661](https://github.com/google/ExoPlayer/issues/4661)). ([#4661](https://github.com/google/ExoPlayer/issues/4661)).
* Allow edit lists which do not start with a sync sample. * Allow edit lists which do not start with a sync sample.
......
...@@ -1318,8 +1318,10 @@ public class DefaultTrackSelector extends MappingTrackSelector { ...@@ -1318,8 +1318,10 @@ public class DefaultTrackSelector extends MappingTrackSelector {
} }
} }
boolean selectedAudioTracks = false; AudioTrackScore selectedAudioTrackScore = null;
boolean selectedTextTracks = false; int selectedAudioRendererIndex = C.INDEX_UNSET;
int selectedTextTrackScore = Integer.MIN_VALUE;
int selectedTextRendererIndex = C.INDEX_UNSET;
for (int i = 0; i < rendererCount; i++) { for (int i = 0; i < rendererCount; i++) {
int trackType = mappedTrackInfo.getRendererType(i); int trackType = mappedTrackInfo.getRendererType(i);
switch (trackType) { switch (trackType) {
...@@ -1327,23 +1329,38 @@ public class DefaultTrackSelector extends MappingTrackSelector { ...@@ -1327,23 +1329,38 @@ public class DefaultTrackSelector extends MappingTrackSelector {
// Already done. Do nothing. // Already done. Do nothing.
break; break;
case C.TRACK_TYPE_AUDIO: case C.TRACK_TYPE_AUDIO:
if (!selectedAudioTracks) { Pair<TrackSelection, AudioTrackScore> audioSelection =
rendererTrackSelections[i] = selectAudioTrack(
selectAudioTrack( mappedTrackInfo.getTrackGroups(i),
mappedTrackInfo.getTrackGroups(i), rendererFormatSupports[i],
rendererFormatSupports[i], rendererMixedMimeTypeAdaptationSupports[i],
rendererMixedMimeTypeAdaptationSupports[i], params,
params, seenVideoRendererWithMappedTracks ? null : adaptiveTrackSelectionFactory);
seenVideoRendererWithMappedTracks ? null : adaptiveTrackSelectionFactory); if (audioSelection != null
selectedAudioTracks = rendererTrackSelections[i] != null; && (selectedAudioTrackScore == null
|| audioSelection.second.compareTo(selectedAudioTrackScore) > 0)) {
if (selectedAudioRendererIndex != C.INDEX_UNSET) {
// We've already made a selection for another audio renderer, but it had a lower
// score. Clear the selection for that renderer.
rendererTrackSelections[selectedAudioRendererIndex] = null;
}
rendererTrackSelections[i] = audioSelection.first;
selectedAudioTrackScore = audioSelection.second;
selectedAudioRendererIndex = i;
} }
break; break;
case C.TRACK_TYPE_TEXT: case C.TRACK_TYPE_TEXT:
if (!selectedTextTracks) { Pair<TrackSelection, Integer> textSelection =
rendererTrackSelections[i] = selectTextTrack(mappedTrackInfo.getTrackGroups(i), rendererFormatSupports[i], params);
selectTextTrack( if (textSelection != null && textSelection.second > selectedTextTrackScore) {
mappedTrackInfo.getTrackGroups(i), rendererFormatSupports[i], params); if (selectedTextRendererIndex != C.INDEX_UNSET) {
selectedTextTracks = rendererTrackSelections[i] != null; // We've already made a selection for another text renderer, but it had a lower score.
// Clear the selection for that renderer.
rendererTrackSelections[selectedTextRendererIndex] = null;
}
rendererTrackSelections[i] = textSelection.first;
selectedTextTrackScore = textSelection.second;
selectedTextRendererIndex = i;
} }
break; break;
default: default:
...@@ -1599,10 +1616,11 @@ public class DefaultTrackSelector extends MappingTrackSelector { ...@@ -1599,10 +1616,11 @@ public class DefaultTrackSelector extends MappingTrackSelector {
* @param params The selector's current constraint parameters. * @param params The selector's current constraint parameters.
* @param adaptiveTrackSelectionFactory A factory for generating adaptive track selections, or * @param adaptiveTrackSelectionFactory A factory for generating adaptive track selections, or
* null if a fixed track selection is required. * null if a fixed track selection is required.
* @return The {@link TrackSelection} for the renderer, or null if no selection was made. * @return The {@link TrackSelection} and corresponding {@link AudioTrackScore}, or null if no
* selection was made.
* @throws ExoPlaybackException If an error occurs while selecting the tracks. * @throws ExoPlaybackException If an error occurs while selecting the tracks.
*/ */
protected @Nullable TrackSelection selectAudioTrack( protected @Nullable Pair<TrackSelection, AudioTrackScore> selectAudioTrack(
TrackGroupArray groups, TrackGroupArray groups,
int[][] formatSupports, int[][] formatSupports,
int mixedMimeTypeAdaptationSupports, int mixedMimeTypeAdaptationSupports,
...@@ -1635,6 +1653,8 @@ public class DefaultTrackSelector extends MappingTrackSelector { ...@@ -1635,6 +1653,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
} }
TrackGroup selectedGroup = groups.get(selectedGroupIndex); TrackGroup selectedGroup = groups.get(selectedGroupIndex);
TrackSelection selection = null;
if (!params.forceHighestSupportedBitrate if (!params.forceHighestSupportedBitrate
&& !params.forceLowestBitrate && !params.forceLowestBitrate
&& adaptiveTrackSelectionFactory != null) { && adaptiveTrackSelectionFactory != null) {
...@@ -1643,11 +1663,17 @@ public class DefaultTrackSelector extends MappingTrackSelector { ...@@ -1643,11 +1663,17 @@ public class DefaultTrackSelector extends MappingTrackSelector {
getAdaptiveAudioTracks( getAdaptiveAudioTracks(
selectedGroup, formatSupports[selectedGroupIndex], params.allowMixedMimeAdaptiveness); selectedGroup, formatSupports[selectedGroupIndex], params.allowMixedMimeAdaptiveness);
if (adaptiveTracks.length > 0) { if (adaptiveTracks.length > 0) {
return adaptiveTrackSelectionFactory selection =
.createTrackSelection(selectedGroup, getBandwidthMeter(), adaptiveTracks); adaptiveTrackSelectionFactory.createTrackSelection(
selectedGroup, getBandwidthMeter(), adaptiveTracks);
} }
} }
return new FixedTrackSelection(selectedGroup, selectedTrackIndex); if (selection == null) {
// We didn't make an adaptive selection, so make a fixed one instead.
selection = new FixedTrackSelection(selectedGroup, selectedTrackIndex);
}
return Pair.create(selection, Assertions.checkNotNull(selectedTrackScore));
} }
private static int[] getAdaptiveAudioTracks(TrackGroup group, int[] formatSupport, private static int[] getAdaptiveAudioTracks(TrackGroup group, int[] formatSupport,
...@@ -1712,10 +1738,11 @@ public class DefaultTrackSelector extends MappingTrackSelector { ...@@ -1712,10 +1738,11 @@ public class DefaultTrackSelector extends MappingTrackSelector {
* @param formatSupport The result of {@link RendererCapabilities#supportsFormat} for each mapped * @param formatSupport The result of {@link RendererCapabilities#supportsFormat} for each mapped
* track, indexed by track group index and track index (in that order). * track, indexed by track group index and track index (in that order).
* @param params The selector's current constraint parameters. * @param params The selector's current constraint parameters.
* @return The {@link TrackSelection} for the renderer, or null if no selection was made. * @return The {@link TrackSelection} and corresponding track score, or null if no selection was
* made.
* @throws ExoPlaybackException If an error occurs while selecting the tracks. * @throws ExoPlaybackException If an error occurs while selecting the tracks.
*/ */
protected @Nullable TrackSelection selectTextTrack( protected @Nullable Pair<TrackSelection, Integer> selectTextTrack(
TrackGroupArray groups, int[][] formatSupport, Parameters params) TrackGroupArray groups, int[][] formatSupport, Parameters params)
throws ExoPlaybackException { throws ExoPlaybackException {
TrackGroup selectedGroup = null; TrackGroup selectedGroup = null;
...@@ -1770,8 +1797,10 @@ public class DefaultTrackSelector extends MappingTrackSelector { ...@@ -1770,8 +1797,10 @@ public class DefaultTrackSelector extends MappingTrackSelector {
} }
} }
} }
return selectedGroup == null ? null return selectedGroup == null
: new FixedTrackSelection(selectedGroup, selectedTrackIndex); ? null
: Pair.create(
new FixedTrackSelection(selectedGroup, selectedTrackIndex), selectedTrackScore);
} }
// General track selection methods. // General track selection methods.
...@@ -2032,12 +2061,9 @@ public class DefaultTrackSelector extends MappingTrackSelector { ...@@ -2032,12 +2061,9 @@ public class DefaultTrackSelector extends MappingTrackSelector {
} }
} }
/** /** Represents how well an audio track matches the selection {@link Parameters}. */
* A representation of how well a track fits with our track selection {@link Parameters}.
*
* <p>This is used to rank different audio tracks relatively with each other.
*/
private static final class AudioTrackScore implements Comparable<AudioTrackScore> { private static final class AudioTrackScore implements Comparable<AudioTrackScore> {
private final Parameters parameters; private final Parameters parameters;
private final int withinRendererCapabilitiesScore; private final int withinRendererCapabilitiesScore;
private final int matchLanguageScore; private final int matchLanguageScore;
...@@ -2057,7 +2083,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { ...@@ -2057,7 +2083,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
} }
/** /**
* Compares the score of the current track format with another {@link AudioTrackScore}. * Compares this score with another.
* *
* @param other The other score to compare to. * @param other The other score to compare to.
* @return A positive integer if this score is better than the other. Zero if they are equal. A * @return A positive integer if this score is better than the other. Zero if they are equal. A
...@@ -2086,35 +2112,6 @@ public class DefaultTrackSelector extends MappingTrackSelector { ...@@ -2086,35 +2112,6 @@ public class DefaultTrackSelector extends MappingTrackSelector {
return resultSign * compareInts(this.bitrate, other.bitrate); return resultSign * compareInts(this.bitrate, other.bitrate);
} }
} }
@Override
public boolean equals(@Nullable Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
AudioTrackScore that = (AudioTrackScore) o;
return withinRendererCapabilitiesScore == that.withinRendererCapabilitiesScore
&& matchLanguageScore == that.matchLanguageScore
&& defaultSelectionFlagScore == that.defaultSelectionFlagScore
&& channelCount == that.channelCount && sampleRate == that.sampleRate
&& bitrate == that.bitrate;
}
@Override
public int hashCode() {
int result = withinRendererCapabilitiesScore;
result = 31 * result + matchLanguageScore;
result = 31 * result + defaultSelectionFlagScore;
result = 31 * result + channelCount;
result = 31 * result + sampleRate;
result = 31 * result + bitrate;
return result;
}
} }
/** /**
......
...@@ -17,6 +17,7 @@ package com.google.android.exoplayer2.trackselection; ...@@ -17,6 +17,7 @@ package com.google.android.exoplayer2.trackselection;
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.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.Matchers.any; import static org.mockito.Matchers.any;
...@@ -76,31 +77,8 @@ public final class DefaultTrackSelectorTest { ...@@ -76,31 +77,8 @@ public final class DefaultTrackSelectorTest {
private static final RendererCapabilities[] RENDERER_CAPABILITIES_WITH_NO_SAMPLE_RENDERER = private static final RendererCapabilities[] RENDERER_CAPABILITIES_WITH_NO_SAMPLE_RENDERER =
new RendererCapabilities[] {VIDEO_CAPABILITIES, NO_SAMPLE_CAPABILITIES}; new RendererCapabilities[] {VIDEO_CAPABILITIES, NO_SAMPLE_CAPABILITIES};
private static final Format VIDEO_FORMAT = private static final Format VIDEO_FORMAT = buildVideoFormat("video");
Format.createVideoSampleFormat( private static final Format AUDIO_FORMAT = buildAudioFormat("audio");
"video",
MimeTypes.VIDEO_H264,
null,
Format.NO_VALUE,
Format.NO_VALUE,
1024,
768,
Format.NO_VALUE,
null,
null);
private static final Format AUDIO_FORMAT =
Format.createAudioSampleFormat(
"audio",
MimeTypes.AUDIO_AAC,
null,
Format.NO_VALUE,
Format.NO_VALUE,
2,
44100,
null,
null,
0,
null);
private static final TrackGroup VIDEO_TRACK_GROUP = new TrackGroup(VIDEO_FORMAT); private static final TrackGroup VIDEO_TRACK_GROUP = new TrackGroup(VIDEO_FORMAT);
private static final TrackGroup AUDIO_TRACK_GROUP = new TrackGroup(AUDIO_FORMAT); private static final TrackGroup AUDIO_TRACK_GROUP = new TrackGroup(AUDIO_FORMAT);
private static final TrackGroupArray TRACK_GROUPS = private static final TrackGroupArray TRACK_GROUPS =
...@@ -339,12 +317,9 @@ public final class DefaultTrackSelectorTest { ...@@ -339,12 +317,9 @@ public final class DefaultTrackSelectorTest {
*/ */
@Test @Test
public void testSelectTracksSelectTrackWithSelectionFlag() throws Exception { public void testSelectTracksSelectTrackWithSelectionFlag() throws Exception {
Format audioFormat = Format audioFormat = buildAudioFormat("audio", /* language= */ null, /* selectionFlags= */ 0);
Format.createAudioSampleFormat("audio", MimeTypes.AUDIO_AAC, null, Format.NO_VALUE,
Format.NO_VALUE, 2, 44100, null, null, 0, null);
Format formatWithSelectionFlag = Format formatWithSelectionFlag =
Format.createAudioSampleFormat("audio", MimeTypes.AUDIO_AAC, null, Format.NO_VALUE, buildAudioFormat("audio", /* language= */ null, C.SELECTION_FLAG_DEFAULT);
Format.NO_VALUE, 2, 44100, null, null, C.SELECTION_FLAG_DEFAULT, null);
TrackSelectorResult result = trackSelector.selectTracks( TrackSelectorResult result = trackSelector.selectTracks(
new RendererCapabilities[] {ALL_AUDIO_FORMAT_SUPPORTED_RENDERER_CAPABILITIES}, new RendererCapabilities[] {ALL_AUDIO_FORMAT_SUPPORTED_RENDERER_CAPABILITIES},
...@@ -405,12 +380,8 @@ public final class DefaultTrackSelectorTest { ...@@ -405,12 +380,8 @@ public final class DefaultTrackSelectorTest {
*/ */
@Test @Test
public void testSelectTracksPreferTrackWithinCapabilities() throws Exception { public void testSelectTracksPreferTrackWithinCapabilities() throws Exception {
Format supportedFormat = Format supportedFormat = buildAudioFormat("supportedFormat");
Format.createAudioSampleFormat("supportedFormat", MimeTypes.AUDIO_AAC, null, Format exceededFormat = buildAudioFormat("exceededFormat");
Format.NO_VALUE, Format.NO_VALUE, 2, 44100, null, null, 0, null);
Format exceededFormat =
Format.createAudioSampleFormat("exceededFormat", MimeTypes.AUDIO_AAC, null,
Format.NO_VALUE, Format.NO_VALUE, 2, 44100, null, null, 0, null);
Map<String, Integer> mappedCapabilities = new HashMap<>(); Map<String, Integer> mappedCapabilities = new HashMap<>();
mappedCapabilities.put(supportedFormat.id, FORMAT_HANDLED); mappedCapabilities.put(supportedFormat.id, FORMAT_HANDLED);
...@@ -781,10 +752,8 @@ public final class DefaultTrackSelectorTest { ...@@ -781,10 +752,8 @@ public final class DefaultTrackSelectorTest {
RendererCapabilities[] textRendererCapabilities = RendererCapabilities[] textRendererCapabilities =
new RendererCapabilities[] {ALL_TEXT_FORMAT_SUPPORTED_RENDERER_CAPABILITIES}; new RendererCapabilities[] {ALL_TEXT_FORMAT_SUPPORTED_RENDERER_CAPABILITIES};
TrackSelectorResult result;
// There is no text language preference, the first track flagged as default should be selected. // There is no text language preference, the first track flagged as default should be selected.
result = TrackSelectorResult result =
trackSelector.selectTracks( trackSelector.selectTracks(
textRendererCapabilities, wrapFormats(forcedOnly, forcedDefault, defaultOnly, noFlag)); textRendererCapabilities, wrapFormats(forcedOnly, forcedDefault, defaultOnly, noFlag));
assertThat(result.selections.get(0).getFormat(0)).isSameAs(forcedDefault); assertThat(result.selections.get(0).getFormat(0)).isSameAs(forcedDefault);
...@@ -878,10 +847,10 @@ public final class DefaultTrackSelectorTest { ...@@ -878,10 +847,10 @@ public final class DefaultTrackSelectorTest {
RendererCapabilities[] textRendererCapabilites = RendererCapabilities[] textRendererCapabilites =
new RendererCapabilities[] {ALL_TEXT_FORMAT_SUPPORTED_RENDERER_CAPABILITIES}; new RendererCapabilities[] {ALL_TEXT_FORMAT_SUPPORTED_RENDERER_CAPABILITIES};
TrackSelectorResult result; TrackSelectorResult result =
trackSelector.selectTracks(
result = trackSelector.selectTracks(textRendererCapabilites, textRendererCapabilites,
wrapFormats(spanish, german, undeterminedUnd, undeterminedNull)); wrapFormats(spanish, german, undeterminedUnd, undeterminedNull));
assertThat(result.selections.get(0)).isNull(); assertThat(result.selections.get(0)).isNull();
trackSelector.setParameters( trackSelector.setParameters(
...@@ -913,6 +882,48 @@ public final class DefaultTrackSelectorTest { ...@@ -913,6 +882,48 @@ public final class DefaultTrackSelectorTest {
assertThat(result.selections.get(0)).isNull(); assertThat(result.selections.get(0)).isNull();
} }
/** Tests audio track selection when there are multiple audio renderers. */
@Test
public void testSelectPreferredTextTrackMultipleRenderers() throws Exception {
Format english = buildTextFormat("en", "en");
Format german = buildTextFormat("de", "de");
// First renderer handles english.
Map<String, Integer> firstRendererMappedCapabilities = new HashMap<>();
firstRendererMappedCapabilities.put(english.id, FORMAT_HANDLED);
firstRendererMappedCapabilities.put(german.id, FORMAT_UNSUPPORTED_SUBTYPE);
RendererCapabilities firstRendererCapabilities =
new FakeMappedRendererCapabilities(C.TRACK_TYPE_TEXT, firstRendererMappedCapabilities);
// Second renderer handles german.
Map<String, Integer> secondRendererMappedCapabilities = new HashMap<>();
secondRendererMappedCapabilities.put(english.id, FORMAT_UNSUPPORTED_SUBTYPE);
secondRendererMappedCapabilities.put(german.id, FORMAT_HANDLED);
RendererCapabilities secondRendererCapabilities =
new FakeMappedRendererCapabilities(C.TRACK_TYPE_TEXT, secondRendererMappedCapabilities);
RendererCapabilities[] rendererCapabilities =
new RendererCapabilities[] {firstRendererCapabilities, secondRendererCapabilities};
// Without an explicit language preference, nothing should be selected.
TrackSelectorResult result =
trackSelector.selectTracks(rendererCapabilities, wrapFormats(english, german));
assertThat(result.selections.get(0)).isNull();
assertThat(result.selections.get(1)).isNull();
// Explicit language preference for english. First renderer should be used.
trackSelector.setParameters(trackSelector.buildUponParameters().setPreferredTextLanguage("en"));
result = trackSelector.selectTracks(rendererCapabilities, wrapFormats(english, german));
assertThat(result.selections.get(0).getFormat(0)).isSameAs(english);
assertThat(result.selections.get(1)).isNull();
// Explicit language preference for German. Second renderer should be used.
trackSelector.setParameters(trackSelector.buildUponParameters().setPreferredTextLanguage("de"));
result = trackSelector.selectTracks(rendererCapabilities, wrapFormats(english, german));
assertThat(result.selections.get(0)).isNull();
assertThat(result.selections.get(1).getFormat(0)).isSameAs(german);
}
/** /**
* Tests that track selector will select audio tracks with lower bitrate when {@link Parameters} * Tests that track selector will select audio tracks with lower bitrate when {@link Parameters}
* indicate lowest bitrate preference, even when tracks are within capabilities. * indicate lowest bitrate preference, even when tracks are within capabilities.
...@@ -987,6 +998,50 @@ public final class DefaultTrackSelectorTest { ...@@ -987,6 +998,50 @@ public final class DefaultTrackSelectorTest {
.createTrackSelection(trackGroupArray.get(0), bandwidthMeter, 1, 2); .createTrackSelection(trackGroupArray.get(0), bandwidthMeter, 1, 2);
} }
/** Tests audio track selection when there are multiple audio renderers. */
@Test
public void testSelectPreferredAudioTrackMultipleRenderers() throws Exception {
Format english = buildAudioFormat("en", "en");
Format german = buildAudioFormat("de", "de");
// First renderer handles english.
Map<String, Integer> firstRendererMappedCapabilities = new HashMap<>();
firstRendererMappedCapabilities.put(english.id, FORMAT_HANDLED);
firstRendererMappedCapabilities.put(german.id, FORMAT_UNSUPPORTED_SUBTYPE);
RendererCapabilities firstRendererCapabilities =
new FakeMappedRendererCapabilities(C.TRACK_TYPE_AUDIO, firstRendererMappedCapabilities);
// Second renderer handles german.
Map<String, Integer> secondRendererMappedCapabilities = new HashMap<>();
secondRendererMappedCapabilities.put(english.id, FORMAT_UNSUPPORTED_SUBTYPE);
secondRendererMappedCapabilities.put(german.id, FORMAT_HANDLED);
RendererCapabilities secondRendererCapabilities =
new FakeMappedRendererCapabilities(C.TRACK_TYPE_AUDIO, secondRendererMappedCapabilities);
RendererCapabilities[] rendererCapabilities =
new RendererCapabilities[] {firstRendererCapabilities, secondRendererCapabilities};
// Without an explicit language preference, prefer the first renderer.
TrackSelectorResult result =
trackSelector.selectTracks(rendererCapabilities, wrapFormats(english, german));
assertThat(result.selections.get(0).getFormat(0)).isSameAs(english);
assertThat(result.selections.get(1)).isNull();
// Explicit language preference for english. First renderer should be used.
trackSelector.setParameters(
trackSelector.buildUponParameters().setPreferredAudioLanguage("en"));
result = trackSelector.selectTracks(rendererCapabilities, wrapFormats(english, german));
assertThat(result.selections.get(0).getFormat(0)).isSameAs(english);
assertThat(result.selections.get(1)).isNull();
// Explicit language preference for German. Second renderer should be used.
trackSelector.setParameters(
trackSelector.buildUponParameters().setPreferredAudioLanguage("de"));
result = trackSelector.selectTracks(rendererCapabilities, wrapFormats(english, german));
assertThat(result.selections.get(0)).isNull();
assertThat(result.selections.get(1).getFormat(0)).isSameAs(german);
}
@Test @Test
public void testSelectTracksWithMultipleVideoTracksReturnsAdaptiveTrackSelection() public void testSelectTracksWithMultipleVideoTracksReturnsAdaptiveTrackSelection()
throws Exception { throws Exception {
...@@ -1057,6 +1112,43 @@ public final class DefaultTrackSelectorTest { ...@@ -1057,6 +1112,43 @@ public final class DefaultTrackSelectorTest {
return new TrackGroupArray(trackGroups); return new TrackGroupArray(trackGroups);
} }
private static Format buildVideoFormat(String id) {
return Format.createVideoSampleFormat(
id,
MimeTypes.VIDEO_H264,
null,
Format.NO_VALUE,
Format.NO_VALUE,
1024,
768,
Format.NO_VALUE,
null,
null);
}
private static Format buildAudioFormat(String id) {
return buildAudioFormat(id, /* language= */ null);
}
private static Format buildAudioFormat(String id, String language) {
return buildAudioFormat(id, language, /* selectionFlags= */ 0);
}
private static Format buildAudioFormat(String id, String language, int selectionFlags) {
return Format.createAudioSampleFormat(
id,
MimeTypes.AUDIO_AAC,
/* codecs= */ null,
/* bitrate= */ Format.NO_VALUE,
/* maxInputSize= */ Format.NO_VALUE,
/* channelCount= */ 2,
/* sampleRate= */ 44100,
/* initializationData= */ null,
/* drmInitData= */ null,
selectionFlags,
language);
}
private static Format buildTextFormat(String id, String language) { private static Format buildTextFormat(String id, String language) {
return buildTextFormat(id, language, /* selectionFlags= */ 0); return buildTextFormat(id, language, /* selectionFlags= */ 0);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment