Commit a5180432 by hschlueter Committed by Ian Baker

Merge GlFrameProcessor#setInputSize() and initialize().

PiperOrigin-RevId: 439266087
parent 9f7abd4f
...@@ -91,7 +91,7 @@ public final class AdvancedFrameProcessorPixelTest { ...@@ -91,7 +91,7 @@ public final class AdvancedFrameProcessorPixelTest {
String testId = "updateProgramAndDraw_noEdits"; String testId = "updateProgramAndDraw_noEdits";
Matrix identityMatrix = new Matrix(); Matrix identityMatrix = new Matrix();
advancedFrameProcessor = new AdvancedFrameProcessor(getApplicationContext(), identityMatrix); advancedFrameProcessor = new AdvancedFrameProcessor(getApplicationContext(), identityMatrix);
advancedFrameProcessor.initialize(inputTexId); advancedFrameProcessor.initialize(inputTexId, width, height);
Bitmap expectedBitmap = BitmapTestUtil.readBitmap(FIRST_FRAME_PNG_ASSET_STRING); Bitmap expectedBitmap = BitmapTestUtil.readBitmap(FIRST_FRAME_PNG_ASSET_STRING);
advancedFrameProcessor.updateProgramAndDraw(/* presentationTimeUs= */ 0); advancedFrameProcessor.updateProgramAndDraw(/* presentationTimeUs= */ 0);
...@@ -114,7 +114,7 @@ public final class AdvancedFrameProcessorPixelTest { ...@@ -114,7 +114,7 @@ public final class AdvancedFrameProcessorPixelTest {
translateRightMatrix.postTranslate(/* dx= */ 1, /* dy= */ 0); translateRightMatrix.postTranslate(/* dx= */ 1, /* dy= */ 0);
advancedFrameProcessor = advancedFrameProcessor =
new AdvancedFrameProcessor(getApplicationContext(), translateRightMatrix); new AdvancedFrameProcessor(getApplicationContext(), translateRightMatrix);
advancedFrameProcessor.initialize(inputTexId); advancedFrameProcessor.initialize(inputTexId, width, height);
Bitmap expectedBitmap = Bitmap expectedBitmap =
BitmapTestUtil.readBitmap(TRANSLATE_RIGHT_EXPECTED_OUTPUT_PNG_ASSET_STRING); BitmapTestUtil.readBitmap(TRANSLATE_RIGHT_EXPECTED_OUTPUT_PNG_ASSET_STRING);
...@@ -137,7 +137,7 @@ public final class AdvancedFrameProcessorPixelTest { ...@@ -137,7 +137,7 @@ public final class AdvancedFrameProcessorPixelTest {
Matrix scaleNarrowMatrix = new Matrix(); Matrix scaleNarrowMatrix = new Matrix();
scaleNarrowMatrix.postScale(.5f, 1.2f); scaleNarrowMatrix.postScale(.5f, 1.2f);
advancedFrameProcessor = new AdvancedFrameProcessor(getApplicationContext(), scaleNarrowMatrix); advancedFrameProcessor = new AdvancedFrameProcessor(getApplicationContext(), scaleNarrowMatrix);
advancedFrameProcessor.initialize(inputTexId); advancedFrameProcessor.initialize(inputTexId, width, height);
Bitmap expectedBitmap = Bitmap expectedBitmap =
BitmapTestUtil.readBitmap(SCALE_NARROW_EXPECTED_OUTPUT_PNG_ASSET_STRING); BitmapTestUtil.readBitmap(SCALE_NARROW_EXPECTED_OUTPUT_PNG_ASSET_STRING);
...@@ -160,7 +160,7 @@ public final class AdvancedFrameProcessorPixelTest { ...@@ -160,7 +160,7 @@ public final class AdvancedFrameProcessorPixelTest {
Matrix rotate90Matrix = new Matrix(); Matrix rotate90Matrix = new Matrix();
rotate90Matrix.postRotate(/* degrees= */ 90); rotate90Matrix.postRotate(/* degrees= */ 90);
advancedFrameProcessor = new AdvancedFrameProcessor(getApplicationContext(), rotate90Matrix); advancedFrameProcessor = new AdvancedFrameProcessor(getApplicationContext(), rotate90Matrix);
advancedFrameProcessor.initialize(inputTexId); advancedFrameProcessor.initialize(inputTexId, width, height);
Bitmap expectedBitmap = BitmapTestUtil.readBitmap(ROTATE_90_EXPECTED_OUTPUT_PNG_ASSET_STRING); Bitmap expectedBitmap = BitmapTestUtil.readBitmap(ROTATE_90_EXPECTED_OUTPUT_PNG_ASSET_STRING);
advancedFrameProcessor.updateProgramAndDraw(/* presentationTimeUs= */ 0); advancedFrameProcessor.updateProgramAndDraw(/* presentationTimeUs= */ 0);
......
...@@ -138,7 +138,7 @@ public final class FrameProcessorChainTest { ...@@ -138,7 +138,7 @@ public final class FrameProcessorChainTest {
} }
@Override @Override
public void setInputSize(int inputWidth, int inputHeight) {} public void initialize(int inputTexId, int inputWidth, int inputHeight) {}
@Override @Override
public Size getOutputSize() { public Size getOutputSize() {
...@@ -146,9 +146,6 @@ public final class FrameProcessorChainTest { ...@@ -146,9 +146,6 @@ public final class FrameProcessorChainTest {
} }
@Override @Override
public void initialize(int inputTexId) {}
@Override
public void updateProgramAndDraw(long presentationTimeNs) {} public void updateProgramAndDraw(long presentationTimeNs) {}
@Override @Override
......
...@@ -104,17 +104,8 @@ public final class AdvancedFrameProcessor implements GlFrameProcessor { ...@@ -104,17 +104,8 @@ public final class AdvancedFrameProcessor implements GlFrameProcessor {
} }
@Override @Override
public void setInputSize(int inputWidth, int inputHeight) { public void initialize(int inputTexId, int inputWidth, int inputHeight) throws IOException {
size = new Size(inputWidth, inputHeight); size = new Size(inputWidth, inputHeight);
}
@Override
public Size getOutputSize() {
return checkStateNotNull(size);
}
@Override
public void initialize(int inputTexId) throws IOException {
// TODO(b/205002913): check the loaded program is consistent with the attributes and uniforms // TODO(b/205002913): check the loaded program is consistent with the attributes and uniforms
// expected in the code. // expected in the code.
glProgram = new GlProgram(context, VERTEX_SHADER_TRANSFORMATION_PATH, FRAGMENT_SHADER_PATH); glProgram = new GlProgram(context, VERTEX_SHADER_TRANSFORMATION_PATH, FRAGMENT_SHADER_PATH);
...@@ -128,6 +119,11 @@ public final class AdvancedFrameProcessor implements GlFrameProcessor { ...@@ -128,6 +119,11 @@ public final class AdvancedFrameProcessor implements GlFrameProcessor {
} }
@Override @Override
public Size getOutputSize() {
return checkStateNotNull(size);
}
@Override
public void updateProgramAndDraw(long presentationTimeUs) { public void updateProgramAndDraw(long presentationTimeUs) {
checkStateNotNull(glProgram); checkStateNotNull(glProgram);
glProgram.use(); glProgram.use();
......
...@@ -60,17 +60,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -60,17 +60,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
} }
@Override @Override
public void setInputSize(int inputWidth, int inputHeight) { public void initialize(int inputTexId, int inputWidth, int inputHeight) throws IOException {
size = new Size(inputWidth, inputHeight); size = new Size(inputWidth, inputHeight);
}
@Override
public Size getOutputSize() {
return checkStateNotNull(size);
}
@Override
public void initialize(int inputTexId) throws IOException {
// TODO(b/205002913): check the loaded program is consistent with the attributes and uniforms // TODO(b/205002913): check the loaded program is consistent with the attributes and uniforms
// expected in the code. // expected in the code.
String vertexShaderFilePath = String vertexShaderFilePath =
...@@ -94,6 +85,11 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -94,6 +85,11 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
} }
} }
@Override
public Size getOutputSize() {
return checkStateNotNull(size);
}
/** /**
* Sets the texture transform matrix for converting an external surface texture's coordinates to * Sets the texture transform matrix for converting an external surface texture's coordinates to
* sampling locations. * sampling locations.
......
...@@ -154,16 +154,14 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -154,16 +154,14 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
} }
int inputExternalTexId = GlUtil.createExternalTexture(); int inputExternalTexId = GlUtil.createExternalTexture();
externalCopyFrameProcessor.setInputSize(inputWidth, inputHeight); externalCopyFrameProcessor.initialize(inputExternalTexId, inputWidth, inputHeight);
externalCopyFrameProcessor.initialize(inputExternalTexId);
int[] framebuffers = new int[frameProcessors.size()]; int[] framebuffers = new int[frameProcessors.size()];
Size inputSize = externalCopyFrameProcessor.getOutputSize(); Size inputSize = externalCopyFrameProcessor.getOutputSize();
for (int i = 0; i < frameProcessors.size(); i++) { for (int i = 0; i < frameProcessors.size(); i++) {
int inputTexId = GlUtil.createTexture(inputSize.getWidth(), inputSize.getHeight()); int inputTexId = GlUtil.createTexture(inputSize.getWidth(), inputSize.getHeight());
framebuffers[i] = GlUtil.createFboForTexture(inputTexId); framebuffers[i] = GlUtil.createFboForTexture(inputTexId);
frameProcessors.get(i).setInputSize(inputSize.getWidth(), inputSize.getHeight()); frameProcessors.get(i).initialize(inputTexId, inputSize.getWidth(), inputSize.getHeight());
frameProcessors.get(i).initialize(inputTexId);
inputSize = frameProcessors.get(i).getOutputSize(); inputSize = frameProcessors.get(i).getOutputSize();
} }
return new FrameProcessorChain( return new FrameProcessorChain(
......
...@@ -25,49 +25,40 @@ import java.io.IOException; ...@@ -25,49 +25,40 @@ import java.io.IOException;
* *
* <ol> * <ol>
* <li>The constructor, for implementation-specific arguments. * <li>The constructor, for implementation-specific arguments.
* <li>{@link #setInputSize(int, int)}, to configure based on input dimensions. * <li>{@link #initialize(int,int,int)}, to set up graphics initialization.
* <li>{@link #initialize(int)}, to set up graphics initialization.
* <li>{@link #updateProgramAndDraw(long)}, to process one frame. * <li>{@link #updateProgramAndDraw(long)}, to process one frame.
* <li>{@link #release()}, upon conclusion of processing. * <li>{@link #release()}, upon conclusion of processing.
* </ol> * </ol>
*/ */
public interface GlFrameProcessor { public interface GlFrameProcessor {
// TODO(b/213313666): Investigate whether all configuration can be moved to initialize by
// using a placeholder surface until the encoder surface is known. If so, convert
// configureOutputSize to a simple getter.
/** /**
* Sets the input size of frames processed through {@link #updateProgramAndDraw(long)}. * Performs all initialization that requires OpenGL, such as, loading and compiling a GLSL shader
* program.
* *
* <p>This method must be called before {@link #initialize(int)} and does not use OpenGL, as * <p>This method may only be called if there is a current OpenGL context.
* calling this method without a current OpenGL context is allowed.
* *
* <p>After setting the input size, the output size can be obtained using {@link * @param inputTexId Identifier of a 2D OpenGL texture.
* #getOutputSize()}. * @param inputWidth The input width, in pixels.
* @param inputHeight The input height, in pixels.
*/ */
void setInputSize(int inputWidth, int inputHeight); void initialize(int inputTexId, int inputWidth, int inputHeight) throws IOException;
/** /**
* Returns the output {@link Size} of frames processed through {@link * Returns the output {@link Size} of frames processed through {@link
* #updateProgramAndDraw(long)}. * #updateProgramAndDraw(long)}.
* *
* <p>Must call {@link #setInputSize(int, int)} before calling this method. * <p>This method may only be called after the frame processor has been {@link
* #initialize(int,int,int) initialized}.
*/ */
Size getOutputSize(); Size getOutputSize();
/** /**
* Does any initialization necessary such as loading and compiling a GLSL shader programs.
*
* <p>This method may only be called after creating the OpenGL context and focusing a render
* target.
*/
void initialize(int inputTexId) throws IOException;
/**
* Updates the shader program's vertex attributes and uniforms, binds them, and draws. * Updates the shader program's vertex attributes and uniforms, binds them, and draws.
* *
* <p>The frame processor must be {@linkplain #initialize(int) initialized}. The caller is * <p>This method may only be called after the frame processor has been {@link
* responsible for focussing the correct render target before calling this method. * #initialize(int,int,int) initialized}. The caller is responsible for focussing the correct
* render target before calling this method.
* *
* @param presentationTimeUs The presentation timestamp of the current frame, in microseconds. * @param presentationTimeUs The presentation timestamp of the current frame, in microseconds.
*/ */
......
...@@ -21,10 +21,12 @@ import static com.google.android.exoplayer2.util.Assertions.checkStateNotNull; ...@@ -21,10 +21,12 @@ import static com.google.android.exoplayer2.util.Assertions.checkStateNotNull;
import android.content.Context; import android.content.Context;
import android.graphics.Matrix; import android.graphics.Matrix;
import android.util.Size; import android.util.Size;
import androidx.annotation.VisibleForTesting;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.util.GlUtil; import com.google.android.exoplayer2.util.GlUtil;
import java.io.IOException; import java.io.IOException;
import org.checkerframework.checker.nullness.qual.EnsuresNonNull;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/** Controls how a frame is viewed, by changing resolution. */ /** Controls how a frame is viewed, by changing resolution. */
...@@ -33,6 +35,7 @@ public final class PresentationFrameProcessor implements GlFrameProcessor { ...@@ -33,6 +35,7 @@ public final class PresentationFrameProcessor implements GlFrameProcessor {
/** A builder for {@link PresentationFrameProcessor} instances. */ /** A builder for {@link PresentationFrameProcessor} instances. */
public static final class Builder { public static final class Builder {
// Mandatory field. // Mandatory field.
private final Context context; private final Context context;
...@@ -78,12 +81,10 @@ public final class PresentationFrameProcessor implements GlFrameProcessor { ...@@ -78,12 +81,10 @@ public final class PresentationFrameProcessor implements GlFrameProcessor {
private final Context context; private final Context context;
private final int requestedHeight; private final int requestedHeight;
private @MonotonicNonNull AdvancedFrameProcessor advancedFrameProcessor;
private int inputWidth;
private int inputHeight;
private int outputRotationDegrees;
private @MonotonicNonNull Size outputSize; private @MonotonicNonNull Size outputSize;
private int outputRotationDegrees;
private @MonotonicNonNull Matrix transformationMatrix; private @MonotonicNonNull Matrix transformationMatrix;
private @MonotonicNonNull AdvancedFrameProcessor advancedFrameProcessor;
/** /**
* Creates a new instance. * Creates a new instance.
...@@ -95,17 +96,27 @@ public final class PresentationFrameProcessor implements GlFrameProcessor { ...@@ -95,17 +96,27 @@ public final class PresentationFrameProcessor implements GlFrameProcessor {
this.context = context; this.context = context;
this.requestedHeight = requestedHeight; this.requestedHeight = requestedHeight;
inputWidth = C.LENGTH_UNSET;
inputHeight = C.LENGTH_UNSET;
outputRotationDegrees = C.LENGTH_UNSET; outputRotationDegrees = C.LENGTH_UNSET;
} }
@Override
public void initialize(int inputTexId, int inputWidth, int inputHeight) throws IOException {
configureOutputSizeAndTransformationMatrix(inputWidth, inputHeight);
advancedFrameProcessor = new AdvancedFrameProcessor(context, transformationMatrix);
advancedFrameProcessor.initialize(inputTexId, inputWidth, inputHeight);
}
@Override
public Size getOutputSize() {
return checkStateNotNull(outputSize);
}
/** /**
* Returns {@link Format#rotationDegrees} for the output frame. * Returns {@link Format#rotationDegrees} for the output frame.
* *
* <p>Return values may be {@code 0} or {@code 90} degrees. * <p>Return values may be {@code 0} or {@code 90} degrees.
* *
* <p>This method can only be called after {@link #setInputSize(int, int)}. * <p>The frame processor must be {@linkplain #initialize(int,int,int) initialized}.
*/ */
public int getOutputRotationDegrees() { public int getOutputRotationDegrees() {
checkState(outputRotationDegrees != C.LENGTH_UNSET); checkState(outputRotationDegrees != C.LENGTH_UNSET);
...@@ -113,20 +124,28 @@ public final class PresentationFrameProcessor implements GlFrameProcessor { ...@@ -113,20 +124,28 @@ public final class PresentationFrameProcessor implements GlFrameProcessor {
} }
@Override @Override
public void setInputSize(int inputWidth, int inputHeight) { public void updateProgramAndDraw(long presentationTimeUs) {
this.inputWidth = inputWidth; checkStateNotNull(advancedFrameProcessor).updateProgramAndDraw(presentationTimeUs);
this.inputHeight = inputHeight; }
transformationMatrix = new Matrix();
@Override
public void release() {
if (advancedFrameProcessor != null) {
advancedFrameProcessor.release();
}
}
@EnsuresNonNull("transformationMatrix")
@VisibleForTesting // Allows roboletric testing of output size calculation without OpenGL.
/* package */ void configureOutputSizeAndTransformationMatrix(int inputWidth, int inputHeight) {
transformationMatrix = new Matrix();
int displayWidth = inputWidth; int displayWidth = inputWidth;
int displayHeight = inputHeight; int displayHeight = inputHeight;
// Scale width and height to desired requestedHeight, preserving aspect ratio. // Scale width and height to desired requestedHeight, preserving aspect ratio.
if (requestedHeight != C.LENGTH_UNSET && requestedHeight != displayHeight) { if (requestedHeight != C.LENGTH_UNSET && requestedHeight != displayHeight) {
displayWidth = Math.round((float) requestedHeight * displayWidth / displayHeight); displayWidth = Math.round((float) requestedHeight * displayWidth / displayHeight);
displayHeight = requestedHeight; displayHeight = requestedHeight;
} }
// Encoders commonly support higher maximum widths than maximum heights. Rotate the decoded // Encoders commonly support higher maximum widths than maximum heights. Rotate the decoded
// frame before encoding, so the encoded frame's width >= height, and set // frame before encoding, so the encoded frame's width >= height, and set
// outputRotationDegrees to ensure the frame is displayed in the correct orientation. // outputRotationDegrees to ensure the frame is displayed in the correct orientation.
...@@ -141,29 +160,4 @@ public final class PresentationFrameProcessor implements GlFrameProcessor { ...@@ -141,29 +160,4 @@ public final class PresentationFrameProcessor implements GlFrameProcessor {
outputSize = new Size(displayWidth, displayHeight); outputSize = new Size(displayWidth, displayHeight);
} }
} }
@Override
public Size getOutputSize() {
return checkStateNotNull(outputSize);
}
@Override
public void initialize(int inputTexId) throws IOException {
checkStateNotNull(transformationMatrix);
advancedFrameProcessor = new AdvancedFrameProcessor(context, transformationMatrix);
advancedFrameProcessor.setInputSize(inputWidth, inputHeight);
advancedFrameProcessor.initialize(inputTexId);
}
@Override
public void updateProgramAndDraw(long presentationTimeUs) {
checkStateNotNull(advancedFrameProcessor).updateProgramAndDraw(presentationTimeUs);
}
@Override
public void release() {
if (advancedFrameProcessor != null) {
advancedFrameProcessor.release();
}
}
} }
...@@ -22,9 +22,10 @@ import static java.lang.Math.min; ...@@ -22,9 +22,10 @@ import static java.lang.Math.min;
import android.content.Context; import android.content.Context;
import android.graphics.Matrix; import android.graphics.Matrix;
import android.util.Size; import android.util.Size;
import com.google.android.exoplayer2.C; import androidx.annotation.VisibleForTesting;
import com.google.android.exoplayer2.util.GlUtil; import com.google.android.exoplayer2.util.GlUtil;
import java.io.IOException; import java.io.IOException;
import org.checkerframework.checker.nullness.qual.EnsuresNonNull;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/** /**
...@@ -98,8 +99,6 @@ public final class ScaleToFitFrameProcessor implements GlFrameProcessor { ...@@ -98,8 +99,6 @@ public final class ScaleToFitFrameProcessor implements GlFrameProcessor {
private final Matrix transformationMatrix; private final Matrix transformationMatrix;
private @MonotonicNonNull AdvancedFrameProcessor advancedFrameProcessor; private @MonotonicNonNull AdvancedFrameProcessor advancedFrameProcessor;
private int inputWidth;
private int inputHeight;
private @MonotonicNonNull Size outputSize; private @MonotonicNonNull Size outputSize;
private @MonotonicNonNull Matrix adjustedTransformationMatrix; private @MonotonicNonNull Matrix adjustedTransformationMatrix;
...@@ -118,15 +117,35 @@ public final class ScaleToFitFrameProcessor implements GlFrameProcessor { ...@@ -118,15 +117,35 @@ public final class ScaleToFitFrameProcessor implements GlFrameProcessor {
this.transformationMatrix = new Matrix(); this.transformationMatrix = new Matrix();
this.transformationMatrix.postScale(scaleX, scaleY); this.transformationMatrix.postScale(scaleX, scaleY);
this.transformationMatrix.postRotate(rotationDegrees); this.transformationMatrix.postRotate(rotationDegrees);
}
@Override
public void initialize(int inputTexId, int inputWidth, int inputHeight) throws IOException {
configureOutputSizeAndTransformationMatrix(inputWidth, inputHeight);
advancedFrameProcessor = new AdvancedFrameProcessor(context, adjustedTransformationMatrix);
advancedFrameProcessor.initialize(inputTexId, inputWidth, inputHeight);
}
@Override
public Size getOutputSize() {
return checkStateNotNull(outputSize);
}
inputWidth = C.LENGTH_UNSET; @Override
inputHeight = C.LENGTH_UNSET; public void updateProgramAndDraw(long presentationTimeUs) {
checkStateNotNull(advancedFrameProcessor).updateProgramAndDraw(presentationTimeUs);
} }
@Override @Override
public void setInputSize(int inputWidth, int inputHeight) { public void release() {
this.inputWidth = inputWidth; if (advancedFrameProcessor != null) {
this.inputHeight = inputHeight; advancedFrameProcessor.release();
}
}
@EnsuresNonNull("adjustedTransformationMatrix")
@VisibleForTesting // Allows roboletric testing of output size calculation without OpenGL.
/* package */ void configureOutputSizeAndTransformationMatrix(int inputWidth, int inputHeight) {
adjustedTransformationMatrix = new Matrix(transformationMatrix); adjustedTransformationMatrix = new Matrix(transformationMatrix);
if (transformationMatrix.isIdentity()) { if (transformationMatrix.isIdentity()) {
...@@ -163,29 +182,4 @@ public final class ScaleToFitFrameProcessor implements GlFrameProcessor { ...@@ -163,29 +182,4 @@ public final class ScaleToFitFrameProcessor implements GlFrameProcessor {
adjustedTransformationMatrix.postScale(1f / xScale, 1f / yScale); adjustedTransformationMatrix.postScale(1f / xScale, 1f / yScale);
outputSize = new Size(Math.round(inputWidth * xScale), Math.round(inputHeight * yScale)); outputSize = new Size(Math.round(inputWidth * xScale), Math.round(inputHeight * yScale));
} }
@Override
public Size getOutputSize() {
return checkStateNotNull(outputSize);
}
@Override
public void initialize(int inputTexId) throws IOException {
checkStateNotNull(adjustedTransformationMatrix);
advancedFrameProcessor = new AdvancedFrameProcessor(context, adjustedTransformationMatrix);
advancedFrameProcessor.setInputSize(inputWidth, inputHeight);
advancedFrameProcessor.initialize(inputTexId);
}
@Override
public void updateProgramAndDraw(long presentationTimeUs) {
checkStateNotNull(advancedFrameProcessor).updateProgramAndDraw(presentationTimeUs);
}
@Override
public void release() {
if (advancedFrameProcessor != null) {
advancedFrameProcessor.release();
}
}
} }
/*
* Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.transformer;
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
import static com.google.common.truth.Truth.assertThat;
import android.graphics.Matrix;
import android.util.Size;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* Unit tests for {@link AdvancedFrameProcessor}.
*
* <p>See {@code AdvancedFrameProcessorPixelTest} for pixel tests testing {@link
* AdvancedFrameProcessor} given a transformation matrix.
*/
@RunWith(AndroidJUnit4.class)
public final class AdvancedFrameProcessorTest {
@Test
public void getOutputSize_withIdentityMatrix_leavesSizeUnchanged() {
Matrix identityMatrix = new Matrix();
int inputWidth = 200;
int inputHeight = 150;
AdvancedFrameProcessor advancedFrameProcessor =
new AdvancedFrameProcessor(getApplicationContext(), identityMatrix);
advancedFrameProcessor.setInputSize(inputWidth, inputHeight);
Size outputSize = advancedFrameProcessor.getOutputSize();
assertThat(outputSize.getWidth()).isEqualTo(inputWidth);
assertThat(outputSize.getHeight()).isEqualTo(inputHeight);
}
@Test
public void getOutputSize_withTransformationMatrix_leavesSizeUnchanged() {
Matrix transformationMatrix = new Matrix();
transformationMatrix.postRotate(/* degrees= */ 90);
transformationMatrix.postScale(/* sx= */ .5f, /* sy= */ 1.2f);
int inputWidth = 200;
int inputHeight = 150;
AdvancedFrameProcessor advancedFrameProcessor =
new AdvancedFrameProcessor(getApplicationContext(), transformationMatrix);
advancedFrameProcessor.setInputSize(inputWidth, inputHeight);
Size outputSize = advancedFrameProcessor.getOutputSize();
assertThat(outputSize.getWidth()).isEqualTo(inputWidth);
assertThat(outputSize.getHeight()).isEqualTo(inputHeight);
}
}
...@@ -39,7 +39,7 @@ public final class PresentationFrameProcessorTest { ...@@ -39,7 +39,7 @@ public final class PresentationFrameProcessorTest {
PresentationFrameProcessor presentationFrameProcessor = PresentationFrameProcessor presentationFrameProcessor =
new PresentationFrameProcessor.Builder(getApplicationContext()).build(); new PresentationFrameProcessor.Builder(getApplicationContext()).build();
presentationFrameProcessor.setInputSize(inputWidth, inputHeight); presentationFrameProcessor.configureOutputSizeAndTransformationMatrix(inputWidth, inputHeight);
Size outputSize = presentationFrameProcessor.getOutputSize(); Size outputSize = presentationFrameProcessor.getOutputSize();
assertThat(presentationFrameProcessor.getOutputRotationDegrees()).isEqualTo(0); assertThat(presentationFrameProcessor.getOutputRotationDegrees()).isEqualTo(0);
...@@ -54,7 +54,7 @@ public final class PresentationFrameProcessorTest { ...@@ -54,7 +54,7 @@ public final class PresentationFrameProcessorTest {
PresentationFrameProcessor presentationFrameProcessor = PresentationFrameProcessor presentationFrameProcessor =
new PresentationFrameProcessor.Builder(getApplicationContext()).build(); new PresentationFrameProcessor.Builder(getApplicationContext()).build();
presentationFrameProcessor.setInputSize(inputWidth, inputHeight); presentationFrameProcessor.configureOutputSizeAndTransformationMatrix(inputWidth, inputHeight);
Size outputSize = presentationFrameProcessor.getOutputSize(); Size outputSize = presentationFrameProcessor.getOutputSize();
assertThat(presentationFrameProcessor.getOutputRotationDegrees()).isEqualTo(0); assertThat(presentationFrameProcessor.getOutputRotationDegrees()).isEqualTo(0);
...@@ -69,7 +69,7 @@ public final class PresentationFrameProcessorTest { ...@@ -69,7 +69,7 @@ public final class PresentationFrameProcessorTest {
PresentationFrameProcessor presentationFrameProcessor = PresentationFrameProcessor presentationFrameProcessor =
new PresentationFrameProcessor.Builder(getApplicationContext()).build(); new PresentationFrameProcessor.Builder(getApplicationContext()).build();
presentationFrameProcessor.setInputSize(inputWidth, inputHeight); presentationFrameProcessor.configureOutputSizeAndTransformationMatrix(inputWidth, inputHeight);
Size outputSize = presentationFrameProcessor.getOutputSize(); Size outputSize = presentationFrameProcessor.getOutputSize();
assertThat(presentationFrameProcessor.getOutputRotationDegrees()).isEqualTo(90); assertThat(presentationFrameProcessor.getOutputRotationDegrees()).isEqualTo(90);
...@@ -87,7 +87,7 @@ public final class PresentationFrameProcessorTest { ...@@ -87,7 +87,7 @@ public final class PresentationFrameProcessorTest {
.setResolution(requestedHeight) .setResolution(requestedHeight)
.build(); .build();
presentationFrameProcessor.setInputSize(inputWidth, inputHeight); presentationFrameProcessor.configureOutputSizeAndTransformationMatrix(inputWidth, inputHeight);
Size outputSize = presentationFrameProcessor.getOutputSize(); Size outputSize = presentationFrameProcessor.getOutputSize();
assertThat(presentationFrameProcessor.getOutputRotationDegrees()).isEqualTo(0); assertThat(presentationFrameProcessor.getOutputRotationDegrees()).isEqualTo(0);
......
...@@ -17,7 +17,6 @@ package com.google.android.exoplayer2.transformer; ...@@ -17,7 +17,6 @@ package com.google.android.exoplayer2.transformer;
import static androidx.test.core.app.ApplicationProvider.getApplicationContext; import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
import android.util.Size; import android.util.Size;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
...@@ -40,7 +39,7 @@ public final class ScaleToFitFrameProcessorTest { ...@@ -40,7 +39,7 @@ public final class ScaleToFitFrameProcessorTest {
ScaleToFitFrameProcessor scaleToFitFrameProcessor = ScaleToFitFrameProcessor scaleToFitFrameProcessor =
new ScaleToFitFrameProcessor.Builder(getApplicationContext()).build(); new ScaleToFitFrameProcessor.Builder(getApplicationContext()).build();
scaleToFitFrameProcessor.setInputSize(inputWidth, inputHeight); scaleToFitFrameProcessor.configureOutputSizeAndTransformationMatrix(inputWidth, inputHeight);
Size outputSize = scaleToFitFrameProcessor.getOutputSize(); Size outputSize = scaleToFitFrameProcessor.getOutputSize();
assertThat(outputSize.getWidth()).isEqualTo(inputWidth); assertThat(outputSize.getWidth()).isEqualTo(inputWidth);
...@@ -48,17 +47,6 @@ public final class ScaleToFitFrameProcessorTest { ...@@ -48,17 +47,6 @@ public final class ScaleToFitFrameProcessorTest {
} }
@Test @Test
public void initializeBeforeConfigure_throwsIllegalStateException() {
ScaleToFitFrameProcessor scaleToFitFrameProcessor =
new ScaleToFitFrameProcessor.Builder(getApplicationContext()).build();
// configureOutputSize not called before initialize.
assertThrows(
IllegalStateException.class,
() -> scaleToFitFrameProcessor.initialize(/* inputTexId= */ 0));
}
@Test
public void getOutputSize_scaleNarrow_decreasesWidth() { public void getOutputSize_scaleNarrow_decreasesWidth() {
int inputWidth = 200; int inputWidth = 200;
int inputHeight = 150; int inputHeight = 150;
...@@ -67,7 +55,7 @@ public final class ScaleToFitFrameProcessorTest { ...@@ -67,7 +55,7 @@ public final class ScaleToFitFrameProcessorTest {
.setScale(/* scaleX= */ .5f, /* scaleY= */ 1f) .setScale(/* scaleX= */ .5f, /* scaleY= */ 1f)
.build(); .build();
scaleToFitFrameProcessor.setInputSize(inputWidth, inputHeight); scaleToFitFrameProcessor.configureOutputSizeAndTransformationMatrix(inputWidth, inputHeight);
Size outputSize = scaleToFitFrameProcessor.getOutputSize(); Size outputSize = scaleToFitFrameProcessor.getOutputSize();
assertThat(outputSize.getWidth()).isEqualTo(Math.round(inputWidth * .5f)); assertThat(outputSize.getWidth()).isEqualTo(Math.round(inputWidth * .5f));
...@@ -83,7 +71,7 @@ public final class ScaleToFitFrameProcessorTest { ...@@ -83,7 +71,7 @@ public final class ScaleToFitFrameProcessorTest {
.setScale(/* scaleX= */ 2f, /* scaleY= */ 1f) .setScale(/* scaleX= */ 2f, /* scaleY= */ 1f)
.build(); .build();
scaleToFitFrameProcessor.setInputSize(inputWidth, inputHeight); scaleToFitFrameProcessor.configureOutputSizeAndTransformationMatrix(inputWidth, inputHeight);
Size outputSize = scaleToFitFrameProcessor.getOutputSize(); Size outputSize = scaleToFitFrameProcessor.getOutputSize();
assertThat(outputSize.getWidth()).isEqualTo(inputWidth * 2); assertThat(outputSize.getWidth()).isEqualTo(inputWidth * 2);
...@@ -99,7 +87,7 @@ public final class ScaleToFitFrameProcessorTest { ...@@ -99,7 +87,7 @@ public final class ScaleToFitFrameProcessorTest {
.setScale(/* scaleX= */ 1f, /* scaleY= */ 2f) .setScale(/* scaleX= */ 1f, /* scaleY= */ 2f)
.build(); .build();
scaleToFitFrameProcessor.setInputSize(inputWidth, inputHeight); scaleToFitFrameProcessor.configureOutputSizeAndTransformationMatrix(inputWidth, inputHeight);
Size outputSize = scaleToFitFrameProcessor.getOutputSize(); Size outputSize = scaleToFitFrameProcessor.getOutputSize();
assertThat(outputSize.getWidth()).isEqualTo(inputWidth); assertThat(outputSize.getWidth()).isEqualTo(inputWidth);
...@@ -115,7 +103,7 @@ public final class ScaleToFitFrameProcessorTest { ...@@ -115,7 +103,7 @@ public final class ScaleToFitFrameProcessorTest {
.setRotationDegrees(90) .setRotationDegrees(90)
.build(); .build();
scaleToFitFrameProcessor.setInputSize(inputWidth, inputHeight); scaleToFitFrameProcessor.configureOutputSizeAndTransformationMatrix(inputWidth, inputHeight);
Size outputSize = scaleToFitFrameProcessor.getOutputSize(); Size outputSize = scaleToFitFrameProcessor.getOutputSize();
assertThat(outputSize.getWidth()).isEqualTo(inputHeight); assertThat(outputSize.getWidth()).isEqualTo(inputHeight);
...@@ -132,7 +120,7 @@ public final class ScaleToFitFrameProcessorTest { ...@@ -132,7 +120,7 @@ public final class ScaleToFitFrameProcessorTest {
.build(); .build();
long expectedOutputWidthHeight = 247; long expectedOutputWidthHeight = 247;
scaleToFitFrameProcessor.setInputSize(inputWidth, inputHeight); scaleToFitFrameProcessor.configureOutputSizeAndTransformationMatrix(inputWidth, inputHeight);
Size outputSize = scaleToFitFrameProcessor.getOutputSize(); Size outputSize = scaleToFitFrameProcessor.getOutputSize();
assertThat(outputSize.getWidth()).isEqualTo(expectedOutputWidthHeight); assertThat(outputSize.getWidth()).isEqualTo(expectedOutputWidthHeight);
......
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