Decouple output size listener and setting output surface

This is because `onOutputSizeChanged()` should in theory be called on the
listener executor.

PiperOrigin-RevId: 566591784
This commit is contained in:
claincly 2023-09-19 04:40:30 -07:00 committed by Copybara-Service
parent 0c918d2c47
commit 24e700c216
4 changed files with 39 additions and 13 deletions

View File

@ -40,6 +40,7 @@ import androidx.media3.common.Effect;
import androidx.media3.common.FrameInfo;
import androidx.media3.common.GlObjectsProvider;
import androidx.media3.common.GlTextureInfo;
import androidx.media3.common.SurfaceInfo;
import androidx.media3.common.VideoFrameProcessingException;
import androidx.media3.common.VideoFrameProcessor;
import androidx.media3.common.util.Consumer;
@ -195,8 +196,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
@Override
public void onOutputSizeChanged(int width, int height) {
checkNotNull(compositionVideoFrameProcessor)
.setOutputSurfaceInfo(listener.onOutputSizeChanged(width, height));
listenerExecutor.execute(() -> listener.onOutputSizeChanged(width, height));
}
@Override
@ -297,6 +297,11 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
return preProcessingVideoFrameProcessorWrapper;
}
@Override
public void setOutputSurfaceInfo(@Nullable SurfaceInfo outputSurfaceInfo) {
checkNotNull(compositionVideoFrameProcessor).setOutputSurfaceInfo(outputSurfaceInfo);
}
@Override
public boolean hasProducedFrameWithTimestampZero() {
return hasProducedFrameWithTimestampZero;

View File

@ -25,6 +25,7 @@ import androidx.media3.common.ColorInfo;
import androidx.media3.common.DebugViewProvider;
import androidx.media3.common.Effect;
import androidx.media3.common.FrameInfo;
import androidx.media3.common.SurfaceInfo;
import androidx.media3.common.VideoFrameProcessingException;
import androidx.media3.common.VideoFrameProcessor;
import androidx.media3.common.util.Consumer;
@ -157,9 +158,7 @@ import java.util.concurrent.Executor;
@Override
public void onOutputSizeChanged(int width, int height) {
// TODO: b/289986435 - Allow setting output surface info on VideoGraph.
checkNotNull(videoFrameProcessingWrapper)
.setOutputSurfaceInfo(listener.onOutputSizeChanged(width, height));
listenerExecutor.execute(() -> listener.onOutputSizeChanged(width, height));
}
@Override
@ -188,6 +187,11 @@ import java.util.concurrent.Executor;
return videoFrameProcessingWrapper;
}
@Override
public void setOutputSurfaceInfo(@Nullable SurfaceInfo outputSurfaceInfo) {
checkNotNull(videoFrameProcessingWrapper).setOutputSurfaceInfo(outputSurfaceInfo);
}
@Override
public boolean hasProducedFrameWithTimestampZero() {
return hasProducedFrameWithTimestampZero;

View File

@ -68,12 +68,8 @@ import java.util.concurrent.Executor;
*
* @param width The new output width in pixels.
* @param height The new output width in pixels.
* @return A {@link SurfaceInfo} to which the {@link VideoGraph} renders to, or {@code null} if
* the output is not needed.
*/
// TODO - b/289985577: Consider returning void from this method.
@Nullable
SurfaceInfo onOutputSizeChanged(int width, int height);
void onOutputSizeChanged(int width, int height);
/** Called after the {@link VideoGraph} has rendered its final output frame. */
void onEnded(long finalFramePresentationTimeUs);
@ -108,6 +104,23 @@ import java.util.concurrent.Executor;
*/
GraphInput createInput() throws VideoFrameProcessingException;
/**
* Sets the output surface and supporting information.
*
* <p>The new output {@link SurfaceInfo} is applied from the next output frame rendered onwards.
* If the output {@link SurfaceInfo} is {@code null}, the {@code VideoGraph} will stop rendering
* pending frames and resume rendering once a non-null {@link SurfaceInfo} is set.
*
* <p>If the dimensions given in {@link SurfaceInfo} do not match the {@linkplain
* Listener#onOutputSizeChanged(int,int) output size after applying the final effect} the frames
* are resized before rendering to the surface and letter/pillar-boxing is applied.
*
* <p>The caller is responsible for tracking the lifecycle of the {@link SurfaceInfo#surface}
* including calling this method with a new surface if it is destroyed. When this method returns,
* the previous output surface is no longer being used and can safely be released by the caller.
*/
void setOutputSurfaceInfo(@Nullable SurfaceInfo outputSurfaceInfo);
/**
* Returns whether the {@code VideoGraph} has produced a frame with zero presentation timestamp.
*/

View File

@ -498,16 +498,15 @@ import org.checkerframework.dataflow.qual.Pure;
initialTimestampOffsetUs);
}
@Nullable
@Override
public SurfaceInfo onOutputSizeChanged(int width, int height) {
public void onOutputSizeChanged(int width, int height) {
@Nullable SurfaceInfo surfaceInfo = null;
try {
surfaceInfo = encoderWrapper.getSurfaceInfo(width, height);
} catch (ExportException e) {
errorConsumer.accept(e);
}
return surfaceInfo;
setOutputSurfaceInfo(surfaceInfo);
}
@Override
@ -535,6 +534,11 @@ import org.checkerframework.dataflow.qual.Pure;
return videoGraph.createInput();
}
@Override
public void setOutputSurfaceInfo(@Nullable SurfaceInfo outputSurfaceInfo) {
videoGraph.setOutputSurfaceInfo(outputSurfaceInfo);
}
@Override
public boolean hasProducedFrameWithTimestampZero() {
return videoGraph.hasProducedFrameWithTimestampZero();