mirror of
https://github.com/androidx/media.git
synced 2025-05-07 15:40:37 +08:00
Increase target live offset when rebuffering.
Issue: #4904 PiperOrigin-RevId: 340654178
This commit is contained in:
parent
2416d99857
commit
effbc22a62
@ -33,6 +33,10 @@ import com.google.android.exoplayer2.util.Util;
|
|||||||
* fallback values set with {@link Builder#setFallbackMinPlaybackSpeed(float)} and {@link
|
* fallback values set with {@link Builder#setFallbackMinPlaybackSpeed(float)} and {@link
|
||||||
* Builder#setFallbackMaxPlaybackSpeed(float)} or the {@link #DEFAULT_FALLBACK_MIN_PLAYBACK_SPEED
|
* Builder#setFallbackMaxPlaybackSpeed(float)} or the {@link #DEFAULT_FALLBACK_MIN_PLAYBACK_SPEED
|
||||||
* minimum} and {@link #DEFAULT_FALLBACK_MAX_PLAYBACK_SPEED maximum} fallback default values.
|
* minimum} and {@link #DEFAULT_FALLBACK_MAX_PLAYBACK_SPEED maximum} fallback default values.
|
||||||
|
*
|
||||||
|
* <p>When the player rebuffers, the target live offset {@link
|
||||||
|
* Builder#setTargetLiveOffsetIncrementOnRebufferMs(long) is increased} to adjust to the reduced
|
||||||
|
* network capabilities.
|
||||||
*/
|
*/
|
||||||
public final class DefaultLivePlaybackSpeedControl implements LivePlaybackSpeedControl {
|
public final class DefaultLivePlaybackSpeedControl implements LivePlaybackSpeedControl {
|
||||||
|
|
||||||
@ -60,6 +64,12 @@ public final class DefaultLivePlaybackSpeedControl implements LivePlaybackSpeedC
|
|||||||
*/
|
*/
|
||||||
public static final float DEFAULT_PROPORTIONAL_CONTROL_FACTOR = 0.05f;
|
public static final float DEFAULT_PROPORTIONAL_CONTROL_FACTOR = 0.05f;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default increment applied to the target live offset each time the player is rebuffering, in
|
||||||
|
* milliseconds
|
||||||
|
*/
|
||||||
|
public static final long DEFAULT_TARGET_LIVE_OFFSET_INCREMENT_ON_REBUFFER_MS = 500;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The maximum difference between the current live offset and the target live offset for which
|
* The maximum difference between the current live offset and the target live offset for which
|
||||||
* unit speed (1.0f) is used.
|
* unit speed (1.0f) is used.
|
||||||
@ -73,6 +83,7 @@ public final class DefaultLivePlaybackSpeedControl implements LivePlaybackSpeedC
|
|||||||
private float fallbackMaxPlaybackSpeed;
|
private float fallbackMaxPlaybackSpeed;
|
||||||
private long minUpdateIntervalMs;
|
private long minUpdateIntervalMs;
|
||||||
private float proportionalControlFactorUs;
|
private float proportionalControlFactorUs;
|
||||||
|
private long targetLiveOffsetIncrementOnRebufferUs;
|
||||||
|
|
||||||
/** Creates a builder. */
|
/** Creates a builder. */
|
||||||
public Builder() {
|
public Builder() {
|
||||||
@ -80,6 +91,8 @@ public final class DefaultLivePlaybackSpeedControl implements LivePlaybackSpeedC
|
|||||||
fallbackMaxPlaybackSpeed = DEFAULT_FALLBACK_MAX_PLAYBACK_SPEED;
|
fallbackMaxPlaybackSpeed = DEFAULT_FALLBACK_MAX_PLAYBACK_SPEED;
|
||||||
minUpdateIntervalMs = DEFAULT_MIN_UPDATE_INTERVAL_MS;
|
minUpdateIntervalMs = DEFAULT_MIN_UPDATE_INTERVAL_MS;
|
||||||
proportionalControlFactorUs = DEFAULT_PROPORTIONAL_CONTROL_FACTOR / C.MICROS_PER_SECOND;
|
proportionalControlFactorUs = DEFAULT_PROPORTIONAL_CONTROL_FACTOR / C.MICROS_PER_SECOND;
|
||||||
|
targetLiveOffsetIncrementOnRebufferUs =
|
||||||
|
C.msToUs(DEFAULT_TARGET_LIVE_OFFSET_INCREMENT_ON_REBUFFER_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -145,13 +158,29 @@ public final class DefaultLivePlaybackSpeedControl implements LivePlaybackSpeedC
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the increment applied to the target live offset each time the player is rebuffering, in
|
||||||
|
* milliseconds.
|
||||||
|
*
|
||||||
|
* @param targetLiveOffsetIncrementOnRebufferMs The increment applied to the target live offset
|
||||||
|
* when the player is rebuffering, in milliseconds
|
||||||
|
* @return This builder, for convenience.
|
||||||
|
*/
|
||||||
|
public Builder setTargetLiveOffsetIncrementOnRebufferMs(
|
||||||
|
long targetLiveOffsetIncrementOnRebufferMs) {
|
||||||
|
Assertions.checkArgument(targetLiveOffsetIncrementOnRebufferMs >= 0);
|
||||||
|
this.targetLiveOffsetIncrementOnRebufferUs = C.msToUs(targetLiveOffsetIncrementOnRebufferMs);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/** Builds an instance. */
|
/** Builds an instance. */
|
||||||
public DefaultLivePlaybackSpeedControl build() {
|
public DefaultLivePlaybackSpeedControl build() {
|
||||||
return new DefaultLivePlaybackSpeedControl(
|
return new DefaultLivePlaybackSpeedControl(
|
||||||
fallbackMinPlaybackSpeed,
|
fallbackMinPlaybackSpeed,
|
||||||
fallbackMaxPlaybackSpeed,
|
fallbackMaxPlaybackSpeed,
|
||||||
minUpdateIntervalMs,
|
minUpdateIntervalMs,
|
||||||
proportionalControlFactorUs);
|
proportionalControlFactorUs,
|
||||||
|
targetLiveOffsetIncrementOnRebufferUs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,9 +188,11 @@ public final class DefaultLivePlaybackSpeedControl implements LivePlaybackSpeedC
|
|||||||
private final float fallbackMaxPlaybackSpeed;
|
private final float fallbackMaxPlaybackSpeed;
|
||||||
private final long minUpdateIntervalMs;
|
private final long minUpdateIntervalMs;
|
||||||
private final float proportionalControlFactor;
|
private final float proportionalControlFactor;
|
||||||
|
private final long targetLiveOffsetRebufferDeltaUs;
|
||||||
|
|
||||||
private long mediaConfigurationTargetLiveOffsetUs;
|
private long mediaConfigurationTargetLiveOffsetUs;
|
||||||
private long targetLiveOffsetOverrideUs;
|
private long targetLiveOffsetOverrideUs;
|
||||||
|
private long idealTargetLiveOffsetUs;
|
||||||
private long minTargetLiveOffsetUs;
|
private long minTargetLiveOffsetUs;
|
||||||
private long maxTargetLiveOffsetUs;
|
private long maxTargetLiveOffsetUs;
|
||||||
private long currentTargetLiveOffsetUs;
|
private long currentTargetLiveOffsetUs;
|
||||||
@ -175,11 +206,13 @@ public final class DefaultLivePlaybackSpeedControl implements LivePlaybackSpeedC
|
|||||||
float fallbackMinPlaybackSpeed,
|
float fallbackMinPlaybackSpeed,
|
||||||
float fallbackMaxPlaybackSpeed,
|
float fallbackMaxPlaybackSpeed,
|
||||||
long minUpdateIntervalMs,
|
long minUpdateIntervalMs,
|
||||||
float proportionalControlFactor) {
|
float proportionalControlFactor,
|
||||||
|
long targetLiveOffsetRebufferDeltaUs) {
|
||||||
this.fallbackMinPlaybackSpeed = fallbackMinPlaybackSpeed;
|
this.fallbackMinPlaybackSpeed = fallbackMinPlaybackSpeed;
|
||||||
this.fallbackMaxPlaybackSpeed = fallbackMaxPlaybackSpeed;
|
this.fallbackMaxPlaybackSpeed = fallbackMaxPlaybackSpeed;
|
||||||
this.minUpdateIntervalMs = minUpdateIntervalMs;
|
this.minUpdateIntervalMs = minUpdateIntervalMs;
|
||||||
this.proportionalControlFactor = proportionalControlFactor;
|
this.proportionalControlFactor = proportionalControlFactor;
|
||||||
|
this.targetLiveOffsetRebufferDeltaUs = targetLiveOffsetRebufferDeltaUs;
|
||||||
mediaConfigurationTargetLiveOffsetUs = C.TIME_UNSET;
|
mediaConfigurationTargetLiveOffsetUs = C.TIME_UNSET;
|
||||||
targetLiveOffsetOverrideUs = C.TIME_UNSET;
|
targetLiveOffsetOverrideUs = C.TIME_UNSET;
|
||||||
minTargetLiveOffsetUs = C.TIME_UNSET;
|
minTargetLiveOffsetUs = C.TIME_UNSET;
|
||||||
@ -188,6 +221,7 @@ public final class DefaultLivePlaybackSpeedControl implements LivePlaybackSpeedC
|
|||||||
maxPlaybackSpeed = fallbackMaxPlaybackSpeed;
|
maxPlaybackSpeed = fallbackMaxPlaybackSpeed;
|
||||||
adjustedPlaybackSpeed = 1.0f;
|
adjustedPlaybackSpeed = 1.0f;
|
||||||
lastPlaybackSpeedUpdateMs = C.TIME_UNSET;
|
lastPlaybackSpeedUpdateMs = C.TIME_UNSET;
|
||||||
|
idealTargetLiveOffsetUs = C.TIME_UNSET;
|
||||||
currentTargetLiveOffsetUs = C.TIME_UNSET;
|
currentTargetLiveOffsetUs = C.TIME_UNSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,6 +247,19 @@ public final class DefaultLivePlaybackSpeedControl implements LivePlaybackSpeedC
|
|||||||
maybeResetTargetLiveOffsetUs();
|
maybeResetTargetLiveOffsetUs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifyRebuffer() {
|
||||||
|
if (currentTargetLiveOffsetUs == C.TIME_UNSET) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
currentTargetLiveOffsetUs += targetLiveOffsetRebufferDeltaUs;
|
||||||
|
if (maxTargetLiveOffsetUs != C.TIME_UNSET
|
||||||
|
&& currentTargetLiveOffsetUs > maxTargetLiveOffsetUs) {
|
||||||
|
currentTargetLiveOffsetUs = maxTargetLiveOffsetUs;
|
||||||
|
}
|
||||||
|
lastPlaybackSpeedUpdateMs = C.TIME_UNSET;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getAdjustedPlaybackSpeed(long liveOffsetUs) {
|
public float getAdjustedPlaybackSpeed(long liveOffsetUs) {
|
||||||
if (mediaConfigurationTargetLiveOffsetUs == C.TIME_UNSET) {
|
if (mediaConfigurationTargetLiveOffsetUs == C.TIME_UNSET) {
|
||||||
@ -254,9 +301,10 @@ public final class DefaultLivePlaybackSpeedControl implements LivePlaybackSpeedC
|
|||||||
idealOffsetUs = maxTargetLiveOffsetUs;
|
idealOffsetUs = maxTargetLiveOffsetUs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (currentTargetLiveOffsetUs == idealOffsetUs) {
|
if (idealTargetLiveOffsetUs == idealOffsetUs) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
idealTargetLiveOffsetUs = idealOffsetUs;
|
||||||
currentTargetLiveOffsetUs = idealOffsetUs;
|
currentTargetLiveOffsetUs = idealOffsetUs;
|
||||||
lastPlaybackSpeedUpdateMs = C.TIME_UNSET;
|
lastPlaybackSpeedUpdateMs = C.TIME_UNSET;
|
||||||
}
|
}
|
||||||
|
@ -189,7 +189,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
private boolean released;
|
private boolean released;
|
||||||
private boolean pauseAtEndOfWindow;
|
private boolean pauseAtEndOfWindow;
|
||||||
private boolean pendingPauseAtEndOfPeriod;
|
private boolean pendingPauseAtEndOfPeriod;
|
||||||
private boolean rebuffering;
|
private boolean isRebuffering;
|
||||||
private boolean shouldContinueLoading;
|
private boolean shouldContinueLoading;
|
||||||
@Player.RepeatMode private int repeatMode;
|
@Player.RepeatMode private int repeatMode;
|
||||||
private boolean shuffleModeEnabled;
|
private boolean shuffleModeEnabled;
|
||||||
@ -733,7 +733,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
playbackInfoUpdate.incrementPendingOperationAcks(operationAck ? 1 : 0);
|
playbackInfoUpdate.incrementPendingOperationAcks(operationAck ? 1 : 0);
|
||||||
playbackInfoUpdate.setPlayWhenReadyChangeReason(reason);
|
playbackInfoUpdate.setPlayWhenReadyChangeReason(reason);
|
||||||
playbackInfo = playbackInfo.copyWithPlayWhenReady(playWhenReady, playbackSuppressionReason);
|
playbackInfo = playbackInfo.copyWithPlayWhenReady(playWhenReady, playbackSuppressionReason);
|
||||||
rebuffering = false;
|
isRebuffering = false;
|
||||||
if (!shouldPlayWhenReady()) {
|
if (!shouldPlayWhenReady()) {
|
||||||
stopRenderers();
|
stopRenderers();
|
||||||
updatePlaybackPositions();
|
updatePlaybackPositions();
|
||||||
@ -811,7 +811,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void startRenderers() throws ExoPlaybackException {
|
private void startRenderers() throws ExoPlaybackException {
|
||||||
rebuffering = false;
|
isRebuffering = false;
|
||||||
mediaClock.start();
|
mediaClock.start();
|
||||||
for (Renderer renderer : renderers) {
|
for (Renderer renderer : renderers) {
|
||||||
if (isRendererEnabled(renderer)) {
|
if (isRendererEnabled(renderer)) {
|
||||||
@ -868,6 +868,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
|
|
||||||
// Adjust live playback speed to new position.
|
// Adjust live playback speed to new position.
|
||||||
if (playbackInfo.playWhenReady
|
if (playbackInfo.playWhenReady
|
||||||
|
&& playbackInfo.playbackState == Player.STATE_READY
|
||||||
&& isCurrentPeriodInMovingLiveWindow()
|
&& isCurrentPeriodInMovingLiveWindow()
|
||||||
&& playbackInfo.playbackParameters.speed == 1f) {
|
&& playbackInfo.playbackParameters.speed == 1f) {
|
||||||
float adjustedSpeed =
|
float adjustedSpeed =
|
||||||
@ -960,8 +961,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
}
|
}
|
||||||
} else if (playbackInfo.playbackState == Player.STATE_READY
|
} else if (playbackInfo.playbackState == Player.STATE_READY
|
||||||
&& !(enabledRendererCount == 0 ? isTimelineReady() : renderersAllowPlayback)) {
|
&& !(enabledRendererCount == 0 ? isTimelineReady() : renderersAllowPlayback)) {
|
||||||
rebuffering = shouldPlayWhenReady();
|
isRebuffering = shouldPlayWhenReady();
|
||||||
setState(Player.STATE_BUFFERING);
|
setState(Player.STATE_BUFFERING);
|
||||||
|
livePlaybackSpeedControl.notifyRebuffer();
|
||||||
stopRenderers();
|
stopRenderers();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1168,7 +1170,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
boolean forceBufferingState)
|
boolean forceBufferingState)
|
||||||
throws ExoPlaybackException {
|
throws ExoPlaybackException {
|
||||||
stopRenderers();
|
stopRenderers();
|
||||||
rebuffering = false;
|
isRebuffering = false;
|
||||||
if (forceBufferingState || playbackInfo.playbackState == Player.STATE_READY) {
|
if (forceBufferingState || playbackInfo.playbackState == Player.STATE_READY) {
|
||||||
setState(Player.STATE_BUFFERING);
|
setState(Player.STATE_BUFFERING);
|
||||||
}
|
}
|
||||||
@ -1311,7 +1313,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
boolean releaseMediaSourceList,
|
boolean releaseMediaSourceList,
|
||||||
boolean resetError) {
|
boolean resetError) {
|
||||||
handler.removeMessages(MSG_DO_SOME_WORK);
|
handler.removeMessages(MSG_DO_SOME_WORK);
|
||||||
rebuffering = false;
|
isRebuffering = false;
|
||||||
mediaClock.stop();
|
mediaClock.stop();
|
||||||
rendererPositionUs = 0;
|
rendererPositionUs = 0;
|
||||||
for (Renderer renderer : renderers) {
|
for (Renderer renderer : renderers) {
|
||||||
@ -1701,7 +1703,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
|| loadControl.shouldStartPlayback(
|
|| loadControl.shouldStartPlayback(
|
||||||
getTotalBufferedDurationUs(),
|
getTotalBufferedDurationUs(),
|
||||||
mediaClock.getPlaybackParameters().speed,
|
mediaClock.getPlaybackParameters().speed,
|
||||||
rebuffering,
|
isRebuffering,
|
||||||
targetLiveOffsetUs);
|
targetLiveOffsetUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,6 +40,14 @@ public interface LivePlaybackSpeedControl {
|
|||||||
*/
|
*/
|
||||||
void setTargetLiveOffsetOverrideUs(long liveOffsetUs);
|
void setTargetLiveOffsetOverrideUs(long liveOffsetUs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies the live playback speed control that a rebuffer occurred.
|
||||||
|
*
|
||||||
|
* <p>A rebuffer is defined to be caused by buffer depletion rather than a user action. Hence this
|
||||||
|
* method is not called during initial or when buffering as a result of a seek operation.
|
||||||
|
*/
|
||||||
|
void notifyRebuffer();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the adjusted playback speed in order get closer towards the {@link
|
* Returns the adjusted playback speed in order get closer towards the {@link
|
||||||
* #getTargetLiveOffsetUs() target live offset}.
|
* #getTargetLiveOffsetUs() target live offset}.
|
||||||
|
@ -19,7 +19,10 @@ import static com.google.common.truth.Truth.assertThat;
|
|||||||
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
import com.google.android.exoplayer2.MediaItem.LiveConfiguration;
|
import com.google.android.exoplayer2.MediaItem.LiveConfiguration;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.robolectric.shadows.ShadowSystemClock;
|
import org.robolectric.shadows.ShadowSystemClock;
|
||||||
@ -37,7 +40,7 @@ public class DefaultLivePlaybackSpeedControlTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getTargetLiveOffsetUs_afterSetLiveConfiguration_usesMediaLiveOffset() {
|
public void getTargetLiveOffsetUs_afterSetLiveConfiguration_returnsMediaLiveOffset() {
|
||||||
DefaultLivePlaybackSpeedControl defaultLivePlaybackSpeedControl =
|
DefaultLivePlaybackSpeedControl defaultLivePlaybackSpeedControl =
|
||||||
new DefaultLivePlaybackSpeedControl.Builder().build();
|
new DefaultLivePlaybackSpeedControl.Builder().build();
|
||||||
defaultLivePlaybackSpeedControl.setLiveConfiguration(
|
defaultLivePlaybackSpeedControl.setLiveConfiguration(
|
||||||
@ -53,7 +56,7 @@ public class DefaultLivePlaybackSpeedControlTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void
|
public void
|
||||||
getTargetLiveOffsetUs_afterSetLiveConfigurationWithTargetGreaterThanMax_usesMaxLiveOffset() {
|
getTargetLiveOffsetUs_afterSetLiveConfigurationWithTargetGreaterThanMax_returnsMaxLiveOffset() {
|
||||||
DefaultLivePlaybackSpeedControl defaultLivePlaybackSpeedControl =
|
DefaultLivePlaybackSpeedControl defaultLivePlaybackSpeedControl =
|
||||||
new DefaultLivePlaybackSpeedControl.Builder().build();
|
new DefaultLivePlaybackSpeedControl.Builder().build();
|
||||||
defaultLivePlaybackSpeedControl.setLiveConfiguration(
|
defaultLivePlaybackSpeedControl.setLiveConfiguration(
|
||||||
@ -69,7 +72,7 @@ public class DefaultLivePlaybackSpeedControlTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void
|
public void
|
||||||
getTargetLiveOffsetUs_afterSetLiveConfigurationWithTargetLessThanMin_usesMinLiveOffset() {
|
getTargetLiveOffsetUs_afterSetLiveConfigurationWithTargetLessThanMin_returnsMinLiveOffset() {
|
||||||
DefaultLivePlaybackSpeedControl defaultLivePlaybackSpeedControl =
|
DefaultLivePlaybackSpeedControl defaultLivePlaybackSpeedControl =
|
||||||
new DefaultLivePlaybackSpeedControl.Builder().build();
|
new DefaultLivePlaybackSpeedControl.Builder().build();
|
||||||
defaultLivePlaybackSpeedControl.setLiveConfiguration(
|
defaultLivePlaybackSpeedControl.setLiveConfiguration(
|
||||||
@ -84,7 +87,7 @@ public class DefaultLivePlaybackSpeedControlTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getTargetLiveOffsetUs_withSetTargetLiveOffsetOverrideUs_usesOverride() {
|
public void getTargetLiveOffsetUs_afterSetTargetLiveOffsetOverrideUs_returnsOverride() {
|
||||||
DefaultLivePlaybackSpeedControl defaultLivePlaybackSpeedControl =
|
DefaultLivePlaybackSpeedControl defaultLivePlaybackSpeedControl =
|
||||||
new DefaultLivePlaybackSpeedControl.Builder().build();
|
new DefaultLivePlaybackSpeedControl.Builder().build();
|
||||||
|
|
||||||
@ -104,7 +107,7 @@ public class DefaultLivePlaybackSpeedControlTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void
|
public void
|
||||||
getTargetLiveOffsetUs_withSetTargetLiveOffsetOverrideUsGreaterThanMax_usesMaxLiveOffset() {
|
getTargetLiveOffsetUs_afterSetTargetLiveOffsetOverrideUsGreaterThanMax_returnsMaxLiveOffset() {
|
||||||
DefaultLivePlaybackSpeedControl defaultLivePlaybackSpeedControl =
|
DefaultLivePlaybackSpeedControl defaultLivePlaybackSpeedControl =
|
||||||
new DefaultLivePlaybackSpeedControl.Builder().build();
|
new DefaultLivePlaybackSpeedControl.Builder().build();
|
||||||
|
|
||||||
@ -124,7 +127,7 @@ public class DefaultLivePlaybackSpeedControlTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void
|
public void
|
||||||
getTargetLiveOffsetUs_withSetTargetLiveOffsetOverrideUsLessThanMin_usesMinLiveOffset() {
|
getTargetLiveOffsetUs_afterSetTargetLiveOffsetOverrideUsLessThanMin_returnsMinLiveOffset() {
|
||||||
DefaultLivePlaybackSpeedControl defaultLivePlaybackSpeedControl =
|
DefaultLivePlaybackSpeedControl defaultLivePlaybackSpeedControl =
|
||||||
new DefaultLivePlaybackSpeedControl.Builder().build();
|
new DefaultLivePlaybackSpeedControl.Builder().build();
|
||||||
|
|
||||||
@ -156,7 +159,7 @@ public class DefaultLivePlaybackSpeedControlTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void
|
public void
|
||||||
getTargetLiveOffsetUs_afterSetTargetLiveOffsetOverrideWithTimeUnset_usesMediaLiveOffset() {
|
getTargetLiveOffsetUs_afterSetTargetLiveOffsetOverrideWithTimeUnset_returnsMediaLiveOffset() {
|
||||||
DefaultLivePlaybackSpeedControl defaultLivePlaybackSpeedControl =
|
DefaultLivePlaybackSpeedControl defaultLivePlaybackSpeedControl =
|
||||||
new DefaultLivePlaybackSpeedControl.Builder().build();
|
new DefaultLivePlaybackSpeedControl.Builder().build();
|
||||||
defaultLivePlaybackSpeedControl.setTargetLiveOffsetOverrideUs(123_456_789);
|
defaultLivePlaybackSpeedControl.setTargetLiveOffsetOverrideUs(123_456_789);
|
||||||
@ -174,6 +177,153 @@ public class DefaultLivePlaybackSpeedControlTest {
|
|||||||
assertThat(targetLiveOffsetUs).isEqualTo(42_000);
|
assertThat(targetLiveOffsetUs).isEqualTo(42_000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getTargetLiveOffsetUs_afterNotifyRebuffer_returnsIncreasedTargetOffset() {
|
||||||
|
DefaultLivePlaybackSpeedControl defaultLivePlaybackSpeedControl =
|
||||||
|
new DefaultLivePlaybackSpeedControl.Builder()
|
||||||
|
.setTargetLiveOffsetIncrementOnRebufferMs(3)
|
||||||
|
.build();
|
||||||
|
defaultLivePlaybackSpeedControl.setLiveConfiguration(
|
||||||
|
new LiveConfiguration(
|
||||||
|
/* targetLiveOffsetMs= */ 42,
|
||||||
|
/* minLiveOffsetMs= */ 5,
|
||||||
|
/* maxLiveOffsetMs= */ 400,
|
||||||
|
/* minPlaybackSpeed= */ 1f,
|
||||||
|
/* maxPlaybackSpeed= */ 1f));
|
||||||
|
|
||||||
|
long targetLiveOffsetBeforeUs = defaultLivePlaybackSpeedControl.getTargetLiveOffsetUs();
|
||||||
|
defaultLivePlaybackSpeedControl.notifyRebuffer();
|
||||||
|
long targetLiveOffsetAfterUs = defaultLivePlaybackSpeedControl.getTargetLiveOffsetUs();
|
||||||
|
|
||||||
|
assertThat(targetLiveOffsetAfterUs).isGreaterThan(targetLiveOffsetBeforeUs);
|
||||||
|
assertThat(targetLiveOffsetAfterUs - targetLiveOffsetBeforeUs).isEqualTo(3_000);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getTargetLiveOffsetUs_afterRepeatedNotifyRebuffer_returnsMaxLiveOffset() {
|
||||||
|
DefaultLivePlaybackSpeedControl defaultLivePlaybackSpeedControl =
|
||||||
|
new DefaultLivePlaybackSpeedControl.Builder()
|
||||||
|
.setTargetLiveOffsetIncrementOnRebufferMs(3)
|
||||||
|
.build();
|
||||||
|
defaultLivePlaybackSpeedControl.setLiveConfiguration(
|
||||||
|
new LiveConfiguration(
|
||||||
|
/* targetLiveOffsetMs= */ 42,
|
||||||
|
/* minLiveOffsetMs= */ 5,
|
||||||
|
/* maxLiveOffsetMs= */ 400,
|
||||||
|
/* minPlaybackSpeed= */ 1f,
|
||||||
|
/* maxPlaybackSpeed= */ 1f));
|
||||||
|
|
||||||
|
List<Long> targetOffsetsUs = new ArrayList<>();
|
||||||
|
for (int i = 0; i < 500; i++) {
|
||||||
|
targetOffsetsUs.add(defaultLivePlaybackSpeedControl.getTargetLiveOffsetUs());
|
||||||
|
defaultLivePlaybackSpeedControl.notifyRebuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(targetOffsetsUs).isInOrder();
|
||||||
|
assertThat(Iterables.getLast(targetOffsetsUs)).isEqualTo(400_000);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void
|
||||||
|
getTargetLiveOffsetUs_afterNotifyRebufferWithIncrementOfZero_returnsOriginalTargetOffset() {
|
||||||
|
DefaultLivePlaybackSpeedControl defaultLivePlaybackSpeedControl =
|
||||||
|
new DefaultLivePlaybackSpeedControl.Builder()
|
||||||
|
.setTargetLiveOffsetIncrementOnRebufferMs(0)
|
||||||
|
.build();
|
||||||
|
defaultLivePlaybackSpeedControl.setLiveConfiguration(
|
||||||
|
new LiveConfiguration(
|
||||||
|
/* targetLiveOffsetMs= */ 42,
|
||||||
|
/* minLiveOffsetMs= */ 5,
|
||||||
|
/* maxLiveOffsetMs= */ 400,
|
||||||
|
/* minPlaybackSpeed= */ 1f,
|
||||||
|
/* maxPlaybackSpeed= */ 1f));
|
||||||
|
|
||||||
|
defaultLivePlaybackSpeedControl.notifyRebuffer();
|
||||||
|
long targetLiveOffsetUs = defaultLivePlaybackSpeedControl.getTargetLiveOffsetUs();
|
||||||
|
|
||||||
|
assertThat(targetLiveOffsetUs).isEqualTo(42_000);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void
|
||||||
|
getTargetLiveOffsetUs_afterNotifyRebufferAndSetTargetLiveOffsetOverrideUs_returnsOverride() {
|
||||||
|
DefaultLivePlaybackSpeedControl defaultLivePlaybackSpeedControl =
|
||||||
|
new DefaultLivePlaybackSpeedControl.Builder()
|
||||||
|
.setTargetLiveOffsetIncrementOnRebufferMs(3)
|
||||||
|
.build();
|
||||||
|
defaultLivePlaybackSpeedControl.setLiveConfiguration(
|
||||||
|
new LiveConfiguration(
|
||||||
|
/* targetLiveOffsetMs= */ 42,
|
||||||
|
/* minLiveOffsetMs= */ 5,
|
||||||
|
/* maxLiveOffsetMs= */ 400,
|
||||||
|
/* minPlaybackSpeed= */ 1f,
|
||||||
|
/* maxPlaybackSpeed= */ 1f));
|
||||||
|
|
||||||
|
defaultLivePlaybackSpeedControl.notifyRebuffer();
|
||||||
|
defaultLivePlaybackSpeedControl.setTargetLiveOffsetOverrideUs(321_000);
|
||||||
|
long targetLiveOffsetUs = defaultLivePlaybackSpeedControl.getTargetLiveOffsetUs();
|
||||||
|
|
||||||
|
assertThat(targetLiveOffsetUs).isEqualTo(321_000);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void
|
||||||
|
getTargetLiveOffsetUs_afterNotifyRebufferAndSetLiveConfigurationWithSameOffset_returnsIncreasedTargetOffset() {
|
||||||
|
DefaultLivePlaybackSpeedControl defaultLivePlaybackSpeedControl =
|
||||||
|
new DefaultLivePlaybackSpeedControl.Builder()
|
||||||
|
.setTargetLiveOffsetIncrementOnRebufferMs(3)
|
||||||
|
.build();
|
||||||
|
defaultLivePlaybackSpeedControl.setLiveConfiguration(
|
||||||
|
new LiveConfiguration(
|
||||||
|
/* targetLiveOffsetMs= */ 42,
|
||||||
|
/* minLiveOffsetMs= */ 5,
|
||||||
|
/* maxLiveOffsetMs= */ 400,
|
||||||
|
/* minPlaybackSpeed= */ 1f,
|
||||||
|
/* maxPlaybackSpeed= */ 1f));
|
||||||
|
|
||||||
|
long targetLiveOffsetBeforeUs = defaultLivePlaybackSpeedControl.getTargetLiveOffsetUs();
|
||||||
|
defaultLivePlaybackSpeedControl.notifyRebuffer();
|
||||||
|
defaultLivePlaybackSpeedControl.setLiveConfiguration(
|
||||||
|
new LiveConfiguration(
|
||||||
|
/* targetLiveOffsetMs= */ 42,
|
||||||
|
/* minLiveOffsetMs= */ 3,
|
||||||
|
/* maxLiveOffsetMs= */ 450,
|
||||||
|
/* minPlaybackSpeed= */ 0.9f,
|
||||||
|
/* maxPlaybackSpeed= */ 1.1f));
|
||||||
|
long targetLiveOffsetAfterUs = defaultLivePlaybackSpeedControl.getTargetLiveOffsetUs();
|
||||||
|
|
||||||
|
assertThat(targetLiveOffsetAfterUs).isGreaterThan(targetLiveOffsetBeforeUs);
|
||||||
|
assertThat(targetLiveOffsetAfterUs - targetLiveOffsetBeforeUs).isEqualTo(3_000);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void
|
||||||
|
getTargetLiveOffsetUs_afterNotifyRebufferAndSetLiveConfigurationWithNewOffset_returnsNewOffset() {
|
||||||
|
DefaultLivePlaybackSpeedControl defaultLivePlaybackSpeedControl =
|
||||||
|
new DefaultLivePlaybackSpeedControl.Builder()
|
||||||
|
.setTargetLiveOffsetIncrementOnRebufferMs(3)
|
||||||
|
.build();
|
||||||
|
defaultLivePlaybackSpeedControl.setLiveConfiguration(
|
||||||
|
new LiveConfiguration(
|
||||||
|
/* targetLiveOffsetMs= */ 42,
|
||||||
|
/* minLiveOffsetMs= */ 5,
|
||||||
|
/* maxLiveOffsetMs= */ 400,
|
||||||
|
/* minPlaybackSpeed= */ 1f,
|
||||||
|
/* maxPlaybackSpeed= */ 1f));
|
||||||
|
|
||||||
|
defaultLivePlaybackSpeedControl.notifyRebuffer();
|
||||||
|
defaultLivePlaybackSpeedControl.setLiveConfiguration(
|
||||||
|
new LiveConfiguration(
|
||||||
|
/* targetLiveOffsetMs= */ 39,
|
||||||
|
/* minLiveOffsetMs= */ 3,
|
||||||
|
/* maxLiveOffsetMs= */ 450,
|
||||||
|
/* minPlaybackSpeed= */ 0.9f,
|
||||||
|
/* maxPlaybackSpeed= */ 1.1f));
|
||||||
|
long targetLiveOffsetUs = defaultLivePlaybackSpeedControl.getTargetLiveOffsetUs();
|
||||||
|
|
||||||
|
assertThat(targetLiveOffsetUs).isEqualTo(39_000);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void adjustPlaybackSpeed_liveOffsetMatchesTargetOffset_returnsUnitSpeed() {
|
public void adjustPlaybackSpeed_liveOffsetMatchesTargetOffset_returnsUnitSpeed() {
|
||||||
DefaultLivePlaybackSpeedControl defaultLivePlaybackSpeedControl =
|
DefaultLivePlaybackSpeedControl defaultLivePlaybackSpeedControl =
|
||||||
@ -367,7 +517,7 @@ public class DefaultLivePlaybackSpeedControlTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void
|
public void
|
||||||
adjustPlaybackSpeed_repeatedCallAfterUpdateLiveConfigurationWithSameOffset_returnsSameAdjustedSpeed() {
|
adjustPlaybackSpeed_repeatedCallAfterSetLiveConfigurationWithSameOffset_returnsSameAdjustedSpeed() {
|
||||||
DefaultLivePlaybackSpeedControl defaultLivePlaybackSpeedControl =
|
DefaultLivePlaybackSpeedControl defaultLivePlaybackSpeedControl =
|
||||||
new DefaultLivePlaybackSpeedControl.Builder().setMinUpdateIntervalMs(123).build();
|
new DefaultLivePlaybackSpeedControl.Builder().setMinUpdateIntervalMs(123).build();
|
||||||
defaultLivePlaybackSpeedControl.setLiveConfiguration(
|
defaultLivePlaybackSpeedControl.setLiveConfiguration(
|
||||||
@ -395,7 +545,7 @@ public class DefaultLivePlaybackSpeedControlTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void
|
public void
|
||||||
adjustPlaybackSpeed_repeatedCallAfterUpdateLiveConfigurationWithNewOffset_updatesSpeedAgain() {
|
adjustPlaybackSpeed_repeatedCallAfterSetLiveConfigurationWithNewOffset_updatesSpeedAgain() {
|
||||||
DefaultLivePlaybackSpeedControl defaultLivePlaybackSpeedControl =
|
DefaultLivePlaybackSpeedControl defaultLivePlaybackSpeedControl =
|
||||||
new DefaultLivePlaybackSpeedControl.Builder().setMinUpdateIntervalMs(123).build();
|
new DefaultLivePlaybackSpeedControl.Builder().setMinUpdateIntervalMs(123).build();
|
||||||
defaultLivePlaybackSpeedControl.setLiveConfiguration(
|
defaultLivePlaybackSpeedControl.setLiveConfiguration(
|
||||||
@ -422,7 +572,8 @@ public class DefaultLivePlaybackSpeedControlTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void adjustPlaybackSpeed_repeatedCallAfterNewTargetLiveOffset_updatesSpeedAgain() {
|
public void
|
||||||
|
adjustPlaybackSpeed_repeatedCallAfterSetTargetLiveOffsetOverrideUs_updatesSpeedAgain() {
|
||||||
DefaultLivePlaybackSpeedControl defaultLivePlaybackSpeedControl =
|
DefaultLivePlaybackSpeedControl defaultLivePlaybackSpeedControl =
|
||||||
new DefaultLivePlaybackSpeedControl.Builder().setMinUpdateIntervalMs(123).build();
|
new DefaultLivePlaybackSpeedControl.Builder().setMinUpdateIntervalMs(123).build();
|
||||||
defaultLivePlaybackSpeedControl.setLiveConfiguration(
|
defaultLivePlaybackSpeedControl.setLiveConfiguration(
|
||||||
@ -441,4 +592,25 @@ public class DefaultLivePlaybackSpeedControlTest {
|
|||||||
|
|
||||||
assertThat(adjustedSpeed1).isNotEqualTo(adjustedSpeed2);
|
assertThat(adjustedSpeed1).isNotEqualTo(adjustedSpeed2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void adjustPlaybackSpeed_repeatedCallAfterNotifyRebuffer_updatesSpeedAgain() {
|
||||||
|
DefaultLivePlaybackSpeedControl defaultLivePlaybackSpeedControl =
|
||||||
|
new DefaultLivePlaybackSpeedControl.Builder().setMinUpdateIntervalMs(123).build();
|
||||||
|
defaultLivePlaybackSpeedControl.setLiveConfiguration(
|
||||||
|
new LiveConfiguration(
|
||||||
|
/* targetLiveOffsetMs= */ 2_000,
|
||||||
|
/* minLiveOffsetMs= */ C.TIME_UNSET,
|
||||||
|
/* maxLiveOffsetMs= */ C.TIME_UNSET,
|
||||||
|
/* minPlaybackSpeed= */ C.RATE_UNSET,
|
||||||
|
/* maxPlaybackSpeed= */ C.RATE_UNSET));
|
||||||
|
|
||||||
|
float adjustedSpeed1 =
|
||||||
|
defaultLivePlaybackSpeedControl.getAdjustedPlaybackSpeed(/* liveOffsetUs= */ 1_500_000);
|
||||||
|
defaultLivePlaybackSpeedControl.notifyRebuffer();
|
||||||
|
float adjustedSpeed2 =
|
||||||
|
defaultLivePlaybackSpeedControl.getAdjustedPlaybackSpeed(/* liveOffsetUs= */ 2_500_000);
|
||||||
|
|
||||||
|
assertThat(adjustedSpeed1).isNotEqualTo(adjustedSpeed2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user