Commit 54d3df4b by andrewlewis Committed by Oliver Woodman

Drop to keyframe in LibvpxVideoRenderer

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=171517156
parent e8871659
......@@ -109,12 +109,12 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
private DrmSession<ExoMediaCrypto> drmSession;
private DrmSession<ExoMediaCrypto> pendingDrmSession;
@ReinitializationState
private int decoderReinitializationState;
private @ReinitializationState int decoderReinitializationState;
private boolean decoderReceivedBuffers;
private Bitmap bitmap;
private boolean renderedFirstFrame;
private boolean forceRenderFrame;
private long joiningDeadlineMs;
private Surface surface;
private VpxOutputBufferRenderer outputBufferRenderer;
......@@ -129,6 +129,7 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
private long droppedFrameAccumulationStartTimeMs;
private int droppedFrames;
private int consecutiveDroppedFrameCount;
private int buffersInCodecCount;
/**
* @param scaleToFit Whether video frames should be scaled to fit when rendering.
......@@ -257,6 +258,7 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
return false;
}
decoderCounters.skippedOutputBufferCount += outputBuffer.skippedOutputBufferCount;
buffersInCodecCount -= outputBuffer.skippedOutputBufferCount;
}
if (nextOutputBuffer == null) {
......@@ -279,26 +281,42 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
if (outputMode == VpxDecoder.OUTPUT_MODE_NONE) {
// Skip frames in sync with playback, so we'll be at the right frame if the mode changes.
if (isBufferLate(outputBuffer.timeUs - positionUs)) {
forceRenderFrame = false;
skipBuffer();
buffersInCodecCount--;
return true;
}
return false;
}
if (forceRenderFrame) {
forceRenderFrame = false;
renderBuffer();
buffersInCodecCount--;
return true;
}
final long nextOutputBufferTimeUs =
nextOutputBuffer != null && !nextOutputBuffer.isEndOfStream()
? nextOutputBuffer.timeUs : C.TIME_UNSET;
if (shouldDropOutputBuffer(
long earlyUs = outputBuffer.timeUs - positionUs;
if (shouldDropBuffersToKeyframe(earlyUs) && maybeDropBuffersToKeyframe(positionUs)) {
forceRenderFrame = true;
return false;
} else if (shouldDropOutputBuffer(
outputBuffer.timeUs, nextOutputBufferTimeUs, positionUs, joiningDeadlineMs)) {
dropBuffer();
buffersInCodecCount--;
return true;
}
// If we have yet to render a frame to the current output (either initially or immediately
// following a seek), render one irrespective of the state or current position.
if (!renderedFirstFrame
|| (getState() == STATE_STARTED && outputBuffer.timeUs <= positionUs + 30000)) {
|| (getState() == STATE_STARTED && earlyUs <= 30000)) {
renderBuffer();
buffersInCodecCount--;
}
return false;
}
......@@ -307,18 +325,29 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
* Returns whether the current frame should be dropped.
*
* @param outputBufferTimeUs The timestamp of the current output buffer.
* @param nextOutputBufferTimeUs The timestamp of the next output buffer or
* {@link C#TIME_UNSET} if the next output buffer is unavailable.
* @param nextOutputBufferTimeUs The timestamp of the next output buffer or {@link C#TIME_UNSET}
* if the next output buffer is unavailable.
* @param positionUs The current playback position.
* @param joiningDeadlineMs The joining deadline.
* @return Returns whether to drop the current output buffer.
*/
protected boolean shouldDropOutputBuffer(long outputBufferTimeUs, long nextOutputBufferTimeUs,
private boolean shouldDropOutputBuffer(long outputBufferTimeUs, long nextOutputBufferTimeUs,
long positionUs, long joiningDeadlineMs) {
return isBufferLate(outputBufferTimeUs - positionUs)
&& (joiningDeadlineMs != C.TIME_UNSET || nextOutputBufferTimeUs != C.TIME_UNSET);
}
/**
* Returns whether to drop all buffers from the buffer being processed to the keyframe at or after
* the current playback position, if possible.
*
* @param earlyUs The time until the current buffer should be presented in microseconds. A
* negative value indicates that the buffer is late.
*/
private boolean shouldDropBuffersToKeyframe(long earlyUs) {
return isBufferVeryLate(earlyUs);
}
private void renderBuffer() {
int bufferMode = outputBuffer.mode;
boolean renderRgb = bufferMode == VpxDecoder.OUTPUT_MODE_RGB && surface != null;
......@@ -342,18 +371,35 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
}
private void dropBuffer() {
decoderCounters.droppedBufferCount++;
droppedFrames++;
consecutiveDroppedFrameCount++;
decoderCounters.maxConsecutiveDroppedBufferCount = Math.max(
consecutiveDroppedFrameCount, decoderCounters.maxConsecutiveDroppedBufferCount);
if (droppedFrames == maxDroppedFramesToNotify) {
maybeNotifyDroppedFrames();
}
updateDroppedBufferCounters(1);
outputBuffer.release();
outputBuffer = null;
}
private boolean maybeDropBuffersToKeyframe(long positionUs) throws ExoPlaybackException {
int droppedSourceBufferCount = skipSource(positionUs);
if (droppedSourceBufferCount == 0) {
return false;
}
decoderCounters.droppedToKeyframeCount++;
// We dropped some buffers to catch up, so update the decoder counters and flush the codec,
// which releases all pending buffers buffers including the current output buffer.
updateDroppedBufferCounters(buffersInCodecCount + droppedSourceBufferCount);
flushDecoder();
return true;
}
private void updateDroppedBufferCounters(int droppedBufferCount) {
decoderCounters.droppedBufferCount += droppedBufferCount;
droppedFrames += droppedBufferCount;
consecutiveDroppedFrameCount += droppedBufferCount;
decoderCounters.maxConsecutiveDroppedBufferCount = Math.max(consecutiveDroppedFrameCount,
decoderCounters.maxConsecutiveDroppedBufferCount);
if (droppedFrames >= maxDroppedFramesToNotify) {
maybeNotifyDroppedFrames();
}
}
private void skipBuffer() {
decoderCounters.skippedOutputBufferCount++;
outputBuffer.release();
......@@ -426,6 +472,7 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
inputBuffer.flip();
inputBuffer.colorInfo = formatHolder.format.colorInfo;
decoder.queueInputBuffer(inputBuffer);
buffersInCodecCount++;
decoderReceivedBuffers = true;
decoderCounters.inputBufferCount++;
inputBuffer = null;
......@@ -445,6 +492,8 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
private void flushDecoder() throws ExoPlaybackException {
waitingForKeys = false;
forceRenderFrame = false;
buffersInCodecCount = 0;
if (decoderReinitializationState != REINITIALIZATION_STATE_NONE) {
releaseDecoder();
maybeInitDecoder();
......@@ -601,6 +650,8 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
decoderCounters.decoderReleaseCount++;
decoderReinitializationState = REINITIALIZATION_STATE_NONE;
decoderReceivedBuffers = false;
forceRenderFrame = false;
buffersInCodecCount = 0;
}
private void onInputFormatChanged(Format newFormat) throws ExoPlaybackException {
......@@ -735,8 +786,13 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
}
private static boolean isBufferLate(long earlyUs) {
// Class a buffer as late if it should have been presented more than 30ms ago.
// Class a buffer as late if it should have been presented more than 30 ms ago.
return earlyUs < -30000;
}
private static boolean isBufferVeryLate(long earlyUs) {
// Class a buffer as very late if it should have been presented more than 500 ms ago.
return earlyUs < -500000;
}
}
......@@ -532,6 +532,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
if (surface == dummySurface) {
// Skip frames in sync with playback, so we'll be at the right frame if the mode changes.
if (isBufferLate(earlyUs)) {
forceRenderFrame = false;
skipOutputBuffer(codec, bufferIndex, presentationTimeUs);
return true;
}
......@@ -569,7 +570,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
if (shouldDropBuffersToKeyframe(earlyUs, elapsedRealtimeUs)
&& maybeDropBuffersToKeyframe(codec, bufferIndex, presentationTimeUs, positionUs)) {
forceRenderFrame = true;
return true;
return false;
} else if (shouldDropOutputBuffer(earlyUs, elapsedRealtimeUs)) {
dropOutputBuffer(codec, bufferIndex, presentationTimeUs);
return true;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment