Add TrackSelection.Factory createTrackSelections
createTrackSelections decides whether to create an adaptive or a fixed track seletion to create. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=222231011
This commit is contained in:
parent
55cc0df558
commit
527f2cf730
@ -1006,8 +1006,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||||||
* @param groups The {@link TrackGroupArray}.
|
* @param groups The {@link TrackGroupArray}.
|
||||||
* @return The override, or null if no override exists.
|
* @return The override, or null if no override exists.
|
||||||
*/
|
*/
|
||||||
public final @Nullable SelectionOverride getSelectionOverride(
|
@Nullable
|
||||||
int rendererIndex, TrackGroupArray groups) {
|
public final SelectionOverride getSelectionOverride(int rendererIndex, TrackGroupArray groups) {
|
||||||
Map<TrackGroupArray, SelectionOverride> overrides = selectionOverrides.get(rendererIndex);
|
Map<TrackGroupArray, SelectionOverride> overrides = selectionOverrides.get(rendererIndex);
|
||||||
return overrides != null ? overrides.get(groups) : null;
|
return overrides != null ? overrides.get(groups) : null;
|
||||||
}
|
}
|
||||||
@ -1327,10 +1327,9 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||||||
private static final int[] NO_TRACKS = new int[0];
|
private static final int[] NO_TRACKS = new int[0];
|
||||||
private static final int WITHIN_RENDERER_CAPABILITIES_BONUS = 1000;
|
private static final int WITHIN_RENDERER_CAPABILITIES_BONUS = 1000;
|
||||||
|
|
||||||
private final TrackSelection.Factory adaptiveTrackSelectionFactory;
|
private final TrackSelection.Factory trackSelectionFactory;
|
||||||
private final AtomicReference<Parameters> parametersReference;
|
private final AtomicReference<Parameters> parametersReference;
|
||||||
|
|
||||||
/** Constructs an instance that uses a default factory to create adaptive track selections. */
|
|
||||||
public DefaultTrackSelector() {
|
public DefaultTrackSelector() {
|
||||||
this(new AdaptiveTrackSelection.Factory());
|
this(new AdaptiveTrackSelection.Factory());
|
||||||
}
|
}
|
||||||
@ -1345,13 +1344,9 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||||||
this(new AdaptiveTrackSelection.Factory(bandwidthMeter));
|
this(new AdaptiveTrackSelection.Factory(bandwidthMeter));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @param trackSelectionFactory A factory for {@link TrackSelection}s. */
|
||||||
* Constructs an instance that uses a factory to create adaptive track selections.
|
public DefaultTrackSelector(TrackSelection.Factory trackSelectionFactory) {
|
||||||
*
|
this.trackSelectionFactory = trackSelectionFactory;
|
||||||
* @param adaptiveTrackSelectionFactory A factory for adaptive {@link TrackSelection}s.
|
|
||||||
*/
|
|
||||||
public DefaultTrackSelector(TrackSelection.Factory adaptiveTrackSelectionFactory) {
|
|
||||||
this.adaptiveTrackSelectionFactory = adaptiveTrackSelectionFactory;
|
|
||||||
parametersReference = new AtomicReference<>(Parameters.DEFAULT);
|
parametersReference = new AtomicReference<>(Parameters.DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1420,8 +1415,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||||||
|
|
||||||
/** @deprecated Use {@link Parameters#getSelectionOverride(int, TrackGroupArray)}. */
|
/** @deprecated Use {@link Parameters#getSelectionOverride(int, TrackGroupArray)}. */
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public final @Nullable SelectionOverride getSelectionOverride(
|
@Nullable
|
||||||
int rendererIndex, TrackGroupArray groups) {
|
public final SelectionOverride getSelectionOverride(int rendererIndex, TrackGroupArray groups) {
|
||||||
return getParameters().getSelectionOverride(rendererIndex, groups);
|
return getParameters().getSelectionOverride(rendererIndex, groups);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1460,7 +1455,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||||||
throws ExoPlaybackException {
|
throws ExoPlaybackException {
|
||||||
Parameters params = parametersReference.get();
|
Parameters params = parametersReference.get();
|
||||||
int rendererCount = mappedTrackInfo.getRendererCount();
|
int rendererCount = mappedTrackInfo.getRendererCount();
|
||||||
@NullableType TrackSelection[] rendererTrackSelections =
|
TrackSelection.@NullableType Definition[] definitions =
|
||||||
selectAllTracks(
|
selectAllTracks(
|
||||||
mappedTrackInfo,
|
mappedTrackInfo,
|
||||||
rendererFormatSupports,
|
rendererFormatSupports,
|
||||||
@ -1470,28 +1465,24 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||||||
// Apply track disabling and overriding.
|
// Apply track disabling and overriding.
|
||||||
for (int i = 0; i < rendererCount; i++) {
|
for (int i = 0; i < rendererCount; i++) {
|
||||||
if (params.getRendererDisabled(i)) {
|
if (params.getRendererDisabled(i)) {
|
||||||
rendererTrackSelections[i] = null;
|
definitions[i] = null;
|
||||||
} else {
|
continue;
|
||||||
|
}
|
||||||
TrackGroupArray rendererTrackGroups = mappedTrackInfo.getTrackGroups(i);
|
TrackGroupArray rendererTrackGroups = mappedTrackInfo.getTrackGroups(i);
|
||||||
if (params.hasSelectionOverride(i, rendererTrackGroups)) {
|
if (params.hasSelectionOverride(i, rendererTrackGroups)) {
|
||||||
SelectionOverride override = params.getSelectionOverride(i, rendererTrackGroups);
|
SelectionOverride override = params.getSelectionOverride(i, rendererTrackGroups);
|
||||||
if (override == null) {
|
definitions[i] =
|
||||||
rendererTrackSelections[i] = null;
|
override == null
|
||||||
} else if (override.length == 1) {
|
? null
|
||||||
rendererTrackSelections[i] =
|
: new TrackSelection.Definition(
|
||||||
new FixedTrackSelection(
|
rendererTrackGroups.get(override.groupIndex), override.tracks);
|
||||||
rendererTrackGroups.get(override.groupIndex), override.tracks[0]);
|
|
||||||
} else {
|
|
||||||
rendererTrackSelections[i] =
|
|
||||||
adaptiveTrackSelectionFactory.createTrackSelection(
|
|
||||||
rendererTrackGroups.get(override.groupIndex),
|
|
||||||
getBandwidthMeter(),
|
|
||||||
override.tracks);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NullableType
|
||||||
|
TrackSelection[] rendererTrackSelections =
|
||||||
|
trackSelectionFactory.createTrackSelections(definitions, getBandwidthMeter());
|
||||||
|
|
||||||
// Initialize the renderer configurations to the default configuration for all renderers with
|
// Initialize the renderer configurations to the default configuration for all renderers with
|
||||||
// selections, and null otherwise.
|
// selections, and null otherwise.
|
||||||
@NullableType RendererConfiguration[] rendererConfigurations =
|
@NullableType RendererConfiguration[] rendererConfigurations =
|
||||||
@ -1530,32 +1521,33 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||||||
* each mapped track, indexed by renderer, track group and track (in that order).
|
* each mapped track, indexed by renderer, track group and track (in that order).
|
||||||
* @param rendererMixedMimeTypeAdaptationSupports The result of {@link
|
* @param rendererMixedMimeTypeAdaptationSupports The result of {@link
|
||||||
* RendererCapabilities#supportsMixedMimeTypeAdaptation()} for each renderer.
|
* RendererCapabilities#supportsMixedMimeTypeAdaptation()} for each renderer.
|
||||||
* @return Track selections for each renderer. A null selection indicates the renderer should be
|
* @return The {@link TrackSelection.Definition}s for the renderers. A null entry indicates no
|
||||||
* disabled, unless RendererCapabilities#getTrackType()} is {@link C#TRACK_TYPE_NONE}.
|
* selection was made.
|
||||||
* @throws ExoPlaybackException If an error occurs while selecting the tracks.
|
* @throws ExoPlaybackException If an error occurs while selecting the tracks.
|
||||||
*/
|
*/
|
||||||
protected @NullableType TrackSelection[] selectAllTracks(
|
protected TrackSelection.@NullableType Definition[] selectAllTracks(
|
||||||
MappedTrackInfo mappedTrackInfo,
|
MappedTrackInfo mappedTrackInfo,
|
||||||
int[][][] rendererFormatSupports,
|
int[][][] rendererFormatSupports,
|
||||||
int[] rendererMixedMimeTypeAdaptationSupports,
|
int[] rendererMixedMimeTypeAdaptationSupports,
|
||||||
Parameters params)
|
Parameters params)
|
||||||
throws ExoPlaybackException {
|
throws ExoPlaybackException {
|
||||||
int rendererCount = mappedTrackInfo.getRendererCount();
|
int rendererCount = mappedTrackInfo.getRendererCount();
|
||||||
@NullableType TrackSelection[] rendererTrackSelections = new TrackSelection[rendererCount];
|
TrackSelection.@NullableType Definition[] definitions =
|
||||||
|
new TrackSelection.Definition[rendererCount];
|
||||||
|
|
||||||
boolean seenVideoRendererWithMappedTracks = false;
|
boolean seenVideoRendererWithMappedTracks = false;
|
||||||
boolean selectedVideoTracks = false;
|
boolean selectedVideoTracks = false;
|
||||||
for (int i = 0; i < rendererCount; i++) {
|
for (int i = 0; i < rendererCount; i++) {
|
||||||
if (C.TRACK_TYPE_VIDEO == mappedTrackInfo.getRendererType(i)) {
|
if (C.TRACK_TYPE_VIDEO == mappedTrackInfo.getRendererType(i)) {
|
||||||
if (!selectedVideoTracks) {
|
if (!selectedVideoTracks) {
|
||||||
rendererTrackSelections[i] =
|
definitions[i] =
|
||||||
selectVideoTrack(
|
selectVideoTrack(
|
||||||
mappedTrackInfo.getTrackGroups(i),
|
mappedTrackInfo.getTrackGroups(i),
|
||||||
rendererFormatSupports[i],
|
rendererFormatSupports[i],
|
||||||
rendererMixedMimeTypeAdaptationSupports[i],
|
rendererMixedMimeTypeAdaptationSupports[i],
|
||||||
params,
|
params,
|
||||||
adaptiveTrackSelectionFactory);
|
/* enableAdaptiveTrackSelection= */ true);
|
||||||
selectedVideoTracks = rendererTrackSelections[i] != null;
|
selectedVideoTracks = definitions[i] != null;
|
||||||
}
|
}
|
||||||
seenVideoRendererWithMappedTracks |= mappedTrackInfo.getTrackGroups(i).length > 0;
|
seenVideoRendererWithMappedTracks |= mappedTrackInfo.getTrackGroups(i).length > 0;
|
||||||
}
|
}
|
||||||
@ -1572,49 +1564,49 @@ 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:
|
||||||
Pair<TrackSelection, AudioTrackScore> audioSelection =
|
Pair<TrackSelection.Definition, AudioTrackScore> audioSelection =
|
||||||
selectAudioTrack(
|
selectAudioTrack(
|
||||||
mappedTrackInfo.getTrackGroups(i),
|
mappedTrackInfo.getTrackGroups(i),
|
||||||
rendererFormatSupports[i],
|
rendererFormatSupports[i],
|
||||||
rendererMixedMimeTypeAdaptationSupports[i],
|
rendererMixedMimeTypeAdaptationSupports[i],
|
||||||
params,
|
params,
|
||||||
seenVideoRendererWithMappedTracks ? null : adaptiveTrackSelectionFactory);
|
!seenVideoRendererWithMappedTracks);
|
||||||
if (audioSelection != null
|
if (audioSelection != null
|
||||||
&& (selectedAudioTrackScore == null
|
&& (selectedAudioTrackScore == null
|
||||||
|| audioSelection.second.compareTo(selectedAudioTrackScore) > 0)) {
|
|| audioSelection.second.compareTo(selectedAudioTrackScore) > 0)) {
|
||||||
if (selectedAudioRendererIndex != C.INDEX_UNSET) {
|
if (selectedAudioRendererIndex != C.INDEX_UNSET) {
|
||||||
// We've already made a selection for another audio renderer, but it had a lower
|
// We've already made a selection for another audio renderer, but it had a lower
|
||||||
// score. Clear the selection for that renderer.
|
// score. Clear the selection for that renderer.
|
||||||
rendererTrackSelections[selectedAudioRendererIndex] = null;
|
definitions[selectedAudioRendererIndex] = null;
|
||||||
}
|
}
|
||||||
rendererTrackSelections[i] = audioSelection.first;
|
definitions[i] = audioSelection.first;
|
||||||
selectedAudioTrackScore = audioSelection.second;
|
selectedAudioTrackScore = audioSelection.second;
|
||||||
selectedAudioRendererIndex = i;
|
selectedAudioRendererIndex = i;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case C.TRACK_TYPE_TEXT:
|
case C.TRACK_TYPE_TEXT:
|
||||||
Pair<TrackSelection, Integer> textSelection =
|
Pair<TrackSelection.Definition, Integer> textSelection =
|
||||||
selectTextTrack(mappedTrackInfo.getTrackGroups(i), rendererFormatSupports[i], params);
|
selectTextTrack(mappedTrackInfo.getTrackGroups(i), rendererFormatSupports[i], params);
|
||||||
if (textSelection != null && textSelection.second > selectedTextTrackScore) {
|
if (textSelection != null && textSelection.second > selectedTextTrackScore) {
|
||||||
if (selectedTextRendererIndex != C.INDEX_UNSET) {
|
if (selectedTextRendererIndex != C.INDEX_UNSET) {
|
||||||
// We've already made a selection for another text renderer, but it had a lower score.
|
// We've already made a selection for another text renderer, but it had a lower score.
|
||||||
// Clear the selection for that renderer.
|
// Clear the selection for that renderer.
|
||||||
rendererTrackSelections[selectedTextRendererIndex] = null;
|
definitions[selectedTextRendererIndex] = null;
|
||||||
}
|
}
|
||||||
rendererTrackSelections[i] = textSelection.first;
|
definitions[i] = textSelection.first;
|
||||||
selectedTextTrackScore = textSelection.second;
|
selectedTextTrackScore = textSelection.second;
|
||||||
selectedTextRendererIndex = i;
|
selectedTextRendererIndex = i;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
rendererTrackSelections[i] =
|
definitions[i] =
|
||||||
selectOtherTrack(
|
selectOtherTrack(
|
||||||
trackType, mappedTrackInfo.getTrackGroups(i), rendererFormatSupports[i], params);
|
trackType, mappedTrackInfo.getTrackGroups(i), rendererFormatSupports[i], params);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return rendererTrackSelections;
|
return definitions;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Video track selection implementation.
|
// Video track selection implementation.
|
||||||
@ -1629,45 +1621,38 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||||||
* @param mixedMimeTypeAdaptationSupports The result of {@link
|
* @param mixedMimeTypeAdaptationSupports The result of {@link
|
||||||
* RendererCapabilities#supportsMixedMimeTypeAdaptation()} for the renderer.
|
* RendererCapabilities#supportsMixedMimeTypeAdaptation()} for the renderer.
|
||||||
* @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 enableAdaptiveTrackSelection Whether adaptive track selection is allowed.
|
||||||
* null if a fixed track selection is required.
|
* @return The {@link TrackSelection.Definition} for the renderer, or null if no selection was
|
||||||
* @return The {@link TrackSelection} for the renderer, or null if no selection was made.
|
* made.
|
||||||
* @throws ExoPlaybackException If an error occurs while selecting the tracks.
|
* @throws ExoPlaybackException If an error occurs while selecting the tracks.
|
||||||
*/
|
*/
|
||||||
protected @Nullable TrackSelection selectVideoTrack(
|
@Nullable
|
||||||
|
protected TrackSelection.Definition selectVideoTrack(
|
||||||
TrackGroupArray groups,
|
TrackGroupArray groups,
|
||||||
int[][] formatSupports,
|
int[][] formatSupports,
|
||||||
int mixedMimeTypeAdaptationSupports,
|
int mixedMimeTypeAdaptationSupports,
|
||||||
Parameters params,
|
Parameters params,
|
||||||
@Nullable TrackSelection.Factory adaptiveTrackSelectionFactory)
|
boolean enableAdaptiveTrackSelection)
|
||||||
throws ExoPlaybackException {
|
throws ExoPlaybackException {
|
||||||
TrackSelection selection = null;
|
TrackSelection.Definition definition = null;
|
||||||
if (!params.forceHighestSupportedBitrate
|
if (!params.forceHighestSupportedBitrate
|
||||||
&& !params.forceLowestBitrate
|
&& !params.forceLowestBitrate
|
||||||
&& adaptiveTrackSelectionFactory != null) {
|
&& enableAdaptiveTrackSelection) {
|
||||||
selection =
|
definition =
|
||||||
selectAdaptiveVideoTrack(
|
selectAdaptiveVideoTrack(groups, formatSupports, mixedMimeTypeAdaptationSupports, params);
|
||||||
groups,
|
|
||||||
formatSupports,
|
|
||||||
mixedMimeTypeAdaptationSupports,
|
|
||||||
params,
|
|
||||||
adaptiveTrackSelectionFactory,
|
|
||||||
getBandwidthMeter());
|
|
||||||
}
|
}
|
||||||
if (selection == null) {
|
if (definition == null) {
|
||||||
selection = selectFixedVideoTrack(groups, formatSupports, params);
|
definition = selectFixedVideoTrack(groups, formatSupports, params);
|
||||||
}
|
}
|
||||||
return selection;
|
return definition;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static @Nullable TrackSelection selectAdaptiveVideoTrack(
|
@Nullable
|
||||||
|
private static TrackSelection.Definition selectAdaptiveVideoTrack(
|
||||||
TrackGroupArray groups,
|
TrackGroupArray groups,
|
||||||
int[][] formatSupport,
|
int[][] formatSupport,
|
||||||
int mixedMimeTypeAdaptationSupports,
|
int mixedMimeTypeAdaptationSupports,
|
||||||
Parameters params,
|
Parameters params) {
|
||||||
TrackSelection.Factory adaptiveTrackSelectionFactory,
|
|
||||||
BandwidthMeter bandwidthMeter)
|
|
||||||
throws ExoPlaybackException {
|
|
||||||
int requiredAdaptiveSupport =
|
int requiredAdaptiveSupport =
|
||||||
params.allowVideoNonSeamlessAdaptiveness
|
params.allowVideoNonSeamlessAdaptiveness
|
||||||
? (RendererCapabilities.ADAPTIVE_NOT_SEAMLESS | RendererCapabilities.ADAPTIVE_SEAMLESS)
|
? (RendererCapabilities.ADAPTIVE_NOT_SEAMLESS | RendererCapabilities.ADAPTIVE_SEAMLESS)
|
||||||
@ -1691,8 +1676,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||||||
params.viewportHeight,
|
params.viewportHeight,
|
||||||
params.viewportOrientationMayChange);
|
params.viewportOrientationMayChange);
|
||||||
if (adaptiveTracks.length > 0) {
|
if (adaptiveTracks.length > 0) {
|
||||||
return adaptiveTrackSelectionFactory.createTrackSelection(
|
return new TrackSelection.Definition(group, adaptiveTracks);
|
||||||
group, bandwidthMeter, adaptiveTracks);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -1835,7 +1819,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||||||
&& (format.bitrate == Format.NO_VALUE || format.bitrate <= maxVideoBitrate);
|
&& (format.bitrate == Format.NO_VALUE || format.bitrate <= maxVideoBitrate);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static @Nullable TrackSelection selectFixedVideoTrack(
|
@Nullable
|
||||||
|
private static TrackSelection.Definition selectFixedVideoTrack(
|
||||||
TrackGroupArray groups, int[][] formatSupports, Parameters params) {
|
TrackGroupArray groups, int[][] formatSupports, Parameters params) {
|
||||||
TrackGroup selectedGroup = null;
|
TrackGroup selectedGroup = null;
|
||||||
int selectedTrackIndex = 0;
|
int selectedTrackIndex = 0;
|
||||||
@ -1897,8 +1882,9 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return selectedGroup == null ? null
|
return selectedGroup == null
|
||||||
: new FixedTrackSelection(selectedGroup, selectedTrackIndex);
|
? null
|
||||||
|
: new TrackSelection.Definition(selectedGroup, selectedTrackIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Audio track selection implementation.
|
// Audio track selection implementation.
|
||||||
@ -1913,19 +1899,19 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||||||
* @param mixedMimeTypeAdaptationSupports The result of {@link
|
* @param mixedMimeTypeAdaptationSupports The result of {@link
|
||||||
* RendererCapabilities#supportsMixedMimeTypeAdaptation()} for the renderer.
|
* RendererCapabilities#supportsMixedMimeTypeAdaptation()} for the renderer.
|
||||||
* @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 enableAdaptiveTrackSelection Whether adaptive track selection is allowed.
|
||||||
* null if a fixed track selection is required.
|
* @return The {@link TrackSelection.Definition} and corresponding {@link AudioTrackScore}, or
|
||||||
* @return The {@link TrackSelection} and corresponding {@link AudioTrackScore}, or null if no
|
* null if no selection was made.
|
||||||
* selection was made.
|
|
||||||
* @throws ExoPlaybackException If an error occurs while selecting the tracks.
|
* @throws ExoPlaybackException If an error occurs while selecting the tracks.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
protected @Nullable Pair<TrackSelection, AudioTrackScore> selectAudioTrack(
|
@Nullable
|
||||||
|
protected Pair<TrackSelection.Definition, AudioTrackScore> selectAudioTrack(
|
||||||
TrackGroupArray groups,
|
TrackGroupArray groups,
|
||||||
int[][] formatSupports,
|
int[][] formatSupports,
|
||||||
int mixedMimeTypeAdaptationSupports,
|
int mixedMimeTypeAdaptationSupports,
|
||||||
Parameters params,
|
Parameters params,
|
||||||
@Nullable TrackSelection.Factory adaptiveTrackSelectionFactory)
|
boolean enableAdaptiveTrackSelection)
|
||||||
throws ExoPlaybackException {
|
throws ExoPlaybackException {
|
||||||
int selectedTrackIndex = C.INDEX_UNSET;
|
int selectedTrackIndex = C.INDEX_UNSET;
|
||||||
int selectedGroupIndex = C.INDEX_UNSET;
|
int selectedGroupIndex = C.INDEX_UNSET;
|
||||||
@ -1958,10 +1944,10 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||||||
|
|
||||||
TrackGroup selectedGroup = groups.get(selectedGroupIndex);
|
TrackGroup selectedGroup = groups.get(selectedGroupIndex);
|
||||||
|
|
||||||
TrackSelection selection = null;
|
TrackSelection.Definition definition = null;
|
||||||
if (!params.forceHighestSupportedBitrate
|
if (!params.forceHighestSupportedBitrate
|
||||||
&& !params.forceLowestBitrate
|
&& !params.forceLowestBitrate
|
||||||
&& adaptiveTrackSelectionFactory != null) {
|
&& enableAdaptiveTrackSelection) {
|
||||||
// If the group of the track with the highest score allows it, try to enable adaptation.
|
// If the group of the track with the highest score allows it, try to enable adaptation.
|
||||||
int[] adaptiveTracks =
|
int[] adaptiveTracks =
|
||||||
getAdaptiveAudioTracks(
|
getAdaptiveAudioTracks(
|
||||||
@ -1970,17 +1956,15 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||||||
params.allowAudioMixedMimeTypeAdaptiveness,
|
params.allowAudioMixedMimeTypeAdaptiveness,
|
||||||
params.allowAudioMixedSampleRateAdaptiveness);
|
params.allowAudioMixedSampleRateAdaptiveness);
|
||||||
if (adaptiveTracks.length > 0) {
|
if (adaptiveTracks.length > 0) {
|
||||||
selection =
|
definition = new TrackSelection.Definition(selectedGroup, adaptiveTracks);
|
||||||
adaptiveTrackSelectionFactory.createTrackSelection(
|
|
||||||
selectedGroup, getBandwidthMeter(), adaptiveTracks);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (selection == null) {
|
if (definition == null) {
|
||||||
// We didn't make an adaptive selection, so make a fixed one instead.
|
// We didn't make an adaptive selection, so make a fixed one instead.
|
||||||
selection = new FixedTrackSelection(selectedGroup, selectedTrackIndex);
|
definition = new TrackSelection.Definition(selectedGroup, selectedTrackIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Pair.create(selection, Assertions.checkNotNull(selectedTrackScore));
|
return Pair.create(definition, Assertions.checkNotNull(selectedTrackScore));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int[] getAdaptiveAudioTracks(
|
private static int[] getAdaptiveAudioTracks(
|
||||||
@ -2076,11 +2060,12 @@ 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} and corresponding track score, or null if no selection was
|
* @return The {@link TrackSelection.Definition} and corresponding track score, or null if no
|
||||||
* made.
|
* 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 Pair<TrackSelection, Integer> selectTextTrack(
|
@Nullable
|
||||||
|
protected Pair<TrackSelection.Definition, Integer> selectTextTrack(
|
||||||
TrackGroupArray groups, int[][] formatSupport, Parameters params)
|
TrackGroupArray groups, int[][] formatSupport, Parameters params)
|
||||||
throws ExoPlaybackException {
|
throws ExoPlaybackException {
|
||||||
TrackGroup selectedGroup = null;
|
TrackGroup selectedGroup = null;
|
||||||
@ -2138,7 +2123,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||||||
return selectedGroup == null
|
return selectedGroup == null
|
||||||
? null
|
? null
|
||||||
: Pair.create(
|
: Pair.create(
|
||||||
new FixedTrackSelection(selectedGroup, selectedTrackIndex), selectedTrackScore);
|
new TrackSelection.Definition(selectedGroup, selectedTrackIndex), selectedTrackScore);
|
||||||
}
|
}
|
||||||
|
|
||||||
// General track selection methods.
|
// General track selection methods.
|
||||||
@ -2155,7 +2140,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||||||
* @return The {@link TrackSelection} for the renderer, or null if no selection was made.
|
* @return The {@link TrackSelection} for the renderer, 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 selectOtherTrack(
|
@Nullable
|
||||||
|
protected TrackSelection.Definition selectOtherTrack(
|
||||||
int trackType, TrackGroupArray groups, int[][] formatSupport, Parameters params)
|
int trackType, TrackGroupArray groups, int[][] formatSupport, Parameters params)
|
||||||
throws ExoPlaybackException {
|
throws ExoPlaybackException {
|
||||||
TrackGroup selectedGroup = null;
|
TrackGroup selectedGroup = null;
|
||||||
@ -2181,8 +2167,9 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return selectedGroup == null ? null
|
return selectedGroup == null
|
||||||
: new FixedTrackSelection(selectedGroup, selectedTrackIndex);
|
? null
|
||||||
|
: new TrackSelection.Definition(selectedGroup, selectedTrackIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Utility methods.
|
// Utility methods.
|
||||||
|
@ -22,7 +22,9 @@ import com.google.android.exoplayer2.source.TrackGroup;
|
|||||||
import com.google.android.exoplayer2.source.chunk.MediaChunk;
|
import com.google.android.exoplayer2.source.chunk.MediaChunk;
|
||||||
import com.google.android.exoplayer2.source.chunk.MediaChunkIterator;
|
import com.google.android.exoplayer2.source.chunk.MediaChunkIterator;
|
||||||
import com.google.android.exoplayer2.upstream.BandwidthMeter;
|
import com.google.android.exoplayer2.upstream.BandwidthMeter;
|
||||||
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import org.checkerframework.checker.nullness.compatqual.NullableType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A track selection consisting of a static subset of selected tracks belonging to a {@link
|
* A track selection consisting of a static subset of selected tracks belonging to a {@link
|
||||||
@ -35,6 +37,24 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public interface TrackSelection {
|
public interface TrackSelection {
|
||||||
|
|
||||||
|
/** Contains of a subset of selected tracks belonging to a {@link TrackGroup}. */
|
||||||
|
final class Definition {
|
||||||
|
/** The {@link TrackGroup} which tracks belong to. */
|
||||||
|
public final TrackGroup group;
|
||||||
|
/** The indices of the selected tracks in {@link #group}. */
|
||||||
|
public final int[] tracks;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param group The {@link TrackGroup}. Must not be null.
|
||||||
|
* @param tracks The indices of the selected tracks within the {@link TrackGroup}. Must not be
|
||||||
|
* null or empty. May be in any order.
|
||||||
|
*/
|
||||||
|
public Definition(TrackGroup group, int... tracks) {
|
||||||
|
this.group = group;
|
||||||
|
this.tracks = tracks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory for {@link TrackSelection} instances.
|
* Factory for {@link TrackSelection} instances.
|
||||||
*/
|
*/
|
||||||
@ -51,6 +71,33 @@ public interface TrackSelection {
|
|||||||
*/
|
*/
|
||||||
TrackSelection createTrackSelection(
|
TrackSelection createTrackSelection(
|
||||||
TrackGroup group, BandwidthMeter bandwidthMeter, int... tracks);
|
TrackGroup group, BandwidthMeter bandwidthMeter, int... tracks);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new selection for each {@link Definition}.
|
||||||
|
*
|
||||||
|
* @param definitions A {@link Definition} array. May include null values.
|
||||||
|
* @param bandwidthMeter A {@link BandwidthMeter} which can be used to select tracks.
|
||||||
|
* @return The created selections. For null entries in {@code definitions} returns null values.
|
||||||
|
*/
|
||||||
|
default @NullableType TrackSelection[] createTrackSelections(
|
||||||
|
@NullableType Definition[] definitions, BandwidthMeter bandwidthMeter) {
|
||||||
|
TrackSelection[] selections = new TrackSelection[definitions.length];
|
||||||
|
boolean createdAdaptiveTrackSelection = false;
|
||||||
|
for (int i = 0; i < definitions.length; i++) {
|
||||||
|
Definition definition = definitions[i];
|
||||||
|
if (definition == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (definition.tracks.length > 1) {
|
||||||
|
Assertions.checkState(!createdAdaptiveTrackSelection);
|
||||||
|
createdAdaptiveTrackSelection = true;
|
||||||
|
selections[i] = createTrackSelection(definition.group, bandwidthMeter, definition.tracks);
|
||||||
|
} else {
|
||||||
|
selections[i] = new FixedTrackSelection(definition.group, definition.tracks[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return selections;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -773,7 +773,7 @@ public final class ExoPlayerTest {
|
|||||||
}
|
}
|
||||||
// There are 2 renderers, and track selections are made twice. The second time one renderer is
|
// There are 2 renderers, and track selections are made twice. The second time one renderer is
|
||||||
// disabled, so only one out of the two track selections is enabled.
|
// disabled, so only one out of the two track selections is enabled.
|
||||||
assertThat(createdTrackSelections).hasSize(4);
|
assertThat(createdTrackSelections).hasSize(3);
|
||||||
assertThat(numSelectionsEnabled).isEqualTo(3);
|
assertThat(numSelectionsEnabled).isEqualTo(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +50,6 @@ import com.google.android.exoplayer2.testutil.HostActivity;
|
|||||||
import com.google.android.exoplayer2.testutil.HostActivity.HostedTest;
|
import com.google.android.exoplayer2.testutil.HostActivity.HostedTest;
|
||||||
import com.google.android.exoplayer2.testutil.MetricsLogger;
|
import com.google.android.exoplayer2.testutil.MetricsLogger;
|
||||||
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
|
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
|
||||||
import com.google.android.exoplayer2.trackselection.FixedTrackSelection;
|
|
||||||
import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
|
import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
|
||||||
import com.google.android.exoplayer2.trackselection.RandomTrackSelection;
|
import com.google.android.exoplayer2.trackselection.RandomTrackSelection;
|
||||||
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
||||||
@ -382,6 +381,7 @@ public final class DashTestRunner {
|
|||||||
|
|
||||||
private DashTestTrackSelector(String tag, String audioFormatId, String[] videoFormatIds,
|
private DashTestTrackSelector(String tag, String audioFormatId, String[] videoFormatIds,
|
||||||
boolean canIncludeAdditionalVideoFormats) {
|
boolean canIncludeAdditionalVideoFormats) {
|
||||||
|
super(new RandomTrackSelection.Factory(/* seed= */ 0));
|
||||||
this.tag = tag;
|
this.tag = tag;
|
||||||
this.audioFormatId = audioFormatId;
|
this.audioFormatId = audioFormatId;
|
||||||
this.videoFormatIds = videoFormatIds;
|
this.videoFormatIds = videoFormatIds;
|
||||||
@ -389,7 +389,7 @@ public final class DashTestRunner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected TrackSelection[] selectAllTracks(
|
protected TrackSelection.Definition[] selectAllTracks(
|
||||||
MappedTrackInfo mappedTrackInfo,
|
MappedTrackInfo mappedTrackInfo,
|
||||||
int[][][] rendererFormatSupports,
|
int[][][] rendererFormatSupports,
|
||||||
int[] rendererMixedMimeTypeAdaptationSupports,
|
int[] rendererMixedMimeTypeAdaptationSupports,
|
||||||
@ -403,22 +403,22 @@ public final class DashTestRunner {
|
|||||||
TrackGroupArray audioTrackGroups = mappedTrackInfo.getTrackGroups(AUDIO_RENDERER_INDEX);
|
TrackGroupArray audioTrackGroups = mappedTrackInfo.getTrackGroups(AUDIO_RENDERER_INDEX);
|
||||||
Assertions.checkState(videoTrackGroups.length == 1);
|
Assertions.checkState(videoTrackGroups.length == 1);
|
||||||
Assertions.checkState(audioTrackGroups.length == 1);
|
Assertions.checkState(audioTrackGroups.length == 1);
|
||||||
TrackSelection[] selections = new TrackSelection[mappedTrackInfo.getRendererCount()];
|
TrackSelection.Definition[] definitions =
|
||||||
selections[VIDEO_RENDERER_INDEX] =
|
new TrackSelection.Definition[mappedTrackInfo.getRendererCount()];
|
||||||
new RandomTrackSelection(
|
definitions[VIDEO_RENDERER_INDEX] =
|
||||||
|
new TrackSelection.Definition(
|
||||||
videoTrackGroups.get(0),
|
videoTrackGroups.get(0),
|
||||||
getVideoTrackIndices(
|
getVideoTrackIndices(
|
||||||
videoTrackGroups.get(0),
|
videoTrackGroups.get(0),
|
||||||
rendererFormatSupports[VIDEO_RENDERER_INDEX][0],
|
rendererFormatSupports[VIDEO_RENDERER_INDEX][0],
|
||||||
videoFormatIds,
|
videoFormatIds,
|
||||||
canIncludeAdditionalVideoFormats),
|
canIncludeAdditionalVideoFormats));
|
||||||
0 /* seed */);
|
definitions[AUDIO_RENDERER_INDEX] =
|
||||||
selections[AUDIO_RENDERER_INDEX] =
|
new TrackSelection.Definition(
|
||||||
new FixedTrackSelection(
|
|
||||||
audioTrackGroups.get(0), getTrackIndex(audioTrackGroups.get(0), audioFormatId));
|
audioTrackGroups.get(0), getTrackIndex(audioTrackGroups.get(0), audioFormatId));
|
||||||
includedAdditionalVideoFormats =
|
includedAdditionalVideoFormats =
|
||||||
selections[VIDEO_RENDERER_INDEX].length() > videoFormatIds.length;
|
definitions[VIDEO_RENDERER_INDEX].tracks.length > videoFormatIds.length;
|
||||||
return selections;
|
return definitions;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int[] getVideoTrackIndices(
|
private int[] getVideoTrackIndices(
|
||||||
|
@ -15,21 +15,19 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.testutil;
|
package com.google.android.exoplayer2.testutil;
|
||||||
|
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import com.google.android.exoplayer2.ExoPlaybackException;
|
|
||||||
import com.google.android.exoplayer2.source.TrackGroup;
|
import com.google.android.exoplayer2.source.TrackGroup;
|
||||||
import com.google.android.exoplayer2.source.TrackGroupArray;
|
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||||
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
|
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
|
||||||
import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
|
import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
|
||||||
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
||||||
|
import com.google.android.exoplayer2.upstream.BandwidthMeter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/** A fake {@link MappingTrackSelector} that returns {@link FakeTrackSelection}s. */
|
/** A fake {@link MappingTrackSelector} that returns {@link FakeTrackSelection}s. */
|
||||||
public class FakeTrackSelector extends DefaultTrackSelector {
|
public class FakeTrackSelector extends DefaultTrackSelector {
|
||||||
|
|
||||||
private final List<FakeTrackSelection> trackSelections = new ArrayList<>();
|
private final FakeTrackSelectionFactory fakeTrackSelectionFactory;
|
||||||
private final boolean mayReuseTrackSelection;
|
|
||||||
|
|
||||||
public FakeTrackSelector() {
|
public FakeTrackSelector() {
|
||||||
this(false);
|
this(false);
|
||||||
@ -41,28 +39,48 @@ public class FakeTrackSelector extends DefaultTrackSelector {
|
|||||||
* using the same {@link TrackGroup}.
|
* using the same {@link TrackGroup}.
|
||||||
*/
|
*/
|
||||||
public FakeTrackSelector(boolean mayReuseTrackSelection) {
|
public FakeTrackSelector(boolean mayReuseTrackSelection) {
|
||||||
this.mayReuseTrackSelection = mayReuseTrackSelection;
|
this(new FakeTrackSelectionFactory(mayReuseTrackSelection));
|
||||||
|
}
|
||||||
|
|
||||||
|
private FakeTrackSelector(FakeTrackSelectionFactory fakeTrackSelectionFactory) {
|
||||||
|
super(fakeTrackSelectionFactory);
|
||||||
|
this.fakeTrackSelectionFactory = fakeTrackSelectionFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected TrackSelection[] selectAllTracks(
|
protected TrackSelection.Definition[] selectAllTracks(
|
||||||
MappedTrackInfo mappedTrackInfo,
|
MappedTrackInfo mappedTrackInfo,
|
||||||
int[][][] rendererFormatSupports,
|
int[][][] rendererFormatSupports,
|
||||||
int[] rendererMixedMimeTypeAdaptationSupports,
|
int[] rendererMixedMimeTypeAdaptationSupports,
|
||||||
Parameters params)
|
Parameters params) {
|
||||||
throws ExoPlaybackException {
|
|
||||||
int rendererCount = mappedTrackInfo.getRendererCount();
|
int rendererCount = mappedTrackInfo.getRendererCount();
|
||||||
TrackSelection[] selections = new TrackSelection[rendererCount];
|
TrackSelection.Definition[] definitions = new TrackSelection.Definition[rendererCount];
|
||||||
for (int i = 0; i < rendererCount; i++) {
|
for (int i = 0; i < rendererCount; i++) {
|
||||||
TrackGroupArray trackGroupArray = mappedTrackInfo.getTrackGroups(i);
|
TrackGroupArray trackGroupArray = mappedTrackInfo.getTrackGroups(i);
|
||||||
boolean hasTracks = trackGroupArray.length > 0;
|
boolean hasTracks = trackGroupArray.length > 0;
|
||||||
selections[i] = hasTracks ? reuseOrCreateTrackSelection(trackGroupArray.get(0)) : null;
|
definitions[i] = hasTracks ? new TrackSelection.Definition(trackGroupArray.get(0)) : null;
|
||||||
}
|
}
|
||||||
return selections;
|
return definitions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
/** Returns list of all {@link FakeTrackSelection}s that this track selector has made so far. */
|
||||||
private FakeTrackSelection reuseOrCreateTrackSelection(TrackGroup trackGroup) {
|
public List<FakeTrackSelection> getAllTrackSelections() {
|
||||||
|
return fakeTrackSelectionFactory.trackSelections;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class FakeTrackSelectionFactory implements TrackSelection.Factory {
|
||||||
|
|
||||||
|
private final List<FakeTrackSelection> trackSelections;
|
||||||
|
private final boolean mayReuseTrackSelection;
|
||||||
|
|
||||||
|
public FakeTrackSelectionFactory(boolean mayReuseTrackSelection) {
|
||||||
|
this.mayReuseTrackSelection = mayReuseTrackSelection;
|
||||||
|
trackSelections = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TrackSelection createTrackSelection(
|
||||||
|
TrackGroup trackGroup, BandwidthMeter bandwidthMeter, int... tracks) {
|
||||||
if (mayReuseTrackSelection) {
|
if (mayReuseTrackSelection) {
|
||||||
for (FakeTrackSelection trackSelection : trackSelections) {
|
for (FakeTrackSelection trackSelection : trackSelections) {
|
||||||
if (trackSelection.getTrackGroup().equals(trackGroup)) {
|
if (trackSelection.getTrackGroup().equals(trackGroup)) {
|
||||||
@ -75,9 +93,17 @@ public class FakeTrackSelector extends DefaultTrackSelector {
|
|||||||
return trackSelection;
|
return trackSelection;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns list of all {@link FakeTrackSelection}s that this track selector has made so far. */
|
@Override
|
||||||
public List<FakeTrackSelection> getAllTrackSelections() {
|
public TrackSelection[] createTrackSelections(
|
||||||
return trackSelections;
|
TrackSelection.Definition[] definitions, BandwidthMeter bandwidthMeter) {
|
||||||
|
TrackSelection[] selections = new TrackSelection[definitions.length];
|
||||||
|
for (int i = 0; i < definitions.length; i++) {
|
||||||
|
TrackSelection.Definition definition = definitions[i];
|
||||||
|
if (definition != null) {
|
||||||
|
selections[i] = createTrackSelection(definition.group, bandwidthMeter, definition.tracks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return selections;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user