mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Update DefaultTrackSelector to use more conditions when selecting audio track
Update the audio track selection logic in DefaultTrackSelector: - When forcing lowest bitrate, use bitrate as tie-breaker when track scores are the same, prefer the lower bitrate. - Otherwise, use one of the following values as tie-breaker in order: - ChannelCount - SampleRate - BitRate If the format being checked is within renderer's capabilities, select it if it has higher tie-break value, else, select it if it has lower tie-break value. If all tie-break values are the same, prefer the already selected track. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=171803092
This commit is contained in:
parent
5d4fa335f9
commit
763f663d01
2 changed files with 762 additions and 30 deletions
|
|
@ -762,10 +762,9 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
||||||
protected TrackSelection selectAudioTrack(TrackGroupArray groups, int[][] formatSupport,
|
protected TrackSelection selectAudioTrack(TrackGroupArray groups, int[][] formatSupport,
|
||||||
Parameters params, TrackSelection.Factory adaptiveTrackSelectionFactory)
|
Parameters params, TrackSelection.Factory adaptiveTrackSelectionFactory)
|
||||||
throws ExoPlaybackException {
|
throws ExoPlaybackException {
|
||||||
int selectedGroupIndex = C.INDEX_UNSET;
|
|
||||||
int selectedTrackIndex = C.INDEX_UNSET;
|
int selectedTrackIndex = C.INDEX_UNSET;
|
||||||
int selectedTrackScore = 0;
|
int selectedGroupIndex = C.INDEX_UNSET;
|
||||||
int selectedBitrate = Format.NO_VALUE;
|
AudioTrackScore selectedTrackScore = null;
|
||||||
for (int groupIndex = 0; groupIndex < groups.length; groupIndex++) {
|
for (int groupIndex = 0; groupIndex < groups.length; groupIndex++) {
|
||||||
TrackGroup trackGroup = groups.get(groupIndex);
|
TrackGroup trackGroup = groups.get(groupIndex);
|
||||||
int[] trackFormatSupport = formatSupport[groupIndex];
|
int[] trackFormatSupport = formatSupport[groupIndex];
|
||||||
|
|
@ -773,15 +772,12 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
||||||
if (isSupported(trackFormatSupport[trackIndex],
|
if (isSupported(trackFormatSupport[trackIndex],
|
||||||
params.exceedRendererCapabilitiesIfNecessary)) {
|
params.exceedRendererCapabilitiesIfNecessary)) {
|
||||||
Format format = trackGroup.getFormat(trackIndex);
|
Format format = trackGroup.getFormat(trackIndex);
|
||||||
int trackScore = getAudioTrackScore(trackFormatSupport[trackIndex],
|
AudioTrackScore trackScore =
|
||||||
params.preferredAudioLanguage, format);
|
new AudioTrackScore(format, params, trackFormatSupport[trackIndex]);
|
||||||
if (trackScore > selectedTrackScore
|
if (selectedTrackScore == null || trackScore.compareTo(selectedTrackScore) > 0) {
|
||||||
|| (trackScore == selectedTrackScore && params.forceLowestBitrate
|
|
||||||
&& compareFormatValues(format.bitrate, selectedBitrate) < 0)) {
|
|
||||||
selectedGroupIndex = groupIndex;
|
selectedGroupIndex = groupIndex;
|
||||||
selectedTrackIndex = trackIndex;
|
selectedTrackIndex = trackIndex;
|
||||||
selectedTrackScore = trackScore;
|
selectedTrackScore = trackScore;
|
||||||
selectedBitrate = format.bitrate;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -804,27 +800,6 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
||||||
return new FixedTrackSelection(selectedGroup, selectedTrackIndex);
|
return new FixedTrackSelection(selectedGroup, selectedTrackIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getAudioTrackScore(int formatSupport, String preferredLanguage,
|
|
||||||
Format format) {
|
|
||||||
boolean isDefault = (format.selectionFlags & C.SELECTION_FLAG_DEFAULT) != 0;
|
|
||||||
int trackScore;
|
|
||||||
if (formatHasLanguage(format, preferredLanguage)) {
|
|
||||||
if (isDefault) {
|
|
||||||
trackScore = 4;
|
|
||||||
} else {
|
|
||||||
trackScore = 3;
|
|
||||||
}
|
|
||||||
} else if (isDefault) {
|
|
||||||
trackScore = 2;
|
|
||||||
} else {
|
|
||||||
trackScore = 1;
|
|
||||||
}
|
|
||||||
if (isSupported(formatSupport, false)) {
|
|
||||||
trackScore += WITHIN_RENDERER_CAPABILITIES_BONUS;
|
|
||||||
}
|
|
||||||
return trackScore;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int[] getAdaptiveAudioTracks(TrackGroup group, int[] formatSupport,
|
private static int[] getAdaptiveAudioTracks(TrackGroup group, int[] formatSupport,
|
||||||
boolean allowMixedMimeTypes) {
|
boolean allowMixedMimeTypes) {
|
||||||
int selectedConfigurationTrackCount = 0;
|
int selectedConfigurationTrackCount = 0;
|
||||||
|
|
@ -1090,6 +1065,103 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 final Parameters parameters;
|
||||||
|
private final int withinRendererCapabilitiesScore;
|
||||||
|
private final int matchLanguageScore;
|
||||||
|
private final int defaultSelectionFlagScore;
|
||||||
|
private final int channelCount;
|
||||||
|
private final int sampleRate;
|
||||||
|
private final int bitrate;
|
||||||
|
|
||||||
|
public AudioTrackScore(Format format, Parameters parameters, int formatSupport) {
|
||||||
|
this.parameters = parameters;
|
||||||
|
withinRendererCapabilitiesScore = isSupported(formatSupport, false) ? 1 : 0;
|
||||||
|
matchLanguageScore = formatHasLanguage(format, parameters.preferredAudioLanguage) ? 1 : 0;
|
||||||
|
defaultSelectionFlagScore = (format.selectionFlags & C.SELECTION_FLAG_DEFAULT) != 0 ? 1 : 0;
|
||||||
|
channelCount = format.channelCount;
|
||||||
|
sampleRate = format.sampleRate;
|
||||||
|
bitrate = format.bitrate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares the score of the current track format with another {@link AudioTrackScore}.
|
||||||
|
*
|
||||||
|
* @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 negative integer if this score is worse than the other.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int compareTo(AudioTrackScore other) {
|
||||||
|
if (this.withinRendererCapabilitiesScore != other.withinRendererCapabilitiesScore) {
|
||||||
|
return compareInts(this.withinRendererCapabilitiesScore,
|
||||||
|
other.withinRendererCapabilitiesScore);
|
||||||
|
} else if (this.matchLanguageScore != other.matchLanguageScore) {
|
||||||
|
return compareInts(this.matchLanguageScore, other.matchLanguageScore);
|
||||||
|
} else if (this.defaultSelectionFlagScore != other.defaultSelectionFlagScore) {
|
||||||
|
return compareInts(this.defaultSelectionFlagScore, other.defaultSelectionFlagScore);
|
||||||
|
} else if (parameters.forceLowestBitrate) {
|
||||||
|
return compareInts(other.bitrate, this.bitrate);
|
||||||
|
} else {
|
||||||
|
// If the format are within renderer capabilities, prefer higher values of channel count,
|
||||||
|
// sample rate and bit rate in that order. Otherwise, prefer lower values.
|
||||||
|
int resultSign = withinRendererCapabilitiesScore == 1 ? 1 : -1;
|
||||||
|
if (this.channelCount != other.channelCount) {
|
||||||
|
return resultSign * compareInts(this.channelCount, other.channelCount);
|
||||||
|
} else if (this.sampleRate != other.sampleRate) {
|
||||||
|
return resultSign * compareInts(this.sampleRate, other.sampleRate);
|
||||||
|
}
|
||||||
|
return resultSign * compareInts(this.bitrate, other.bitrate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares two integers in a safe way and avoiding potential overflow.
|
||||||
|
*
|
||||||
|
* @param first The first value.
|
||||||
|
* @param second The second value.
|
||||||
|
* @return A negative integer if the first value is less than the second. Zero if they are equal.
|
||||||
|
* A positive integer if the first value is greater than the second.
|
||||||
|
*/
|
||||||
|
private static int compareInts(int first, int second) {
|
||||||
|
return first > second ? 1 : (second > first ? -1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
private static final class AudioConfigurationTuple {
|
private static final class AudioConfigurationTuple {
|
||||||
|
|
||||||
public final int channelCount;
|
public final int channelCount;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,660 @@
|
||||||
|
package com.google.android.exoplayer2.trackselection;
|
||||||
|
|
||||||
|
import static com.google.android.exoplayer2.RendererCapabilities.FORMAT_EXCEEDS_CAPABILITIES;
|
||||||
|
import static com.google.android.exoplayer2.RendererCapabilities.FORMAT_HANDLED;
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.MockitoAnnotations.initMocks;
|
||||||
|
|
||||||
|
import com.google.android.exoplayer2.C;
|
||||||
|
import com.google.android.exoplayer2.ExoPlaybackException;
|
||||||
|
import com.google.android.exoplayer2.Format;
|
||||||
|
import com.google.android.exoplayer2.RendererCapabilities;
|
||||||
|
import com.google.android.exoplayer2.source.TrackGroup;
|
||||||
|
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||||
|
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters;
|
||||||
|
import com.google.android.exoplayer2.trackselection.TrackSelector.InvalidationListener;
|
||||||
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.robolectric.RobolectricTestRunner;
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for {@link DefaultTrackSelector}.
|
||||||
|
*/
|
||||||
|
@RunWith(RobolectricTestRunner.class)
|
||||||
|
@Config(sdk = Config.TARGET_SDK, manifest = Config.NONE)
|
||||||
|
public final class DefaultTrackSelectorTest {
|
||||||
|
|
||||||
|
private static final Parameters DEFAULT_PARAMETERS = new Parameters();
|
||||||
|
private static final RendererCapabilities ALL_AUDIO_FORMAT_SUPPORTED_RENDERER_CAPABILITIES =
|
||||||
|
new FakeRendererCapabilities(C.TRACK_TYPE_AUDIO);
|
||||||
|
private static final RendererCapabilities ALL_AUDIO_FORMAT_EXCEEDED_RENDERER_CAPABILITIES =
|
||||||
|
new FakeRendererCapabilities(C.TRACK_TYPE_AUDIO, FORMAT_EXCEEDS_CAPABILITIES);
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private InvalidationListener invalidationListener;
|
||||||
|
|
||||||
|
private DefaultTrackSelector trackSelector;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
initMocks(this);
|
||||||
|
trackSelector = new DefaultTrackSelector();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that track selector will not call
|
||||||
|
* {@link InvalidationListener#onTrackSelectionsInvalidated()} when it's set with default
|
||||||
|
* values of {@link Parameters}.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSetParameterWithDefaultParametersDoesNotNotifyInvalidationListener()
|
||||||
|
throws Exception {
|
||||||
|
trackSelector.init(invalidationListener);
|
||||||
|
trackSelector.setParameters(DEFAULT_PARAMETERS);
|
||||||
|
|
||||||
|
verify(invalidationListener, never()).onTrackSelectionsInvalidated();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that track selector will call {@link InvalidationListener#onTrackSelectionsInvalidated()}
|
||||||
|
* when it's set with non-default values of {@link Parameters}.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSetParameterWithNonDefaultParameterNotifyInvalidationListener()
|
||||||
|
throws Exception {
|
||||||
|
Parameters parameters = DEFAULT_PARAMETERS.withPreferredAudioLanguage("en");
|
||||||
|
trackSelector.init(invalidationListener);
|
||||||
|
trackSelector.setParameters(parameters);
|
||||||
|
|
||||||
|
verify(invalidationListener).onTrackSelectionsInvalidated();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that track selector will not call
|
||||||
|
* {@link InvalidationListener#onTrackSelectionsInvalidated()} again when it's set with
|
||||||
|
* the same values of {@link Parameters}.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSetParameterWithSameParametersDoesNotNotifyInvalidationListenerAgain()
|
||||||
|
throws Exception {
|
||||||
|
Parameters parameters = DEFAULT_PARAMETERS.withPreferredAudioLanguage("en");
|
||||||
|
trackSelector.init(invalidationListener);
|
||||||
|
trackSelector.setParameters(parameters);
|
||||||
|
trackSelector.setParameters(parameters);
|
||||||
|
|
||||||
|
verify(invalidationListener, times(1)).onTrackSelectionsInvalidated();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that track selector will select audio track with {@link C#SELECTION_FLAG_DEFAULT}
|
||||||
|
* given default values of {@link Parameters}.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSelectTracksSelectTrackWithSelectionFlag() throws Exception {
|
||||||
|
Format audioFormat =
|
||||||
|
Format.createAudioSampleFormat("audio", MimeTypes.AUDIO_AAC, null, Format.NO_VALUE,
|
||||||
|
Format.NO_VALUE, 2, 44100, null, null, 0, null);
|
||||||
|
Format formatWithSelectionFlag =
|
||||||
|
Format.createAudioSampleFormat("audio", MimeTypes.AUDIO_AAC, null, Format.NO_VALUE,
|
||||||
|
Format.NO_VALUE, 2, 44100, null, null, C.SELECTION_FLAG_DEFAULT, null);
|
||||||
|
|
||||||
|
TrackSelectorResult result = trackSelector.selectTracks(
|
||||||
|
new RendererCapabilities[] {ALL_AUDIO_FORMAT_SUPPORTED_RENDERER_CAPABILITIES},
|
||||||
|
singleTrackGroup(formatWithSelectionFlag, audioFormat));
|
||||||
|
assertThat(result.selections.get(0).getSelectedFormat()).isEqualTo(formatWithSelectionFlag);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that track selector will select audio track with language that match preferred language
|
||||||
|
* given by {@link Parameters}.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSelectTracksSelectPreferredAudioLanguage()
|
||||||
|
throws Exception {
|
||||||
|
Parameters parameters = DEFAULT_PARAMETERS.withPreferredAudioLanguage("en");
|
||||||
|
trackSelector.setParameters(parameters);
|
||||||
|
|
||||||
|
Format frAudioFormat =
|
||||||
|
Format.createAudioSampleFormat("audio", MimeTypes.AUDIO_AAC, null, Format.NO_VALUE,
|
||||||
|
Format.NO_VALUE, 2, 44100, null, null, 0, "fr");
|
||||||
|
Format enAudioFormat =
|
||||||
|
Format.createAudioSampleFormat("audio", MimeTypes.AUDIO_AAC, null, Format.NO_VALUE,
|
||||||
|
Format.NO_VALUE, 2, 44100, null, null, 0, "en");
|
||||||
|
|
||||||
|
TrackSelectorResult result = trackSelector.selectTracks(
|
||||||
|
new RendererCapabilities[] {ALL_AUDIO_FORMAT_SUPPORTED_RENDERER_CAPABILITIES},
|
||||||
|
singleTrackGroup(frAudioFormat, enAudioFormat));
|
||||||
|
|
||||||
|
assertThat(result.selections.get(0).getSelectedFormat()).isEqualTo(enAudioFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that track selector will prefer selecting audio track with language that match preferred
|
||||||
|
* language given by {@link Parameters} over track with {@link C#SELECTION_FLAG_DEFAULT}.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSelectTracksSelectPreferredAudioLanguageOverSelectionFlag()
|
||||||
|
throws Exception {
|
||||||
|
Parameters parameters = DEFAULT_PARAMETERS.withPreferredAudioLanguage("en");
|
||||||
|
trackSelector.setParameters(parameters);
|
||||||
|
|
||||||
|
Format frAudioFormat =
|
||||||
|
Format.createAudioSampleFormat("audio", MimeTypes.AUDIO_AAC, null, Format.NO_VALUE,
|
||||||
|
Format.NO_VALUE, 2, 44100, null, null, C.SELECTION_FLAG_DEFAULT, "fr");
|
||||||
|
Format enAudioFormat =
|
||||||
|
Format.createAudioSampleFormat("audio", MimeTypes.AUDIO_AAC, null, Format.NO_VALUE,
|
||||||
|
Format.NO_VALUE, 2, 44100, null, null, 0, "en");
|
||||||
|
|
||||||
|
TrackSelectorResult result = trackSelector.selectTracks(
|
||||||
|
new RendererCapabilities[] {ALL_AUDIO_FORMAT_SUPPORTED_RENDERER_CAPABILITIES},
|
||||||
|
singleTrackGroup(frAudioFormat, enAudioFormat));
|
||||||
|
|
||||||
|
assertThat(result.selections.get(0).getSelectedFormat()).isEqualTo(enAudioFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that track selector will prefer tracks that are within renderer's capabilities over
|
||||||
|
* track that exceed renderer's capabilities.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSelectTracksPreferTrackWithinCapabilities()
|
||||||
|
throws Exception {
|
||||||
|
Format supportedFormat =
|
||||||
|
Format.createAudioSampleFormat("supportedFormat", MimeTypes.AUDIO_AAC, null,
|
||||||
|
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<>();
|
||||||
|
mappedCapabilities.put(supportedFormat.id, FORMAT_HANDLED);
|
||||||
|
mappedCapabilities.put(exceededFormat.id, FORMAT_EXCEEDS_CAPABILITIES);
|
||||||
|
RendererCapabilities mappedAudioRendererCapabilities =
|
||||||
|
new FakeMappedRendererCapabilities(C.TRACK_TYPE_AUDIO, mappedCapabilities);
|
||||||
|
|
||||||
|
TrackSelectorResult result = trackSelector.selectTracks(
|
||||||
|
new RendererCapabilities[] {mappedAudioRendererCapabilities},
|
||||||
|
singleTrackGroup(exceededFormat, supportedFormat));
|
||||||
|
|
||||||
|
assertThat(result.selections.get(0).getSelectedFormat()).isEqualTo(supportedFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that track selector will select a track that exceeds the renderer's capabilities when
|
||||||
|
* there are no other choice, given the default {@link Parameters}.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSelectTracksWithNoTrackWithinCapabilitiesSelectExceededCapabilityTrack()
|
||||||
|
throws Exception {
|
||||||
|
|
||||||
|
Format audioFormat =
|
||||||
|
Format.createAudioSampleFormat("audio", MimeTypes.AUDIO_AAC, null, Format.NO_VALUE,
|
||||||
|
Format.NO_VALUE, 2, 44100, null, null, 0, null);
|
||||||
|
TrackSelectorResult result = trackSelector.selectTracks(
|
||||||
|
new RendererCapabilities[] {ALL_AUDIO_FORMAT_EXCEEDED_RENDERER_CAPABILITIES},
|
||||||
|
singleTrackGroup(audioFormat));
|
||||||
|
|
||||||
|
assertThat(result.selections.get(0).getSelectedFormat()).isEqualTo(audioFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that track selector will return a null track selection for a renderer when
|
||||||
|
* all tracks exceed that renderer's capabilities when {@link Parameters} does not allow
|
||||||
|
* exceeding-capabilities tracks.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSelectTracksWithNoTrackWithinCapabilitiesAndSetByParamsReturnNoSelection()
|
||||||
|
throws Exception {
|
||||||
|
Parameters parameters = DEFAULT_PARAMETERS.withExceedRendererCapabilitiesIfNecessary(false);
|
||||||
|
trackSelector.setParameters(parameters);
|
||||||
|
|
||||||
|
Format audioFormat =
|
||||||
|
Format.createAudioSampleFormat("audio", MimeTypes.AUDIO_AAC, null, Format.NO_VALUE,
|
||||||
|
Format.NO_VALUE, 2, 44100, null, null, 0, null);
|
||||||
|
TrackSelectorResult result = trackSelector.selectTracks(
|
||||||
|
new RendererCapabilities[] {ALL_AUDIO_FORMAT_EXCEEDED_RENDERER_CAPABILITIES},
|
||||||
|
singleTrackGroup(audioFormat));
|
||||||
|
|
||||||
|
assertThat(result.selections.get(0)).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that track selector will prefer tracks that are within renderer's capabilities over
|
||||||
|
* tracks that have {@link C#SELECTION_FLAG_DEFAULT} but exceed renderer's capabilities.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSelectTracksPreferTrackWithinCapabilitiesOverSelectionFlag()
|
||||||
|
throws Exception {
|
||||||
|
Format supportedFormat =
|
||||||
|
Format.createAudioSampleFormat("supportedFormat", MimeTypes.AUDIO_AAC, null,
|
||||||
|
Format.NO_VALUE, Format.NO_VALUE, 2, 44100, null, null, 0, null);
|
||||||
|
Format exceededWithSelectionFlagFormat =
|
||||||
|
Format.createAudioSampleFormat("exceededFormat", MimeTypes.AUDIO_AAC, null,
|
||||||
|
Format.NO_VALUE, Format.NO_VALUE, 2, 44100, null, null, C.SELECTION_FLAG_DEFAULT, null);
|
||||||
|
|
||||||
|
Map<String, Integer> mappedCapabilities = new HashMap<>();
|
||||||
|
mappedCapabilities.put(supportedFormat.id, FORMAT_HANDLED);
|
||||||
|
mappedCapabilities.put(exceededWithSelectionFlagFormat.id, FORMAT_EXCEEDS_CAPABILITIES);
|
||||||
|
RendererCapabilities mappedAudioRendererCapabilities =
|
||||||
|
new FakeMappedRendererCapabilities(C.TRACK_TYPE_AUDIO, mappedCapabilities);
|
||||||
|
|
||||||
|
TrackSelectorResult result = trackSelector.selectTracks(
|
||||||
|
new RendererCapabilities[] {mappedAudioRendererCapabilities},
|
||||||
|
singleTrackGroup(exceededWithSelectionFlagFormat, supportedFormat));
|
||||||
|
|
||||||
|
assertThat(result.selections.get(0).getSelectedFormat()).isEqualTo(supportedFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that track selector will prefer tracks that are within renderer's capabilities over
|
||||||
|
* track that have language matching preferred audio given by {@link Parameters} but exceed
|
||||||
|
* renderer's capabilities.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSelectTracksPreferTrackWithinCapabilitiesOverPreferredLanguage()
|
||||||
|
throws Exception {
|
||||||
|
Parameters parameters = DEFAULT_PARAMETERS.withPreferredAudioLanguage("en");
|
||||||
|
trackSelector.setParameters(parameters);
|
||||||
|
|
||||||
|
Format supportedFrFormat =
|
||||||
|
Format.createAudioSampleFormat("supportedFormat", MimeTypes.AUDIO_AAC, null,
|
||||||
|
Format.NO_VALUE, Format.NO_VALUE, 2, 44100, null, null, 0, "fr");
|
||||||
|
Format exceededEnFormat =
|
||||||
|
Format.createAudioSampleFormat("exceededFormat", MimeTypes.AUDIO_AAC, null,
|
||||||
|
Format.NO_VALUE, Format.NO_VALUE, 2, 44100, null, null, 0, "en");
|
||||||
|
|
||||||
|
Map<String, Integer> mappedCapabilities = new HashMap<>();
|
||||||
|
mappedCapabilities.put(exceededEnFormat.id, FORMAT_EXCEEDS_CAPABILITIES);
|
||||||
|
mappedCapabilities.put(supportedFrFormat.id, FORMAT_HANDLED);
|
||||||
|
RendererCapabilities mappedAudioRendererCapabilities =
|
||||||
|
new FakeMappedRendererCapabilities(C.TRACK_TYPE_AUDIO, mappedCapabilities);
|
||||||
|
|
||||||
|
TrackSelectorResult result = trackSelector.selectTracks(
|
||||||
|
new RendererCapabilities[] {mappedAudioRendererCapabilities},
|
||||||
|
singleTrackGroup(exceededEnFormat, supportedFrFormat));
|
||||||
|
|
||||||
|
assertThat(result.selections.get(0).getSelectedFormat()).isEqualTo(supportedFrFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that track selector will prefer tracks that are within renderer's capabilities over
|
||||||
|
* track that have both language matching preferred audio given by {@link Parameters} and
|
||||||
|
* {@link C#SELECTION_FLAG_DEFAULT}, but exceed renderer's capabilities.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSelectTracksPreferTrackWithinCapabilitiesOverSelectionFlagAndPreferredLanguage()
|
||||||
|
throws Exception {
|
||||||
|
Parameters parameters = DEFAULT_PARAMETERS.withPreferredAudioLanguage("en");
|
||||||
|
trackSelector.setParameters(parameters);
|
||||||
|
|
||||||
|
Format supportedFrFormat =
|
||||||
|
Format.createAudioSampleFormat("supportedFormat", MimeTypes.AUDIO_AAC, null,
|
||||||
|
Format.NO_VALUE, Format.NO_VALUE, 2, 44100, null, null, 0, "fr");
|
||||||
|
Format exceededDefaultSelectionEnFormat =
|
||||||
|
Format.createAudioSampleFormat("exceededFormat", MimeTypes.AUDIO_AAC, null,
|
||||||
|
Format.NO_VALUE, Format.NO_VALUE, 2, 44100, null, null, C.SELECTION_FLAG_DEFAULT, "en");
|
||||||
|
|
||||||
|
Map<String, Integer> mappedCapabilities = new HashMap<>();
|
||||||
|
mappedCapabilities.put(exceededDefaultSelectionEnFormat.id, FORMAT_EXCEEDS_CAPABILITIES);
|
||||||
|
mappedCapabilities.put(supportedFrFormat.id, FORMAT_HANDLED);
|
||||||
|
RendererCapabilities mappedAudioRendererCapabilities =
|
||||||
|
new FakeMappedRendererCapabilities(C.TRACK_TYPE_AUDIO, mappedCapabilities);
|
||||||
|
|
||||||
|
TrackSelectorResult result = trackSelector.selectTracks(
|
||||||
|
new RendererCapabilities[] {mappedAudioRendererCapabilities},
|
||||||
|
singleTrackGroup(exceededDefaultSelectionEnFormat, supportedFrFormat));
|
||||||
|
|
||||||
|
assertThat(result.selections.get(0).getSelectedFormat()).isEqualTo(supportedFrFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that track selector will select audio tracks with higher num channel when other factors
|
||||||
|
* are the same, and tracks are within renderer's capabilities.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSelectTracksWithinCapabilitiesSelectHigherNumChannel()
|
||||||
|
throws Exception {
|
||||||
|
Format lowerChannelFormat =
|
||||||
|
Format.createAudioSampleFormat("audioFormat", MimeTypes.AUDIO_AAC, null, Format.NO_VALUE,
|
||||||
|
Format.NO_VALUE, 2, 44100, null, null, 0, null);
|
||||||
|
Format higherChannelFormat =
|
||||||
|
Format.createAudioSampleFormat("audioFormat", MimeTypes.AUDIO_AAC, null, Format.NO_VALUE,
|
||||||
|
Format.NO_VALUE, 6, 44100, null, null, 0, null);
|
||||||
|
|
||||||
|
TrackSelectorResult result = trackSelector.selectTracks(
|
||||||
|
new RendererCapabilities[] {ALL_AUDIO_FORMAT_SUPPORTED_RENDERER_CAPABILITIES},
|
||||||
|
singleTrackGroup(higherChannelFormat, lowerChannelFormat));
|
||||||
|
|
||||||
|
assertThat(result.selections.get(0).getSelectedFormat()).isEqualTo(higherChannelFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that track selector will select audio tracks with higher sample rate when other factors
|
||||||
|
* are the same, and tracks are within renderer's capabilities.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSelectTracksWithinCapabilitiesSelectHigherSampleRate()
|
||||||
|
throws Exception {
|
||||||
|
Format higherSampleRateFormat =
|
||||||
|
Format.createAudioSampleFormat("audioFormat", MimeTypes.AUDIO_AAC, null, Format.NO_VALUE,
|
||||||
|
Format.NO_VALUE, 2, 44100, null, null, 0, null);
|
||||||
|
Format lowerSampleRateFormat =
|
||||||
|
Format.createAudioSampleFormat("audioFormat", MimeTypes.AUDIO_AAC, null, Format.NO_VALUE,
|
||||||
|
Format.NO_VALUE, 2, 22050, null, null, 0, null);
|
||||||
|
|
||||||
|
TrackSelectorResult result = trackSelector.selectTracks(
|
||||||
|
new RendererCapabilities[] {ALL_AUDIO_FORMAT_SUPPORTED_RENDERER_CAPABILITIES},
|
||||||
|
singleTrackGroup(higherSampleRateFormat, lowerSampleRateFormat));
|
||||||
|
|
||||||
|
assertThat(result.selections.get(0).getSelectedFormat()).isEqualTo(higherSampleRateFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSelectTracksWithinCapabilitiesSelectHigherBitrate()
|
||||||
|
throws Exception {
|
||||||
|
Format lowerBitrateFormat =
|
||||||
|
Format.createAudioSampleFormat("audioFormat", MimeTypes.AUDIO_AAC, null, 15000,
|
||||||
|
Format.NO_VALUE, 2, 44100, null, null, 0, null);
|
||||||
|
Format higherBitrateFormat =
|
||||||
|
Format.createAudioSampleFormat("audioFormat", MimeTypes.AUDIO_AAC, null, 30000,
|
||||||
|
Format.NO_VALUE, 2, 44100, null, null, 0, null);
|
||||||
|
|
||||||
|
TrackSelectorResult result = trackSelector.selectTracks(
|
||||||
|
new RendererCapabilities[] {ALL_AUDIO_FORMAT_SUPPORTED_RENDERER_CAPABILITIES},
|
||||||
|
singleTrackGroup(lowerBitrateFormat, higherBitrateFormat));
|
||||||
|
|
||||||
|
assertThat(result.selections.get(0).getSelectedFormat()).isEqualTo(higherBitrateFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 {
|
||||||
|
Format lowerChannelHigherSampleRateFormat =
|
||||||
|
Format.createAudioSampleFormat("audioFormat", MimeTypes.AUDIO_AAC, null, Format.NO_VALUE,
|
||||||
|
Format.NO_VALUE, 2, 44100, null, null, 0, null);
|
||||||
|
Format higherChannelLowerSampleRateFormat =
|
||||||
|
Format.createAudioSampleFormat("audioFormat", MimeTypes.AUDIO_AAC, null, Format.NO_VALUE,
|
||||||
|
Format.NO_VALUE, 6, 22050, null, null, 0, null);
|
||||||
|
|
||||||
|
TrackSelectorResult result = trackSelector.selectTracks(
|
||||||
|
new RendererCapabilities[] {ALL_AUDIO_FORMAT_SUPPORTED_RENDERER_CAPABILITIES},
|
||||||
|
singleTrackGroup(higherChannelLowerSampleRateFormat, lowerChannelHigherSampleRateFormat));
|
||||||
|
|
||||||
|
assertThat(result.selections.get(0).getSelectedFormat())
|
||||||
|
.isEqualTo(higherChannelLowerSampleRateFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that track selector will prefer audio tracks with higher sample rate over tracks with
|
||||||
|
* higher bitrate when other factors are the same, and tracks are within renderer's
|
||||||
|
* capabilities.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSelectTracksPreferHigherSampleRateBeforeBitrate()
|
||||||
|
throws Exception {
|
||||||
|
Format higherSampleRateLowerBitrateFormat =
|
||||||
|
Format.createAudioSampleFormat("audioFormat", MimeTypes.AUDIO_AAC, null, 15000,
|
||||||
|
Format.NO_VALUE, 2, 44100, null, null, 0, null);
|
||||||
|
Format lowerSampleRateHigherBitrateFormat =
|
||||||
|
Format.createAudioSampleFormat("audioFormat", MimeTypes.AUDIO_AAC, null, 30000,
|
||||||
|
Format.NO_VALUE, 2, 22050, null, null, 0, null);
|
||||||
|
|
||||||
|
TrackSelectorResult result = trackSelector.selectTracks(
|
||||||
|
new RendererCapabilities[] {ALL_AUDIO_FORMAT_SUPPORTED_RENDERER_CAPABILITIES},
|
||||||
|
singleTrackGroup(higherSampleRateLowerBitrateFormat, lowerSampleRateHigherBitrateFormat));
|
||||||
|
|
||||||
|
assertThat(result.selections.get(0).getSelectedFormat())
|
||||||
|
.isEqualTo(higherSampleRateLowerBitrateFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that track selector will select audio tracks with lower num channel when other factors
|
||||||
|
* are the same, and tracks exceed renderer's capabilities.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSelectTracksExceedingCapabilitiesSelectLowerNumChannel()
|
||||||
|
throws Exception {
|
||||||
|
Format lowerChannelFormat =
|
||||||
|
Format.createAudioSampleFormat("audioFormat", MimeTypes.AUDIO_AAC, null, Format.NO_VALUE,
|
||||||
|
Format.NO_VALUE, 2, 44100, null, null, 0, null);
|
||||||
|
Format higherChannelFormat =
|
||||||
|
Format.createAudioSampleFormat("audioFormat", MimeTypes.AUDIO_AAC, null, Format.NO_VALUE,
|
||||||
|
Format.NO_VALUE, 6, 44100, null, null, 0, null);
|
||||||
|
|
||||||
|
TrackSelectorResult result = trackSelector.selectTracks(
|
||||||
|
new RendererCapabilities[] {ALL_AUDIO_FORMAT_EXCEEDED_RENDERER_CAPABILITIES},
|
||||||
|
singleTrackGroup(higherChannelFormat, lowerChannelFormat));
|
||||||
|
|
||||||
|
assertThat(result.selections.get(0).getSelectedFormat()).isEqualTo(lowerChannelFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that track selector will select audio tracks with lower sample rate when other factors
|
||||||
|
* are the same, and tracks exceed renderer's capabilities.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSelectTracksExceedingCapabilitiesSelectLowerSampleRate()
|
||||||
|
throws Exception {
|
||||||
|
Format lowerSampleRateFormat =
|
||||||
|
Format.createAudioSampleFormat("audioFormat", MimeTypes.AUDIO_AAC, null, Format.NO_VALUE,
|
||||||
|
Format.NO_VALUE, 2, 22050, null, null, 0, null);
|
||||||
|
Format higherSampleRateFormat =
|
||||||
|
Format.createAudioSampleFormat("audioFormat", MimeTypes.AUDIO_AAC, null, Format.NO_VALUE,
|
||||||
|
Format.NO_VALUE, 2, 44100, null, null, 0, null);
|
||||||
|
|
||||||
|
TrackSelectorResult result = trackSelector.selectTracks(
|
||||||
|
new RendererCapabilities[] {ALL_AUDIO_FORMAT_EXCEEDED_RENDERER_CAPABILITIES},
|
||||||
|
singleTrackGroup(higherSampleRateFormat, lowerSampleRateFormat));
|
||||||
|
|
||||||
|
assertThat(result.selections.get(0).getSelectedFormat()).isEqualTo(lowerSampleRateFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that track selector will select audio tracks with lower bit-rate when other factors
|
||||||
|
* are the same, and tracks exceed renderer's capabilities.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSelectTracksExceedingCapabilitiesSelectLowerBitrate()
|
||||||
|
throws Exception {
|
||||||
|
Format lowerBitrateFormat =
|
||||||
|
Format.createAudioSampleFormat("audioFormat", MimeTypes.AUDIO_AAC, null, 15000,
|
||||||
|
Format.NO_VALUE, 2, 44100, null, null, 0, null);
|
||||||
|
Format higherBitrateFormat =
|
||||||
|
Format.createAudioSampleFormat("audioFormat", MimeTypes.AUDIO_AAC, null, 30000,
|
||||||
|
Format.NO_VALUE, 2, 44100, null, null, 0, null);
|
||||||
|
|
||||||
|
TrackSelectorResult result = trackSelector.selectTracks(
|
||||||
|
new RendererCapabilities[] {ALL_AUDIO_FORMAT_EXCEEDED_RENDERER_CAPABILITIES},
|
||||||
|
singleTrackGroup(lowerBitrateFormat, higherBitrateFormat));
|
||||||
|
|
||||||
|
assertThat(result.selections.get(0).getSelectedFormat()).isEqualTo(lowerBitrateFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that track selector will prefer audio tracks with lower channel count over tracks with
|
||||||
|
* lower sample rate when other factors are the same, and tracks are within renderer's
|
||||||
|
* capabilities.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSelectTracksExceedingCapabilitiesPreferLowerNumChannelBeforeSampleRate()
|
||||||
|
throws Exception {
|
||||||
|
Format lowerChannelHigherSampleRateFormat =
|
||||||
|
Format.createAudioSampleFormat("audioFormat", MimeTypes.AUDIO_AAC, null, Format.NO_VALUE,
|
||||||
|
Format.NO_VALUE, 2, 44100, null, null, 0, null);
|
||||||
|
Format higherChannelLowerSampleRateFormat =
|
||||||
|
Format.createAudioSampleFormat("audioFormat", MimeTypes.AUDIO_AAC, null, Format.NO_VALUE,
|
||||||
|
Format.NO_VALUE, 6, 22050, null, null, 0, null);
|
||||||
|
|
||||||
|
TrackSelectorResult result = trackSelector.selectTracks(
|
||||||
|
new RendererCapabilities[] {ALL_AUDIO_FORMAT_EXCEEDED_RENDERER_CAPABILITIES},
|
||||||
|
singleTrackGroup(higherChannelLowerSampleRateFormat, lowerChannelHigherSampleRateFormat));
|
||||||
|
|
||||||
|
assertThat(result.selections.get(0).getSelectedFormat())
|
||||||
|
.isEqualTo(lowerChannelHigherSampleRateFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that track selector will prefer audio tracks with lower sample rate over tracks with
|
||||||
|
* lower bitrate when other factors are the same, and tracks are within renderer's
|
||||||
|
* capabilities.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSelectTracksExceedingCapabilitiesPreferLowerSampleRateBeforeBitrate()
|
||||||
|
throws Exception {
|
||||||
|
Format higherSampleRateLowerBitrateFormat =
|
||||||
|
Format.createAudioSampleFormat("audioFormat", MimeTypes.AUDIO_AAC, null, 15000,
|
||||||
|
Format.NO_VALUE, 2, 44100, null, null, 0, null);
|
||||||
|
Format lowerSampleRateHigherBitrateFormat =
|
||||||
|
Format.createAudioSampleFormat("audioFormat", MimeTypes.AUDIO_AAC, null, 30000,
|
||||||
|
Format.NO_VALUE, 2, 22050, null, null, 0, null);
|
||||||
|
|
||||||
|
TrackSelectorResult result = trackSelector.selectTracks(
|
||||||
|
new RendererCapabilities[] {ALL_AUDIO_FORMAT_EXCEEDED_RENDERER_CAPABILITIES},
|
||||||
|
singleTrackGroup(higherSampleRateLowerBitrateFormat, lowerSampleRateHigherBitrateFormat));
|
||||||
|
|
||||||
|
assertThat(result.selections.get(0).getSelectedFormat())
|
||||||
|
.isEqualTo(lowerSampleRateHigherBitrateFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that track selector will select audio tracks with lower bitrate when {@link Parameters}
|
||||||
|
* indicate lowest bitrate preference, even when tracks are within capabilities.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testSelectTracksWithinCapabilitiesAndForceLowestBitrateSelectLowerBitrate()
|
||||||
|
throws Exception {
|
||||||
|
Parameters parameters = DEFAULT_PARAMETERS.withForceLowestBitrate(true);
|
||||||
|
trackSelector.setParameters(parameters);
|
||||||
|
|
||||||
|
Format lowerBitrateFormat =
|
||||||
|
Format.createAudioSampleFormat("audioFormat", MimeTypes.AUDIO_AAC, null, 15000,
|
||||||
|
Format.NO_VALUE, 2, 44100, null, null, 0, null);
|
||||||
|
Format higherBitrateFormat =
|
||||||
|
Format.createAudioSampleFormat("audioFormat", MimeTypes.AUDIO_AAC, null, 30000,
|
||||||
|
Format.NO_VALUE, 2, 44100, null, null, 0, null);
|
||||||
|
|
||||||
|
TrackSelectorResult result = trackSelector.selectTracks(
|
||||||
|
new RendererCapabilities[] {ALL_AUDIO_FORMAT_SUPPORTED_RENDERER_CAPABILITIES},
|
||||||
|
singleTrackGroup(lowerBitrateFormat, higherBitrateFormat));
|
||||||
|
|
||||||
|
assertThat(result.selections.get(0).getSelectedFormat()).isEqualTo(lowerBitrateFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TrackGroupArray singleTrackGroup(Format... formats) {
|
||||||
|
return new TrackGroupArray(new TrackGroup(formats));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link RendererCapabilities} that advertises support for all formats of a given type using
|
||||||
|
* a provided support value. For any format that does not have the given track type,
|
||||||
|
* {@link #supportsFormat(Format)} will return {@link #FORMAT_UNSUPPORTED_TYPE}.
|
||||||
|
*/
|
||||||
|
private static final class FakeRendererCapabilities implements RendererCapabilities {
|
||||||
|
|
||||||
|
private final int trackType;
|
||||||
|
private final int supportValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@link FakeRendererCapabilities} that advertises adaptive support for all
|
||||||
|
* tracks of the given type.
|
||||||
|
*
|
||||||
|
* @param trackType the track type of all formats that this renderer capabilities advertises
|
||||||
|
* support for.
|
||||||
|
*/
|
||||||
|
FakeRendererCapabilities(int trackType) {
|
||||||
|
this(trackType, FORMAT_HANDLED | ADAPTIVE_SEAMLESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@link FakeRendererCapabilities} that advertises support level using given value
|
||||||
|
* for all tracks of the given type.
|
||||||
|
*
|
||||||
|
* @param trackType the track type of all formats that this renderer capabilities advertises
|
||||||
|
* support for.
|
||||||
|
* @param supportValue the support level value that will be returned for formats with
|
||||||
|
* the given type.
|
||||||
|
*/
|
||||||
|
FakeRendererCapabilities(int trackType, int supportValue) {
|
||||||
|
this.trackType = trackType;
|
||||||
|
this.supportValue = supportValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTrackType() {
|
||||||
|
return trackType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int supportsFormat(Format format) throws ExoPlaybackException {
|
||||||
|
return MimeTypes.getTrackType(format.sampleMimeType) == trackType
|
||||||
|
? (supportValue) : FORMAT_UNSUPPORTED_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int supportsMixedMimeTypeAdaptation() throws ExoPlaybackException {
|
||||||
|
return ADAPTIVE_SEAMLESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link RendererCapabilities} that advertises support for different formats using a mapping
|
||||||
|
* between format ID and format-support value.
|
||||||
|
*/
|
||||||
|
private static final class FakeMappedRendererCapabilities implements RendererCapabilities {
|
||||||
|
|
||||||
|
private final int trackType;
|
||||||
|
private final Map<String, Integer> formatToCapability;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@link FakeRendererCapabilities} that advertises support level using the given
|
||||||
|
* mapping between format ID and format-support value.
|
||||||
|
*
|
||||||
|
* @param trackType the track type to be returned for {@link #getTrackType()}
|
||||||
|
* @param formatToCapability a map of (format id, support level) that will be used to return
|
||||||
|
* support level for any given format. For any format that's not in the map,
|
||||||
|
* {@link #supportsFormat(Format)} will return {@link #FORMAT_UNSUPPORTED_TYPE}.
|
||||||
|
*/
|
||||||
|
FakeMappedRendererCapabilities(int trackType, Map<String, Integer> formatToCapability) {
|
||||||
|
this.trackType = trackType;
|
||||||
|
this.formatToCapability = new HashMap<>(formatToCapability);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTrackType() {
|
||||||
|
return trackType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int supportsFormat(Format format) throws ExoPlaybackException {
|
||||||
|
return format.id != null && formatToCapability.containsKey(format.id)
|
||||||
|
? formatToCapability.get(format.id)
|
||||||
|
: FORMAT_UNSUPPORTED_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int supportsMixedMimeTypeAdaptation() throws ExoPlaybackException {
|
||||||
|
return ADAPTIVE_SEAMLESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue