@@ -356,6 +356,73 @@ public void render_withBufferLimitEqualToNumberOfSamples_rendersLastFrameAfterEn
356
356
assertThat (argumentDecoderCounters .getValue ().skippedOutputBufferCount ).isEqualTo (2 );
357
357
}
358
358
359
+ @ Test
360
+ public void render_withoutSampleDependencies_rendersLastFrameAfterEndOfStream () throws Exception {
361
+ ArgumentCaptor <DecoderCounters > argumentDecoderCounters =
362
+ ArgumentCaptor .forClass (DecoderCounters .class );
363
+ FakeSampleStream fakeSampleStream =
364
+ new FakeSampleStream (
365
+ new DefaultAllocator (/* trimOnReset= */ true , /* individualAllocationSize= */ 1024 ),
366
+ /* mediaSourceEventDispatcher= */ null ,
367
+ DrmSessionManager .DRM_UNSUPPORTED ,
368
+ new DrmSessionEventListener .EventDispatcher (),
369
+ /* initialFormat= */ VIDEO_H264 ,
370
+ ImmutableList .of (
371
+ oneByteSample (/* timeUs= */ 0 , C .BUFFER_FLAG_KEY_FRAME ), // First buffer.
372
+ // Second buffer will be skipped before decoder during a seek.
373
+ oneByteSample (/* timeUs= */ 10_000 , C .BUFFER_FLAG_NOT_DEPENDED_ON ),
374
+ // Last buffer without sample dependencies will be rendered.
375
+ oneByteSample (/* timeUs= */ 20_000 , C .BUFFER_FLAG_NOT_DEPENDED_ON ),
376
+ END_OF_STREAM_ITEM ));
377
+ fakeSampleStream .writeData (/* startPositionUs= */ 0 );
378
+ // Seek to time after samples.
379
+ fakeSampleStream .seekToUs (30_000 , /* allowTimeBeyondBuffer= */ true );
380
+ mediaCodecVideoRenderer =
381
+ new MediaCodecVideoRenderer (
382
+ ApplicationProvider .getApplicationContext (),
383
+ new ForwardingSynchronousMediaCodecAdapterWithBufferLimit .Factory (/* bufferLimit= */ 3 ),
384
+ mediaCodecSelector ,
385
+ /* allowedJoiningTimeMs= */ 0 ,
386
+ /* enableDecoderFallback= */ false ,
387
+ /* eventHandler= */ new Handler (testMainLooper ),
388
+ eventListener ,
389
+ /* maxDroppedFramesToNotify= */ 1 );
390
+ mediaCodecVideoRenderer .init (/* index= */ 0 , PlayerId .UNSET , Clock .DEFAULT );
391
+ mediaCodecVideoRenderer .handleMessage (Renderer .MSG_SET_VIDEO_OUTPUT , surface );
392
+ mediaCodecVideoRenderer .enable (
393
+ RendererConfiguration .DEFAULT ,
394
+ new Format [] {VIDEO_H264 },
395
+ fakeSampleStream ,
396
+ /* positionUs= */ 0 ,
397
+ /* joining= */ false ,
398
+ /* mayRenderStartOfStream= */ true ,
399
+ /* startPositionUs= */ 30_000 ,
400
+ /* offsetUs= */ 0 ,
401
+ new MediaSource .MediaPeriodId (new Object ()));
402
+
403
+ mediaCodecVideoRenderer .start ();
404
+ mediaCodecVideoRenderer .setCurrentStreamFinal ();
405
+ mediaCodecVideoRenderer .render (0 , SystemClock .elapsedRealtime () * 1000 );
406
+ // Call to render has reads all samples including the END_OF_STREAM_ITEM because the
407
+ // previous sample is skipped before decoding.
408
+ assertThat (mediaCodecVideoRenderer .hasReadStreamToEnd ()).isTrue ();
409
+ int posUs = 30_000 ;
410
+ while (!mediaCodecVideoRenderer .isEnded ()) {
411
+ mediaCodecVideoRenderer .render (posUs , SystemClock .elapsedRealtime () * 1000 );
412
+ posUs += 40_000 ;
413
+ }
414
+ shadowOf (testMainLooper ).idle ();
415
+
416
+ verify (eventListener ).onRenderedFirstFrame (eq (surface ), /* renderTimeMs= */ anyLong ());
417
+ verify (eventListener ).onVideoEnabled (argumentDecoderCounters .capture ());
418
+ // First key frame is decoded and skipped as an output buffer.
419
+ assertThat (argumentDecoderCounters .getValue ().skippedOutputBufferCount ).isEqualTo (1 );
420
+ // Second frame is skipped before the decoder, as an input buffer.
421
+ assertThat (argumentDecoderCounters .getValue ().skippedInputBufferCount ).isEqualTo (1 );
422
+ // Last frame is rendered.
423
+ assertThat (argumentDecoderCounters .getValue ().renderedOutputBufferCount ).isEqualTo (1 );
424
+ }
425
+
359
426
@ Test
360
427
public void
361
428
render_withClippingMediaPeriodAndBufferContainingLastAndClippingSamples_rendersLastFrame ()
0 commit comments