mirror of
https://github.com/samsonjs/media.git
synced 2026-04-10 12:05:47 +00:00
Copy getting-stuck-prevention into DefaultLoadControl.
We will eventually remove the workaround from ExoPlayerImplInternal
added in
b84bde0252
and replace it by an error that gets thrown if the LoadControl behaves
badly.
PiperOrigin-RevId: 295556131
This commit is contained in:
parent
faff66e9df
commit
56ec705275
2 changed files with 36 additions and 9 deletions
|
|
@ -246,7 +246,7 @@ public class DefaultLoadControl implements LoadControl {
|
|||
private final long backBufferDurationUs;
|
||||
private final boolean retainBackBufferFromKeyframe;
|
||||
|
||||
private int targetBufferSize;
|
||||
private int targetBufferBytes;
|
||||
private boolean isBuffering;
|
||||
private boolean hasVideo;
|
||||
|
||||
|
|
@ -334,6 +334,10 @@ public class DefaultLoadControl implements LoadControl {
|
|||
this.bufferForPlaybackUs = C.msToUs(bufferForPlaybackMs);
|
||||
this.bufferForPlaybackAfterRebufferUs = C.msToUs(bufferForPlaybackAfterRebufferMs);
|
||||
this.targetBufferBytesOverwrite = targetBufferBytes;
|
||||
this.targetBufferBytes =
|
||||
targetBufferBytesOverwrite != C.LENGTH_UNSET
|
||||
? targetBufferBytesOverwrite
|
||||
: DEFAULT_MUXED_BUFFER_SIZE;
|
||||
this.prioritizeTimeOverSizeThresholds = prioritizeTimeOverSizeThresholds;
|
||||
this.backBufferDurationUs = C.msToUs(backBufferDurationMs);
|
||||
this.retainBackBufferFromKeyframe = retainBackBufferFromKeyframe;
|
||||
|
|
@ -348,11 +352,11 @@ public class DefaultLoadControl implements LoadControl {
|
|||
public void onTracksSelected(Renderer[] renderers, TrackGroupArray trackGroups,
|
||||
TrackSelectionArray trackSelections) {
|
||||
hasVideo = hasVideo(renderers, trackSelections);
|
||||
targetBufferSize =
|
||||
targetBufferBytes =
|
||||
targetBufferBytesOverwrite == C.LENGTH_UNSET
|
||||
? calculateTargetBufferSize(renderers, trackSelections)
|
||||
? calculateTargetBufferBytes(renderers, trackSelections)
|
||||
: targetBufferBytesOverwrite;
|
||||
allocator.setTargetBufferSize(targetBufferSize);
|
||||
allocator.setTargetBufferSize(targetBufferBytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -382,7 +386,7 @@ public class DefaultLoadControl implements LoadControl {
|
|||
|
||||
@Override
|
||||
public boolean shouldContinueLoading(long bufferedDurationUs, float playbackSpeed) {
|
||||
boolean targetBufferSizeReached = allocator.getTotalBytesAllocated() >= targetBufferSize;
|
||||
boolean targetBufferSizeReached = allocator.getTotalBytesAllocated() >= targetBufferBytes;
|
||||
long minBufferUs = hasVideo ? minBufferVideoUs : minBufferAudioUs;
|
||||
if (playbackSpeed > 1) {
|
||||
// The playback speed is faster than real time, so scale up the minimum required media
|
||||
|
|
@ -391,6 +395,8 @@ public class DefaultLoadControl implements LoadControl {
|
|||
Util.getMediaDurationForPlayoutDuration(minBufferUs, playbackSpeed);
|
||||
minBufferUs = Math.min(mediaDurationMinBufferUs, maxBufferUs);
|
||||
}
|
||||
// Prevent playback from getting stuck if minBufferUs is too small.
|
||||
minBufferUs = Math.max(minBufferUs, 500_000);
|
||||
if (bufferedDurationUs < minBufferUs) {
|
||||
isBuffering = prioritizeTimeOverSizeThresholds || !targetBufferSizeReached;
|
||||
} else if (bufferedDurationUs >= maxBufferUs || targetBufferSizeReached) {
|
||||
|
|
@ -407,7 +413,7 @@ public class DefaultLoadControl implements LoadControl {
|
|||
return minBufferDurationUs <= 0
|
||||
|| bufferedDurationUs >= minBufferDurationUs
|
||||
|| (!prioritizeTimeOverSizeThresholds
|
||||
&& allocator.getTotalBytesAllocated() >= targetBufferSize);
|
||||
&& allocator.getTotalBytesAllocated() >= targetBufferBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -418,7 +424,7 @@ public class DefaultLoadControl implements LoadControl {
|
|||
* @param trackSelectionArray The selected tracks.
|
||||
* @return The target buffer size in bytes.
|
||||
*/
|
||||
protected int calculateTargetBufferSize(
|
||||
protected int calculateTargetBufferBytes(
|
||||
Renderer[] renderers, TrackSelectionArray trackSelectionArray) {
|
||||
int targetBufferSize = 0;
|
||||
for (int i = 0; i < renderers.length; i++) {
|
||||
|
|
@ -430,7 +436,10 @@ public class DefaultLoadControl implements LoadControl {
|
|||
}
|
||||
|
||||
private void reset(boolean resetAllocator) {
|
||||
targetBufferSize = 0;
|
||||
targetBufferBytes =
|
||||
targetBufferBytesOverwrite == C.LENGTH_UNSET
|
||||
? DEFAULT_MUXED_BUFFER_SIZE
|
||||
: targetBufferBytesOverwrite;
|
||||
isBuffering = false;
|
||||
if (resetAllocator) {
|
||||
allocator.reset();
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ public class DefaultLoadControlTest {
|
|||
@Test
|
||||
public void testShouldContinueLoading_untilMaxBufferExceeded() {
|
||||
createDefaultLoadControl();
|
||||
|
||||
assertThat(loadControl.shouldContinueLoading(/* bufferedDurationUs= */ 0, SPEED)).isTrue();
|
||||
assertThat(loadControl.shouldContinueLoading(MIN_BUFFER_US, SPEED)).isTrue();
|
||||
assertThat(loadControl.shouldContinueLoading(MAX_BUFFER_US - 1, SPEED)).isTrue();
|
||||
|
|
@ -56,11 +57,27 @@ public class DefaultLoadControlTest {
|
|||
public void testShouldNotContinueLoadingOnceBufferingStopped_untilBelowMinBuffer() {
|
||||
createDefaultLoadControl();
|
||||
assertThat(loadControl.shouldContinueLoading(MAX_BUFFER_US, SPEED)).isFalse();
|
||||
|
||||
assertThat(loadControl.shouldContinueLoading(MAX_BUFFER_US - 1, SPEED)).isFalse();
|
||||
assertThat(loadControl.shouldContinueLoading(MIN_BUFFER_US, SPEED)).isFalse();
|
||||
assertThat(loadControl.shouldContinueLoading(MIN_BUFFER_US - 1, SPEED)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void
|
||||
testContinueLoadingOnceBufferingStopped_andBufferAlmostEmpty_evenIfMinBufferNotReached() {
|
||||
builder.setBufferDurationsMs(
|
||||
/* minBufferMs= */ 0,
|
||||
/* maxBufferMs= */ (int) C.usToMs(MAX_BUFFER_US),
|
||||
/* bufferForPlaybackMs= */ 0,
|
||||
/* bufferForPlaybackAfterRebufferMs= */ 0);
|
||||
createDefaultLoadControl();
|
||||
assertThat(loadControl.shouldContinueLoading(MAX_BUFFER_US, SPEED)).isFalse();
|
||||
|
||||
assertThat(loadControl.shouldContinueLoading(5 * C.MICROS_PER_SECOND, SPEED)).isFalse();
|
||||
assertThat(loadControl.shouldContinueLoading(500L, SPEED)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShouldContinueLoadingWithTargetBufferBytesReached_untilMinBufferReached() {
|
||||
createDefaultLoadControl();
|
||||
|
|
@ -81,6 +98,7 @@ public class DefaultLoadControlTest {
|
|||
makeSureTargetBufferBytesReached();
|
||||
|
||||
assertThat(loadControl.shouldContinueLoading(/* bufferedDurationUs= */ 0, SPEED)).isFalse();
|
||||
assertThat(loadControl.shouldContinueLoading(MIN_BUFFER_US - 1, SPEED)).isFalse();
|
||||
assertThat(loadControl.shouldContinueLoading(MIN_BUFFER_US, SPEED)).isFalse();
|
||||
assertThat(loadControl.shouldContinueLoading(MAX_BUFFER_US, SPEED)).isFalse();
|
||||
}
|
||||
|
|
@ -91,7 +109,6 @@ public class DefaultLoadControlTest {
|
|||
|
||||
// At normal playback speed, we stop buffering when the buffer reaches the minimum.
|
||||
assertThat(loadControl.shouldContinueLoading(MIN_BUFFER_US, SPEED)).isFalse();
|
||||
|
||||
// At double playback speed, we continue loading.
|
||||
assertThat(loadControl.shouldContinueLoading(MIN_BUFFER_US, /* playbackSpeed= */ 2f)).isTrue();
|
||||
}
|
||||
|
|
@ -107,6 +124,7 @@ public class DefaultLoadControlTest {
|
|||
@Test
|
||||
public void testStartsPlayback_whenMinBufferSizeReached() {
|
||||
createDefaultLoadControl();
|
||||
|
||||
assertThat(loadControl.shouldStartPlayback(MIN_BUFFER_US, SPEED, /* rebuffering= */ false))
|
||||
.isTrue();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue