mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
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
This commit is contained in:
parent
ef24125d20
commit
23c07e5c4d
1 changed files with 18 additions and 10 deletions
|
|
@ -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 {
|
||||||
* @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 {
|
||||||
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 {
|
||||||
(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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
// 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 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue