diff --git a/library/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java b/library/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java
index f62d5d9075..f72f99f212 100644
--- a/library/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java
+++ b/library/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java
@@ -54,6 +54,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
public final boolean allowNonSeamlessAdaptiveness;
public final int maxVideoWidth;
public final int maxVideoHeight;
+ public final int maxVideoBitrate;
public final boolean exceedVideoConstraintsIfNecessary;
public final boolean exceedRendererCapabilitiesIfNecessary;
public final int viewportWidth;
@@ -68,14 +69,15 @@ public class DefaultTrackSelector extends MappingTrackSelector {
*
Adaptation between different mime types is not allowed.
* Non seamless adaptation is allowed.
* No max limit for video width/height.
+ * No max video bitrate.
* Video constraints are exceeded if no supported selection can be made otherwise.
* Renderer capabilities are exceeded if no supported selection can be made.
* No viewport width/height constraints are set.
*
*/
public Parameters() {
- this(null, null, false, true, Integer.MAX_VALUE, Integer.MAX_VALUE, true, true,
- Integer.MAX_VALUE, Integer.MAX_VALUE, true);
+ this(null, null, false, true, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, true,
+ true, Integer.MAX_VALUE, Integer.MAX_VALUE, true);
}
/**
@@ -88,6 +90,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
* @param allowNonSeamlessAdaptiveness Whether non-seamless adaptation is allowed.
* @param maxVideoWidth Maximum allowed video width.
* @param maxVideoHeight Maximum allowed video height.
+ * @param maxVideoBitrate Maximum allowed video bitrate.
* @param exceedVideoConstraintsIfNecessary Whether to exceed video constraints when no
* selection can be made otherwise.
* @param exceedRendererCapabilitiesIfNecessary Whether to exceed renderer capabilities when no
@@ -98,15 +101,16 @@ public class DefaultTrackSelector extends MappingTrackSelector {
*/
public Parameters(String preferredAudioLanguage, String preferredTextLanguage,
boolean allowMixedMimeAdaptiveness, boolean allowNonSeamlessAdaptiveness,
- int maxVideoWidth, int maxVideoHeight, boolean exceedVideoConstraintsIfNecessary,
- boolean exceedRendererCapabilitiesIfNecessary, int viewportWidth, int viewportHeight,
- boolean orientationMayChange) {
+ int maxVideoWidth, int maxVideoHeight, int maxVideoBitrate,
+ boolean exceedVideoConstraintsIfNecessary, boolean exceedRendererCapabilitiesIfNecessary,
+ int viewportWidth, int viewportHeight, boolean orientationMayChange) {
this.preferredAudioLanguage = preferredAudioLanguage;
this.preferredTextLanguage = preferredTextLanguage;
this.allowMixedMimeAdaptiveness = allowMixedMimeAdaptiveness;
this.allowNonSeamlessAdaptiveness = allowNonSeamlessAdaptiveness;
this.maxVideoWidth = maxVideoWidth;
this.maxVideoHeight = maxVideoHeight;
+ this.maxVideoBitrate = maxVideoBitrate;
this.exceedVideoConstraintsIfNecessary = exceedVideoConstraintsIfNecessary;
this.exceedRendererCapabilitiesIfNecessary = exceedRendererCapabilitiesIfNecessary;
this.viewportWidth = viewportWidth;
@@ -130,8 +134,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
}
return new Parameters(preferredAudioLanguage, preferredTextLanguage,
allowMixedMimeAdaptiveness, allowNonSeamlessAdaptiveness, maxVideoWidth, maxVideoHeight,
- exceedVideoConstraintsIfNecessary, exceedRendererCapabilitiesIfNecessary, viewportWidth,
- viewportHeight, orientationMayChange);
+ maxVideoBitrate, exceedVideoConstraintsIfNecessary, exceedRendererCapabilitiesIfNecessary,
+ viewportWidth, viewportHeight, orientationMayChange);
}
/**
@@ -148,8 +152,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
}
return new Parameters(preferredAudioLanguage, preferredTextLanguage,
allowMixedMimeAdaptiveness, allowNonSeamlessAdaptiveness, maxVideoWidth, maxVideoHeight,
- exceedVideoConstraintsIfNecessary, exceedRendererCapabilitiesIfNecessary, viewportWidth,
- viewportHeight, orientationMayChange);
+ maxVideoBitrate, exceedVideoConstraintsIfNecessary, exceedRendererCapabilitiesIfNecessary,
+ viewportWidth, viewportHeight, orientationMayChange);
}
/**
@@ -164,8 +168,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
}
return new Parameters(preferredAudioLanguage, preferredTextLanguage,
allowMixedMimeAdaptiveness, allowNonSeamlessAdaptiveness, maxVideoWidth, maxVideoHeight,
- exceedVideoConstraintsIfNecessary, exceedRendererCapabilitiesIfNecessary, viewportWidth,
- viewportHeight, orientationMayChange);
+ maxVideoBitrate, exceedVideoConstraintsIfNecessary, exceedRendererCapabilitiesIfNecessary,
+ viewportWidth, viewportHeight, orientationMayChange);
}
/**
@@ -180,8 +184,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
}
return new Parameters(preferredAudioLanguage, preferredTextLanguage,
allowMixedMimeAdaptiveness, allowNonSeamlessAdaptiveness, maxVideoWidth, maxVideoHeight,
- exceedVideoConstraintsIfNecessary, exceedRendererCapabilitiesIfNecessary, viewportWidth,
- viewportHeight, orientationMayChange);
+ maxVideoBitrate, exceedVideoConstraintsIfNecessary, exceedRendererCapabilitiesIfNecessary,
+ viewportWidth, viewportHeight, orientationMayChange);
}
/**
@@ -197,8 +201,24 @@ public class DefaultTrackSelector extends MappingTrackSelector {
}
return new Parameters(preferredAudioLanguage, preferredTextLanguage,
allowMixedMimeAdaptiveness, allowNonSeamlessAdaptiveness, maxVideoWidth, maxVideoHeight,
- exceedVideoConstraintsIfNecessary, exceedRendererCapabilitiesIfNecessary, viewportWidth,
- viewportHeight, orientationMayChange);
+ maxVideoBitrate, exceedVideoConstraintsIfNecessary, exceedRendererCapabilitiesIfNecessary,
+ viewportWidth, viewportHeight, orientationMayChange);
+ }
+
+ /**
+ * Returns a {@link Parameters} instance with the provided max video bitrate.
+ *
+ * @param maxVideoBitrate The max video bitrate.
+ * @return A {@link Parameters} instance with the provided max video bitrate.
+ */
+ public Parameters withMaxVideoBitrate(int maxVideoBitrate) {
+ if (maxVideoBitrate == this.maxVideoBitrate) {
+ return this;
+ }
+ return new Parameters(preferredAudioLanguage, preferredTextLanguage,
+ allowMixedMimeAdaptiveness, allowNonSeamlessAdaptiveness, maxVideoWidth, maxVideoHeight,
+ maxVideoBitrate, exceedVideoConstraintsIfNecessary, exceedRendererCapabilitiesIfNecessary,
+ viewportWidth, viewportHeight, orientationMayChange);
}
/**
@@ -235,8 +255,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
}
return new Parameters(preferredAudioLanguage, preferredTextLanguage,
allowMixedMimeAdaptiveness, allowNonSeamlessAdaptiveness, maxVideoWidth, maxVideoHeight,
- exceedVideoConstraintsIfNecessary, exceedRendererCapabilitiesIfNecessary, viewportWidth,
- viewportHeight, orientationMayChange);
+ maxVideoBitrate, exceedVideoConstraintsIfNecessary, exceedRendererCapabilitiesIfNecessary,
+ viewportWidth, viewportHeight, orientationMayChange);
}
/**
@@ -255,8 +275,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
}
return new Parameters(preferredAudioLanguage, preferredTextLanguage,
allowMixedMimeAdaptiveness, allowNonSeamlessAdaptiveness, maxVideoWidth, maxVideoHeight,
- exceedVideoConstraintsIfNecessary, exceedRendererCapabilitiesIfNecessary, viewportWidth,
- viewportHeight, orientationMayChange);
+ maxVideoBitrate, exceedVideoConstraintsIfNecessary, exceedRendererCapabilitiesIfNecessary,
+ viewportWidth, viewportHeight, orientationMayChange);
}
/**
@@ -275,8 +295,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
}
return new Parameters(preferredAudioLanguage, preferredTextLanguage,
allowMixedMimeAdaptiveness, allowNonSeamlessAdaptiveness, maxVideoWidth, maxVideoHeight,
- exceedVideoConstraintsIfNecessary, exceedRendererCapabilitiesIfNecessary, viewportWidth,
- viewportHeight, orientationMayChange);
+ maxVideoBitrate, exceedVideoConstraintsIfNecessary, exceedRendererCapabilitiesIfNecessary,
+ viewportWidth, viewportHeight, orientationMayChange);
}
/**
@@ -319,6 +339,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
&& exceedRendererCapabilitiesIfNecessary == other.exceedRendererCapabilitiesIfNecessary
&& orientationMayChange == other.orientationMayChange
&& viewportWidth == other.viewportWidth && viewportHeight == other.viewportHeight
+ && maxVideoBitrate == other.maxVideoBitrate
&& TextUtils.equals(preferredAudioLanguage, other.preferredAudioLanguage)
&& TextUtils.equals(preferredTextLanguage, other.preferredTextLanguage);
}
@@ -331,6 +352,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
result = 31 * result + (allowNonSeamlessAdaptiveness ? 1 : 0);
result = 31 * result + maxVideoWidth;
result = 31 * result + maxVideoHeight;
+ result = 31 * result + maxVideoBitrate;
result = 31 * result + (exceedVideoConstraintsIfNecessary ? 1 : 0);
result = 31 * result + (exceedRendererCapabilitiesIfNecessary ? 1 : 0);
result = 31 * result + (orientationMayChange ? 1 : 0);
@@ -406,7 +428,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
case C.TRACK_TYPE_VIDEO:
rendererTrackSelections[i] = selectVideoTrack(rendererCapabilities[i],
rendererTrackGroupArrays[i], rendererFormatSupports[i], params.maxVideoWidth,
- params.maxVideoHeight, params.allowNonSeamlessAdaptiveness,
+ params.maxVideoHeight, params.maxVideoBitrate, params.allowNonSeamlessAdaptiveness,
params.allowMixedMimeAdaptiveness, params.viewportWidth, params.viewportHeight,
params.orientationMayChange, adaptiveVideoTrackSelectionFactory,
params.exceedVideoConstraintsIfNecessary,
@@ -436,30 +458,30 @@ public class DefaultTrackSelector extends MappingTrackSelector {
protected TrackSelection selectVideoTrack(RendererCapabilities rendererCapabilities,
TrackGroupArray groups, int[][] formatSupport, int maxVideoWidth, int maxVideoHeight,
- boolean allowNonSeamlessAdaptiveness, boolean allowMixedMimeAdaptiveness, int viewportWidth,
- int viewportHeight, boolean orientationMayChange,
+ int maxVideoBitrate, boolean allowNonSeamlessAdaptiveness, boolean allowMixedMimeAdaptiveness,
+ int viewportWidth, int viewportHeight, boolean orientationMayChange,
TrackSelection.Factory adaptiveVideoTrackSelectionFactory,
boolean exceedConstraintsIfNecessary, boolean exceedRendererCapabilitiesIfNecessary)
throws ExoPlaybackException {
TrackSelection selection = null;
if (adaptiveVideoTrackSelectionFactory != null) {
selection = selectAdaptiveVideoTrack(rendererCapabilities, groups, formatSupport,
- maxVideoWidth, maxVideoHeight, allowNonSeamlessAdaptiveness,
+ maxVideoWidth, maxVideoHeight, maxVideoBitrate, allowNonSeamlessAdaptiveness,
allowMixedMimeAdaptiveness, viewportWidth, viewportHeight,
orientationMayChange, adaptiveVideoTrackSelectionFactory);
}
if (selection == null) {
selection = selectFixedVideoTrack(groups, formatSupport, maxVideoWidth, maxVideoHeight,
- viewportWidth, viewportHeight, orientationMayChange, exceedConstraintsIfNecessary,
- exceedRendererCapabilitiesIfNecessary);
+ maxVideoBitrate, viewportWidth, viewportHeight, orientationMayChange,
+ exceedConstraintsIfNecessary, exceedRendererCapabilitiesIfNecessary);
}
return selection;
}
private static TrackSelection selectAdaptiveVideoTrack(RendererCapabilities rendererCapabilities,
TrackGroupArray groups, int[][] formatSupport, int maxVideoWidth, int maxVideoHeight,
- boolean allowNonSeamlessAdaptiveness, boolean allowMixedMimeAdaptiveness, int viewportWidth,
- int viewportHeight, boolean orientationMayChange,
+ int maxVideoBitrate, boolean allowNonSeamlessAdaptiveness, boolean allowMixedMimeAdaptiveness,
+ int viewportWidth, int viewportHeight, boolean orientationMayChange,
TrackSelection.Factory adaptiveVideoTrackSelectionFactory) throws ExoPlaybackException {
int requiredAdaptiveSupport = allowNonSeamlessAdaptiveness
? (RendererCapabilities.ADAPTIVE_NOT_SEAMLESS | RendererCapabilities.ADAPTIVE_SEAMLESS)
@@ -470,7 +492,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
TrackGroup group = groups.get(i);
int[] adaptiveTracks = getAdaptiveTracksForGroup(group, formatSupport[i],
allowMixedMimeTypes, requiredAdaptiveSupport, maxVideoWidth, maxVideoHeight,
- viewportWidth, viewportHeight, orientationMayChange);
+ maxVideoBitrate, viewportWidth, viewportHeight, orientationMayChange);
if (adaptiveTracks.length > 0) {
return adaptiveVideoTrackSelectionFactory.createTrackSelection(group, adaptiveTracks);
}
@@ -480,7 +502,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
private static int[] getAdaptiveTracksForGroup(TrackGroup group, int[] formatSupport,
boolean allowMixedMimeTypes, int requiredAdaptiveSupport, int maxVideoWidth,
- int maxVideoHeight, int viewportWidth, int viewportHeight, boolean orientationMayChange) {
+ int maxVideoHeight, int maxVideoBitrate, int viewportWidth, int viewportHeight,
+ boolean orientationMayChange) {
if (group.length < 2) {
return NO_TRACKS;
}
@@ -499,11 +522,10 @@ public class DefaultTrackSelector extends MappingTrackSelector {
for (int i = 0; i < selectedTrackIndices.size(); i++) {
int trackIndex = selectedTrackIndices.get(i);
String sampleMimeType = group.getFormat(trackIndex).sampleMimeType;
- if (!seenMimeTypes.contains(sampleMimeType)) {
- seenMimeTypes.add(sampleMimeType);
+ if (seenMimeTypes.add(sampleMimeType)) {
int countForMimeType = getAdaptiveTrackCountForMimeType(group, formatSupport,
requiredAdaptiveSupport, sampleMimeType, maxVideoWidth, maxVideoHeight,
- selectedTrackIndices);
+ maxVideoBitrate, selectedTrackIndices);
if (countForMimeType > selectedMimeTypeTrackCount) {
selectedMimeType = sampleMimeType;
selectedMimeTypeTrackCount = countForMimeType;
@@ -514,19 +536,20 @@ public class DefaultTrackSelector extends MappingTrackSelector {
// Filter by the selected mime type.
filterAdaptiveTrackCountForMimeType(group, formatSupport, requiredAdaptiveSupport,
- selectedMimeType, maxVideoWidth, maxVideoHeight, selectedTrackIndices);
+ selectedMimeType, maxVideoWidth, maxVideoHeight, maxVideoBitrate, selectedTrackIndices);
return selectedTrackIndices.size() < 2 ? NO_TRACKS : Util.toArray(selectedTrackIndices);
}
private static int getAdaptiveTrackCountForMimeType(TrackGroup group, int[] formatSupport,
int requiredAdaptiveSupport, String mimeType, int maxVideoWidth, int maxVideoHeight,
- List selectedTrackIndices) {
+ int maxVideoBitrate, List selectedTrackIndices) {
int adaptiveTrackCount = 0;
for (int i = 0; i < selectedTrackIndices.size(); i++) {
int trackIndex = selectedTrackIndices.get(i);
if (isSupportedAdaptiveVideoTrack(group.getFormat(trackIndex), mimeType,
- formatSupport[trackIndex], requiredAdaptiveSupport, maxVideoWidth, maxVideoHeight)) {
+ formatSupport[trackIndex], requiredAdaptiveSupport, maxVideoWidth, maxVideoHeight,
+ maxVideoBitrate)) {
adaptiveTrackCount++;
}
}
@@ -535,28 +558,31 @@ public class DefaultTrackSelector extends MappingTrackSelector {
private static void filterAdaptiveTrackCountForMimeType(TrackGroup group, int[] formatSupport,
int requiredAdaptiveSupport, String mimeType, int maxVideoWidth, int maxVideoHeight,
- List selectedTrackIndices) {
+ int maxVideoBitrate, List selectedTrackIndices) {
for (int i = selectedTrackIndices.size() - 1; i >= 0; i--) {
int trackIndex = selectedTrackIndices.get(i);
if (!isSupportedAdaptiveVideoTrack(group.getFormat(trackIndex), mimeType,
- formatSupport[trackIndex], requiredAdaptiveSupport, maxVideoWidth, maxVideoHeight)) {
+ formatSupport[trackIndex], requiredAdaptiveSupport, maxVideoWidth, maxVideoHeight,
+ maxVideoBitrate)) {
selectedTrackIndices.remove(i);
}
}
}
private static boolean isSupportedAdaptiveVideoTrack(Format format, String mimeType,
- int formatSupport, int requiredAdaptiveSupport, int maxVideoWidth, int maxVideoHeight) {
+ int formatSupport, int requiredAdaptiveSupport, int maxVideoWidth, int maxVideoHeight,
+ int maxVideoBitrate) {
return isSupported(formatSupport, false) && ((formatSupport & requiredAdaptiveSupport) != 0)
&& (mimeType == null || Util.areEqual(format.sampleMimeType, mimeType))
&& (format.width == Format.NO_VALUE || format.width <= maxVideoWidth)
- && (format.height == Format.NO_VALUE || format.height <= maxVideoHeight);
+ && (format.height == Format.NO_VALUE || format.height <= maxVideoHeight)
+ && (format.bitrate == Format.NO_VALUE || format.bitrate <= maxVideoBitrate);
}
private static TrackSelection selectFixedVideoTrack(TrackGroupArray groups,
- int[][] formatSupport, int maxVideoWidth, int maxVideoHeight, int viewportWidth,
- int viewportHeight, boolean orientationMayChange, boolean exceedConstraintsIfNecessary,
- boolean exceedRendererCapabilitiesIfNecessary) {
+ int[][] formatSupport, int maxVideoWidth, int maxVideoHeight, int maxVideoBitrate,
+ int viewportWidth, int viewportHeight, boolean orientationMayChange,
+ boolean exceedConstraintsIfNecessary, boolean exceedRendererCapabilitiesIfNecessary) {
TrackGroup selectedGroup = null;
int selectedTrackIndex = 0;
int selectedTrackScore = 0;
@@ -572,7 +598,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
Format format = trackGroup.getFormat(trackIndex);
boolean isWithinConstraints = selectedTrackIndices.contains(trackIndex)
&& (format.width == Format.NO_VALUE || format.width <= maxVideoWidth)
- && (format.height == Format.NO_VALUE || format.height <= maxVideoHeight);
+ && (format.height == Format.NO_VALUE || format.height <= maxVideoHeight)
+ && (format.bitrate == Format.NO_VALUE || format.bitrate <= maxVideoBitrate);
if (!isWithinConstraints && !exceedConstraintsIfNecessary) {
// Track should not be selected.
continue;