Commit 37559dea by hschlueter Committed by Ian Baker

Configure the frame sizes in FrameProcessorChain instead of caller.

Configuring the frame sizes between frame processors is now the
FrameProcessorChain's rather than the caller's responsibility.
The caller can getOutputSize() and override it for encoder fallback
in configure().

PiperOrigin-RevId: 437048436
parent 20daaa20
......@@ -41,9 +41,7 @@ import android.util.Size;
import androidx.annotation.Nullable;
import androidx.media3.common.MimeTypes;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.common.collect.Iterables;
import java.nio.ByteBuffer;
import java.util.List;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.junit.After;
import org.junit.Test;
......@@ -247,24 +245,26 @@ public final class FrameProcessorChainPixelTest {
int inputWidth = checkNotNull(mediaFormat).getInteger(MediaFormat.KEY_WIDTH);
int inputHeight = mediaFormat.getInteger(MediaFormat.KEY_HEIGHT);
List<GlFrameProcessor> frameProcessorsList = asList(frameProcessors);
List<Size> sizes =
FrameProcessorChain.configureSizes(inputWidth, inputHeight, frameProcessorsList);
assertThat(sizes).isNotEmpty();
int outputWidth = Iterables.getLast(sizes).getWidth();
int outputHeight = Iterables.getLast(sizes).getHeight();
outputImageReader =
ImageReader.newInstance(
outputWidth, outputHeight, PixelFormat.RGBA_8888, /* maxImages= */ 1);
frameProcessorChain =
new FrameProcessorChain(
context,
PIXEL_WIDTH_HEIGHT_RATIO,
frameProcessorsList,
sizes,
inputWidth,
inputHeight,
asList(frameProcessors),
/* enableExperimentalHdrEditing= */ false);
Size outputSize = frameProcessorChain.getOutputSize();
outputImageReader =
ImageReader.newInstance(
outputSize.getWidth(),
outputSize.getHeight(),
PixelFormat.RGBA_8888,
/* maxImages= */ 1);
frameProcessorChain.configure(
outputImageReader.getSurface(), outputWidth, outputHeight, /* debugSurfaceView= */ null);
outputImageReader.getSurface(),
outputSize.getWidth(),
outputSize.getHeight(),
/* debugSurfaceView= */ null);
frameProcessorChain.registerInputFrame();
// Queue the first video frame from the extractor.
......
......@@ -29,7 +29,6 @@ import androidx.media3.common.Format;
import androidx.media3.common.util.Util;
import androidx.media3.decoder.DecoderInputBuffer;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import java.util.List;
import org.checkerframework.dataflow.qual.Pure;
......@@ -70,6 +69,7 @@ import org.checkerframework.dataflow.qual.Pure;
int decodedHeight =
(inputFormat.rotationDegrees % 180 == 0) ? inputFormat.height : inputFormat.width;
// TODO(b/214975934): Allow a list of frame processors to be passed into the sample pipeline.
// TODO(b/213190310): Don't create a ScaleToFitFrameProcessor if scale and rotation are unset.
ScaleToFitFrameProcessor scaleToFitFrameProcessor =
new ScaleToFitFrameProcessor.Builder(context)
......@@ -80,13 +80,15 @@ import org.checkerframework.dataflow.qual.Pure;
new PresentationFrameProcessor.Builder(context)
.setResolution(transformationRequest.outputHeight)
.build();
// TODO(b/214975934): Allow a list of frame processors to be passed into the sample pipeline.
ImmutableList<GlFrameProcessor> frameProcessors =
ImmutableList.of(scaleToFitFrameProcessor, presentationFrameProcessor);
List<Size> frameProcessorSizes =
FrameProcessorChain.configureSizes(decodedWidth, decodedHeight, frameProcessors);
Size requestedEncoderSize = Iterables.getLast(frameProcessorSizes);
// TODO(b/213190310): Move output rotation configuration to PresentationFrameProcessor.
frameProcessorChain =
new FrameProcessorChain(
context,
inputFormat.pixelWidthHeightRatio,
/* inputWidth= */ decodedWidth,
/* inputHeight= */ decodedHeight,
ImmutableList.of(scaleToFitFrameProcessor, presentationFrameProcessor),
transformationRequest.enableHdrEditing);
Size requestedEncoderSize = frameProcessorChain.getOutputSize();
outputRotationDegrees = presentationFrameProcessor.getOutputRotationDegrees();
Format requestedEncoderFormat =
......@@ -110,13 +112,6 @@ import org.checkerframework.dataflow.qual.Pure;
requestedEncoderFormat,
encoderSupportedFormat));
frameProcessorChain =
new FrameProcessorChain(
context,
inputFormat.pixelWidthHeightRatio,
frameProcessors,
frameProcessorSizes,
transformationRequest.enableHdrEditing);
frameProcessorChain.configure(
/* outputSurface= */ encoder.getInputSurface(),
/* outputWidth= */ encoderSupportedFormat.width,
......
......@@ -35,6 +35,7 @@ import org.junit.runner.RunWith;
*/
@RunWith(AndroidJUnit4.class)
public final class FrameProcessorChainTest {
@Test
public void construct_withSupportedPixelWidthHeightRatio_completesSuccessfully()
throws TransformationException {
......@@ -43,8 +44,9 @@ public final class FrameProcessorChainTest {
new FrameProcessorChain(
context,
/* pixelWidthHeightRatio= */ 1,
/* inputWidth= */ 200,
/* inputHeight= */ 100,
/* frameProcessors= */ ImmutableList.of(),
/* sizes= */ ImmutableList.of(new Size(200, 100)),
/* enableExperimentalHdrEditing= */ false);
}
......@@ -59,8 +61,9 @@ public final class FrameProcessorChainTest {
new FrameProcessorChain(
context,
/* pixelWidthHeightRatio= */ 2,
/* inputWidth= */ 200,
/* inputHeight= */ 100,
/* frameProcessors= */ ImmutableList.of(),
/* sizes= */ ImmutableList.of(new Size(200, 100)),
/* enableExperimentalHdrEditing= */ false));
assertThat(exception).hasCauseThat().isInstanceOf(UnsupportedOperationException.class);
......@@ -68,46 +71,63 @@ public final class FrameProcessorChainTest {
}
@Test
public void configureOutputDimensions_withEmptyList_returnsInputSize() {
public void getOutputSize_withoutFrameProcessors_returnsInputSize()
throws TransformationException {
Size inputSize = new Size(200, 100);
FrameProcessorChain frameProcessorChain =
createFrameProcessorChainWithFakeFrameProcessors(
inputSize, /* frameProcessorOutputSizes= */ ImmutableList.of());
List<Size> sizes =
FrameProcessorChain.configureSizes(
inputSize.getWidth(), inputSize.getHeight(), /* frameProcessors= */ ImmutableList.of());
Size outputSize = frameProcessorChain.getOutputSize();
assertThat(sizes).containsExactly(inputSize);
assertThat(outputSize).isEqualTo(inputSize);
}
@Test
public void configureOutputDimensions_withOneFrameProcessor_returnsItsInputAndOutputDimensions() {
public void getOutputSize_withOneFrameProcessor_returnsItsOutputSize()
throws TransformationException {
Size inputSize = new Size(200, 100);
Size outputSize = new Size(300, 250);
GlFrameProcessor frameProcessor = new FakeFrameProcessor(outputSize);
Size frameProcessorOutputSize = new Size(300, 250);
FrameProcessorChain frameProcessorChain =
createFrameProcessorChainWithFakeFrameProcessors(
inputSize, /* frameProcessorOutputSizes= */ ImmutableList.of(frameProcessorOutputSize));
List<Size> sizes =
FrameProcessorChain.configureSizes(
inputSize.getWidth(), inputSize.getHeight(), ImmutableList.of(frameProcessor));
Size frameProcessorChainOutputSize = frameProcessorChain.getOutputSize();
assertThat(sizes).containsExactly(inputSize, outputSize).inOrder();
assertThat(frameProcessorChainOutputSize).isEqualTo(frameProcessorOutputSize);
}
@Test
public void configureOutputDimensions_withThreeFrameProcessors_propagatesOutputDimensions() {
public void getOutputSize_withThreeFrameProcessors_returnsLastOutputSize()
throws TransformationException {
Size inputSize = new Size(200, 100);
Size outputSize1 = new Size(300, 250);
Size outputSize2 = new Size(400, 244);
Size outputSize3 = new Size(150, 160);
GlFrameProcessor frameProcessor1 = new FakeFrameProcessor(outputSize1);
GlFrameProcessor frameProcessor2 = new FakeFrameProcessor(outputSize2);
GlFrameProcessor frameProcessor3 = new FakeFrameProcessor(outputSize3);
FrameProcessorChain frameProcessorChain =
createFrameProcessorChainWithFakeFrameProcessors(
inputSize,
/* frameProcessorOutputSizes= */ ImmutableList.of(
outputSize1, outputSize2, outputSize3));
Size frameProcessorChainOutputSize = frameProcessorChain.getOutputSize();
List<Size> sizes =
FrameProcessorChain.configureSizes(
assertThat(frameProcessorChainOutputSize).isEqualTo(outputSize3);
}
private static FrameProcessorChain createFrameProcessorChainWithFakeFrameProcessors(
Size inputSize, List<Size> frameProcessorOutputSizes) throws TransformationException {
ImmutableList.Builder<GlFrameProcessor> frameProcessors = new ImmutableList.Builder<>();
for (Size element : frameProcessorOutputSizes) {
frameProcessors.add(new FakeFrameProcessor(element));
}
return new FrameProcessorChain(
getApplicationContext(),
/* pixelWidthHeightRatio= */ 1,
inputSize.getWidth(),
inputSize.getHeight(),
ImmutableList.of(frameProcessor1, frameProcessor2, frameProcessor3));
assertThat(sizes).containsExactly(inputSize, outputSize1, outputSize2, outputSize3).inOrder();
frameProcessors.build(),
/* enableExperimentalHdrEditing= */ false);
}
private static class FakeFrameProcessor implements GlFrameProcessor {
......
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