Allow changing input pixelWidthHeightRatio for GlEffectsFrameProcessor.

pixelWidthHeightRatio is now passed to setInputFrameInfo instead of
the factory.

PiperOrigin-RevId: 457696703
This commit is contained in:
hschlueter 2022-06-28 11:22:45 +00:00 committed by Marc Baechinger
parent b7241d4eb3
commit b7b5f20e59
5 changed files with 35 additions and 41 deletions

View File

@ -366,7 +366,6 @@ public final class GlEffectsFrameProcessorPixelTest {
frameProcessingEnded = true; frameProcessingEnded = true;
} }
}, },
pixelWidthHeightRatio,
/* streamOffsetUs= */ 0L, /* streamOffsetUs= */ 0L,
effects, effects,
/* outputSurfaceProvider= */ (requestedWidth, requestedHeight) -> { /* outputSurfaceProvider= */ (requestedWidth, requestedHeight) -> {
@ -381,7 +380,8 @@ public final class GlEffectsFrameProcessorPixelTest {
}, },
Transformer.DebugViewProvider.NONE, Transformer.DebugViewProvider.NONE,
/* enableExperimentalHdrEditing= */ false)); /* enableExperimentalHdrEditing= */ false));
glEffectsFrameProcessor.setInputFrameInfo(new FrameInfo(inputWidth, inputHeight)); glEffectsFrameProcessor.setInputFrameInfo(
new FrameInfo(inputWidth, inputHeight, pixelWidthHeightRatio));
glEffectsFrameProcessor.registerInputFrame(); glEffectsFrameProcessor.registerInputFrame();
// Queue the first video frame from the extractor. // Queue the first video frame from the extractor.

View File

@ -23,15 +23,17 @@ import static androidx.media3.common.util.Assertions.checkArgument;
public final int width; public final int width;
/** The height of the frame, in pixels. */ /** The height of the frame, in pixels. */
public final int height; public final int height;
/** The ratio of width over height for each pixel. */
public final float pixelWidthHeightRatio;
// TODO(b/227625423): Add pixelWidthHeightRatio.
// TODO(b/227624622): Add color space information for HDR. // TODO(b/227624622): Add color space information for HDR.
public FrameInfo(int width, int height) { public FrameInfo(int width, int height, float pixelWidthHeightRatio) {
checkArgument(width > 0, "width must be positive, but is: " + width); checkArgument(width > 0, "width must be positive, but is: " + width);
checkArgument(height > 0, "height must be positive, but is: " + height); checkArgument(height > 0, "height must be positive, but is: " + height);
this.width = width; this.width = width;
this.height = height; this.height = height;
this.pixelWidthHeightRatio = pixelWidthHeightRatio;
} }
} }

View File

@ -46,6 +46,9 @@ import android.view.Surface;
* *
* <p>The new input information is applied from the next frame {@linkplain #registerInputFrame() * <p>The new input information is applied from the next frame {@linkplain #registerInputFrame()
* registered} onwards. * registered} onwards.
*
* <p>Pixels are expanded using the {@link FrameInfo#pixelWidthHeightRatio} so that the output
* frames' pixels have a ratio of 1.
*/ */
void setInputFrameInfo(FrameInfo inputFrameInfo); void setInputFrameInfo(FrameInfo inputFrameInfo);

View File

@ -50,8 +50,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
* *
* @param context A {@link Context}. * @param context A {@link Context}.
* @param listener A {@link Listener}. * @param listener A {@link Listener}.
* @param pixelWidthHeightRatio The ratio of width over height for each pixel. Pixels are expanded
* by this ratio so that the output frame's pixels have a ratio of 1.
* @param effects The {@link GlEffect GlEffects} to apply to each frame. * @param effects The {@link GlEffect GlEffects} to apply to each frame.
* @param outputSurfaceProvider A {@link SurfaceInfo.Provider} managing the output {@link * @param outputSurfaceProvider A {@link SurfaceInfo.Provider} managing the output {@link
* Surface}. * Surface}.
@ -64,7 +62,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
public static GlEffectsFrameProcessor create( public static GlEffectsFrameProcessor create(
Context context, Context context,
FrameProcessor.Listener listener, FrameProcessor.Listener listener,
float pixelWidthHeightRatio,
long streamOffsetUs, long streamOffsetUs,
List<GlEffect> effects, List<GlEffect> effects,
SurfaceInfo.Provider outputSurfaceProvider, SurfaceInfo.Provider outputSurfaceProvider,
@ -80,7 +77,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
createOpenGlObjectsAndFrameProcessor( createOpenGlObjectsAndFrameProcessor(
context, context,
listener, listener,
pixelWidthHeightRatio,
streamOffsetUs, streamOffsetUs,
effects, effects,
outputSurfaceProvider, outputSurfaceProvider,
@ -110,7 +106,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
private static GlEffectsFrameProcessor createOpenGlObjectsAndFrameProcessor( private static GlEffectsFrameProcessor createOpenGlObjectsAndFrameProcessor(
Context context, Context context,
FrameProcessor.Listener listener, FrameProcessor.Listener listener,
float pixelWidthHeightRatio,
long streamOffsetUs, long streamOffsetUs,
List<GlEffect> effects, List<GlEffect> effects,
SurfaceInfo.Provider outputSurfaceProvider, SurfaceInfo.Provider outputSurfaceProvider,
@ -136,20 +131,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
GlUtil.focusPlaceholderEglSurface(eglContext, eglDisplay); GlUtil.focusPlaceholderEglSurface(eglContext, eglDisplay);
} }
ImmutableList.Builder<GlMatrixTransformation> matrixTransformationListBuilder =
new ImmutableList.Builder<>();
if (pixelWidthHeightRatio != 1f) {
matrixTransformationListBuilder.add(
createPixelWidthHeightRatioTransformation(pixelWidthHeightRatio));
}
ImmutableList<GlTextureProcessor> textureProcessors = ImmutableList<GlTextureProcessor> textureProcessors =
getGlTextureProcessorsForGlEffects( getGlTextureProcessorsForGlEffects(
context, context,
effects, effects,
eglDisplay, eglDisplay,
eglContext, eglContext,
matrixTransformationListBuilder,
outputSurfaceProvider, outputSurfaceProvider,
streamOffsetUs, streamOffsetUs,
listener, listener,
@ -173,26 +160,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
textureProcessors); textureProcessors);
} }
/**
* Returns a new {@link GlMatrixTransformation} to expand or shrink the frame based on the {@code
* pixelWidthHeightRatio}.
*
* <p>If {@code pixelWidthHeightRatio} is 1, this method returns an identity transformation that
* can be ignored.
*/
private static GlMatrixTransformation createPixelWidthHeightRatioTransformation(
float pixelWidthHeightRatio) {
if (pixelWidthHeightRatio > 1f) {
return new ScaleToFitTransformation.Builder()
.setScale(/* scaleX= */ pixelWidthHeightRatio, /* scaleY= */ 1f)
.build();
} else {
return new ScaleToFitTransformation.Builder()
.setScale(/* scaleX= */ 1f, /* scaleY= */ 1f / pixelWidthHeightRatio)
.build();
}
}
/** /**
* Combines consecutive {@link GlMatrixTransformation} instances into a single {@link * Combines consecutive {@link GlMatrixTransformation} instances into a single {@link
* MatrixTransformationProcessor} and converts all other {@link GlEffect} instances to separate * MatrixTransformationProcessor} and converts all other {@link GlEffect} instances to separate
@ -207,7 +174,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
List<GlEffect> effects, List<GlEffect> effects,
EGLDisplay eglDisplay, EGLDisplay eglDisplay,
EGLContext eglContext, EGLContext eglContext,
ImmutableList.Builder<GlMatrixTransformation> matrixTransformationListBuilder,
SurfaceInfo.Provider outputSurfaceProvider, SurfaceInfo.Provider outputSurfaceProvider,
long streamOffsetUs, long streamOffsetUs,
FrameProcessor.Listener listener, FrameProcessor.Listener listener,
@ -216,6 +182,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
throws FrameProcessingException { throws FrameProcessingException {
ImmutableList.Builder<GlTextureProcessor> textureProcessorListBuilder = ImmutableList.Builder<GlTextureProcessor> textureProcessorListBuilder =
new ImmutableList.Builder<>(); new ImmutableList.Builder<>();
ImmutableList.Builder<GlMatrixTransformation> matrixTransformationListBuilder =
new ImmutableList.Builder<>();
for (int i = 0; i < effects.size(); i++) { for (int i = 0; i < effects.size(); i++) {
GlEffect effect = effects.get(i); GlEffect effect = effects.get(i);
if (effect instanceof GlMatrixTransformation) { if (effect instanceof GlMatrixTransformation) {
@ -396,7 +364,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
long presentationTimeUs = inputFrameTimeNs / 1000 - streamOffsetUs; long presentationTimeUs = inputFrameTimeNs / 1000 - streamOffsetUs;
inputSurfaceTexture.getTransformMatrix(inputSurfaceTextureTransformMatrix); inputSurfaceTexture.getTransformMatrix(inputSurfaceTextureTransformMatrix);
inputExternalTextureProcessor.setTextureTransformMatrix(inputSurfaceTextureTransformMatrix); inputExternalTextureProcessor.setTextureTransformMatrix(inputSurfaceTextureTransformMatrix);
FrameInfo inputFrameInfo = pendingInputFrames.remove(); FrameInfo inputFrameInfo = adjustForPixelWidthHeightRatio(pendingInputFrames.remove());
checkState( checkState(
inputExternalTextureProcessor.maybeQueueInputFrame( inputExternalTextureProcessor.maybeQueueInputFrame(
new TextureInfo( new TextureInfo(
@ -409,6 +377,27 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
// asynchronously by the texture processors chained after it. // asynchronously by the texture processors chained after it.
} }
/**
* Expands or shrinks the frame based on the {@link FrameInfo#pixelWidthHeightRatio} and returns a
* new {@link FrameInfo} instance with scaled dimensions and {@link
* FrameInfo#pixelWidthHeightRatio} 1.
*/
private FrameInfo adjustForPixelWidthHeightRatio(FrameInfo frameInfo) {
if (frameInfo.pixelWidthHeightRatio > 1f) {
return new FrameInfo(
(int) (frameInfo.width * frameInfo.pixelWidthHeightRatio),
frameInfo.height,
/* pixelWidthHeightRatio= */ 1);
} else if (frameInfo.pixelWidthHeightRatio < 1f) {
return new FrameInfo(
frameInfo.width,
(int) (frameInfo.height / frameInfo.pixelWidthHeightRatio),
/* pixelWidthHeightRatio= */ 1);
} else {
return frameInfo;
}
}
/** /**
* Propagates the end-of-stream signal through the texture processors once no more input frames * Propagates the end-of-stream signal through the texture processors once no more input frames
* are pending. * are pending.

View File

@ -119,7 +119,6 @@ import org.checkerframework.dataflow.qual.Pure;
} }
} }
}, },
inputFormat.pixelWidthHeightRatio,
streamOffsetUs, streamOffsetUs,
effectsListBuilder.build(), effectsListBuilder.build(),
/* outputSurfaceProvider= */ encoderWrapper, /* outputSurfaceProvider= */ encoderWrapper,
@ -129,7 +128,8 @@ import org.checkerframework.dataflow.qual.Pure;
throw TransformationException.createForFrameProcessingException( throw TransformationException.createForFrameProcessingException(
e, TransformationException.ERROR_CODE_GL_INIT_FAILED); e, TransformationException.ERROR_CODE_GL_INIT_FAILED);
} }
frameProcessor.setInputFrameInfo(new FrameInfo(decodedWidth, decodedHeight)); frameProcessor.setInputFrameInfo(
new FrameInfo(decodedWidth, decodedHeight, inputFormat.pixelWidthHeightRatio));
decoder = decoder =
decoderFactory.createForVideoDecoding( decoderFactory.createForVideoDecoding(