Skip to content

Commit

Permalink
Update default min duration for playbacks with video to match max dur…
Browse files Browse the repository at this point in the history
…ation.

Experiments show this is beneficial for rebuffers with only minor impact
on battery usage.

Configurations which explicitly set a minimum buffer duration are unaffected.

Issue:#2083
PiperOrigin-RevId: 244823642
  • Loading branch information
tonihei authored and ojw28 committed Apr 26, 2019
1 parent f62fa43 commit 9463c31
Showing 1 changed file with 60 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,14 @@ public class DefaultLoadControl implements LoadControl {

/**
* The default minimum duration of media that the player will attempt to ensure is buffered at all
* times, in milliseconds.
* times, in milliseconds. This value is only applied to playbacks without video.
*/
public static final int DEFAULT_MIN_BUFFER_MS = 15000;

/**
* The default maximum duration of media that the player will attempt to buffer, in milliseconds.
* For playbacks with video, this is also the default minimum duration of media that the player
* will attempt to ensure is buffered.
*/
public static final int DEFAULT_MAX_BUFFER_MS = 50000;

Expand Down Expand Up @@ -69,7 +71,8 @@ public class DefaultLoadControl implements LoadControl {
public static final class Builder {

private DefaultAllocator allocator;
private int minBufferMs;
private int minBufferAudioMs;
private int minBufferVideoMs;
private int maxBufferMs;
private int bufferForPlaybackMs;
private int bufferForPlaybackAfterRebufferMs;
Expand All @@ -81,7 +84,8 @@ public static final class Builder {

/** Constructs a new instance. */
public Builder() {
minBufferMs = DEFAULT_MIN_BUFFER_MS;
minBufferAudioMs = DEFAULT_MIN_BUFFER_MS;
minBufferVideoMs = DEFAULT_MAX_BUFFER_MS;
maxBufferMs = DEFAULT_MAX_BUFFER_MS;
bufferForPlaybackMs = DEFAULT_BUFFER_FOR_PLAYBACK_MS;
bufferForPlaybackAfterRebufferMs = DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS;
Expand Down Expand Up @@ -125,7 +129,18 @@ public Builder setBufferDurationsMs(
int bufferForPlaybackMs,
int bufferForPlaybackAfterRebufferMs) {
Assertions.checkState(!createDefaultLoadControlCalled);
this.minBufferMs = minBufferMs;
assertGreaterOrEqual(bufferForPlaybackMs, 0, "bufferForPlaybackMs", "0");
assertGreaterOrEqual(
bufferForPlaybackAfterRebufferMs, 0, "bufferForPlaybackAfterRebufferMs", "0");
assertGreaterOrEqual(minBufferMs, bufferForPlaybackMs, "minBufferMs", "bufferForPlaybackMs");
assertGreaterOrEqual(
minBufferMs,
bufferForPlaybackAfterRebufferMs,
"minBufferMs",
"bufferForPlaybackAfterRebufferMs");
assertGreaterOrEqual(maxBufferMs, minBufferMs, "maxBufferMs", "minBufferMs");
this.minBufferAudioMs = minBufferMs;
this.minBufferVideoMs = minBufferMs;
this.maxBufferMs = maxBufferMs;
this.bufferForPlaybackMs = bufferForPlaybackMs;
this.bufferForPlaybackAfterRebufferMs = bufferForPlaybackAfterRebufferMs;
Expand Down Expand Up @@ -173,6 +188,7 @@ public Builder setPrioritizeTimeOverSizeThresholds(boolean prioritizeTimeOverSiz
*/
public Builder setBackBuffer(int backBufferDurationMs, boolean retainBackBufferFromKeyframe) {
Assertions.checkState(!createDefaultLoadControlCalled);
assertGreaterOrEqual(backBufferDurationMs, 0, "backBufferDurationMs", "0");
this.backBufferDurationMs = backBufferDurationMs;
this.retainBackBufferFromKeyframe = retainBackBufferFromKeyframe;
return this;
Expand All @@ -187,7 +203,8 @@ public DefaultLoadControl createDefaultLoadControl() {
}
return new DefaultLoadControl(
allocator,
minBufferMs,
minBufferAudioMs,
minBufferVideoMs,
maxBufferMs,
bufferForPlaybackMs,
bufferForPlaybackAfterRebufferMs,
Expand All @@ -200,7 +217,8 @@ public DefaultLoadControl createDefaultLoadControl() {

private final DefaultAllocator allocator;

private final long minBufferUs;
private final long minBufferAudioUs;
private final long minBufferVideoUs;
private final long maxBufferUs;
private final long bufferForPlaybackUs;
private final long bufferForPlaybackAfterRebufferUs;
Expand All @@ -211,6 +229,7 @@ public DefaultLoadControl createDefaultLoadControl() {

private int targetBufferSize;
private boolean isBuffering;
private boolean hasVideo;

/** Constructs a new instance, using the {@code DEFAULT_*} constants defined in this class. */
@SuppressWarnings("deprecation")
Expand All @@ -220,16 +239,18 @@ public DefaultLoadControl() {

/** @deprecated Use {@link Builder} instead. */
@Deprecated
@SuppressWarnings("deprecation")
public DefaultLoadControl(DefaultAllocator allocator) {
this(
allocator,
DEFAULT_MIN_BUFFER_MS,
/* minBufferAudioMs= */ DEFAULT_MIN_BUFFER_MS,
/* minBufferVideoMs= */ DEFAULT_MAX_BUFFER_MS,
DEFAULT_MAX_BUFFER_MS,
DEFAULT_BUFFER_FOR_PLAYBACK_MS,
DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS,
DEFAULT_TARGET_BUFFER_BYTES,
DEFAULT_PRIORITIZE_TIME_OVER_SIZE_THRESHOLDS);
DEFAULT_PRIORITIZE_TIME_OVER_SIZE_THRESHOLDS,
DEFAULT_BACK_BUFFER_DURATION_MS,
DEFAULT_RETAIN_BACK_BUFFER_FROM_KEYFRAME);
}

/** @deprecated Use {@link Builder} instead. */
Expand All @@ -244,7 +265,8 @@ public DefaultLoadControl(
boolean prioritizeTimeOverSizeThresholds) {
this(
allocator,
minBufferMs,
/* minBufferAudioMs= */ minBufferMs,
/* minBufferVideoMs= */ minBufferMs,
maxBufferMs,
bufferForPlaybackMs,
bufferForPlaybackAfterRebufferMs,
Expand All @@ -256,7 +278,8 @@ public DefaultLoadControl(

protected DefaultLoadControl(
DefaultAllocator allocator,
int minBufferMs,
int minBufferAudioMs,
int minBufferVideoMs,
int maxBufferMs,
int bufferForPlaybackMs,
int bufferForPlaybackAfterRebufferMs,
Expand All @@ -267,17 +290,27 @@ protected DefaultLoadControl(
assertGreaterOrEqual(bufferForPlaybackMs, 0, "bufferForPlaybackMs", "0");
assertGreaterOrEqual(
bufferForPlaybackAfterRebufferMs, 0, "bufferForPlaybackAfterRebufferMs", "0");
assertGreaterOrEqual(minBufferMs, bufferForPlaybackMs, "minBufferMs", "bufferForPlaybackMs");
assertGreaterOrEqual(
minBufferMs,
minBufferAudioMs, bufferForPlaybackMs, "minBufferAudioMs", "bufferForPlaybackMs");
assertGreaterOrEqual(
minBufferVideoMs, bufferForPlaybackMs, "minBufferVideoMs", "bufferForPlaybackMs");
assertGreaterOrEqual(
minBufferAudioMs,
bufferForPlaybackAfterRebufferMs,
"minBufferMs",
"minBufferAudioMs",
"bufferForPlaybackAfterRebufferMs");
assertGreaterOrEqual(maxBufferMs, minBufferMs, "maxBufferMs", "minBufferMs");
assertGreaterOrEqual(
minBufferVideoMs,
bufferForPlaybackAfterRebufferMs,
"minBufferVideoMs",
"bufferForPlaybackAfterRebufferMs");
assertGreaterOrEqual(maxBufferMs, minBufferAudioMs, "maxBufferMs", "minBufferAudioMs");
assertGreaterOrEqual(maxBufferMs, minBufferVideoMs, "maxBufferMs", "minBufferVideoMs");
assertGreaterOrEqual(backBufferDurationMs, 0, "backBufferDurationMs", "0");

this.allocator = allocator;
this.minBufferUs = C.msToUs(minBufferMs);
this.minBufferAudioUs = C.msToUs(minBufferAudioMs);
this.minBufferVideoUs = C.msToUs(minBufferVideoMs);
this.maxBufferUs = C.msToUs(maxBufferMs);
this.bufferForPlaybackUs = C.msToUs(bufferForPlaybackMs);
this.bufferForPlaybackAfterRebufferUs = C.msToUs(bufferForPlaybackAfterRebufferMs);
Expand All @@ -295,6 +328,7 @@ public void onPrepared() {
@Override
public void onTracksSelected(Renderer[] renderers, TrackGroupArray trackGroups,
TrackSelectionArray trackSelections) {
hasVideo = hasVideo(renderers, trackSelections);
targetBufferSize =
targetBufferBytesOverwrite == C.LENGTH_UNSET
? calculateTargetBufferSize(renderers, trackSelections)
Expand Down Expand Up @@ -330,7 +364,7 @@ public boolean retainBackBufferFromKeyframe() {
@Override
public boolean shouldContinueLoading(long bufferedDurationUs, float playbackSpeed) {
boolean targetBufferSizeReached = allocator.getTotalBytesAllocated() >= targetBufferSize;
long minBufferUs = this.minBufferUs;
long minBufferUs = hasVideo ? minBufferVideoUs : minBufferAudioUs;
if (playbackSpeed > 1) {
// The playback speed is faster than real time, so scale up the minimum required media
// duration to keep enough media buffered for a playout duration of minBufferUs.
Expand Down Expand Up @@ -384,6 +418,15 @@ private void reset(boolean resetAllocator) {
}
}

private static boolean hasVideo(Renderer[] renderers, TrackSelectionArray trackSelectionArray) {
for (int i = 0; i < renderers.length; i++) {
if (renderers[i].getTrackType() == C.TRACK_TYPE_VIDEO && trackSelectionArray.get(i) != null) {
return true;
}
}
return false;
}

private static void assertGreaterOrEqual(int value1, int value2, String name1, String name2) {
Assertions.checkArgument(value1 >= value2, name1 + " cannot be less than " + name2);
}
Expand Down

0 comments on commit 9463c31

Please sign in to comment.