From 18388f02c025181df0dbc448eca3da4faed0d4aa Mon Sep 17 00:00:00 2001 From: samrobinson Date: Mon, 21 Mar 2022 12:16:50 +0000 Subject: [PATCH] Force video encoding if VideoEncoderSettings are not default. Add a MH test exercising this behaviour. PiperOrigin-RevId: 436177198 --- .../transformer/mh/TransformationTest.java | 24 +++++++++++++ .../transformer/DefaultEncoderFactory.java | 7 +++- .../transformer/VideoEncoderSettings.java | 35 +++++++++++++++++++ 3 files changed, 65 insertions(+), 1 deletion(-) diff --git a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/TransformationTest.java b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/TransformationTest.java index b4b59d6436..3b1378d387 100644 --- a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/TransformationTest.java +++ b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/TransformationTest.java @@ -25,10 +25,13 @@ import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.transformer.Codec; +import com.google.android.exoplayer2.transformer.DefaultEncoderFactory; +import com.google.android.exoplayer2.transformer.EncoderSelector; import com.google.android.exoplayer2.transformer.TransformationException; import com.google.android.exoplayer2.transformer.TransformationRequest; import com.google.android.exoplayer2.transformer.Transformer; import com.google.android.exoplayer2.transformer.TransformerAndroidTestRunner; +import com.google.android.exoplayer2.transformer.VideoEncoderSettings; import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.Util; import java.util.List; @@ -97,6 +100,27 @@ public class TransformationTest { .run(testId, MP4_ASSET_WITH_INCREASING_TIMESTAMPS_URI_STRING); } + @Test + public void transformToSpecificBitrate() throws Exception { + final String testId = TAG + "_transformWithSpecificBitrate"; + Context context = ApplicationProvider.getApplicationContext(); + Transformer transformer = + new Transformer.Builder(context) + .setRemoveAudio(true) + .setEncoderFactory( + new DefaultEncoderFactory( + EncoderSelector.DEFAULT, + new VideoEncoderSettings.Builder().setBitrate(5_000_000).build(), + /* enableFallback= */ true)) + .build(); + // TODO(b/223381524): Remove analysis failure suppression after ssim calculation doesn't fail. + new TransformerAndroidTestRunner.Builder(context, transformer) + .setCalculateSsim(true) + .setSuppressAnalysisExceptions(true) + .build() + .run(testId, MP4_ASSET_WITH_INCREASING_TIMESTAMPS_URI_STRING); + } + @Test public void transform4K60() throws Exception { final String testId = TAG + "_transform4K60"; diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactory.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactory.java index 05ef14e90f..5c64da6409 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactory.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactory.java @@ -57,7 +57,7 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory { /** Creates a new instance using a default {@link VideoEncoderSettings}. */ public DefaultEncoderFactory(EncoderSelector videoEncoderSelector, boolean enableFallback) { - this(videoEncoderSelector, new VideoEncoderSettings.Builder().build(), enableFallback); + this(videoEncoderSelector, VideoEncoderSettings.DEFAULT, enableFallback); } /** @@ -191,6 +191,11 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory { /* outputSurface= */ null); } + @Override + public boolean videoNeedsEncoding() { + return !requestedVideoEncoderSettings.equals(VideoEncoderSettings.DEFAULT); + } + /** * Finds an {@link MediaCodecInfo encoder} that supports the requested format most closely. * diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoEncoderSettings.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoEncoderSettings.java index c2f740c979..38cab20323 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoEncoderSettings.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoEncoderSettings.java @@ -19,8 +19,10 @@ package com.google.android.exoplayer2.transformer; import static com.google.android.exoplayer2.util.Assertions.checkArgument; import static java.lang.annotation.ElementType.TYPE_USE; +import android.annotation.SuppressLint; import android.media.MediaCodecInfo; import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.Format; import java.lang.annotation.Documented; import java.lang.annotation.Retention; @@ -38,6 +40,9 @@ public final class VideoEncoderSettings { /** The default I-frame interval in seconds. */ public static final float DEFAULT_I_FRAME_INTERVAL_SECONDS = 1.0f; + /** A default {@link VideoEncoderSettings}. */ + public static final VideoEncoderSettings DEFAULT = new Builder().build(); + /** * The allowed values for {@code bitrateMode}, one of * @@ -49,6 +54,7 @@ public final class VideoEncoderSettings { * MediaCodecInfo.EncoderCapabilities#BITRATE_MODE_CBR_FD}, available from API31. * */ + @SuppressLint("InlinedApi") @Documented @Retention(RetentionPolicy.SOURCE) @Target(TYPE_USE) @@ -205,4 +211,33 @@ public final class VideoEncoderSettings { public Builder buildUpon() { return new Builder(this); } + + @Override + public boolean equals(@Nullable Object o) { + if (this == o) { + return true; + } + if (!(o instanceof VideoEncoderSettings)) { + return false; + } + VideoEncoderSettings that = (VideoEncoderSettings) o; + return bitrate == that.bitrate + && bitrateMode == that.bitrateMode + && profile == that.profile + && level == that.level + && colorProfile == that.colorProfile + && iFrameIntervalSeconds == that.iFrameIntervalSeconds; + } + + @Override + public int hashCode() { + int result = 7; + result = 31 * result + bitrate; + result = 31 * result + bitrateMode; + result = 31 * result + profile; + result = 31 * result + level; + result = 31 * result + colorProfile; + result = 31 * result + Float.floatToIntBits(iFrameIntervalSeconds); + return result; + } }