Skip to content

Commit

Permalink
Add nullness annotations to DecoderVideoRenderer
Browse files Browse the repository at this point in the history
Also fixed a bug where format queue was polled with wrong timestamp value.

#fixit

PiperOrigin-RevId: 570420304
  • Loading branch information
rohitjoins authored and copybara-github committed Oct 3, 2023
1 parent 7a91474 commit a879bae
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package androidx.media3.exoplayer.video;

import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.common.util.Util.msToUs;
import static androidx.media3.exoplayer.DecoderReuseEvaluation.DISCARD_REASON_DRM_SESSION_CHANGED;
import static androidx.media3.exoplayer.DecoderReuseEvaluation.DISCARD_REASON_REUSE_NOT_IMPLEMENTED;
Expand Down Expand Up @@ -116,16 +117,16 @@ public abstract class DecoderVideoRenderer extends BaseRenderer {
private final TimedValueQueue<Format> formatQueue;
private final DecoderInputBuffer flagsOnlyBuffer;

private Format inputFormat;
private Format outputFormat;
@Nullable private Format inputFormat;
@Nullable private Format outputFormat;

@Nullable
private Decoder<
DecoderInputBuffer, ? extends VideoDecoderOutputBuffer, ? extends DecoderException>
decoder;

private DecoderInputBuffer inputBuffer;
private VideoDecoderOutputBuffer outputBuffer;
@Nullable private DecoderInputBuffer inputBuffer;
@Nullable private VideoDecoderOutputBuffer outputBuffer;
private @VideoOutputMode int outputMode;
@Nullable private Object output;
@Nullable private Surface outputSurface;
Expand Down Expand Up @@ -175,13 +176,13 @@ protected DecoderVideoRenderer(
this.allowedJoiningTimeMs = allowedJoiningTimeMs;
this.maxDroppedFramesToNotify = maxDroppedFramesToNotify;
joiningDeadlineMs = C.TIME_UNSET;
clearReportedVideoSize();
formatQueue = new TimedValueQueue<>();
flagsOnlyBuffer = DecoderInputBuffer.newNoDataInstance();
eventDispatcher = new EventDispatcher(eventHandler, eventListener);
decoderReinitializationState = REINITIALIZATION_STATE_NONE;
outputMode = C.VIDEO_OUTPUT_MODE_NONE;
firstFrameState = C.FIRST_FRAME_NOT_RENDERED_ONLY_ALLOWED_IF_STARTED;
decoderCounters = new DecoderCounters();
}

// BaseRenderer implementation.
Expand Down Expand Up @@ -324,7 +325,7 @@ protected void onStopped() {
@Override
protected void onDisabled() {
inputFormat = null;
clearReportedVideoSize();
reportedVideoSize = null;
lowerFirstFrameState(C.FIRST_FRAME_NOT_RENDERED_ONLY_ALLOWED_IF_STARTED);
try {
setSourceDrmSession(null);
Expand Down Expand Up @@ -365,7 +366,7 @@ protected void flushDecoder() throws ExoPlaybackException {
outputBuffer.release();
outputBuffer = null;
}
decoder.flush();
checkNotNull(decoder).flush();
decoderReceivedBuffers = false;
}
}
Expand Down Expand Up @@ -403,7 +404,8 @@ protected void onInputFormatChanged(FormatHolder formatHolder) throws ExoPlaybac

if (decoder == null) {
maybeInitDecoder();
eventDispatcher.inputFormatChanged(inputFormat, /* decoderReuseEvaluation= */ null);
eventDispatcher.inputFormatChanged(
checkNotNull(inputFormat), /* decoderReuseEvaluation= */ null);
return;
}

Expand All @@ -412,12 +414,12 @@ protected void onInputFormatChanged(FormatHolder formatHolder) throws ExoPlaybac
evaluation =
new DecoderReuseEvaluation(
decoder.getName(),
oldFormat,
checkNotNull(oldFormat),
newFormat,
REUSE_RESULT_NO,
DISCARD_REASON_DRM_SESSION_CHANGED);
} else {
evaluation = canReuseDecoder(decoder.getName(), oldFormat, newFormat);
evaluation = canReuseDecoder(decoder.getName(), checkNotNull(oldFormat), newFormat);
}

if (evaluation.result == REUSE_RESULT_NO) {
Expand All @@ -430,7 +432,7 @@ protected void onInputFormatChanged(FormatHolder formatHolder) throws ExoPlaybac
maybeInitDecoder();
}
}
eventDispatcher.inputFormatChanged(inputFormat, evaluation);
eventDispatcher.inputFormatChanged(checkNotNull(inputFormat), evaluation);
}

