diff --git a/demo/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java b/demo/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java index 87098c5705..659962d759 100644 --- a/demo/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java +++ b/demo/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java @@ -456,7 +456,7 @@ public class PlayerActivity extends Activity implements OnKeyListener, OnTouchLi } @Override - public void onDrawnToSurface(Surface surface) { + public void onRenderedFirstFrame(Surface surface) { shutterView.setVisibility(View.GONE); } @@ -471,6 +471,17 @@ public class PlayerActivity extends Activity implements OnKeyListener, OnTouchLi if (trackInfo.hasOnlyUnplayableTracks(C.TRACK_TYPE_AUDIO)) { showToast(R.string.error_unsupported_audio); } + boolean renderingVideo = false; + for (int i = 0; i < trackInfo.rendererCount; i++) { + if (player.getRendererType(i) == C.TRACK_TYPE_VIDEO + && trackInfo.getTrackSelection(i) != null) { + renderingVideo = true; + break; + } + } + if (!renderingVideo) { + shutterView.setVisibility(View.VISIBLE); + } } // User controls diff --git a/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/LibvpxVideoRenderer.java b/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/LibvpxVideoRenderer.java index a156c5506f..feb380883e 100644 --- a/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/LibvpxVideoRenderer.java +++ b/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/LibvpxVideoRenderer.java @@ -67,7 +67,6 @@ public final class LibvpxVideoRenderer extends BaseRenderer { private VpxOutputBuffer nextOutputBuffer; private Bitmap bitmap; - private boolean drawnToSurface; private boolean renderedFirstFrame; private long joiningDeadlineMs; private Surface surface; @@ -234,13 +233,8 @@ public final class LibvpxVideoRenderer extends BaseRenderer { // If we have not rendered any frame so far (either initially or immediately following a seek), // render one frame irrespective of the state or current position. - if (!renderedFirstFrame) { - renderBuffer(); - renderedFirstFrame = true; - return false; - } - - if (getState() == STATE_STARTED && outputBuffer.timeUs <= positionUs + 30000) { + if (!renderedFirstFrame + || (getState() == STATE_STARTED && outputBuffer.timeUs <= positionUs + 30000)) { renderBuffer(); } return false; @@ -252,14 +246,18 @@ public final class LibvpxVideoRenderer extends BaseRenderer { maybeNotifyVideoSizeChanged(outputBuffer.width, outputBuffer.height); if (outputBuffer.mode == VpxDecoder.OUTPUT_MODE_RGB && surface != null) { renderRgbFrame(outputBuffer, scaleToFit); - if (!drawnToSurface) { - drawnToSurface = true; - eventDispatcher.drawnToSurface(surface); + if (!renderedFirstFrame) { + renderedFirstFrame = true; + eventDispatcher.renderedFirstFrame(surface); } outputBuffer.release(); } else if (outputBuffer.mode == VpxDecoder.OUTPUT_MODE_YUV && outputBufferRenderer != null) { // The renderer will release the buffer. outputBufferRenderer.setOutputBuffer(outputBuffer); + if (!renderedFirstFrame) { + renderedFirstFrame = true; + eventDispatcher.renderedFirstFrame(null); + } } else { outputBuffer.release(); } @@ -433,11 +431,11 @@ public final class LibvpxVideoRenderer extends BaseRenderer { if (this.surface == surface) { return; } + renderedFirstFrame = false; this.surface = surface; outputBufferRenderer = null; outputMode = (surface != null) ? VpxDecoder.OUTPUT_MODE_RGB : VpxDecoder.OUTPUT_MODE_NONE; updateDecoder(); - drawnToSurface = false; } private void setOutputBufferRenderer(VpxOutputBufferRenderer outputBufferRenderer) { diff --git a/library/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java b/library/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java index 27b51d0e40..2eb7e2042e 100644 --- a/library/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java +++ b/library/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java @@ -59,7 +59,7 @@ public final class SimpleExoPlayer implements ExoPlayer { public interface VideoListener { void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio); - void onDrawnToSurface(Surface surface); + void onRenderedFirstFrame(Surface surface); } /** @@ -565,9 +565,9 @@ public final class SimpleExoPlayer implements ExoPlayer { } @Override - public void onDrawnToSurface(Surface surface) { + public void onRenderedFirstFrame(Surface surface) { if (videoListener != null) { - videoListener.onDrawnToSurface(surface); + videoListener.onRenderedFirstFrame(surface); } } diff --git a/library/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java b/library/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java index 9dc0b9a8ab..94a0be8a73 100644 --- a/library/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java +++ b/library/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java @@ -63,7 +63,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { private CodecMaxValues codecMaxValues; private Surface surface; - private boolean reportedDrawnToSurface; private boolean renderedFirstFrame; private long joiningDeadlineMs; private long droppedFrameAccumulationStartTimeMs; @@ -295,8 +294,8 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { if (this.surface == surface) { return; } + renderedFirstFrame = false; this.surface = surface; - this.reportedDrawnToSurface = false; int state = getState(); if (state == STATE_ENABLED || state == STATE_STARTED) { releaseCodec(); @@ -467,8 +466,10 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { TraceUtil.endSection(); decoderCounters.renderedOutputBufferCount++; consecutiveDroppedFrameCount = 0; - renderedFirstFrame = true; - maybeNotifyDrawnToSurface(); + if (!renderedFirstFrame) { + renderedFirstFrame = true; + eventDispatcher.renderedFirstFrame(surface); + } } @TargetApi(21) @@ -479,8 +480,10 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { TraceUtil.endSection(); decoderCounters.renderedOutputBufferCount++; consecutiveDroppedFrameCount = 0; - renderedFirstFrame = true; - maybeNotifyDrawnToSurface(); + if (!renderedFirstFrame) { + renderedFirstFrame = true; + eventDispatcher.renderedFirstFrame(surface); + } } @SuppressLint("InlinedApi") @@ -578,13 +581,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { return (maxPixels * 3) / (2 * minCompressionRatio); } - private void maybeNotifyDrawnToSurface() { - if (!reportedDrawnToSurface) { - eventDispatcher.drawnToSurface(surface); - reportedDrawnToSurface = true; - } - } - private void maybeNotifyVideoSizeChanged() { if (lastReportedWidth != currentWidth || lastReportedHeight != currentHeight || lastReportedUnappliedRotationDegrees != currentUnappliedRotationDegrees diff --git a/library/src/main/java/com/google/android/exoplayer2/video/VideoRendererEventListener.java b/library/src/main/java/com/google/android/exoplayer2/video/VideoRendererEventListener.java index f999eeee48..4c7d8a62c1 100644 --- a/library/src/main/java/com/google/android/exoplayer2/video/VideoRendererEventListener.java +++ b/library/src/main/java/com/google/android/exoplayer2/video/VideoRendererEventListener.java @@ -88,12 +88,13 @@ public interface VideoRendererEventListener { float pixelWidthHeightRatio); /** - * Called when a frame is rendered to a surface for the first time following that surface - * having been set as the target for the renderer. + * Called when a frame is rendered for the first time since setting the surface, and when a frame + * is rendered for the first time since the renderer was reset. * - * @param surface The surface to which a first frame has been rendered. + * @param surface The {@link Surface} to which a first frame has been rendered, or {@code null} if + * the renderer renders to something that isn't a {@link Surface}. */ - void onDrawnToSurface(Surface surface); + void onRenderedFirstFrame(Surface surface); /** * Called when the renderer is disabled. @@ -195,14 +196,14 @@ public interface VideoRendererEventListener { } /** - * Invokes {@link VideoRendererEventListener#onDrawnToSurface(Surface)}. + * Invokes {@link VideoRendererEventListener#onRenderedFirstFrame(Surface)}. */ - public void drawnToSurface(final Surface surface) { + public void renderedFirstFrame(final Surface surface) { if (listener != null) { handler.post(new Runnable() { @Override public void run() { - listener.onDrawnToSurface(surface); + listener.onRenderedFirstFrame(surface); } }); }