Transformer: Use Size for output dimensions.

Use android.util.Size, whose naming is much easier to understand than Pair<Integer, Integer>, in both FrameProcessor and EncoderUtil.

PiperOrigin-RevId: 434813986
This commit is contained in:
huangdarwin 2022-03-15 18:48:25 +00:00 committed by Ian Baker
parent fb03db8108
commit 03c02b8b5d
11 changed files with 77 additions and 73 deletions

View File

@ -36,7 +36,7 @@ import android.media.ImageReader;
import android.media.MediaCodec;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.util.Pair;
import android.util.Size;
import androidx.annotation.Nullable;
import androidx.media3.common.C;
import androidx.media3.common.MimeTypes;
@ -244,10 +244,9 @@ public final class FrameEditorDataProcessingTest {
int inputWidth = checkNotNull(mediaFormat).getInteger(MediaFormat.KEY_WIDTH);
int inputHeight = mediaFormat.getInteger(MediaFormat.KEY_HEIGHT);
Pair<Integer, Integer> outputDimensions =
glFrameProcessor.configureOutputDimensions(inputWidth, inputHeight);
int outputWidth = outputDimensions.first;
int outputHeight = outputDimensions.second;
Size outputDimensions = glFrameProcessor.configureOutputDimensions(inputWidth, inputHeight);
int outputWidth = outputDimensions.getWidth();
int outputHeight = outputDimensions.getHeight();
frameEditorOutputImageReader =
ImageReader.newInstance(
outputWidth, outputHeight, PixelFormat.RGBA_8888, /* maxImages= */ 1);

View File

@ -20,7 +20,7 @@ import static androidx.media3.common.util.Assertions.checkStateNotNull;
import android.content.Context;
import android.graphics.Matrix;
import android.opengl.GLES20;
import android.util.Pair;
import android.util.Size;
import androidx.media3.common.util.GlProgram;
import androidx.media3.common.util.GlUtil;
import java.io.IOException;
@ -101,8 +101,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
}
@Override
public Pair<Integer, Integer> configureOutputDimensions(int inputWidth, int inputHeight) {
return new Pair<>(inputWidth, inputHeight);
public Size configureOutputDimensions(int inputWidth, int inputHeight) {
return new Size(inputWidth, inputHeight);
}
@Override

View File

@ -26,6 +26,7 @@ import static java.lang.Math.abs;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.util.Pair;
import android.util.Size;
import androidx.annotation.Nullable;
import androidx.media3.common.Format;
import androidx.media3.common.MimeTypes;
@ -233,7 +234,7 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
encodersForMimeType,
/* cost= */ (encoderInfo) -> {
@Nullable
Pair<Integer, Integer> closestSupportedResolution =
Size closestSupportedResolution =
EncoderUtil.getSupportedResolution(
encoderInfo, mimeType, requestedFormat.width, requestedFormat.height);
if (closestSupportedResolution == null) {
@ -242,13 +243,14 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
}
return abs(
requestedFormat.width * requestedFormat.height
- closestSupportedResolution.first * closestSupportedResolution.second);
- closestSupportedResolution.getWidth()
* closestSupportedResolution.getHeight());
});
if (filteredEncoders.isEmpty()) {
return null;
}
// The supported resolution is the same for all remaining encoders.
Pair<Integer, Integer> finalResolution =
Size finalResolution =
checkNotNull(
EncoderUtil.getSupportedResolution(
filteredEncoders.get(0), mimeType, requestedFormat.width, requestedFormat.height));
@ -256,8 +258,8 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
int requestedBitrate =
requestedFormat.averageBitrate == Format.NO_VALUE
? getSuggestedBitrate(
/* width= */ finalResolution.first,
/* height= */ finalResolution.second,
finalResolution.getWidth(),
finalResolution.getHeight(),
requestedFormat.frameRate == Format.NO_VALUE
? DEFAULT_FRAME_RATE
: requestedFormat.frameRate)
@ -291,8 +293,8 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
.buildUpon()
.setSampleMimeType(mimeType)
.setCodecs(codecs)
.setWidth(finalResolution.first)
.setHeight(finalResolution.second)
.setWidth(finalResolution.getWidth())
.setHeight(finalResolution.getHeight())
.setFrameRate(
requestedFormat.frameRate != Format.NO_VALUE
? requestedFormat.frameRate

View File

@ -22,7 +22,7 @@ import static java.lang.Math.round;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaCodecList;
import android.util.Pair;
import android.util.Size;
import androidx.annotation.DoNotInline;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
@ -80,10 +80,10 @@ public final class EncoderUtil {
* @param mimeType The output MIME type.
* @param width The original width.
* @param height The original height.
* @return A {@link Pair} of width and height, or {@code null} if unable to find a fix.
* @return A {@link Size supported resolution}, or {@code null} if unable to find a fallback.
*/
@Nullable
public static Pair<Integer, Integer> getSupportedResolution(
public static Size getSupportedResolution(
MediaCodecInfo encoderInfo, String mimeType, int width, int height) {
MediaCodecInfo.VideoCapabilities videoEncoderCapabilities =
encoderInfo.getCapabilitiesForType(mimeType).getVideoCapabilities();
@ -94,28 +94,28 @@ public final class EncoderUtil {
width = alignResolution(width, widthAlignment);
height = alignResolution(height, heightAlignment);
if (videoEncoderCapabilities.isSizeSupported(width, height)) {
return Pair.create(width, height);
return new Size(width, height);
}
// Try three-fourths (e.g. 1440 -> 1080).
int newWidth = alignResolution(width * 3 / 4, widthAlignment);
int newHeight = alignResolution(height * 3 / 4, heightAlignment);
if (videoEncoderCapabilities.isSizeSupported(newWidth, newHeight)) {
return Pair.create(newWidth, newHeight);
return new Size(newWidth, newHeight);
}
// Try two-thirds (e.g. 4k -> 1440).
newWidth = alignResolution(width * 2 / 3, widthAlignment);
newHeight = alignResolution(height * 2 / 3, heightAlignment);
if (videoEncoderCapabilities.isSizeSupported(newWidth, newHeight)) {
return Pair.create(newWidth, newHeight);
return new Size(newWidth, newHeight);
}
// Try half (e.g. 4k -> 1080).
newWidth = alignResolution(width / 2, widthAlignment);
newHeight = alignResolution(height / 2, heightAlignment);
if (videoEncoderCapabilities.isSizeSupported(newWidth, newHeight)) {
return Pair.create(newWidth, newHeight);
return new Size(newWidth, newHeight);
}
// Fix frame being too wide or too tall.
@ -127,9 +127,7 @@ public final class EncoderUtil {
height = alignResolution(adjustedHeight, heightAlignment);
}
return videoEncoderCapabilities.isSizeSupported(width, height)
? Pair.create(width, height)
: null;
return videoEncoderCapabilities.isSizeSupported(width, height) ? new Size(width, height) : null;
}
/**

View File

@ -19,7 +19,7 @@ import static androidx.media3.common.util.Assertions.checkStateNotNull;
import android.content.Context;
import android.opengl.GLES20;
import android.util.Pair;
import android.util.Size;
import androidx.media3.common.util.GlProgram;
import androidx.media3.common.util.GlUtil;
import java.io.IOException;
@ -59,8 +59,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
}
@Override
public Pair<Integer, Integer> configureOutputDimensions(int inputWidth, int inputHeight) {
return new Pair<>(inputWidth, inputHeight);
public Size configureOutputDimensions(int inputWidth, int inputHeight) {
return new Size(inputWidth, inputHeight);
}
@Override

View File

@ -15,7 +15,7 @@
*/
package androidx.media3.transformer;
import android.util.Pair;
import android.util.Size;
import java.io.IOException;
/**
@ -34,11 +34,12 @@ import java.io.IOException;
/* package */ interface GlFrameProcessor {
/**
* Returns the output dimensions of frames processed through {@link #updateProgramAndDraw(long)}.
* Returns the output {@link Size dimensions} of frames processed through {@link
* #updateProgramAndDraw(long)}.
*
* <p>This method must be called before {@link #initialize(int)} and does not use OpenGL.
*/
Pair<Integer, Integer> configureOutputDimensions(int inputWidth, int inputHeight);
Size configureOutputDimensions(int inputWidth, int inputHeight);
/**
* Does any initialization necessary such as loading and compiling a GLSL shader programs.

View File

@ -22,7 +22,7 @@ import static java.lang.Math.min;
import android.content.Context;
import android.graphics.Matrix;
import android.util.Pair;
import android.util.Size;
import androidx.media3.common.C;
import androidx.media3.common.Format;
import androidx.media3.common.util.GlUtil;
@ -104,7 +104,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
@Override
@EnsuresNonNull("adjustedTransformationMatrix")
public Pair<Integer, Integer> configureOutputDimensions(int inputWidth, int inputHeight) {
public Size configureOutputDimensions(int inputWidth, int inputHeight) {
this.inputWidth = inputWidth;
this.inputHeight = inputHeight;
adjustedTransformationMatrix = new Matrix(transformationMatrix);
@ -172,7 +172,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
outputHeight = displayHeight;
}
return new Pair<>(outputWidth, outputHeight);
return new Size(outputWidth, outputHeight);
}
@Override

View File

@ -22,7 +22,7 @@ import static androidx.media3.common.util.Util.SDK_INT;
import android.content.Context;
import android.media.MediaCodec;
import android.media.MediaFormat;
import android.util.Pair;
import android.util.Size;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.media3.common.Format;
@ -73,14 +73,14 @@ import org.checkerframework.dataflow.qual.Pure;
context,
transformationRequest.transformationMatrix,
transformationRequest.outputHeight);
Pair<Integer, Integer> requestedEncoderDimensions =
Size requestedEncoderDimensions =
scaleToFitFrameProcessor.configureOutputDimensions(decodedWidth, decodedHeight);
outputRotationDegrees = scaleToFitFrameProcessor.getOutputRotationDegrees();
Format requestedEncoderFormat =
new Format.Builder()
.setWidth(requestedEncoderDimensions.first)
.setHeight(requestedEncoderDimensions.second)
.setWidth(requestedEncoderDimensions.getWidth())
.setHeight(requestedEncoderDimensions.getHeight())
.setRotationDegrees(0)
.setSampleMimeType(
transformationRequest.videoMimeType != null

View File

@ -19,7 +19,7 @@ import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
import static com.google.common.truth.Truth.assertThat;
import android.graphics.Matrix;
import android.util.Pair;
import android.util.Size;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -40,11 +40,11 @@ public final class AdvancedFrameProcessorTest {
AdvancedFrameProcessor advancedFrameProcessor =
new AdvancedFrameProcessor(getApplicationContext(), identityMatrix);
Pair<Integer, Integer> outputDimensions =
Size outputDimensions =
advancedFrameProcessor.configureOutputDimensions(inputWidth, inputHeight);
assertThat(outputDimensions.first).isEqualTo(inputWidth);
assertThat(outputDimensions.second).isEqualTo(inputHeight);
assertThat(outputDimensions.getWidth()).isEqualTo(inputWidth);
assertThat(outputDimensions.getHeight()).isEqualTo(inputHeight);
}
@Test
@ -57,10 +57,10 @@ public final class AdvancedFrameProcessorTest {
AdvancedFrameProcessor advancedFrameProcessor =
new AdvancedFrameProcessor(getApplicationContext(), transformationMatrix);
Pair<Integer, Integer> outputDimensions =
Size outputDimensions =
advancedFrameProcessor.configureOutputDimensions(inputWidth, inputHeight);
assertThat(outputDimensions.first).isEqualTo(inputWidth);
assertThat(outputDimensions.second).isEqualTo(inputHeight);
assertThat(outputDimensions.getWidth()).isEqualTo(inputWidth);
assertThat(outputDimensions.getHeight()).isEqualTo(inputHeight);
}
}

View File

@ -20,7 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.util.Pair;
import android.util.Size;
import androidx.annotation.Nullable;
import androidx.media3.common.MimeTypes;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@ -67,11 +67,12 @@ public class EncoderUtilTest {
MediaCodecInfo encoderInfo = supportedEncoders.get(0);
@Nullable
Pair<Integer, Integer> closestSupportedResolution =
Size closestSupportedResolution =
EncoderUtil.getSupportedResolution(encoderInfo, MIME_TYPE, 1920, 1080);
assertThat(closestSupportedResolution).isNotNull();
assertThat(closestSupportedResolution).isEqualTo(Pair.create(1920, 1080));
assertThat(closestSupportedResolution.getWidth()).isEqualTo(1920);
assertThat(closestSupportedResolution.getHeight()).isEqualTo(1080);
}
@Test
@ -80,11 +81,12 @@ public class EncoderUtilTest {
MediaCodecInfo encoderInfo = supportedEncoders.get(0);
@Nullable
Pair<Integer, Integer> closestSupportedResolution =
Size closestSupportedResolution =
EncoderUtil.getSupportedResolution(encoderInfo, MIME_TYPE, 1919, 1081);
assertThat(closestSupportedResolution).isNotNull();
assertThat(closestSupportedResolution).isEqualTo(Pair.create(1920, 1080));
assertThat(closestSupportedResolution.getWidth()).isEqualTo(1920);
assertThat(closestSupportedResolution.getHeight()).isEqualTo(1080);
}
@Test
@ -93,11 +95,12 @@ public class EncoderUtilTest {
MediaCodecInfo encoderInfo = supportedEncoders.get(0);
@Nullable
Pair<Integer, Integer> closestSupportedResolution =
Size closestSupportedResolution =
EncoderUtil.getSupportedResolution(encoderInfo, MIME_TYPE, 1920, 1920);
assertThat(closestSupportedResolution).isNotNull();
assertThat(closestSupportedResolution).isEqualTo(Pair.create(1440, 1440));
assertThat(closestSupportedResolution.getWidth()).isEqualTo(1440);
assertThat(closestSupportedResolution.getHeight()).isEqualTo(1440);
}
@Test
@ -106,10 +109,11 @@ public class EncoderUtilTest {
MediaCodecInfo encoderInfo = supportedEncoders.get(0);
@Nullable
Pair<Integer, Integer> closestSupportedResolution =
Size closestSupportedResolution =
EncoderUtil.getSupportedResolution(encoderInfo, MIME_TYPE, 3840, 2160);
assertThat(closestSupportedResolution).isNotNull();
assertThat(closestSupportedResolution).isEqualTo(Pair.create(1920, 1080));
assertThat(closestSupportedResolution.getWidth()).isEqualTo(1920);
assertThat(closestSupportedResolution.getHeight()).isEqualTo(1080);
}
}

View File

@ -20,7 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
import android.graphics.Matrix;
import android.util.Pair;
import android.util.Size;
import androidx.media3.common.C;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
@ -43,13 +43,13 @@ public final class ScaleToFitFrameProcessorTest {
ScaleToFitFrameProcessor scaleToFitFrameProcessor =
new ScaleToFitFrameProcessor(getApplicationContext(), identityMatrix, C.LENGTH_UNSET);
Pair<Integer, Integer> outputDimensions =
Size outputDimensions =
scaleToFitFrameProcessor.configureOutputDimensions(inputWidth, inputHeight);
assertThat(scaleToFitFrameProcessor.getOutputRotationDegrees()).isEqualTo(0);
assertThat(scaleToFitFrameProcessor.shouldProcess()).isFalse();
assertThat(outputDimensions.first).isEqualTo(inputWidth);
assertThat(outputDimensions.second).isEqualTo(inputHeight);
assertThat(outputDimensions.getWidth()).isEqualTo(inputWidth);
assertThat(outputDimensions.getHeight()).isEqualTo(inputHeight);
}
@Test
@ -83,13 +83,13 @@ public final class ScaleToFitFrameProcessorTest {
ScaleToFitFrameProcessor scaleToFitFrameProcessor =
new ScaleToFitFrameProcessor(getApplicationContext(), scaleNarrowMatrix, C.LENGTH_UNSET);
Pair<Integer, Integer> outputDimensions =
Size outputDimensions =
scaleToFitFrameProcessor.configureOutputDimensions(inputWidth, inputHeight);
assertThat(scaleToFitFrameProcessor.getOutputRotationDegrees()).isEqualTo(90);
assertThat(scaleToFitFrameProcessor.shouldProcess()).isTrue();
assertThat(outputDimensions.first).isEqualTo(inputHeight);
assertThat(outputDimensions.second).isEqualTo(Math.round(inputWidth * .5f));
assertThat(outputDimensions.getWidth()).isEqualTo(inputHeight);
assertThat(outputDimensions.getHeight()).isEqualTo(Math.round(inputWidth * .5f));
}
@Test
@ -101,13 +101,13 @@ public final class ScaleToFitFrameProcessorTest {
ScaleToFitFrameProcessor scaleToFitFrameProcessor =
new ScaleToFitFrameProcessor(getApplicationContext(), scaleNarrowMatrix, C.LENGTH_UNSET);
Pair<Integer, Integer> outputDimensions =
Size outputDimensions =
scaleToFitFrameProcessor.configureOutputDimensions(inputWidth, inputHeight);
assertThat(scaleToFitFrameProcessor.getOutputRotationDegrees()).isEqualTo(0);
assertThat(scaleToFitFrameProcessor.shouldProcess()).isTrue();
assertThat(outputDimensions.first).isEqualTo(inputWidth * 2);
assertThat(outputDimensions.second).isEqualTo(inputHeight);
assertThat(outputDimensions.getWidth()).isEqualTo(inputWidth * 2);
assertThat(outputDimensions.getHeight()).isEqualTo(inputHeight);
}
@Test
@ -119,13 +119,13 @@ public final class ScaleToFitFrameProcessorTest {
ScaleToFitFrameProcessor scaleToFitFrameProcessor =
new ScaleToFitFrameProcessor(getApplicationContext(), rotate90Matrix, C.LENGTH_UNSET);
Pair<Integer, Integer> outputDimensions =
Size outputDimensions =
scaleToFitFrameProcessor.configureOutputDimensions(inputWidth, inputHeight);
assertThat(scaleToFitFrameProcessor.getOutputRotationDegrees()).isEqualTo(90);
assertThat(scaleToFitFrameProcessor.shouldProcess()).isTrue();
assertThat(outputDimensions.first).isEqualTo(inputWidth);
assertThat(outputDimensions.second).isEqualTo(inputHeight);
assertThat(outputDimensions.getWidth()).isEqualTo(inputWidth);
assertThat(outputDimensions.getHeight()).isEqualTo(inputHeight);
}
@Test
@ -138,13 +138,13 @@ public final class ScaleToFitFrameProcessorTest {
new ScaleToFitFrameProcessor(getApplicationContext(), rotate45Matrix, C.LENGTH_UNSET);
long expectedOutputWidthHeight = 247;
Pair<Integer, Integer> outputDimensions =
Size outputDimensions =
scaleToFitFrameProcessor.configureOutputDimensions(inputWidth, inputHeight);
assertThat(scaleToFitFrameProcessor.getOutputRotationDegrees()).isEqualTo(0);
assertThat(scaleToFitFrameProcessor.shouldProcess()).isTrue();
assertThat(outputDimensions.first).isEqualTo(expectedOutputWidthHeight);
assertThat(outputDimensions.second).isEqualTo(expectedOutputWidthHeight);
assertThat(outputDimensions.getWidth()).isEqualTo(expectedOutputWidthHeight);
assertThat(outputDimensions.getHeight()).isEqualTo(expectedOutputWidthHeight);
}
@Test
@ -156,12 +156,12 @@ public final class ScaleToFitFrameProcessorTest {
ScaleToFitFrameProcessor scaleToFitFrameProcessor =
new ScaleToFitFrameProcessor(getApplicationContext(), identityMatrix, requestedHeight);
Pair<Integer, Integer> outputDimensions =
Size outputDimensions =
scaleToFitFrameProcessor.configureOutputDimensions(inputWidth, inputHeight);
assertThat(scaleToFitFrameProcessor.getOutputRotationDegrees()).isEqualTo(0);
assertThat(scaleToFitFrameProcessor.shouldProcess()).isTrue();
assertThat(outputDimensions.first).isEqualTo(requestedHeight * inputWidth / inputHeight);
assertThat(outputDimensions.second).isEqualTo(requestedHeight);
assertThat(outputDimensions.getWidth()).isEqualTo(requestedHeight * inputWidth / inputHeight);
assertThat(outputDimensions.getHeight()).isEqualTo(requestedHeight);
}
}