Fix frame release timing to be aware of playback speed

PiperOrigin-RevId: 342007987
This commit is contained in:
olly 2020-11-12 10:35:31 +00:00 committed by Christos Tsilopoulos
parent 51c8ffbb0e
commit 2693a107cd

View File

@ -133,7 +133,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
private int droppedFrames; private int droppedFrames;
private int consecutiveDroppedFrameCount; private int consecutiveDroppedFrameCount;
private int buffersInCodecCount; private int buffersInCodecCount;
private long lastRenderTimeUs; private long lastRenderRealtimeUs;
private long totalVideoFrameProcessingOffsetUs; private long totalVideoFrameProcessingOffsetUs;
private int videoFrameProcessingOffsetCount; private int videoFrameProcessingOffsetCount;
@ -411,7 +411,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
super.onStarted(); super.onStarted();
droppedFrames = 0; droppedFrames = 0;
droppedFrameAccumulationStartTimeMs = SystemClock.elapsedRealtime(); droppedFrameAccumulationStartTimeMs = SystemClock.elapsedRealtime();
lastRenderTimeUs = SystemClock.elapsedRealtime() * 1000; lastRenderRealtimeUs = SystemClock.elapsedRealtime() * 1000;
totalVideoFrameProcessingOffsetUs = 0; totalVideoFrameProcessingOffsetUs = 0;
videoFrameProcessingOffsetCount = 0; videoFrameProcessingOffsetCount = 0;
updateSurfaceFrameRate(/* isNewSurface= */ false); updateSurfaceFrameRate(/* isNewSurface= */ false);
@ -753,7 +753,20 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
return true; return true;
} }
long earlyUs = bufferPresentationTimeUs - positionUs; // Note: Use of double rather than float is intentional for accuracy in the calculations below.
double playbackSpeed = getPlaybackSpeed();
boolean isStarted = getState() == STATE_STARTED;
long elapsedRealtimeNowUs = SystemClock.elapsedRealtime() * 1000;
// Calculate how early we are. In other words, the realtime duration that needs to elapse whilst
// the renderer is started before the frame should be rendered. A negative value means that
// we're already late.
long earlyUs = (long) ((bufferPresentationTimeUs - positionUs) / playbackSpeed);
if (isStarted) {
// Account for the elapsed time since the start of this iteration of the rendering loop.
earlyUs -= elapsedRealtimeNowUs - elapsedRealtimeUs;
}
if (surface == dummySurface) { if (surface == dummySurface) {
// Skip frames in sync with playback, so we'll be at the right frame if the mode changes. // Skip frames in sync with playback, so we'll be at the right frame if the mode changes.
if (isBufferLate(earlyUs)) { if (isBufferLate(earlyUs)) {
@ -764,9 +777,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
return false; return false;
} }
long elapsedRealtimeNowUs = SystemClock.elapsedRealtime() * 1000; long elapsedSinceLastRenderUs = elapsedRealtimeNowUs - lastRenderRealtimeUs;
long elapsedSinceLastRenderUs = elapsedRealtimeNowUs - lastRenderTimeUs;
boolean isStarted = getState() == STATE_STARTED;
boolean shouldRenderFirstFrame = boolean shouldRenderFirstFrame =
!renderedFirstFrameAfterEnable !renderedFirstFrameAfterEnable
? (isStarted || mayRenderFirstFrameAfterEnableIfNotStarted) ? (isStarted || mayRenderFirstFrameAfterEnableIfNotStarted)
@ -793,11 +804,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
return false; return false;
} }
// Fine-grained adjustment of earlyUs based on the elapsed time since the start of the current
// iteration of the rendering loop.
long elapsedSinceStartOfLoopUs = elapsedRealtimeNowUs - elapsedRealtimeUs;
earlyUs -= elapsedSinceStartOfLoopUs;
// Compute the buffer's desired release time in nanoseconds. // Compute the buffer's desired release time in nanoseconds.
long systemTimeNs = System.nanoTime(); long systemTimeNs = System.nanoTime();
long unadjustedFrameReleaseTimeNs = systemTimeNs + (earlyUs * 1000); long unadjustedFrameReleaseTimeNs = systemTimeNs + (earlyUs * 1000);
@ -1042,7 +1048,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
TraceUtil.beginSection("releaseOutputBuffer"); TraceUtil.beginSection("releaseOutputBuffer");
codec.releaseOutputBuffer(index, true); codec.releaseOutputBuffer(index, true);
TraceUtil.endSection(); TraceUtil.endSection();
lastRenderTimeUs = SystemClock.elapsedRealtime() * 1000; lastRenderRealtimeUs = SystemClock.elapsedRealtime() * 1000;
decoderCounters.renderedOutputBufferCount++; decoderCounters.renderedOutputBufferCount++;
consecutiveDroppedFrameCount = 0; consecutiveDroppedFrameCount = 0;
maybeNotifyRenderedFirstFrame(); maybeNotifyRenderedFirstFrame();
@ -1064,7 +1070,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
TraceUtil.beginSection("releaseOutputBuffer"); TraceUtil.beginSection("releaseOutputBuffer");
codec.releaseOutputBuffer(index, releaseTimeNs); codec.releaseOutputBuffer(index, releaseTimeNs);
TraceUtil.endSection(); TraceUtil.endSection();
lastRenderTimeUs = SystemClock.elapsedRealtime() * 1000; lastRenderRealtimeUs = SystemClock.elapsedRealtime() * 1000;
decoderCounters.renderedOutputBufferCount++; decoderCounters.renderedOutputBufferCount++;
consecutiveDroppedFrameCount = 0; consecutiveDroppedFrameCount = 0;
maybeNotifyRenderedFirstFrame(); maybeNotifyRenderedFirstFrame();