Commit 23c07e5c by tonihei Committed by Oliver Woodman

Update buffer-based ABR to not select track in constructor.

This mimicks a similar change in the default AdaptiveTrackSelection.
Also adds an option to cap initial format height.

PiperOrigin-RevId: 229923149
parent ef24125d
...@@ -43,7 +43,7 @@ public final class BufferSizeAdaptationBuilder { ...@@ -43,7 +43,7 @@ public final class BufferSizeAdaptationBuilder {
public interface DynamicFormatFilter { public interface DynamicFormatFilter {
/** Filter which allows all formats. */ /** Filter which allows all formats. */
DynamicFormatFilter NO_FILTER = (format, trackBitrate) -> true; DynamicFormatFilter NO_FILTER = (format, trackBitrate, isInitialSelection) -> true;
/** /**
* Called when updating the selected track to determine whether a candidate track is allowed. If * Called when updating the selected track to determine whether a candidate track is allowed. If
...@@ -52,8 +52,9 @@ public final class BufferSizeAdaptationBuilder { ...@@ -52,8 +52,9 @@ public final class BufferSizeAdaptationBuilder {
* @param format The {@link Format} of the candidate track. * @param format The {@link Format} of the candidate track.
* @param trackBitrate The estimated bitrate of the track. May differ from {@link * @param trackBitrate The estimated bitrate of the track. May differ from {@link
* Format#bitrate} if a more accurate estimate of the current track bitrate is available. * Format#bitrate} if a more accurate estimate of the current track bitrate is available.
* @param isInitialSelection Whether this is for the initial track selection.
*/ */
boolean isFormatAllowed(Format format, int trackBitrate); boolean isFormatAllowed(Format format, int trackBitrate, boolean isInitialSelection);
} }
/** /**
...@@ -344,7 +345,7 @@ public final class BufferSizeAdaptationBuilder { ...@@ -344,7 +345,7 @@ public final class BufferSizeAdaptationBuilder {
formatBitrates = new int[length]; formatBitrates = new int[length];
maxBitrate = getFormat(/* index= */ 0).bitrate; maxBitrate = getFormat(/* index= */ 0).bitrate;
minBitrate = getFormat(/* index= */ length - 1).bitrate; minBitrate = getFormat(/* index= */ length - 1).bitrate;
selectionReason = C.SELECTION_REASON_INITIAL; selectionReason = C.SELECTION_REASON_UNKNOWN;
playbackSpeed = 1.0f; playbackSpeed = 1.0f;
// We use a log-linear function to map from bitrate to buffer size: // We use a log-linear function to map from bitrate to buffer size:
...@@ -354,9 +355,6 @@ public final class BufferSizeAdaptationBuilder { ...@@ -354,9 +355,6 @@ public final class BufferSizeAdaptationBuilder {
(maxBufferUs - hysteresisBufferUs - minBufferUs) / Math.log(maxBitrate / minBitrate); (maxBufferUs - hysteresisBufferUs - minBufferUs) / Math.log(maxBitrate / minBitrate);
bitrateToBufferFunctionIntercept = bitrateToBufferFunctionIntercept =
minBufferUs - bitrateToBufferFunctionSlope * Math.log(minBitrate); minBufferUs - bitrateToBufferFunctionSlope * Math.log(minBitrate);
updateFormatBitrates(/* nowMs= */ Long.MIN_VALUE);
selectedIndex = selectIdealIndexUsingBandwidth();
} }
@Override @Override
...@@ -393,6 +391,14 @@ public final class BufferSizeAdaptationBuilder { ...@@ -393,6 +391,14 @@ public final class BufferSizeAdaptationBuilder {
List<? extends MediaChunk> queue, List<? extends MediaChunk> queue,
MediaChunkIterator[] mediaChunkIterators) { MediaChunkIterator[] mediaChunkIterators) {
updateFormatBitrates(/* nowMs= */ clock.elapsedRealtime()); updateFormatBitrates(/* nowMs= */ clock.elapsedRealtime());
// Make initial selection
if (selectionReason == C.SELECTION_REASON_UNKNOWN) {
selectionReason = C.SELECTION_REASON_INITIAL;
selectedIndex = selectIdealIndexUsingBandwidth(/* isInitialSelection= */ true);
return;
}
long bufferUs = getCurrentPeriodBufferedDurationUs(playbackPositionUs, bufferedDurationUs); long bufferUs = getCurrentPeriodBufferedDurationUs(playbackPositionUs, bufferedDurationUs);
int oldSelectedIndex = selectedIndex; int oldSelectedIndex = selectedIndex;
if (isInSteadyState) { if (isInSteadyState) {
...@@ -428,7 +434,8 @@ public final class BufferSizeAdaptationBuilder { ...@@ -428,7 +434,8 @@ public final class BufferSizeAdaptationBuilder {
for (int i = 0; i < formatBitrates.length; i++) { for (int i = 0; i < formatBitrates.length; i++) {
if (formatBitrates[i] != BITRATE_BLACKLISTED) { if (formatBitrates[i] != BITRATE_BLACKLISTED) {
if (getTargetBufferForBitrateUs(formatBitrates[i]) < bufferUs if (getTargetBufferForBitrateUs(formatBitrates[i]) < bufferUs
&& dynamicFormatFilter.isFormatAllowed(getFormat(i), formatBitrates[i])) { && dynamicFormatFilter.isFormatAllowed(
getFormat(i), formatBitrates[i], /* isInitialSelection= */ false)) {
return i; return i;
} }
lowestBitrateNonBlacklistedIndex = i; lowestBitrateNonBlacklistedIndex = i;
...@@ -440,7 +447,7 @@ public final class BufferSizeAdaptationBuilder { ...@@ -440,7 +447,7 @@ public final class BufferSizeAdaptationBuilder {
// Startup. // Startup.
private void selectIndexStartUpPhase(long bufferUs) { private void selectIndexStartUpPhase(long bufferUs) {
int startUpSelectedIndex = selectIdealIndexUsingBandwidth(); int startUpSelectedIndex = selectIdealIndexUsingBandwidth(/* isInitialSelection= */ false);
int steadyStateSelectedIndex = selectIdealIndexUsingBufferSize(bufferUs); int steadyStateSelectedIndex = selectIdealIndexUsingBufferSize(bufferUs);
if (steadyStateSelectedIndex <= selectedIndex) { if (steadyStateSelectedIndex <= selectedIndex) {
// Switch to steady state if we have enough buffer to maintain current selection. // Switch to steady state if we have enough buffer to maintain current selection.
...@@ -457,14 +464,15 @@ public final class BufferSizeAdaptationBuilder { ...@@ -457,14 +464,15 @@ public final class BufferSizeAdaptationBuilder {
} }
} }
private int selectIdealIndexUsingBandwidth() { private int selectIdealIndexUsingBandwidth(boolean isInitialSelection) {
long effectiveBitrate = long effectiveBitrate =
(long) (bandwidthMeter.getBitrateEstimate() * startUpBandwidthFraction); (long) (bandwidthMeter.getBitrateEstimate() * startUpBandwidthFraction);
int lowestBitrateNonBlacklistedIndex = 0; int lowestBitrateNonBlacklistedIndex = 0;
for (int i = 0; i < formatBitrates.length; i++) { for (int i = 0; i < formatBitrates.length; i++) {
if (formatBitrates[i] != BITRATE_BLACKLISTED) { if (formatBitrates[i] != BITRATE_BLACKLISTED) {
if (Math.round(formatBitrates[i] * playbackSpeed) <= effectiveBitrate if (Math.round(formatBitrates[i] * playbackSpeed) <= effectiveBitrate
&& dynamicFormatFilter.isFormatAllowed(getFormat(i), formatBitrates[i])) { && dynamicFormatFilter.isFormatAllowed(
getFormat(i), formatBitrates[i], isInitialSelection)) {
return i; return i;
} }
lowestBitrateNonBlacklistedIndex = i; lowestBitrateNonBlacklistedIndex = i;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment