mirror of
https://github.com/androidx/media.git
synced 2025-05-07 15:40:37 +08:00
Fix frame release timing to be aware of playback speed
PiperOrigin-RevId: 342007987
This commit is contained in:
parent
51c8ffbb0e
commit
2693a107cd
@ -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();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user