Allow changing input pixelWidthHeightRatio for GlEffectsFrameProcessor.
pixelWidthHeightRatio is now passed to setInputFrameInfo instead of the factory. PiperOrigin-RevId: 457696703
This commit is contained in:
parent
b7241d4eb3
commit
b7b5f20e59
@ -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.
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user