From 61c9c169542204fde21a11cc479cd7a80c4fc71c Mon Sep 17 00:00:00 2001 From: olly Date: Thu, 17 Nov 2016 05:59:32 -0800 Subject: [PATCH] Make sure we report video size after Surface is set Issue: #2077 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=139451511 --- .../ext/vp9/LibvpxVideoRenderer.java | 58 +++++++++---------- .../video/MediaCodecVideoRenderer.java | 34 ++++++----- .../video/VideoRendererEventListener.java | 3 +- 3 files changed, 51 insertions(+), 44 deletions(-) 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 2412bf6bf84..e4cc2ae3cef 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 @@ -32,6 +32,7 @@ import com.google.android.exoplayer2.drm.DrmSession; import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.ExoMediaCrypto; +import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.TraceUtil; import com.google.android.exoplayer2.util.Util; @@ -85,8 +86,8 @@ public final class LibvpxVideoRenderer extends BaseRenderer { private boolean inputStreamEnded; private boolean outputStreamEnded; - private int previousWidth; - private int previousHeight; + private int lastReportedWidth; + private int lastReportedHeight; private long droppedFrameAccumulationStartTimeMs; private int droppedFrames; @@ -146,8 +147,7 @@ public LibvpxVideoRenderer(boolean scaleToFit, long allowedJoiningTimeMs, this.drmSessionManager = drmSessionManager; this.playClearSamplesWithoutKeys = playClearSamplesWithoutKeys; joiningDeadlineMs = -1; - previousWidth = -1; - previousHeight = -1; + clearLastReportedVideoSize(); formatHolder = new FormatHolder(); eventDispatcher = new EventDispatcher(eventHandler, eventListener); outputMode = VpxDecoder.OUTPUT_MODE_NONE; @@ -446,6 +446,7 @@ protected void onDisabled() { outputBuffer = null; format = null; waitingForKeys = false; + clearLastReportedVideoSize(); try { releaseDecoder(); } finally { @@ -520,35 +521,29 @@ private void onInputFormatChanged(Format newFormat) throws ExoPlaybackException @Override public void handleMessage(int messageType, Object message) throws ExoPlaybackException { if (messageType == C.MSG_SET_SURFACE) { - setSurface((Surface) message); + setOutput((Surface) message, null); } else if (messageType == MSG_SET_OUTPUT_BUFFER_RENDERER) { - setOutputBufferRenderer((VpxOutputBufferRenderer) message); + setOutput(null, (VpxOutputBufferRenderer) message); } else { super.handleMessage(messageType, message); } } - private void setSurface(Surface surface) { - if (this.surface == surface) { - return; - } + private void setOutput(Surface surface, VpxOutputBufferRenderer outputBufferRenderer) { + // At most one output may be non-null. Both may be null if the output is being cleared. + Assertions.checkState(surface == null || outputBufferRenderer == null); + // Clear state so that we always call the event listener with the video size and when a frame + // is rendered, even if the output hasn't changed. renderedFirstFrame = false; - this.surface = surface; - outputBufferRenderer = null; - outputMode = (surface != null) ? VpxDecoder.OUTPUT_MODE_RGB : VpxDecoder.OUTPUT_MODE_NONE; - updateDecoder(); - } - - private void setOutputBufferRenderer(VpxOutputBufferRenderer outputBufferRenderer) { - if (this.outputBufferRenderer == outputBufferRenderer) { - return; + clearLastReportedVideoSize(); + // We only need to update the decoder if the output has changed. + if (this.surface != surface || this.outputBufferRenderer != outputBufferRenderer) { + this.surface = surface; + this.outputBufferRenderer = outputBufferRenderer; + outputMode = outputBufferRenderer != null ? VpxDecoder.OUTPUT_MODE_YUV + : surface != null ? VpxDecoder.OUTPUT_MODE_RGB : VpxDecoder.OUTPUT_MODE_NONE; + updateDecoder(); } - renderedFirstFrame = false; - this.outputBufferRenderer = outputBufferRenderer; - surface = null; - outputMode = (outputBufferRenderer != null) ? VpxDecoder.OUTPUT_MODE_YUV - : VpxDecoder.OUTPUT_MODE_NONE; - updateDecoder(); } private void updateDecoder() { @@ -565,10 +560,15 @@ private boolean isRendererAvailable() { return surface != null || outputBufferRenderer != null; } - private void maybeNotifyVideoSizeChanged(final int width, final int height) { - if (previousWidth != width || previousHeight != height) { - previousWidth = width; - previousHeight = height; + private void clearLastReportedVideoSize() { + lastReportedWidth = Format.NO_VALUE; + lastReportedHeight = Format.NO_VALUE; + } + + private void maybeNotifyVideoSizeChanged(int width, int height) { + if (lastReportedWidth != width || lastReportedHeight != height) { + lastReportedWidth = width; + lastReportedHeight = height; eventDispatcher.videoSizeChanged(width, height, 0, 1); } } 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 c3921b4d6ab..b94beb10f63 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 @@ -163,9 +163,7 @@ public MediaCodecVideoRenderer(Context context, MediaCodecSelector mediaCodecSel currentHeight = Format.NO_VALUE; currentPixelWidthHeightRatio = Format.NO_VALUE; pendingPixelWidthHeightRatio = Format.NO_VALUE; - lastReportedWidth = Format.NO_VALUE; - lastReportedHeight = Format.NO_VALUE; - lastReportedPixelWidthHeightRatio = Format.NO_VALUE; + clearLastReportedVideoSize(); } @Override @@ -272,9 +270,7 @@ protected void onDisabled() { currentHeight = Format.NO_VALUE; currentPixelWidthHeightRatio = Format.NO_VALUE; pendingPixelWidthHeightRatio = Format.NO_VALUE; - lastReportedWidth = Format.NO_VALUE; - lastReportedHeight = Format.NO_VALUE; - lastReportedPixelWidthHeightRatio = Format.NO_VALUE; + clearLastReportedVideoSize(); frameReleaseTimeHelper.disable(); try { super.onDisabled(); @@ -294,15 +290,18 @@ public void handleMessage(int messageType, Object message) throws ExoPlaybackExc } private void setSurface(Surface surface) throws ExoPlaybackException { - if (this.surface == surface) { - return; - } + // Clear state so that we always call the event listener with the video size and when a frame + // is rendered, even if the surface hasn't changed. renderedFirstFrame = false; - this.surface = surface; - int state = getState(); - if (state == STATE_ENABLED || state == STATE_STARTED) { - releaseCodec(); - maybeInitCodec(); + clearLastReportedVideoSize(); + // We only need to actually release and reinitialize the codec if the surface has changed. + if (this.surface != surface) { + this.surface = surface; + int state = getState(); + if (state == STATE_ENABLED || state == STATE_STARTED) { + releaseCodec(); + maybeInitCodec(); + } } } @@ -584,6 +583,13 @@ private static int getMaxInputSize(Format format) { return (maxPixels * 3) / (2 * minCompressionRatio); } + private void clearLastReportedVideoSize() { + lastReportedWidth = Format.NO_VALUE; + lastReportedHeight = Format.NO_VALUE; + lastReportedPixelWidthHeightRatio = Format.NO_VALUE; + lastReportedUnappliedRotationDegrees = Format.NO_VALUE; + } + 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 4c7d8a62c1e..53d6a76b8db 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 @@ -69,7 +69,8 @@ void onVideoDecoderInitialized(String decoderName, long initializedTimestampMs, void onDroppedFrames(int count, long elapsedMs); /** - * Called each time there's a change in the size of the video being rendered. + * Called before a frame is rendered for the first time since setting the surface, and each time + * there's a change in the size, rotation or pixel aspect ratio of the video being rendered. * * @param width The video width in pixels. * @param height The video height in pixels.