/**
Expand Down Expand Up @@ -598,9 +600,9 @@ protected void renderOutputBuffer(
} else {
maybeNotifyVideoSizeChanged(outputBuffer.width, outputBuffer.height);
if (renderYuv) {
outputBufferRenderer.setOutputBuffer(outputBuffer);
checkNotNull(outputBufferRenderer).setOutputBuffer(outputBuffer);
} else {
renderOutputBufferToSurface(outputBuffer, outputSurface);
renderOutputBufferToSurface(outputBuffer, checkNotNull(outputSurface));
}
consecutiveDroppedFrameCount = 0;
decoderCounters.renderedOutputBufferCount++;
Expand Down Expand Up @@ -715,11 +717,11 @@ private void maybeInitDecoder() throws ExoPlaybackException {

try {
long decoderInitializingTimestamp = SystemClock.elapsedRealtime();
decoder = createDecoder(inputFormat, cryptoConfig);
decoder = createDecoder(checkNotNull(inputFormat), cryptoConfig);
setDecoderOutputMode(outputMode);
long decoderInitializedTimestamp = SystemClock.elapsedRealtime();
eventDispatcher.decoderInitialized(
decoder.getName(),
checkNotNull(decoder).getName(),
decoderInitializedTimestamp,
decoderInitializedTimestamp - decoderInitializingTimestamp);
decoderCounters.decoderInitCount++;
Expand Down Expand Up @@ -749,10 +751,11 @@ private boolean feedInputBuffer() throws DecoderException, ExoPlaybackException
}
}

DecoderInputBuffer inputBuffer = checkNotNull(this.inputBuffer);
if (decoderReinitializationState == REINITIALIZATION_STATE_SIGNAL_END_OF_STREAM) {
inputBuffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM);
decoder.queueInputBuffer(inputBuffer);
inputBuffer = null;
checkNotNull(decoder).queueInputBuffer(inputBuffer);
this.inputBuffer = null;
decoderReinitializationState = REINITIALIZATION_STATE_WAIT_END_OF_STREAM;
return false;
}
Expand All @@ -767,12 +770,12 @@ private boolean feedInputBuffer() throws DecoderException, ExoPlaybackException
case C.RESULT_BUFFER_READ:
if (inputBuffer.isEndOfStream()) {
inputStreamEnded = true;
decoder.queueInputBuffer(inputBuffer);
inputBuffer = null;
checkNotNull(decoder).queueInputBuffer(inputBuffer);
this.inputBuffer = null;
return false;
}
if (waitingForFirstSampleInFormat) {
formatQueue.add(inputBuffer.timeUs, inputFormat);
formatQueue.add(inputBuffer.timeUs, checkNotNull(inputFormat));
waitingForFirstSampleInFormat = false;
}
if (inputBuffer.timeUs < getLastResetPositionUs()) {
Expand All @@ -781,11 +784,11 @@ private boolean feedInputBuffer() throws DecoderException, ExoPlaybackException
inputBuffer.flip();
inputBuffer.format = inputFormat;
onQueueInputBuffer(inputBuffer);
decoder.queueInputBuffer(inputBuffer);
checkNotNull(decoder).queueInputBuffer(inputBuffer);
buffersInCodecCount++;
decoderReceivedBuffers = true;
decoderCounters.queuedInputBufferCount++;
inputBuffer = null;
this.inputBuffer = null;
return true;
default:
throw new IllegalStateException();
Expand All @@ -805,7 +808,7 @@ private boolean feedInputBuffer() throws DecoderException, ExoPlaybackException
private boolean drainOutputBuffer(long positionUs, long elapsedRealtimeUs)
throws ExoPlaybackException, DecoderException {
if (outputBuffer == null) {
outputBuffer = decoder.dequeueOutputBuffer();
outputBuffer = checkNotNull(decoder).dequeueOutputBuffer();
if (outputBuffer == null) {
return false;
}
Expand All @@ -828,7 +831,7 @@ private boolean drainOutputBuffer(long positionUs, long elapsedRealtimeUs)

boolean processedOutputBuffer = processOutputBuffer(positionUs, elapsedRealtimeUs);
if (processedOutputBuffer) {
onProcessedOutputBuffer(outputBuffer.timeUs);
onProcessedOutputBuffer(checkNotNull(outputBuffer).timeUs);
outputBuffer = null;
}
return processedOutputBuffer;
Expand All @@ -850,7 +853,9 @@ private boolean processOutputBuffer(long positionUs, long elapsedRealtimeUs)
initialPositionUs = positionUs;
}

long earlyUs = outputBuffer.timeUs - positionUs;
VideoDecoderOutputBuffer outputBuffer = checkNotNull(this.outputBuffer);
long bufferTimeUs = outputBuffer.timeUs;
long earlyUs = bufferTimeUs - positionUs;
if (!hasOutput()) {
// Skip frames in sync with playback, so we'll be at the right frame if the mode changes.
if (isBufferLate(earlyUs)) {
Expand All @@ -860,14 +865,19 @@ private boolean processOutputBuffer(long positionUs, long elapsedRealtimeUs)
return false;
}

long presentationTimeUs = outputBuffer.timeUs - outputStreamOffsetUs;
Format format = formatQueue.pollFloor(presentationTimeUs);
Format format = formatQueue.pollFloor(bufferTimeUs);
if (format != null) {
outputFormat = format;
} else if (outputFormat == null) {
// After a stream change or after the initial start, there should be an input format change
// which we've not found. Check the Format queue in case the corresponding presentation
// timestamp is greater than bufferTimeUs
outputFormat = formatQueue.pollFirst();
}

long presentationTimeUs = bufferTimeUs - outputStreamOffsetUs;
if (shouldForceRender(earlyUs)) {
renderOutputBuffer(outputBuffer, presentationTimeUs, outputFormat);
renderOutputBuffer(outputBuffer, presentationTimeUs, checkNotNull(outputFormat));
return true;
}

Expand All @@ -886,7 +896,7 @@ && maybeDropBuffersToKeyframe(positionUs)) {
}

if (earlyUs < 30000) {
renderOutputBuffer(outputBuffer, presentationTimeUs, outputFormat);
renderOutputBuffer(outputBuffer, presentationTimeUs, checkNotNull(outputFormat));
return true;
}

Expand Down Expand Up @@ -925,7 +935,7 @@ private void onOutputChanged() {
}

private void onOutputRemoved() {
clearReportedVideoSize();
reportedVideoSize = null;
lowerFirstFrameState(C.FIRST_FRAME_NOT_RENDERED);
}

Expand All @@ -950,20 +960,18 @@ private void lowerFirstFrameState(@C.FirstFrameState int firstFrameState) {
private void maybeNotifyRenderedFirstFrame() {
if (firstFrameState != C.FIRST_FRAME_RENDERED) {
firstFrameState = C.FIRST_FRAME_RENDERED;
eventDispatcher.renderedFirstFrame(output);
if (output != null) {
eventDispatcher.renderedFirstFrame(output);
}
}
}

private void maybeRenotifyRenderedFirstFrame() {
if (firstFrameState == C.FIRST_FRAME_RENDERED) {
if (firstFrameState == C.FIRST_FRAME_RENDERED && output != null) {
eventDispatcher.renderedFirstFrame(output);
}
}

private void clearReportedVideoSize() {
reportedVideoSize = null;
}

private void maybeNotifyVideoSizeChanged(int width, int height) {
if (reportedVideoSize == null
|| reportedVideoSize.width != width
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,6 @@ public MediaCodecVideoRenderer(
decodedVideoSize = VideoSize.UNKNOWN;
tunnelingAudioSessionId = C.AUDIO_SESSION_ID_UNSET;
firstFrameState = C.FIRST_FRAME_NOT_RENDERED_ONLY_ALLOWED_IF_STARTED;
reportedVideoSize = null;
}

@Override
Expand Down

0 comments on commit a879bae

Please sign in to comment.