Use CodecCounters consistently in all renderers.
- Increment skippedBufferCount for VPX and ADTR. - Set maxConsecutiveDroppedOutputBufferCount count for VPX. Tweak its meaning to ignore skipped frames. - Remove outputFormat/outputBuffer changed counts. These add limited value. Also, MediaCodec is moving toward a model where you don't see the output buffers changing because you dequeue them one at a time (like how our extension decoders work). ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=122258530
This commit is contained in:
parent
3760f514a9
commit
efaea81194
@ -79,8 +79,9 @@ public final class LibvpxVideoTrackRenderer extends TrackRenderer {
|
|||||||
private int previousWidth;
|
private int previousWidth;
|
||||||
private int previousHeight;
|
private int previousHeight;
|
||||||
|
|
||||||
private int droppedFrameCount;
|
|
||||||
private long droppedFrameAccumulationStartTimeMs;
|
private long droppedFrameAccumulationStartTimeMs;
|
||||||
|
private int droppedFrameCount;
|
||||||
|
private int consecutiveDroppedFrameCount;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param scaleToFit Boolean that indicates if video frames should be scaled to fit when
|
* @param scaleToFit Boolean that indicates if video frames should be scaled to fit when
|
||||||
@ -183,6 +184,7 @@ public final class LibvpxVideoTrackRenderer extends TrackRenderer {
|
|||||||
if (outputBuffer == null) {
|
if (outputBuffer == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
codecCounters.skippedOutputBufferCount += outputBuffer.skippedOutputBufferCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nextOutputBuffer == null) {
|
if (nextOutputBuffer == null) {
|
||||||
@ -202,6 +204,9 @@ public final class LibvpxVideoTrackRenderer extends TrackRenderer {
|
|||||||
// Drop frame if we are too late.
|
// Drop frame if we are too late.
|
||||||
codecCounters.droppedOutputBufferCount++;
|
codecCounters.droppedOutputBufferCount++;
|
||||||
droppedFrameCount++;
|
droppedFrameCount++;
|
||||||
|
consecutiveDroppedFrameCount++;
|
||||||
|
codecCounters.maxConsecutiveDroppedOutputBufferCount = Math.max(consecutiveDroppedFrameCount,
|
||||||
|
codecCounters.maxConsecutiveDroppedOutputBufferCount);
|
||||||
if (droppedFrameCount == maxDroppedFrameCountToNotify) {
|
if (droppedFrameCount == maxDroppedFrameCountToNotify) {
|
||||||
notifyAndResetDroppedFrameCount();
|
notifyAndResetDroppedFrameCount();
|
||||||
}
|
}
|
||||||
@ -227,6 +232,7 @@ public final class LibvpxVideoTrackRenderer extends TrackRenderer {
|
|||||||
|
|
||||||
private void renderBuffer() {
|
private void renderBuffer() {
|
||||||
codecCounters.renderedOutputBufferCount++;
|
codecCounters.renderedOutputBufferCount++;
|
||||||
|
consecutiveDroppedFrameCount = 0;
|
||||||
notifyIfVideoSizeChanged(outputBuffer.width, outputBuffer.height);
|
notifyIfVideoSizeChanged(outputBuffer.width, outputBuffer.height);
|
||||||
if (outputBuffer.mode == VpxDecoder.OUTPUT_MODE_RGB && surface != null) {
|
if (outputBuffer.mode == VpxDecoder.OUTPUT_MODE_RGB && surface != null) {
|
||||||
renderRgbFrame(outputBuffer, scaleToFit);
|
renderRgbFrame(outputBuffer, scaleToFit);
|
||||||
@ -320,6 +326,7 @@ public final class LibvpxVideoTrackRenderer extends TrackRenderer {
|
|||||||
inputStreamEnded = false;
|
inputStreamEnded = false;
|
||||||
outputStreamEnded = false;
|
outputStreamEnded = false;
|
||||||
renderedFirstFrame = false;
|
renderedFirstFrame = false;
|
||||||
|
consecutiveDroppedFrameCount = 0;
|
||||||
if (decoder != null) {
|
if (decoder != null) {
|
||||||
flushDecoder();
|
flushDecoder();
|
||||||
}
|
}
|
||||||
|
@ -24,14 +24,40 @@ package com.google.android.exoplayer;
|
|||||||
*/
|
*/
|
||||||
public final class CodecCounters {
|
public final class CodecCounters {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of times the codec has been initialized.
|
||||||
|
*/
|
||||||
public int codecInitCount;
|
public int codecInitCount;
|
||||||
|
/**
|
||||||
|
* The number of times the codec has been released.
|
||||||
|
*/
|
||||||
public int codecReleaseCount;
|
public int codecReleaseCount;
|
||||||
|
/**
|
||||||
|
* The number of queued input buffers.
|
||||||
|
*/
|
||||||
public int inputBufferCount;
|
public int inputBufferCount;
|
||||||
public int outputFormatChangedCount;
|
/**
|
||||||
public int outputBuffersChangedCount;
|
* The number of rendered output buffers.
|
||||||
|
*/
|
||||||
public int renderedOutputBufferCount;
|
public int renderedOutputBufferCount;
|
||||||
|
/**
|
||||||
|
* The number of skipped output buffers.
|
||||||
|
* <p>
|
||||||
|
* A skipped output buffer is an output buffer that was deliberately not rendered.
|
||||||
|
*/
|
||||||
public int skippedOutputBufferCount;
|
public int skippedOutputBufferCount;
|
||||||
|
/**
|
||||||
|
* The number of dropped output buffers.
|
||||||
|
* <p>
|
||||||
|
* A dropped output buffer is an output buffer that was supposed to be rendered, but was instead
|
||||||
|
* dropped because it could not be rendered in time.
|
||||||
|
*/
|
||||||
public int droppedOutputBufferCount;
|
public int droppedOutputBufferCount;
|
||||||
|
/**
|
||||||
|
* The maximum number of dropped output buffers without an interleaving rendered output buffer.
|
||||||
|
* <p>
|
||||||
|
* Skipped output buffers are ignored for the purposes of calculating this value.
|
||||||
|
*/
|
||||||
public int maxConsecutiveDroppedOutputBufferCount;
|
public int maxConsecutiveDroppedOutputBufferCount;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -46,15 +72,13 @@ public final class CodecCounters {
|
|||||||
|
|
||||||
public String getDebugString() {
|
public String getDebugString() {
|
||||||
ensureUpdated();
|
ensureUpdated();
|
||||||
return "cic:" + codecInitCount
|
return "ic:" + codecInitCount
|
||||||
+ " crc:" + codecReleaseCount
|
+ " rc:" + codecReleaseCount
|
||||||
+ " ibc:" + inputBufferCount
|
+ " ib:" + inputBufferCount
|
||||||
+ " ofc:" + outputFormatChangedCount
|
+ " rb:" + renderedOutputBufferCount
|
||||||
+ " obc:" + outputBuffersChangedCount
|
+ " sb:" + skippedOutputBufferCount
|
||||||
+ " ren:" + renderedOutputBufferCount
|
+ " db:" + droppedOutputBufferCount
|
||||||
+ " sob:" + skippedOutputBufferCount
|
+ " mcdb:" + maxConsecutiveDroppedOutputBufferCount;
|
||||||
+ " dob:" + droppedOutputBufferCount
|
|
||||||
+ " mcdob:" + maxConsecutiveDroppedOutputBufferCount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -827,7 +827,6 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
|
|||||||
format.setInteger(android.media.MediaFormat.KEY_CHANNEL_COUNT, 1);
|
format.setInteger(android.media.MediaFormat.KEY_CHANNEL_COUNT, 1);
|
||||||
}
|
}
|
||||||
onOutputFormatChanged(codec, format);
|
onOutputFormatChanged(codec, format);
|
||||||
codecCounters.outputFormatChangedCount++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -836,7 +835,6 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
|
|||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
private void processOutputBuffersChanged() {
|
private void processOutputBuffersChanged() {
|
||||||
outputBuffers = codec.getOutputBuffers();
|
outputBuffers = codec.getOutputBuffers();
|
||||||
codecCounters.outputBuffersChangedCount++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -392,7 +392,6 @@ public class MediaCodecVideoTrackRenderer extends MediaCodecTrackRenderer {
|
|||||||
boolean shouldSkip) {
|
boolean shouldSkip) {
|
||||||
if (shouldSkip) {
|
if (shouldSkip) {
|
||||||
skipOutputBuffer(codec, bufferIndex);
|
skipOutputBuffer(codec, bufferIndex);
|
||||||
consecutiveDroppedFrameCount = 0;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -402,7 +401,6 @@ public class MediaCodecVideoTrackRenderer extends MediaCodecTrackRenderer {
|
|||||||
} else {
|
} else {
|
||||||
renderOutputBuffer(codec, bufferIndex);
|
renderOutputBuffer(codec, bufferIndex);
|
||||||
}
|
}
|
||||||
consecutiveDroppedFrameCount = 0;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -433,7 +431,6 @@ public class MediaCodecVideoTrackRenderer extends MediaCodecTrackRenderer {
|
|||||||
// Let the underlying framework time the release.
|
// Let the underlying framework time the release.
|
||||||
if (earlyUs < 50000) {
|
if (earlyUs < 50000) {
|
||||||
renderOutputBufferV21(codec, bufferIndex, adjustedReleaseTimeNs);
|
renderOutputBufferV21(codec, bufferIndex, adjustedReleaseTimeNs);
|
||||||
consecutiveDroppedFrameCount = 0;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -450,7 +447,6 @@ public class MediaCodecVideoTrackRenderer extends MediaCodecTrackRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
renderOutputBuffer(codec, bufferIndex);
|
renderOutputBuffer(codec, bufferIndex);
|
||||||
consecutiveDroppedFrameCount = 0;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -486,6 +482,7 @@ public class MediaCodecVideoTrackRenderer extends MediaCodecTrackRenderer {
|
|||||||
codec.releaseOutputBuffer(bufferIndex, true);
|
codec.releaseOutputBuffer(bufferIndex, true);
|
||||||
TraceUtil.endSection();
|
TraceUtil.endSection();
|
||||||
codecCounters.renderedOutputBufferCount++;
|
codecCounters.renderedOutputBufferCount++;
|
||||||
|
consecutiveDroppedFrameCount = 0;
|
||||||
renderedFirstFrame = true;
|
renderedFirstFrame = true;
|
||||||
maybeNotifyDrawnToSurface();
|
maybeNotifyDrawnToSurface();
|
||||||
}
|
}
|
||||||
@ -497,6 +494,7 @@ public class MediaCodecVideoTrackRenderer extends MediaCodecTrackRenderer {
|
|||||||
codec.releaseOutputBuffer(bufferIndex, releaseTimeNs);
|
codec.releaseOutputBuffer(bufferIndex, releaseTimeNs);
|
||||||
TraceUtil.endSection();
|
TraceUtil.endSection();
|
||||||
codecCounters.renderedOutputBufferCount++;
|
codecCounters.renderedOutputBufferCount++;
|
||||||
|
consecutiveDroppedFrameCount = 0;
|
||||||
renderedFirstFrame = true;
|
renderedFirstFrame = true;
|
||||||
maybeNotifyDrawnToSurface();
|
maybeNotifyDrawnToSurface();
|
||||||
}
|
}
|
||||||
|
@ -164,6 +164,7 @@ public abstract class AudioDecoderTrackRenderer extends TrackRenderer implements
|
|||||||
if (outputBuffer == null) {
|
if (outputBuffer == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
codecCounters.skippedOutputBufferCount += outputBuffer.skippedOutputBufferCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (outputBuffer.isEndOfStream()) {
|
if (outputBuffer.isEndOfStream()) {
|
||||||
|
@ -27,6 +27,11 @@ public abstract class OutputBuffer extends Buffer {
|
|||||||
*/
|
*/
|
||||||
public long timestampUs;
|
public long timestampUs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of buffers immediately prior to this one that were skipped in the {@link Decoder}.
|
||||||
|
*/
|
||||||
|
public int skippedOutputBufferCount;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Releases the output buffer for reuse. Must be called when the buffer is no longer needed.
|
* Releases the output buffer for reuse. Must be called when the buffer is no longer needed.
|
||||||
*/
|
*/
|
||||||
|
@ -56,6 +56,7 @@ public abstract class SimpleDecoder<I extends DecoderInputBuffer, O extends Outp
|
|||||||
private E exception;
|
private E exception;
|
||||||
private boolean flushed;
|
private boolean flushed;
|
||||||
private boolean released;
|
private boolean released;
|
||||||
|
private int skippedOutputBufferCount;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param inputBuffers An array of nulls that will be used to store references to input buffers.
|
* @param inputBuffers An array of nulls that will be used to store references to input buffers.
|
||||||
@ -148,6 +149,7 @@ public abstract class SimpleDecoder<I extends DecoderInputBuffer, O extends Outp
|
|||||||
public final void flush() {
|
public final void flush() {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
flushed = true;
|
flushed = true;
|
||||||
|
skippedOutputBufferCount = 0;
|
||||||
if (dequeuedInputBuffer != null) {
|
if (dequeuedInputBuffer != null) {
|
||||||
releaseInputBufferInternal(dequeuedInputBuffer);
|
releaseInputBufferInternal(dequeuedInputBuffer);
|
||||||
dequeuedInputBuffer = null;
|
dequeuedInputBuffer = null;
|
||||||
@ -242,12 +244,14 @@ public abstract class SimpleDecoder<I extends DecoderInputBuffer, O extends Outp
|
|||||||
}
|
}
|
||||||
|
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
if (flushed || outputBuffer.isDecodeOnly()) {
|
if (flushed) {
|
||||||
// If a flush occurred while decoding or the buffer was only for decoding (not presentation)
|
releaseOutputBufferInternal(outputBuffer);
|
||||||
// then make the output buffer available again rather than queueing it to be consumed.
|
} else if (outputBuffer.isDecodeOnly()) {
|
||||||
|
skippedOutputBufferCount++;
|
||||||
releaseOutputBufferInternal(outputBuffer);
|
releaseOutputBufferInternal(outputBuffer);
|
||||||
} else {
|
} else {
|
||||||
// Queue the decoded output buffer to be consumed.
|
outputBuffer.skippedOutputBufferCount = skippedOutputBufferCount;
|
||||||
|
skippedOutputBufferCount = 0;
|
||||||
queuedOutputBuffers.addLast(outputBuffer);
|
queuedOutputBuffers.addLast(outputBuffer);
|
||||||
}
|
}
|
||||||
// Make the input buffer available again.
|
// Make the input buffer available again.
|
||||||
@ -287,8 +291,9 @@ public abstract class SimpleDecoder<I extends DecoderInputBuffer, O extends Outp
|
|||||||
* @param inputBuffer The buffer to decode.
|
* @param inputBuffer The buffer to decode.
|
||||||
* @param outputBuffer The output buffer to store decoded data. The flag
|
* @param outputBuffer The output buffer to store decoded data. The flag
|
||||||
* {@link C#BUFFER_FLAG_DECODE_ONLY} will be set if the same flag is set on
|
* {@link C#BUFFER_FLAG_DECODE_ONLY} will be set if the same flag is set on
|
||||||
* {@code inputBuffer}, but the decoder may set/unset the flag if required. If the flag is set
|
* {@code inputBuffer}, but may be set/unset as required. If the flag is set when the call
|
||||||
* after this method returns, any output will not be presented.
|
* returns then the output buffer will not be made available to dequeue. The output buffer
|
||||||
|
* may not have been populated in this case.
|
||||||
* @param reset True if the decoder must be reset before decoding.
|
* @param reset True if the decoder must be reset before decoding.
|
||||||
* @return A decoder exception if an error occurred, or null if decoding was successful.
|
* @return A decoder exception if an error occurred, or null if decoding was successful.
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user