Fix blank video when switching on/off screen

This happens when using `ExoPlayer.setVideoEffects()`.

This CL also fixes the first frame not rendered problem, originally solved in
7e65cce967, but rolled back in 5056dfaa2b 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
This commit is contained in:
claincly 2024-01-29 04:20:55 -08:00 committed by Copybara-Service
parent bb533332f4
commit dcae49a561
3 changed files with 12 additions and 13 deletions

View File

@ -55,7 +55,6 @@ import java.util.concurrent.TimeoutException;
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;
@ -103,7 +102,6 @@ public class EffectPlaybackTest {
}
@Test
@Ignore("b/292111083")
public void exoplayerEffectsPreviewTest_ensuresFirstFrameRendered() throws Exception {
assumeTrue(Util.SDK_INT >= 18);

View File

@ -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;
@ -771,14 +772,14 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer
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:
@ -1063,6 +1064,9 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer
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);
@ -1087,7 +1091,9 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer
@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

View File

@ -81,8 +81,6 @@ import androidx.media3.exoplayer.ExoPlaybackException;
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. */
@ -122,8 +120,6 @@ import androidx.media3.exoplayer.ExoPlaybackException;
// 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. */
@ -230,9 +226,8 @@ import androidx.media3.exoplayer.ExoPlaybackException;
long presentationTimeUs = checkStateNotNull(presentationTimestampsUs.remove());
boolean videoSizeUpdated = maybeUpdateVideoSize(presentationTimeUs);
if (videoSizeUpdated && !reportedVideoSizeChange) {
if (videoSizeUpdated) {
frameRenderer.onVideoSizeChanged(reportedVideoSize);
reportedVideoSizeChange = true;
}
long renderTimeNs =
shouldRenderImmediately