Commit e499f6d3 by olly Committed by marcbaechinger

Improve tests to use output surfaces more realistically

Prior to this change, there were some unrealistic quirks in
our Robolectric tests. For example, onRenderedFirstFrame would
be called when using FakeVideoRenderer, despite no output to
render the frame to ever being set. This change improves the
realism of these tests. These changes are required for some
improvements being made to how outputs are set on video
renderers.

PiperOrigin-RevId: 367652169
parent 253c8ce2
...@@ -26,6 +26,8 @@ import static org.mockito.Mockito.atLeastOnce; ...@@ -26,6 +26,8 @@ import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import android.graphics.SurfaceTexture;
import android.view.Surface;
import androidx.test.core.app.ApplicationProvider; import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.analytics.AnalyticsListener; import com.google.android.exoplayer2.analytics.AnalyticsListener;
...@@ -87,6 +89,7 @@ public class SimpleExoPlayerTest { ...@@ -87,6 +89,7 @@ public class SimpleExoPlayerTest {
@Test @Test
public void releaseAfterRendererEvents_triggersPendingVideoEventsInListener() throws Exception { public void releaseAfterRendererEvents_triggersPendingVideoEventsInListener() throws Exception {
Surface surface = new Surface(new SurfaceTexture(/* texName= */ 0));
SimpleExoPlayer player = SimpleExoPlayer player =
new SimpleExoPlayer.Builder( new SimpleExoPlayer.Builder(
ApplicationProvider.getApplicationContext(), ApplicationProvider.getApplicationContext(),
...@@ -98,11 +101,13 @@ public class SimpleExoPlayerTest { ...@@ -98,11 +101,13 @@ public class SimpleExoPlayerTest {
player.addListener(listener); player.addListener(listener);
player.setMediaSource( player.setMediaSource(
new FakeMediaSource(new FakeTimeline(), ExoPlayerTestRunner.VIDEO_FORMAT)); new FakeMediaSource(new FakeTimeline(), ExoPlayerTestRunner.VIDEO_FORMAT));
player.setVideoSurface(surface);
player.prepare(); player.prepare();
player.play(); player.play();
runUntilPlaybackState(player, Player.STATE_READY); runUntilPlaybackState(player, Player.STATE_READY);
player.release(); player.release();
surface.release();
ShadowLooper.runMainLooperToNextTask(); ShadowLooper.runMainLooperToNextTask();
verify(listener, atLeastOnce()).onEvents(any(), any()); // EventListener verify(listener, atLeastOnce()).onEvents(any(), any()); // EventListener
......
...@@ -60,6 +60,7 @@ import static org.mockito.Mockito.mock; ...@@ -60,6 +60,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import android.graphics.SurfaceTexture;
import android.os.Looper; import android.os.Looper;
import android.util.SparseArray; import android.util.SparseArray;
import android.view.Surface; import android.view.Surface;
...@@ -1638,6 +1639,9 @@ public final class AnalyticsCollectorTest { ...@@ -1638,6 +1639,9 @@ public final class AnalyticsCollectorTest {
public void onEvents_isReportedWithCorrectEventTimes() throws Exception { public void onEvents_isReportedWithCorrectEventTimes() throws Exception {
SimpleExoPlayer player = SimpleExoPlayer player =
new TestExoPlayerBuilder(ApplicationProvider.getApplicationContext()).build(); new TestExoPlayerBuilder(ApplicationProvider.getApplicationContext()).build();
Surface surface = new Surface(new SurfaceTexture(/* texName= */ 0));
player.setVideoSurface(surface);
AnalyticsListener listener = mock(AnalyticsListener.class); AnalyticsListener listener = mock(AnalyticsListener.class);
Format[] formats = Format[] formats =
new Format[] { new Format[] {
...@@ -1663,6 +1667,7 @@ public final class AnalyticsCollectorTest { ...@@ -1663,6 +1667,7 @@ public final class AnalyticsCollectorTest {
TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_IDLE); TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_IDLE);
ShadowLooper.runMainLooperToNextTask(); ShadowLooper.runMainLooperToNextTask();
player.release(); player.release();
surface.release();
// Verify that expected individual callbacks have been called and capture EventTimes. // Verify that expected individual callbacks have been called and capture EventTimes.
ArgumentCaptor<AnalyticsListener.EventTime> individualTimelineChangedEventTimes = ArgumentCaptor<AnalyticsListener.EventTime> individualTimelineChangedEventTimes =
...@@ -1982,11 +1987,13 @@ public final class AnalyticsCollectorTest { ...@@ -1982,11 +1987,13 @@ public final class AnalyticsCollectorTest {
@Nullable ActionSchedule actionSchedule, @Nullable ActionSchedule actionSchedule,
RenderersFactory renderersFactory) RenderersFactory renderersFactory)
throws Exception { throws Exception {
Surface surface = new Surface(new SurfaceTexture(/* texName= */ 0));
TestAnalyticsListener listener = new TestAnalyticsListener(); TestAnalyticsListener listener = new TestAnalyticsListener();
try { try {
new ExoPlayerTestRunner.Builder(ApplicationProvider.getApplicationContext()) new ExoPlayerTestRunner.Builder(ApplicationProvider.getApplicationContext())
.setMediaSources(mediaSource) .setMediaSources(mediaSource)
.setRenderersFactory(renderersFactory) .setRenderersFactory(renderersFactory)
.setVideoSurface(surface)
.setAnalyticsListener(listener) .setAnalyticsListener(listener)
.setActionSchedule(actionSchedule) .setActionSchedule(actionSchedule)
.build() .build()
...@@ -1995,6 +2002,8 @@ public final class AnalyticsCollectorTest { ...@@ -1995,6 +2002,8 @@ public final class AnalyticsCollectorTest {
.blockUntilEnded(TIMEOUT_MS); .blockUntilEnded(TIMEOUT_MS);
} catch (ExoPlaybackException e) { } catch (ExoPlaybackException e) {
// Ignore ExoPlaybackException as these may be expected. // Ignore ExoPlaybackException as these may be expected.
} finally {
surface.release();
} }
return listener; return listener;
} }
...@@ -2358,12 +2367,7 @@ public final class AnalyticsCollectorTest { ...@@ -2358,12 +2367,7 @@ public final class AnalyticsCollectorTest {
@Override @Override
public String toString() { public String toString() {
return "{" return "{" + "type=" + eventType + ", windowAndPeriodId=" + eventWindowAndPeriodId + '}';
+ "type="
+ Long.numberOfTrailingZeros(eventType)
+ ", windowAndPeriodId="
+ eventWindowAndPeriodId
+ '}';
} }
} }
} }
...@@ -2375,14 +2379,12 @@ public final class AnalyticsCollectorTest { ...@@ -2375,14 +2379,12 @@ public final class AnalyticsCollectorTest {
*/ */
private static final class EmptyDrmCallback implements MediaDrmCallback { private static final class EmptyDrmCallback implements MediaDrmCallback {
@Override @Override
public byte[] executeProvisionRequest(UUID uuid, ExoMediaDrm.ProvisionRequest request) public byte[] executeProvisionRequest(UUID uuid, ExoMediaDrm.ProvisionRequest request) {
throws MediaDrmCallbackException {
return new byte[0]; return new byte[0];
} }
@Override @Override
public byte[] executeKeyRequest(UUID uuid, ExoMediaDrm.KeyRequest request) public byte[] executeKeyRequest(UUID uuid, ExoMediaDrm.KeyRequest request) {
throws MediaDrmCallbackException {
return new byte[0]; return new byte[0];
} }
} }
......
...@@ -67,11 +67,13 @@ public final class DecoderVideoRendererTest { ...@@ -67,11 +67,13 @@ public final class DecoderVideoRendererTest {
.setHeight(1080) .setHeight(1080)
.build(); .build();
private Surface surface;
private DecoderVideoRenderer renderer; private DecoderVideoRenderer renderer;
@Mock private VideoRendererEventListener eventListener; @Mock private VideoRendererEventListener eventListener;
@Before @Before
public void setUp() { public void setUp() {
surface = new Surface(new SurfaceTexture(/* texName= */ 0));
renderer = renderer =
new DecoderVideoRenderer( new DecoderVideoRenderer(
/* allowedJoiningTimeMs= */ 0, /* allowedJoiningTimeMs= */ 0,
...@@ -168,17 +170,18 @@ public final class DecoderVideoRendererTest { ...@@ -168,17 +170,18 @@ public final class DecoderVideoRendererTest {
}; };
} }
}; };
renderer.setOutputSurface(new Surface(new SurfaceTexture(/* texName= */ 0))); renderer.setOutputSurface(surface);
} }
@After @After
public void shutDown() throws Exception { public void shutDown() {
if (renderer.getState() == Renderer.STATE_STARTED) { if (renderer.getState() == Renderer.STATE_STARTED) {
renderer.stop(); renderer.stop();
} }
if (renderer.getState() == Renderer.STATE_ENABLED) { if (renderer.getState() == Renderer.STATE_ENABLED) {
renderer.disable(); renderer.disable();
} }
surface.release();
} }
@Test @Test
......
...@@ -19,7 +19,6 @@ import static com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSample ...@@ -19,7 +19,6 @@ import static com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSample
import static com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.format; import static com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.format;
import static com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.oneByteSample; import static com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.oneByteSample;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
...@@ -52,6 +51,7 @@ import com.google.android.exoplayer2.upstream.DefaultAllocator; ...@@ -52,6 +51,7 @@ import com.google.android.exoplayer2.upstream.DefaultAllocator;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import java.util.Collections; import java.util.Collections;
import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
...@@ -75,6 +75,7 @@ public class MediaCodecVideoRendererTest { ...@@ -75,6 +75,7 @@ public class MediaCodecVideoRendererTest {
.build(); .build();
private Looper testMainLooper; private Looper testMainLooper;
private Surface surface;
private MediaCodecVideoRenderer mediaCodecVideoRenderer; private MediaCodecVideoRenderer mediaCodecVideoRenderer;
@Nullable private Format currentOutputFormat; @Nullable private Format currentOutputFormat;
...@@ -118,8 +119,13 @@ public class MediaCodecVideoRendererTest { ...@@ -118,8 +119,13 @@ public class MediaCodecVideoRendererTest {
} }
}; };
mediaCodecVideoRenderer.handleMessage( surface = new Surface(new SurfaceTexture(/* texName= */ 0));
Renderer.MSG_SET_SURFACE, new Surface(new SurfaceTexture(/* texName= */ 0))); mediaCodecVideoRenderer.handleMessage(Renderer.MSG_SET_SURFACE, surface);
}
@After
public void cleanUp() {
surface.release();
} }
@Test @Test
...@@ -323,7 +329,7 @@ public class MediaCodecVideoRendererTest { ...@@ -323,7 +329,7 @@ public class MediaCodecVideoRendererTest {
} }
shadowOf(testMainLooper).idle(); shadowOf(testMainLooper).idle();
verify(eventListener).onRenderedFirstFrame(any()); verify(eventListener).onRenderedFirstFrame(eq(surface), /* renderTimeMs= */ anyLong());
} }
@Test @Test
...@@ -353,7 +359,7 @@ public class MediaCodecVideoRendererTest { ...@@ -353,7 +359,7 @@ public class MediaCodecVideoRendererTest {
} }
shadowOf(testMainLooper).idle(); shadowOf(testMainLooper).idle();
verify(eventListener, never()).onRenderedFirstFrame(any()); verify(eventListener, never()).onRenderedFirstFrame(eq(surface), /* renderTimeMs= */ anyLong());
} }
@Test @Test
...@@ -383,7 +389,7 @@ public class MediaCodecVideoRendererTest { ...@@ -383,7 +389,7 @@ public class MediaCodecVideoRendererTest {
} }
shadowOf(testMainLooper).idle(); shadowOf(testMainLooper).idle();
verify(eventListener).onRenderedFirstFrame(any()); verify(eventListener).onRenderedFirstFrame(eq(surface), /* renderTimeMs= */ anyLong());
} }
@Test @Test
...@@ -437,7 +443,8 @@ public class MediaCodecVideoRendererTest { ...@@ -437,7 +443,8 @@ public class MediaCodecVideoRendererTest {
// Expect only the first frame of the first stream to have been rendered. // Expect only the first frame of the first stream to have been rendered.
shadowLooper.idle(); shadowLooper.idle();
verify(eventListener, times(2)).onRenderedFirstFrame(any()); verify(eventListener, times(2))
.onRenderedFirstFrame(eq(surface), /* renderTimeMs= */ anyLong());
} }
@Test @Test
...@@ -488,12 +495,13 @@ public class MediaCodecVideoRendererTest { ...@@ -488,12 +495,13 @@ public class MediaCodecVideoRendererTest {
} }
shadowLooper.idle(); shadowLooper.idle();
verify(eventListener).onRenderedFirstFrame(any()); verify(eventListener).onRenderedFirstFrame(eq(surface), /* renderTimeMs= */ anyLong());
// Render to streamOffsetUs and verify the new first frame gets rendered. // Render to streamOffsetUs and verify the new first frame gets rendered.
mediaCodecVideoRenderer.render(/* positionUs= */ 100, SystemClock.elapsedRealtime() * 1000); mediaCodecVideoRenderer.render(/* positionUs= */ 100, SystemClock.elapsedRealtime() * 1000);
shadowLooper.idle(); shadowLooper.idle();
verify(eventListener, times(2)).onRenderedFirstFrame(any()); verify(eventListener, times(2))
.onRenderedFirstFrame(eq(surface), /* renderTimeMs= */ anyLong());
} }
} }
...@@ -22,6 +22,7 @@ import static junit.framework.TestCase.assertFalse; ...@@ -22,6 +22,7 @@ import static junit.framework.TestCase.assertFalse;
import android.content.Context; import android.content.Context;
import android.os.HandlerThread; import android.os.HandlerThread;
import android.os.Looper; import android.os.Looper;
import android.view.Surface;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlaybackException;
...@@ -80,6 +81,7 @@ public final class ExoPlayerTestRunner implements Player.EventListener, ActionSc ...@@ -80,6 +81,7 @@ public final class ExoPlayerTestRunner implements Player.EventListener, ActionSc
private Format[] supportedFormats; private Format[] supportedFormats;
private Object manifest; private Object manifest;
private ActionSchedule actionSchedule; private ActionSchedule actionSchedule;
private Surface surface;
private Player.EventListener eventListener; private Player.EventListener eventListener;
private AnalyticsListener analyticsListener; private AnalyticsListener analyticsListener;
private Integer expectedPlayerEndedCount; private Integer expectedPlayerEndedCount;
...@@ -277,6 +279,17 @@ public final class ExoPlayerTestRunner implements Player.EventListener, ActionSc ...@@ -277,6 +279,17 @@ public final class ExoPlayerTestRunner implements Player.EventListener, ActionSc
} }
/** /**
* Sets the video {@link Surface}. The default value is {@code null}.
*
* @param surface The {@link Surface} to be used by the player.
* @return This builder.
*/
public Builder setVideoSurface(Surface surface) {
this.surface = surface;
return this;
}
/**
* Sets an {@link Player.EventListener} to be registered to listen to player events. * Sets an {@link Player.EventListener} to be registered to listen to player events.
* *
* @param eventListener A {@link Player.EventListener} to be registered by the test runner to * @param eventListener A {@link Player.EventListener} to be registered by the test runner to
...@@ -334,6 +347,7 @@ public final class ExoPlayerTestRunner implements Player.EventListener, ActionSc ...@@ -334,6 +347,7 @@ public final class ExoPlayerTestRunner implements Player.EventListener, ActionSc
skipSettingMediaSources, skipSettingMediaSources,
initialWindowIndex, initialWindowIndex,
initialPositionMs, initialPositionMs,
surface,
actionSchedule, actionSchedule,
eventListener, eventListener,
analyticsListener, analyticsListener,
...@@ -347,6 +361,7 @@ public final class ExoPlayerTestRunner implements Player.EventListener, ActionSc ...@@ -347,6 +361,7 @@ public final class ExoPlayerTestRunner implements Player.EventListener, ActionSc
private final boolean skipSettingMediaSources; private final boolean skipSettingMediaSources;
private final int initialWindowIndex; private final int initialWindowIndex;
private final long initialPositionMs; private final long initialPositionMs;
@Nullable private final Surface surface;
@Nullable private final ActionSchedule actionSchedule; @Nullable private final ActionSchedule actionSchedule;
@Nullable private final Player.EventListener eventListener; @Nullable private final Player.EventListener eventListener;
@Nullable private final AnalyticsListener analyticsListener; @Nullable private final AnalyticsListener analyticsListener;
...@@ -376,6 +391,7 @@ public final class ExoPlayerTestRunner implements Player.EventListener, ActionSc ...@@ -376,6 +391,7 @@ public final class ExoPlayerTestRunner implements Player.EventListener, ActionSc
boolean skipSettingMediaSources, boolean skipSettingMediaSources,
int initialWindowIndex, int initialWindowIndex,
long initialPositionMs, long initialPositionMs,
@Nullable Surface surface,
@Nullable ActionSchedule actionSchedule, @Nullable ActionSchedule actionSchedule,
@Nullable Player.EventListener eventListener, @Nullable Player.EventListener eventListener,
@Nullable AnalyticsListener analyticsListener, @Nullable AnalyticsListener analyticsListener,
...@@ -386,6 +402,7 @@ public final class ExoPlayerTestRunner implements Player.EventListener, ActionSc ...@@ -386,6 +402,7 @@ public final class ExoPlayerTestRunner implements Player.EventListener, ActionSc
this.skipSettingMediaSources = skipSettingMediaSources; this.skipSettingMediaSources = skipSettingMediaSources;
this.initialWindowIndex = initialWindowIndex; this.initialWindowIndex = initialWindowIndex;
this.initialPositionMs = initialPositionMs; this.initialPositionMs = initialPositionMs;
this.surface = surface;
this.actionSchedule = actionSchedule; this.actionSchedule = actionSchedule;
this.eventListener = eventListener; this.eventListener = eventListener;
this.analyticsListener = analyticsListener; this.analyticsListener = analyticsListener;
...@@ -430,6 +447,12 @@ public final class ExoPlayerTestRunner implements Player.EventListener, ActionSc ...@@ -430,6 +447,12 @@ public final class ExoPlayerTestRunner implements Player.EventListener, ActionSc
() -> { () -> {
try { try {
player = playerBuilder.setLooper(Looper.myLooper()).build(); player = playerBuilder.setLooper(Looper.myLooper()).build();
if (surface != null) {
player.setVideoSurface(surface);
}
if (pauseAtEndOfMediaItems) {
player.setPauseAtEndOfMediaItems(true);
}
player.addListener(ExoPlayerTestRunner.this); player.addListener(ExoPlayerTestRunner.this);
if (eventListener != null) { if (eventListener != null) {
player.addListener(eventListener); player.addListener(eventListener);
...@@ -437,15 +460,12 @@ public final class ExoPlayerTestRunner implements Player.EventListener, ActionSc ...@@ -437,15 +460,12 @@ public final class ExoPlayerTestRunner implements Player.EventListener, ActionSc
if (analyticsListener != null) { if (analyticsListener != null) {
player.addAnalyticsListener(analyticsListener); player.addAnalyticsListener(analyticsListener);
} }
if (pauseAtEndOfMediaItems) {
player.setPauseAtEndOfMediaItems(true);
}
player.play(); player.play();
if (actionSchedule != null) { if (actionSchedule != null) {
actionSchedule.start( actionSchedule.start(
player, player,
playerBuilder.getTrackSelector(), playerBuilder.getTrackSelector(),
/* surface= */ null, surface,
handler, handler,
/* callback= */ ExoPlayerTestRunner.this); /* callback= */ ExoPlayerTestRunner.this);
} }
......
...@@ -18,6 +18,8 @@ package com.google.android.exoplayer2.testutil; ...@@ -18,6 +18,8 @@ package com.google.android.exoplayer2.testutil;
import android.os.Handler; import android.os.Handler;
import android.os.SystemClock; import android.os.SystemClock;
import android.view.Surface;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
...@@ -33,6 +35,7 @@ public class FakeVideoRenderer extends FakeRenderer { ...@@ -33,6 +35,7 @@ public class FakeVideoRenderer extends FakeRenderer {
private final VideoRendererEventListener.EventDispatcher eventDispatcher; private final VideoRendererEventListener.EventDispatcher eventDispatcher;
private final DecoderCounters decoderCounters; private final DecoderCounters decoderCounters;
private @MonotonicNonNull Format format; private @MonotonicNonNull Format format;
@Nullable private Surface surface;
private long streamOffsetUs; private long streamOffsetUs;
private boolean renderedFirstFrameAfterReset; private boolean renderedFirstFrameAfterReset;
private boolean mayRenderFirstFrameAfterEnableIfNotStarted; private boolean mayRenderFirstFrameAfterEnableIfNotStarted;
...@@ -58,10 +61,8 @@ public class FakeVideoRenderer extends FakeRenderer { ...@@ -58,10 +61,8 @@ public class FakeVideoRenderer extends FakeRenderer {
throws ExoPlaybackException { throws ExoPlaybackException {
super.onStreamChanged(formats, startPositionUs, offsetUs); super.onStreamChanged(formats, startPositionUs, offsetUs);
streamOffsetUs = offsetUs; streamOffsetUs = offsetUs;
if (renderedFirstFrameAfterReset) {
renderedFirstFrameAfterReset = false; renderedFirstFrameAfterReset = false;
} }
}
@Override @Override
protected void onStopped() { protected void onStopped() {
...@@ -94,18 +95,32 @@ public class FakeVideoRenderer extends FakeRenderer { ...@@ -94,18 +95,32 @@ public class FakeVideoRenderer extends FakeRenderer {
} }
@Override @Override
public void handleMessage(int messageType, @Nullable Object payload) throws ExoPlaybackException {
switch (messageType) {
case MSG_SET_SURFACE:
surface = (Surface) payload;
renderedFirstFrameAfterReset = false;
break;
default:
super.handleMessage(messageType, payload);
}
}
@Override
protected boolean shouldProcessBuffer(long bufferTimeUs, long playbackPositionUs) { protected boolean shouldProcessBuffer(long bufferTimeUs, long playbackPositionUs) {
boolean shouldProcess = super.shouldProcessBuffer(bufferTimeUs, playbackPositionUs); boolean shouldProcess = super.shouldProcessBuffer(bufferTimeUs, playbackPositionUs);
boolean shouldRenderFirstFrame = boolean shouldRenderFirstFrame =
!renderedFirstFrameAfterEnable surface != null
? (getState() == Renderer.STATE_STARTED || mayRenderFirstFrameAfterEnableIfNotStarted) && (!renderedFirstFrameAfterEnable
: !renderedFirstFrameAfterReset; ? (getState() == Renderer.STATE_STARTED
|| mayRenderFirstFrameAfterEnableIfNotStarted)
: !renderedFirstFrameAfterReset);
shouldProcess |= shouldRenderFirstFrame && playbackPositionUs >= streamOffsetUs; shouldProcess |= shouldRenderFirstFrame && playbackPositionUs >= streamOffsetUs;
if (shouldProcess && !renderedFirstFrameAfterReset) { if (shouldProcess && !renderedFirstFrameAfterReset && surface != null) {
@MonotonicNonNull Format format = Assertions.checkNotNull(this.format); @MonotonicNonNull Format format = Assertions.checkNotNull(this.format);
eventDispatcher.videoSizeChanged( eventDispatcher.videoSizeChanged(
format.width, format.height, format.rotationDegrees, format.pixelWidthHeightRatio); format.width, format.height, format.rotationDegrees, format.pixelWidthHeightRatio);
eventDispatcher.renderedFirstFrame(/* surface= */ null); eventDispatcher.renderedFirstFrame(surface);
renderedFirstFrameAfterReset = true; renderedFirstFrameAfterReset = true;
renderedFirstFrameAfterEnable = true; renderedFirstFrameAfterEnable = true;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment