Commit 2d3156f8 by claincly Committed by christosts

Make sure the first frame is force rendered.

PiperOrigin-RevId: 505960752
parent 0b1a904c
...@@ -689,8 +689,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -689,8 +689,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
Size outputResolution = (Size) checkNotNull(message); Size outputResolution = (Size) checkNotNull(message);
if (outputResolution.getWidth() != 0 if (outputResolution.getWidth() != 0
&& outputResolution.getHeight() != 0 && outputResolution.getHeight() != 0
&& displaySurface != null && displaySurface != null) {
&& frameProcessorManager.isEnabled()) {
frameProcessorManager.setOutputSurfaceInfo(displaySurface, outputResolution); frameProcessorManager.setOutputSurfaceInfo(displaySurface, outputResolution);
} }
break; break;
...@@ -1170,19 +1169,8 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -1170,19 +1169,8 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
return false; return false;
} }
long elapsedSinceLastRenderUs = elapsedRealtimeNowUs - lastRenderRealtimeUs; boolean forceRenderOutputBuffer = shouldForceRender(positionUs, earlyUs);
boolean shouldRenderFirstFrame =
!renderedFirstFrameAfterEnable
? (isStarted || mayRenderFirstFrameAfterEnableIfNotStarted)
: !renderedFirstFrameAfterReset;
// Don't force output until we joined and the position reached the current stream.
boolean forceRenderOutputBuffer =
joiningDeadlineMs == C.TIME_UNSET
&& positionUs >= outputStreamOffsetUs
&& (shouldRenderFirstFrame
|| (isStarted && shouldForceRenderOutputBuffer(earlyUs, elapsedSinceLastRenderUs)));
if (forceRenderOutputBuffer) { if (forceRenderOutputBuffer) {
// TODO(b/238302341): Handle releasing the force rendered frames in FrameProcessor.
boolean notifyFrameMetaDataListener; boolean notifyFrameMetaDataListener;
if (frameProcessorManager.isEnabled()) { if (frameProcessorManager.isEnabled()) {
notifyFrameMetaDataListener = false; notifyFrameMetaDataListener = false;
...@@ -1275,6 +1263,21 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -1275,6 +1263,21 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
return false; return false;
} }
/** Returns whether a buffer or a processed frame should be force rendered. */
private boolean shouldForceRender(long positionUs, long earlyUs) {
boolean isStarted = getState() == STATE_STARTED;
boolean shouldRenderFirstFrame =
!renderedFirstFrameAfterEnable
? (isStarted || mayRenderFirstFrameAfterEnableIfNotStarted)
: !renderedFirstFrameAfterReset;
long elapsedSinceLastRenderUs = SystemClock.elapsedRealtime() * 1000 - lastRenderRealtimeUs;
// Don't force output until we joined and the position reached the current stream.
return joiningDeadlineMs == C.TIME_UNSET
&& positionUs >= getOutputStreamOffsetUs()
&& (shouldRenderFirstFrame
|| (isStarted && shouldForceRenderOutputBuffer(earlyUs, elapsedSinceLastRenderUs)));
}
/** /**
* Calculates the time interval between the current player position and the buffer presentation * Calculates the time interval between the current player position and the buffer presentation
* time. * time.
...@@ -1531,17 +1534,17 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -1531,17 +1534,17 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
* @param presentationTimeUs The presentation time of the output buffer, in microseconds. * @param presentationTimeUs The presentation time of the output buffer, in microseconds.
*/ */
protected void renderOutputBuffer(MediaCodecAdapter codec, int index, long presentationTimeUs) { protected void renderOutputBuffer(MediaCodecAdapter codec, int index, long presentationTimeUs) {
if (!frameProcessorManager.isEnabled()) {
maybeNotifyVideoSizeChanged(decodedVideoSize);
}
TraceUtil.beginSection("releaseOutputBuffer"); TraceUtil.beginSection("releaseOutputBuffer");
codec.releaseOutputBuffer(index, true); codec.releaseOutputBuffer(index, true);
TraceUtil.endSection(); TraceUtil.endSection();
lastRenderRealtimeUs = SystemClock.elapsedRealtime() * 1000;
decoderCounters.renderedOutputBufferCount++; decoderCounters.renderedOutputBufferCount++;
consecutiveDroppedFrameCount = 0; consecutiveDroppedFrameCount = 0;
if (!frameProcessorManager.isEnabled()) {
lastRenderRealtimeUs = SystemClock.elapsedRealtime() * 1000;
maybeNotifyVideoSizeChanged(decodedVideoSize);
maybeNotifyRenderedFirstFrame(); maybeNotifyRenderedFirstFrame();
} }
}
/** /**
* Renders the output buffer with the specified index. This method is only called if the platform * Renders the output buffer with the specified index. This method is only called if the platform
...@@ -1559,17 +1562,17 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -1559,17 +1562,17 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
@RequiresApi(21) @RequiresApi(21)
protected void renderOutputBufferV21( protected void renderOutputBufferV21(
MediaCodecAdapter codec, int index, long presentationTimeUs, long releaseTimeNs) { MediaCodecAdapter codec, int index, long presentationTimeUs, long releaseTimeNs) {
if (!frameProcessorManager.isEnabled()) {
maybeNotifyVideoSizeChanged(decodedVideoSize);
}
TraceUtil.beginSection("releaseOutputBuffer"); TraceUtil.beginSection("releaseOutputBuffer");
codec.releaseOutputBuffer(index, releaseTimeNs); codec.releaseOutputBuffer(index, releaseTimeNs);
TraceUtil.endSection(); TraceUtil.endSection();
lastRenderRealtimeUs = SystemClock.elapsedRealtime() * 1000;
decoderCounters.renderedOutputBufferCount++; decoderCounters.renderedOutputBufferCount++;
consecutiveDroppedFrameCount = 0; consecutiveDroppedFrameCount = 0;
if (!frameProcessorManager.isEnabled()) {
lastRenderRealtimeUs = SystemClock.elapsedRealtime() * 1000;
maybeNotifyVideoSizeChanged(decodedVideoSize);
maybeNotifyRenderedFirstFrame(); maybeNotifyRenderedFirstFrame();
} }
}
private boolean shouldUsePlaceholderSurface(MediaCodecInfo codecInfo) { private boolean shouldUsePlaceholderSurface(MediaCodecInfo codecInfo) {
return Util.SDK_INT >= 23 return Util.SDK_INT >= 23
...@@ -2017,6 +2020,16 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -2017,6 +2020,16 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
throw renderer.createRendererException( throw renderer.createRendererException(
e, inputFormat, PlaybackException.ERROR_CODE_UNSPECIFIED); e, inputFormat, PlaybackException.ERROR_CODE_UNSPECIFIED);
} }
if (currentSurfaceAndSize != null) {
Size outputSurfaceSize = currentSurfaceAndSize.second;
frameProcessor.setOutputSurfaceInfo(
new SurfaceInfo(
currentSurfaceAndSize.first,
outputSurfaceSize.getWidth(),
outputSurfaceSize.getHeight()));
}
setInputFormat(inputFormat); setInputFormat(inputFormat);
return true; return true;
} }
...@@ -2035,9 +2048,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -2035,9 +2048,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
/** /**
* Sets the output surface info. * Sets the output surface info.
* *
* <p>Caller must ensure the {@code FrameProcessorManager} {@link #isEnabled()} before calling
* this method.
*
* @param outputSurface The {@link Surface} to which {@link FrameProcessor} outputs. * @param outputSurface The {@link Surface} to which {@link FrameProcessor} outputs.
* @param outputResolution The {@link Size} of the output resolution. * @param outputResolution The {@link Size} of the output resolution.
*/ */
...@@ -2047,11 +2057,14 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -2047,11 +2057,14 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
&& currentSurfaceAndSize.second.equals(outputResolution)) { && currentSurfaceAndSize.second.equals(outputResolution)) {
return; return;
} }
currentSurfaceAndSize = Pair.create(outputSurface, outputResolution);
if (isEnabled()) {
checkNotNull(frameProcessor) checkNotNull(frameProcessor)
.setOutputSurfaceInfo( .setOutputSurfaceInfo(
new SurfaceInfo( new SurfaceInfo(
outputSurface, outputResolution.getWidth(), outputResolution.getHeight())); outputSurface, outputResolution.getWidth(), outputResolution.getHeight()));
} }
}
/** /**
* Clears the set output surface info. * Clears the set output surface info.
...@@ -2152,6 +2165,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -2152,6 +2165,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
// Locking the entire releasing flow may block the FrameProcessor thread running // Locking the entire releasing flow may block the FrameProcessor thread running
// onOutputFrameAvailable(). // onOutputFrameAvailable().
while (!processedFramesTimestampsUs.isEmpty()) { while (!processedFramesTimestampsUs.isEmpty()) {
boolean isStarted = renderer.getState() == STATE_STARTED;
long bufferPresentationTimeUs = checkNotNull(processedFramesTimestampsUs.peek()); long bufferPresentationTimeUs = checkNotNull(processedFramesTimestampsUs.peek());
long earlyUs = long earlyUs =
renderer.calculateEarlyTimeUs( renderer.calculateEarlyTimeUs(
...@@ -2159,7 +2173,13 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -2159,7 +2173,13 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
elapsedRealtimeUs, elapsedRealtimeUs,
SystemClock.elapsedRealtime() * 1000, SystemClock.elapsedRealtime() * 1000,
bufferPresentationTimeUs, bufferPresentationTimeUs,
renderer.getState() == STATE_STARTED); isStarted);
boolean shouldReleaseFrameImmediately = renderer.shouldForceRender(positionUs, earlyUs);
if (shouldReleaseFrameImmediately) {
releaseOutputFrame(FrameProcessor.RELEASE_OUTPUT_FRAME_IMMEDIATELY);
break;
}
// Only release frames that are reasonably close to presentation. // Only release frames that are reasonably close to presentation.
// This way frameReleaseHelper.onNextFrame() is called only once for each frame. // This way frameReleaseHelper.onNextFrame() is called only once for each frame.
...@@ -2177,8 +2197,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -2177,8 +2197,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
// FrameProcessor input frames in this case. // FrameProcessor input frames in this case.
boolean isLastFrame = processedLastFrame && processedFramesTimestampsUs.size() == 1; boolean isLastFrame = processedLastFrame && processedFramesTimestampsUs.size() == 1;
if (renderer.shouldDropOutputBuffer(earlyUs, elapsedRealtimeUs, isLastFrame)) { if (renderer.shouldDropOutputBuffer(earlyUs, elapsedRealtimeUs, isLastFrame)) {
frameProcessor.releaseOutputFrame(FrameProcessor.DROP_OUTPUT_FRAME); releaseOutputFrame(FrameProcessor.DROP_OUTPUT_FRAME);
processedFramesTimestampsUs.remove();
continue; continue;
} }
...@@ -2194,8 +2213,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -2194,8 +2213,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
pendingOutputSizeChangeNotificationTimeUs = C.TIME_UNSET; pendingOutputSizeChangeNotificationTimeUs = C.TIME_UNSET;
renderer.maybeNotifyVideoSizeChanged(processedFrameSize); renderer.maybeNotifyVideoSizeChanged(processedFrameSize);
} }
frameProcessor.releaseOutputFrame(adjustedFrameReleaseTimeNs); releaseOutputFrame(adjustedFrameReleaseTimeNs);
processedFramesTimestampsUs.remove();
if (isLastFrame) { if (isLastFrame) {
releasedLastFrame = true; releasedLastFrame = true;
} }
...@@ -2221,6 +2239,16 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -2221,6 +2239,16 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
canEnableFrameProcessing = true; canEnableFrameProcessing = true;
} }
private void releaseOutputFrame(long releaseTimeNs) {
checkStateNotNull(frameProcessor);
frameProcessor.releaseOutputFrame(releaseTimeNs);
processedFramesTimestampsUs.remove();
renderer.lastRenderRealtimeUs = SystemClock.elapsedRealtime() * 1000;
if (releaseTimeNs != FrameProcessor.DROP_OUTPUT_FRAME) {
renderer.maybeNotifyRenderedFirstFrame();
}
}
private static final class FrameProcessorAccessor { private static final class FrameProcessorAccessor {
private static @MonotonicNonNull Constructor<?> scaleToFitTransformationBuilderConstructor; private static @MonotonicNonNull Constructor<?> scaleToFitTransformationBuilderConstructor;
......
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