67
67
import androidx .test .core .app .ApplicationProvider ;
68
68
import androidx .test .ext .junit .runners .AndroidJUnit4 ;
69
69
import com .google .common .collect .ImmutableList ;
70
+ import java .util .Arrays ;
70
71
import java .util .List ;
71
72
import java .util .concurrent .atomic .AtomicBoolean ;
72
73
import java .util .concurrent .atomic .AtomicReference ;
@@ -1609,6 +1610,56 @@ public void render(long positionUs, long elapsedRealtimeUs)
1609
1610
assertThat (secondaryVideoState3 ).isEqualTo (Renderer .STATE_STARTED );
1610
1611
}
1611
1612
1613
+ @ Test
1614
+ public void
1615
+ play_withNoSampleRendererAndInitialDiscontinuity_usesPrewarmingAndTransitionsWithoutError ()
1616
+ throws Exception {
1617
+ Clock fakeClock = new FakeClock (/* isAutoAdvancing= */ true );
1618
+ RenderersFactory renderersFactoryWithNoSampleRenderer =
1619
+ new FakeRenderersFactorySupportingSecondaryVideoRenderer (
1620
+ fakeClock , /* includeNoSampleRenderer= */ true );
1621
+ ExoPlayer player =
1622
+ new TestExoPlayerBuilder (context )
1623
+ .setClock (fakeClock )
1624
+ .setRenderersFactory (renderersFactoryWithNoSampleRenderer )
1625
+ .build ();
1626
+ Renderer secondaryVideoRenderer = player .getSecondaryRenderer (/* index= */ 0 );
1627
+ Renderer noSampleRenderer = player .getRenderer (/* index= */ 2 );
1628
+ assertThat (secondaryVideoRenderer .getTrackType ()).isEqualTo (C .TRACK_TYPE_VIDEO );
1629
+ assertThat (noSampleRenderer .getTrackType ()).isEqualTo (C .TRACK_TYPE_NONE );
1630
+ // Set a playlist that allows a new renderer to be enabled early and uses an initial
1631
+ // discontinuity.
1632
+ player .setMediaSources (
1633
+ ImmutableList .of (
1634
+ new FakeMediaSource (new FakeTimeline (), ExoPlayerTestRunner .VIDEO_FORMAT ),
1635
+ new FakeMediaSource (
1636
+ new FakeTimeline (),
1637
+ ExoPlayerTestRunner .VIDEO_FORMAT ,
1638
+ ExoPlayerTestRunner .AUDIO_FORMAT ) {
1639
+ @ Override
1640
+ public MediaPeriod createPeriod (
1641
+ MediaPeriodId id , Allocator allocator , long startPositionUs ) {
1642
+ FakeMediaPeriod fakeMediaPeriod =
1643
+ (FakeMediaPeriod ) super .createPeriod (id , allocator , startPositionUs );
1644
+ fakeMediaPeriod .setDiscontinuityPositionUs (100 );
1645
+ return fakeMediaPeriod ;
1646
+ }
1647
+ }));
1648
+ player .prepare ();
1649
+
1650
+ // Play until secondary video renderer item is started, verifying its being used for prewarming.
1651
+ // This step should not have any influence on the NoSampleRenderer and it should not throw.
1652
+ player .play ();
1653
+ advance (player )
1654
+ .untilBackgroundThreadCondition (
1655
+ () -> secondaryVideoRenderer .getState () == Renderer .STATE_STARTED );
1656
+ @ Renderer .State int noSampleRendererState = noSampleRenderer .getState ();
1657
+ advance (player ).untilState (Player .STATE_ENDED );
1658
+ player .release ();
1659
+
1660
+ assertThat (noSampleRendererState ).isEqualTo (Renderer .STATE_STARTED );
1661
+ }
1662
+
1612
1663
/** {@link FakeMediaSource} that prevents any reading of samples off the sample queue. */
1613
1664
private static final class FakeBlockingMediaSource extends FakeMediaSource {
1614
1665
@@ -1670,9 +1721,16 @@ public int readData(
1670
1721
private static class FakeRenderersFactorySupportingSecondaryVideoRenderer
1671
1722
implements RenderersFactory {
1672
1723
protected final Clock clock ;
1724
+ private final boolean includeNoSampleRenderer ;
1673
1725
1674
1726
public FakeRenderersFactorySupportingSecondaryVideoRenderer (Clock clock ) {
1727
+ this (clock , /* includeNoSampleRenderer= */ false );
1728
+ }
1729
+
1730
+ public FakeRenderersFactorySupportingSecondaryVideoRenderer (
1731
+ Clock clock , boolean includeNoSampleRenderer ) {
1675
1732
this .clock = clock ;
1733
+ this .includeNoSampleRenderer = includeNoSampleRenderer ;
1676
1734
}
1677
1735
1678
1736
@ Override
@@ -1684,10 +1742,25 @@ public Renderer[] createRenderers(
1684
1742
MetadataOutput metadataRendererOutput ) {
1685
1743
HandlerWrapper clockAwareHandler =
1686
1744
clock .createHandler (eventHandler .getLooper (), /* callback= */ null );
1687
- return new Renderer [] {
1688
- new FakeVideoRenderer (clockAwareHandler , videoRendererEventListener ),
1689
- new FakeAudioRenderer (clockAwareHandler , audioRendererEventListener )
1690
- };
1745
+ Renderer [] renderers =
1746
+ new Renderer [] {
1747
+ new FakeVideoRenderer (clockAwareHandler , videoRendererEventListener ),
1748
+ new FakeAudioRenderer (clockAwareHandler , audioRendererEventListener )
1749
+ };
1750
+ if (includeNoSampleRenderer ) {
1751
+ renderers = Arrays .copyOf (renderers , renderers .length + 1 );
1752
+ renderers [renderers .length - 1 ] =
1753
+ new NoSampleRenderer () {
1754
+ @ Override
1755
+ public String getName () {
1756
+ return "NoSampleRenderer" ;
1757
+ }
1758
+
1759
+ @ Override
1760
+ public void render (long positionUs , long elapsedRealtimeUs ) {}
1761
+ };
1762
+ }
1763
+ return renderers ;
1691
1764
}
1692
1765
1693
1766
@ Override
0 commit comments