Skip to content

Commit

Permalink
Fix blank video when switching on/off screen
Browse files Browse the repository at this point in the history
This happens when using `ExoPlayer.setVideoEffects()`.

This CL also fixes the first frame not rendered problem, originally solved in
7e65cce, but rolled back in 5056dfa because the solution introduces
the flash that is observed in b/292111083.

Before media3 1.1 release, the output size of `VideoFrameProcessor` is not
reported to the app. This was changed later after introducing
`CompositingVideoSinkProvider`, where the video size after processing **is**
reported to the app. After this CL, the size is again, not reported.

PiperOrigin-RevId: 602345087
  • Loading branch information
claincly authored and copybara-github committed Jan 29, 2024
1 parent bb53333 commit dcae49a
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@
import java.util.concurrent.atomic.AtomicReference;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.junit.After;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
Expand Down Expand Up @@ -103,7 +102,6 @@ public void tearDown() {
}

@Test
@Ignore("b/292111083")
public void exoplayerEffectsPreviewTest_ensuresFirstFrameRendered() throws Exception {
assumeTrue(Util.SDK_INT >= 18);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer
private boolean codecNeedsSetOutputSurfaceWorkaround;
private boolean codecHandlesHdr10PlusOutOfBandMetadata;
@Nullable private Surface displaySurface;
@Nullable private Size outputResolution;
@Nullable private PlaceholderSurface placeholderSurface;
private boolean haveReportedFirstFrameRenderedForCurrentSurface;
private @C.VideoScalingMode int scalingMode;
Expand Down Expand Up @@ -771,14 +772,14 @@ public void handleMessage(@MessageType int messageType, @Nullable Object message
setVideoEffects(videoEffects);
break;
case MSG_SET_VIDEO_OUTPUT_RESOLUTION:
Size outputResolution = (Size) checkNotNull(message);
outputResolution = (Size) checkNotNull(message);
// TODO: b/292111083 Set the surface on the videoSinkProvider before it's initialized
// otherwise the first frames are missed until a new video output resolution arrives.
if (videoSinkProvider.isInitialized()
&& outputResolution.getWidth() != 0
&& outputResolution.getHeight() != 0
&& checkNotNull(outputResolution).getWidth() != 0
&& checkNotNull(outputResolution).getHeight() != 0
&& displaySurface != null) {
videoSinkProvider.setOutputSurfaceInfo(displaySurface, outputResolution);
videoSinkProvider.setOutputSurfaceInfo(displaySurface, checkNotNull(outputResolution));
}
break;
case MSG_SET_AUDIO_ATTRIBUTES:
Expand Down Expand Up @@ -1063,6 +1064,9 @@ protected void onReadyToInitializeCodec(Format format) throws ExoPlaybackExcepti
if (frameMetadataListener != null) {
videoSinkProvider.setVideoFrameMetadataListener(frameMetadataListener);
}
if (displaySurface != null && outputResolution != null) {
videoSinkProvider.setOutputSurfaceInfo(displaySurface, outputResolution);
}
} catch (VideoSink.VideoSinkException e) {
throw createRendererException(
e, format, PlaybackException.ERROR_CODE_VIDEO_FRAME_PROCESSOR_INIT_FAILED);
Expand All @@ -1087,7 +1091,9 @@ public void onFrameDropped(VideoSink videoSink) {

@Override
public void onVideoSizeChanged(VideoSink videoSink, VideoSize videoSize) {
maybeNotifyVideoSizeChanged(videoSize);
// TODO: b/292111083 - Report video size change to app. Video size reporting is
// removed at the moment to ensure the first frame is rendered, and the video is
// rendered after switching on/off the screen.
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,6 @@ void renderFrame(

private VideoSize reportedVideoSize;
private long outputStreamOffsetUs;
// TODO b/292111083 - Remove the field and trigger the callback on every video size change.
private boolean reportedVideoSizeChange;
private long lastPresentationTimeUs;

/** Creates an instance. */
Expand Down Expand Up @@ -122,8 +120,6 @@ public void flush() {
// we keep the latest value of pendingOutputVideoSize
videoSizeChanges.clear();
}
// Do not clear reportedVideoSizeChange because we report a video size change at most once
// (b/292111083).
}

/** Returns whether the renderer is ready. */
Expand Down Expand Up @@ -230,9 +226,8 @@ private void renderFrame(boolean shouldRenderImmediately) {
long presentationTimeUs = checkStateNotNull(presentationTimestampsUs.remove());

boolean videoSizeUpdated = maybeUpdateVideoSize(presentationTimeUs);
if (videoSizeUpdated && !reportedVideoSizeChange) {
if (videoSizeUpdated) {
frameRenderer.onVideoSizeChanged(reportedVideoSize);
reportedVideoSizeChange = true;
}
long renderTimeNs =
shouldRenderImmediately
Expand Down

0 comments on commit dcae49a

Please sign in to comment.