@@ -145,6 +145,8 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
145145 /* package */ @ Nullable OnFrameRenderedListenerV23 tunnelingOnFrameRenderedListener ;
146146 @ Nullable private VideoFrameMetadataListener frameMetadataListener ;
147147
148+ private long lastInputTimeUs ;
149+ private long lastOutputTimeUs ;
148150 /**
149151 * @param context A context.
150152 * @param mediaCodecSelector A decoder selector.
@@ -231,6 +233,8 @@ public MediaCodecVideoRenderer(
231233 frameReleaseTimeHelper = new VideoFrameReleaseTimeHelper (this .context );
232234 eventDispatcher = new EventDispatcher (eventHandler , eventListener );
233235 deviceNeedsNoPostProcessWorkaround = deviceNeedsNoPostProcessWorkaround ();
236+ lastInputTimeUs = C .TIME_UNSET ;
237+ lastOutputTimeUs = C .TIME_UNSET ;
234238 joiningDeadlineMs = C .TIME_UNSET ;
235239 currentWidth = Format .NO_VALUE ;
236240 currentHeight = Format .NO_VALUE ;
@@ -370,6 +374,8 @@ protected void onPositionReset(long positionUs, boolean joining) throws ExoPlayb
370374 clearRenderedFirstFrame ();
371375 initialPositionUs = C .TIME_UNSET ;
372376 consecutiveDroppedFrameCount = 0 ;
377+ lastInputTimeUs = C .TIME_UNSET ;
378+ lastOutputTimeUs = C .TIME_UNSET ;
373379 if (joining ) {
374380 setJoiningDeadlineMs ();
375381 } else {
@@ -409,7 +415,15 @@ public boolean isReady() {
409415 */
410416 @ Override
411417 protected boolean hasOutputReady () {
412- return tunneling && buffersInCodecCount > 0 || super .hasOutputReady ();
418+ boolean fifoReady = true ;
419+ if (lastOutputTimeUs != C .TIME_UNSET ) {
420+ long fifoLengthUs = lastInputTimeUs - lastOutputTimeUs ;
421+
422+ // make sure there is at least 1/3s of video available in decoder FIFO,
423+ // otherwise decoder may start stalling
424+ fifoReady = fifoLengthUs > 333333 ;
425+ }
426+ return tunneling && fifoReady || super .hasOutputReady ();
413427 }
414428
415429 @ Override
@@ -858,6 +872,7 @@ private void notifyFrameMetadataListener(
858872
859873 /** Called when a buffer was processed in tunneling mode. */
860874 protected void onProcessedTunneledBuffer (long presentationTimeUs ) {
875+ lastOutputTimeUs = presentationTimeUs ;
861876 @ Nullable Format format = updateOutputFormatForTime (presentationTimeUs );
862877 if (format != null ) {
863878 processOutputFormat (getCodec (), format .width , format .height );
0 commit comments