Unconditionally sleep for offload
Unconditionally sleep for offload, if the audio buffer is full. Previously ExoPlayer would not sleep if the expected wake-up was in 2s. This was to prevent underrun if the wake-up was delayed. Experiments have shown that the wakup audio buffer is far more than 2s (around 1min). Additionally, the metric was incorrect because it measured both, AudioTrack + DSP. Finally, this metric was erroneous after a gapless transition, when the head position would reset to 0 and thus the computed delay until next wakeup was too large. PiperOrigin-RevId: 451383701
This commit is contained in:
parent
6b521b2952
commit
74c68b3763
@ -160,15 +160,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
|
|
||||||
private static final int ACTIVE_INTERVAL_MS = 10;
|
private static final int ACTIVE_INTERVAL_MS = 10;
|
||||||
private static final int IDLE_INTERVAL_MS = 1000;
|
private static final int IDLE_INTERVAL_MS = 1000;
|
||||||
/**
|
|
||||||
* Duration under which pausing the main DO_SOME_WORK loop is not expected to yield significant
|
|
||||||
* power saving.
|
|
||||||
*
|
|
||||||
* <p>This value is probably too high, power measurements are needed adjust it, but as renderer
|
|
||||||
* sleep is currently only implemented for audio offload, which uses buffer much bigger than 2s,
|
|
||||||
* this does not matter for now.
|
|
||||||
*/
|
|
||||||
private static final long MIN_RENDERER_SLEEP_DURATION_MS = 2000;
|
|
||||||
/**
|
/**
|
||||||
* Duration for which the player needs to appear stuck before the playback is failed on the
|
* Duration for which the player needs to appear stuck before the playback is failed on the
|
||||||
* assumption that no further progress will be made. To appear stuck, the player's renderers must
|
* assumption that no further progress will be made. To appear stuck, the player's renderers must
|
||||||
@ -2478,11 +2469,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
Renderer.MSG_SET_WAKEUP_LISTENER,
|
Renderer.MSG_SET_WAKEUP_LISTENER,
|
||||||
new Renderer.WakeupListener() {
|
new Renderer.WakeupListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onSleep(long wakeupDeadlineMs) {
|
public void onSleep() {
|
||||||
// Do not sleep if the expected sleep time is not long enough to save significant power.
|
requestForRendererSleep = true;
|
||||||
if (wakeupDeadlineMs >= MIN_RENDERER_SLEEP_DURATION_MS) {
|
|
||||||
requestForRendererSleep = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -62,11 +62,8 @@ public interface Renderer extends PlayerMessage.Target {
|
|||||||
* The renderer no longer needs to render until the next wakeup.
|
* The renderer no longer needs to render until the next wakeup.
|
||||||
*
|
*
|
||||||
* <p>Must be called from the thread ExoPlayer invokes the renderer from.
|
* <p>Must be called from the thread ExoPlayer invokes the renderer from.
|
||||||
*
|
|
||||||
* @param wakeupDeadlineMs Maximum time in milliseconds until {@link #onWakeup()} will be
|
|
||||||
* called.
|
|
||||||
*/
|
*/
|
||||||
void onSleep(long wakeupDeadlineMs);
|
void onSleep();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The renderer needs to render some frames. The client should call {@link #render(long, long)}
|
* The renderer needs to render some frames. The client should call {@link #render(long, long)}
|
||||||
|
@ -104,13 +104,8 @@ public interface AudioSink {
|
|||||||
/** Called when the offload buffer has been partially emptied. */
|
/** Called when the offload buffer has been partially emptied. */
|
||||||
default void onOffloadBufferEmptying() {}
|
default void onOffloadBufferEmptying() {}
|
||||||
|
|
||||||
/**
|
/** Called when the offload buffer has been filled completely. */
|
||||||
* Called when the offload buffer has been filled completely.
|
default void onOffloadBufferFull() {}
|
||||||
*
|
|
||||||
* @param bufferEmptyingDeadlineMs Maximum time in milliseconds until {@link
|
|
||||||
* #onOffloadBufferEmptying()} will be called.
|
|
||||||
*/
|
|
||||||
default void onOffloadBufferFull(long bufferEmptyingDeadlineMs) {}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when {@link AudioSink} has encountered an error.
|
* Called when {@link AudioSink} has encountered an error.
|
||||||
|
@ -386,11 +386,6 @@ import java.lang.reflect.Method;
|
|||||||
return bufferSize - bytesPending;
|
return bufferSize - bytesPending;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the duration of audio that is buffered but unplayed. */
|
|
||||||
public long getPendingBufferDurationMs(long writtenFrames) {
|
|
||||||
return Util.usToMs(framesToDurationUs(writtenFrames - getPlaybackHeadPosition()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns whether the track is in an invalid state and must be recreated. */
|
/** Returns whether the track is in an invalid state and must be recreated. */
|
||||||
public boolean isStalled(long writtenFrames) {
|
public boolean isStalled(long writtenFrames) {
|
||||||
return forceResetWorkaroundTimeMs != C.TIME_UNSET
|
return forceResetWorkaroundTimeMs != C.TIME_UNSET
|
||||||
|
@ -1193,9 +1193,7 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
&& listener != null
|
&& listener != null
|
||||||
&& bytesWritten < bytesRemaining
|
&& bytesWritten < bytesRemaining
|
||||||
&& !isWaitingForOffloadEndOfStreamHandled) {
|
&& !isWaitingForOffloadEndOfStreamHandled) {
|
||||||
long pendingDurationMs =
|
listener.onOffloadBufferFull();
|
||||||
audioTrackPositionTracker.getPendingBufferDurationMs(writtenEncodedFrames);
|
|
||||||
listener.onOffloadBufferFull(pendingDurationMs);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -926,9 +926,9 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onOffloadBufferFull(long bufferEmptyingDeadlineMs) {
|
public void onOffloadBufferFull() {
|
||||||
if (wakeupListener != null) {
|
if (wakeupListener != null) {
|
||||||
wakeupListener.onSleep(bufferEmptyingDeadlineMs);
|
wakeupListener.onSleep();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12144,7 +12144,6 @@ public final class ExoPlayerTest {
|
|||||||
|
|
||||||
/** {@link FakeRenderer} that can sleep and be woken-up. */
|
/** {@link FakeRenderer} that can sleep and be woken-up. */
|
||||||
private static class FakeSleepRenderer extends FakeRenderer {
|
private static class FakeSleepRenderer extends FakeRenderer {
|
||||||
private static final long WAKEUP_DEADLINE_MS = 60 * C.MICROS_PER_SECOND;
|
|
||||||
private final AtomicBoolean sleepOnNextRender;
|
private final AtomicBoolean sleepOnNextRender;
|
||||||
private final AtomicReference<Renderer.WakeupListener> wakeupListenerReceiver;
|
private final AtomicReference<Renderer.WakeupListener> wakeupListenerReceiver;
|
||||||
|
|
||||||
@ -12158,9 +12157,7 @@ public final class ExoPlayerTest {
|
|||||||
wakeupListenerReceiver.get().onWakeup();
|
wakeupListenerReceiver.get().onWakeup();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Call {@link Renderer.WakeupListener#onSleep()} on the next {@link #render(long, long)} */
|
||||||
* Call {@link Renderer.WakeupListener#onSleep(long)} on the next {@link #render(long, long)}
|
|
||||||
*/
|
|
||||||
public FakeSleepRenderer sleepOnNextRender() {
|
public FakeSleepRenderer sleepOnNextRender() {
|
||||||
sleepOnNextRender.set(true);
|
sleepOnNextRender.set(true);
|
||||||
return this;
|
return this;
|
||||||
@ -12180,7 +12177,7 @@ public final class ExoPlayerTest {
|
|||||||
public void render(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackException {
|
public void render(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackException {
|
||||||
super.render(positionUs, elapsedRealtimeUs);
|
super.render(positionUs, elapsedRealtimeUs);
|
||||||
if (sleepOnNextRender.compareAndSet(/* expectedValue= */ true, /* newValue= */ false)) {
|
if (sleepOnNextRender.compareAndSet(/* expectedValue= */ true, /* newValue= */ false)) {
|
||||||
wakeupListenerReceiver.get().onSleep(WAKEUP_DEADLINE_MS);
|
wakeupListenerReceiver.get().onSleep();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user