From 3f718b0d10e1d577620cca9ec76d0af38efc542c Mon Sep 17 00:00:00 2001 From: hschlueter Date: Thu, 9 Jun 2022 18:22:39 +0000 Subject: [PATCH] Check targetSdkVersion for frame dropping workaround. Based on https://developer.android.com/reference/android/media/MediaCodec#using-an-output-surface, frame dropping behaviour depends on the target SDK version. After this change transformer will only use MediaFormat#KEY_ALLOW_FRAME_DROP if both the target and system SDK version are at least 29 and default to its pre 29 behaviour where each decoder output frame must be processed before a new one is rendered to prevent frame dropping otherwise. Also remove deprecated Transformer.Builder constructor without a context and the context setter. PiperOrigin-RevId: 453971097 --- .../transformerdemo/TransformerActivity.java | 1 + .../transformer/AndroidTestUtil.java | 4 +- .../transformer/TransformerEndToEndTest.java | 6 ++- .../RepeatedTranscodeTransformationTest.java | 6 +-- .../transformer/mh/TranscodeQualityTest.java | 4 +- .../transformer/mh/TransformationTest.java | 17 ++++++--- .../mh/analysis/BitrateAnalysisTest.java | 1 + .../EncoderPerformanceAnalysisTest.java | 1 + .../android/exoplayer2/transformer/Codec.java | 6 --- .../exoplayer2/transformer/DefaultCodec.java | 26 +++++++++---- .../transformer/DefaultDecoderFactory.java | 30 ++++++++++++--- .../transformer/DefaultEncoderFactory.java | 22 ++++++++--- .../exoplayer2/transformer/Transformer.java | 38 +++---------------- .../DefaultEncoderFactoryTest.java | 12 ++++-- .../transformer/TransformerBuilderTest.java | 5 --- .../transformer/TransformerEndToEndTest.java | 3 +- 16 files changed, 102 insertions(+), 80 deletions(-) diff --git a/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java b/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java index f808a2e5ac..661390abe4 100644 --- a/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java +++ b/demos/transformer/src/main/java/com/google/android/exoplayer2/transformerdemo/TransformerActivity.java @@ -260,6 +260,7 @@ public final class TransformerActivity extends AppCompatActivity { .setRemoveVideo(bundle.getBoolean(ConfigurationActivity.SHOULD_REMOVE_VIDEO)) .setEncoderFactory( new DefaultEncoderFactory( + /* context= */ this, EncoderSelector.DEFAULT, /* enableFallback= */ bundle.getBoolean(ConfigurationActivity.ENABLE_FALLBACK))); diff --git a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/AndroidTestUtil.java b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/AndroidTestUtil.java index 6666e532d0..397b5e1f39 100644 --- a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/AndroidTestUtil.java +++ b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/AndroidTestUtil.java @@ -224,8 +224,8 @@ public final class AndroidTestUtil { private final Codec.EncoderFactory encoderFactory; /** Creates an instance that wraps {@link DefaultEncoderFactory}. */ - public ForceEncodeEncoderFactory() { - encoderFactory = Codec.EncoderFactory.DEFAULT; + public ForceEncodeEncoderFactory(Context context) { + encoderFactory = new DefaultEncoderFactory(context); } /** diff --git a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java index e9d17cdd8a..fe4b1b1fab 100644 --- a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java +++ b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java @@ -42,7 +42,8 @@ public class TransformerEndToEndTest { .setTransformationRequest( new TransformationRequest.Builder().setResolution(480).build()) .setEncoderFactory( - new DefaultEncoderFactory(EncoderSelector.DEFAULT, /* enableFallback= */ false)) + new DefaultEncoderFactory( + context, EncoderSelector.DEFAULT, /* enableFallback= */ false)) .build(); // Result of the following command: // ffprobe -count_frames -select_streams v:0 -show_entries stream=nb_read_frames sample.mp4 @@ -67,7 +68,8 @@ public class TransformerEndToEndTest { .setTransformationRequest( new TransformationRequest.Builder().setResolution(480).build()) .setEncoderFactory( - new DefaultEncoderFactory(EncoderSelector.DEFAULT, /* enableFallback= */ false)) + new DefaultEncoderFactory( + context, EncoderSelector.DEFAULT, /* enableFallback= */ false)) .build(); long expectedDurationMs = 967; diff --git a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/RepeatedTranscodeTransformationTest.java b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/RepeatedTranscodeTransformationTest.java index 4443279bec..d68ba78b01 100644 --- a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/RepeatedTranscodeTransformationTest.java +++ b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/RepeatedTranscodeTransformationTest.java @@ -48,7 +48,7 @@ public final class RepeatedTranscodeTransformationTest { new Transformer.Builder(context) .setTransformationRequest( new TransformationRequest.Builder().setRotationDegrees(45).build()) - .setEncoderFactory(new AndroidTestUtil.ForceEncodeEncoderFactory()) + .setEncoderFactory(new AndroidTestUtil.ForceEncodeEncoderFactory(context)) .build()) .build(); @@ -78,7 +78,7 @@ public final class RepeatedTranscodeTransformationTest { .setRemoveAudio(true) .setTransformationRequest( new TransformationRequest.Builder().setRotationDegrees(45).build()) - .setEncoderFactory(new AndroidTestUtil.ForceEncodeEncoderFactory()) + .setEncoderFactory(new AndroidTestUtil.ForceEncodeEncoderFactory(context)) .build()) .build(); @@ -107,7 +107,7 @@ public final class RepeatedTranscodeTransformationTest { new Transformer.Builder(context) .setRemoveVideo(true) .setTransformationRequest(new TransformationRequest.Builder().build()) - .setEncoderFactory(new AndroidTestUtil.ForceEncodeEncoderFactory()) + .setEncoderFactory(new AndroidTestUtil.ForceEncodeEncoderFactory(context)) .build()) .build(); diff --git a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/TranscodeQualityTest.java b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/TranscodeQualityTest.java index 79b1882c13..2a44370f3a 100644 --- a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/TranscodeQualityTest.java +++ b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/TranscodeQualityTest.java @@ -52,7 +52,7 @@ public final class TranscodeQualityTest { new Transformer.Builder(context) .setTransformationRequest( new TransformationRequest.Builder().setVideoMimeType(MimeTypes.VIDEO_H264).build()) - .setEncoderFactory(new AndroidTestUtil.ForceEncodeEncoderFactory()) + .setEncoderFactory(new AndroidTestUtil.ForceEncodeEncoderFactory(context)) .setRemoveAudio(true) .build(); @@ -119,7 +119,7 @@ public final class TranscodeQualityTest { new Transformer.Builder(context) .setTransformationRequest( new TransformationRequest.Builder().setVideoMimeType(MimeTypes.VIDEO_H264).build()) - .setEncoderFactory(new AndroidTestUtil.ForceEncodeEncoderFactory()) + .setEncoderFactory(new AndroidTestUtil.ForceEncodeEncoderFactory(context)) .setRemoveAudio(true) .build(); 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 4937565d5e..afbb309ea6 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 @@ -52,7 +52,9 @@ public class TransformationTest { String testId = TAG + "_transform"; Context context = ApplicationProvider.getApplicationContext(); Transformer transformer = - new Transformer.Builder(context).setEncoderFactory(new ForceEncodeEncoderFactory()).build(); + new Transformer.Builder(context) + .setEncoderFactory(new ForceEncodeEncoderFactory(context)) + .build(); new TransformerAndroidTestRunner.Builder(context, transformer) .setMaybeCalculateSsim(true) .build() @@ -80,6 +82,7 @@ public class TransformationTest { .setEncoderFactory( new ForceEncodeEncoderFactory( /* wrappedEncoderFactory= */ new DefaultEncoderFactory( + context, EncoderSelector.DEFAULT, new VideoEncoderSettings.Builder().setBitrate(5_000_000).build(), /* enableFallback= */ true))) @@ -104,7 +107,9 @@ public class TransformationTest { } Transformer transformer = - new Transformer.Builder(context).setEncoderFactory(new ForceEncodeEncoderFactory()).build(); + new Transformer.Builder(context) + .setEncoderFactory(new ForceEncodeEncoderFactory(context)) + .build(); new TransformerAndroidTestRunner.Builder(context, transformer) .setMaybeCalculateSsim(true) .setTimeoutSeconds(180) @@ -125,7 +130,9 @@ public class TransformationTest { return; } Transformer transformer = - new Transformer.Builder(context).setEncoderFactory(new ForceEncodeEncoderFactory()).build(); + new Transformer.Builder(context) + .setEncoderFactory(new ForceEncodeEncoderFactory(context)) + .build(); new TransformerAndroidTestRunner.Builder(context, transformer) .setMaybeCalculateSsim(true) .setTimeoutSeconds(180) @@ -139,7 +146,7 @@ public class TransformationTest { Context context = ApplicationProvider.getApplicationContext(); Transformer transformer = new Transformer.Builder(context) - .setEncoderFactory(new ForceEncodeEncoderFactory()) + .setEncoderFactory(new ForceEncodeEncoderFactory(context)) .setRemoveAudio(true) .build(); new TransformerAndroidTestRunner.Builder(context, transformer) @@ -154,7 +161,7 @@ public class TransformationTest { Context context = ApplicationProvider.getApplicationContext(); Transformer transformer = new Transformer.Builder(context) - .setEncoderFactory(new ForceEncodeEncoderFactory()) + .setEncoderFactory(new ForceEncodeEncoderFactory(context)) .setRemoveVideo(true) .build(); new TransformerAndroidTestRunner.Builder(context, transformer) diff --git a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/analysis/BitrateAnalysisTest.java b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/analysis/BitrateAnalysisTest.java index 7613a57c5c..e65d1f7886 100644 --- a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/analysis/BitrateAnalysisTest.java +++ b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/analysis/BitrateAnalysisTest.java @@ -118,6 +118,7 @@ public class BitrateAnalysisTest { .setEncoderFactory( new AndroidTestUtil.ForceEncodeEncoderFactory( /* wrappedEncoderFactory= */ new DefaultEncoderFactory( + context, EncoderSelector.DEFAULT, new VideoEncoderSettings.Builder() .setBitrate(bitrate) diff --git a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/analysis/EncoderPerformanceAnalysisTest.java b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/analysis/EncoderPerformanceAnalysisTest.java index 3bfcce5740..4f90954b7b 100644 --- a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/analysis/EncoderPerformanceAnalysisTest.java +++ b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/analysis/EncoderPerformanceAnalysisTest.java @@ -128,6 +128,7 @@ public class EncoderPerformanceAnalysisTest { .setEncoderFactory( new AndroidTestUtil.ForceEncodeEncoderFactory( /* wrappedEncoderFactory= */ new DefaultEncoderFactory( + context, EncoderSelector.DEFAULT, new VideoEncoderSettings.Builder() .setEncoderPerformanceParameters(operatingRate, priority) diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Codec.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Codec.java index c9a4e67a2b..a2ead507ef 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Codec.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Codec.java @@ -39,9 +39,6 @@ public interface Codec { /** A factory for {@linkplain Codec decoder} instances. */ interface DecoderFactory { - /** A default {@code DecoderFactory} implementation. */ - DecoderFactory DEFAULT = new DefaultDecoderFactory(); - /** * Returns a {@link Codec} for audio decoding. * @@ -70,9 +67,6 @@ public interface Codec { /** A factory for {@linkplain Codec encoder} instances. */ interface EncoderFactory { - /** A default {@code EncoderFactory} implementation. */ - EncoderFactory DEFAULT = new DefaultEncoderFactory(); - /** * Returns a {@link Codec} for audio encoding. * diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultCodec.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultCodec.java index e9b2165d33..b9090f129f 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultCodec.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultCodec.java @@ -21,6 +21,7 @@ import static com.google.android.exoplayer2.util.Assertions.checkState; import static com.google.android.exoplayer2.util.Assertions.checkStateNotNull; import static com.google.android.exoplayer2.util.Util.SDK_INT; +import android.content.Context; import android.media.MediaCodec; import android.media.MediaCodec.BufferInfo; import android.media.MediaFormat; @@ -52,6 +53,8 @@ public final class DefaultCodec implements Codec { private final MediaCodec mediaCodec; @Nullable private final Surface inputSurface; + private final boolean decoderNeedsFrameDroppingWorkaround; + private @MonotonicNonNull Format outputFormat; @Nullable private ByteBuffer outputBuffer; @@ -63,6 +66,7 @@ public final class DefaultCodec implements Codec { /** * Creates a {@code DefaultCodec}. * + * @param context The {@link Context}. * @param configurationFormat The {@link Format} to configure the {@code DefaultCodec}. See {@link * #getConfigurationFormat()}. The {@link Format#sampleMimeType sampleMimeType} must not be * {@code null}. @@ -73,6 +77,7 @@ public final class DefaultCodec implements Codec { * @param outputSurface The output {@link Surface} if the {@link MediaCodec} outputs to a surface. */ public DefaultCodec( + Context context, Format configurationFormat, MediaFormat configurationMediaFormat, String mediaCodecName, @@ -108,6 +113,7 @@ public final class DefaultCodec implements Codec { } this.mediaCodec = mediaCodec; this.inputSurface = inputSurface; + decoderNeedsFrameDroppingWorkaround = decoderNeedsFrameDroppingWorkaround(context); } @Override @@ -122,15 +128,12 @@ public final class DefaultCodec implements Codec { @Override public int getMaxPendingFrameCount() { - if (SDK_INT < 29) { - // Prior to API 29, decoders may drop frames to keep their output surface from growing out of - // bounds. From API 29, the {@link MediaFormat#KEY_ALLOW_FRAME_DROP} key prevents frame - // dropping even when the surface is full. Frame dropping is never desired, so allow a maximum - // of one frame to be pending at a time. + if (decoderNeedsFrameDroppingWorkaround) { + // Allow a maximum of one frame to be pending at a time to prevent frame dropping. // TODO(b/226330223): Investigate increasing this limit. return 1; } - if (Ascii.toUpperCase(mediaCodec.getCodecInfo().getCanonicalName()).startsWith("OMX.")) { + if (Ascii.toUpperCase(getName()).startsWith("OMX.")) { // Some OMX decoders don't correctly track their number of output buffers available, and get // stuck if too many frames are rendered without being processed, so limit the number of // pending frames to avoid getting stuck. This value is experimentally determined. See also @@ -259,7 +262,7 @@ public final class DefaultCodec implements Codec { * {@inheritDoc} * *

This name is of the actual codec, which may not be the same as the {@code mediaCodecName} - * passed to {@link #DefaultCodec(Format, MediaFormat, String, boolean, Surface)}. + * passed to {@link #DefaultCodec(Context, Format, MediaFormat, String, boolean, Surface)}. * * @see MediaCodec#getCanonicalName() */ @@ -422,4 +425,13 @@ public final class DefaultCodec implements Codec { codec.start(); TraceUtil.endSection(); } + + private static boolean decoderNeedsFrameDroppingWorkaround(Context context) { + // Prior to API 29, decoders may drop frames to keep their output surface from growing out of + // bounds. From API 29, if the app targets API 29 or later, the {@link + // MediaFormat#KEY_ALLOW_FRAME_DROP} key prevents frame dropping even when the surface is full. + // Frame dropping is never desired, so a workaround is needed for older API levels. + return SDK_INT < 29 + || context.getApplicationContext().getApplicationInfo().targetSdkVersion < 29; + } } diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultDecoderFactory.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultDecoderFactory.java index 661d553431..2ed1faaec6 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultDecoderFactory.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultDecoderFactory.java @@ -19,6 +19,8 @@ package com.google.android.exoplayer2.transformer; import static com.google.android.exoplayer2.util.Assertions.checkNotNull; import static com.google.android.exoplayer2.util.Util.SDK_INT; +import android.annotation.SuppressLint; +import android.content.Context; import android.media.MediaFormat; import android.view.Surface; import androidx.annotation.Nullable; @@ -30,6 +32,18 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; /** A default implementation of {@link Codec.DecoderFactory}. */ /* package */ final class DefaultDecoderFactory implements Codec.DecoderFactory { + private final Context context; + + private final boolean decoderSupportsKeyAllowFrameDrop; + + public DefaultDecoderFactory(Context context) { + this.context = context; + + decoderSupportsKeyAllowFrameDrop = + SDK_INT >= 29 + && context.getApplicationContext().getApplicationInfo().targetSdkVersion >= 29; + } + @Override public Codec createForAudioDecoding(Format format) throws TransformationException { MediaFormat mediaFormat = @@ -45,9 +59,15 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; throw createTransformationException(format); } return new DefaultCodec( - format, mediaFormat, mediaCodecName, /* isDecoder= */ true, /* outputSurface= */ null); + context, + format, + mediaFormat, + mediaCodecName, + /* isDecoder= */ true, + /* outputSurface= */ null); } + @SuppressLint("InlinedApi") @Override public Codec createForVideoDecoding( Format format, Surface outputSurface, boolean enableRequestSdrToneMapping) @@ -59,9 +79,9 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; MediaFormatUtil.maybeSetInteger( mediaFormat, MediaFormat.KEY_MAX_INPUT_SIZE, format.maxInputSize); MediaFormatUtil.setCsdBuffers(mediaFormat, format.initializationData); - if (SDK_INT >= 29) { - // On API levels over 29, Transformer decodes as many frames as possible in one render - // cycle. This key ensures no frame dropping when the decoder's output surface is full. + if (decoderSupportsKeyAllowFrameDrop) { + // This key ensures no frame dropping when the decoder's output surface is full. This allows + // transformer to decode as many frames as possible in one render cycle. mediaFormat.setInteger(MediaFormat.KEY_ALLOW_FRAME_DROP, 0); } if (SDK_INT >= 31 && enableRequestSdrToneMapping) { @@ -75,7 +95,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; throw createTransformationException(format); } return new DefaultCodec( - format, mediaFormat, mediaCodecName, /* isDecoder= */ true, outputSurface); + context, format, mediaFormat, mediaCodecName, /* isDecoder= */ true, outputSurface); } @RequiresNonNull("#1.sampleMimeType") 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 e1d4c159f3..309646600c 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 @@ -24,6 +24,7 @@ import static com.google.android.exoplayer2.util.Util.SDK_INT; import static java.lang.Math.abs; import static java.lang.Math.floor; +import android.content.Context; import android.media.MediaCodecInfo; import android.media.MediaFormat; import android.util.Pair; @@ -44,6 +45,7 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory { private static final int DEFAULT_FRAME_RATE = 30; private static final String TAG = "DefaultEncoderFactory"; + private final Context context; private final EncoderSelector videoEncoderSelector; private final VideoEncoderSettings requestedVideoEncoderSettings; private final boolean enableFallback; @@ -52,13 +54,14 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory { * Creates a new instance using the {@link EncoderSelector#DEFAULT default encoder selector}, a * default {@link VideoEncoderSettings}, and with format fallback enabled. */ - public DefaultEncoderFactory() { - this(EncoderSelector.DEFAULT, /* enableFallback= */ true); + public DefaultEncoderFactory(Context context) { + this(context, EncoderSelector.DEFAULT, /* enableFallback= */ true); } /** Creates a new instance using a default {@link VideoEncoderSettings}. */ - public DefaultEncoderFactory(EncoderSelector videoEncoderSelector, boolean enableFallback) { - this(videoEncoderSelector, VideoEncoderSettings.DEFAULT, enableFallback); + public DefaultEncoderFactory( + Context context, EncoderSelector videoEncoderSelector, boolean enableFallback) { + this(context, videoEncoderSelector, VideoEncoderSettings.DEFAULT, enableFallback); } /** @@ -79,14 +82,17 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory { * and {@link VideoEncoderSettings#level} can cause codec configuration failure. Setting an * unsupported {@link VideoEncoderSettings#bitrateMode} may cause encoder instantiation failure. * + * @param context The {@link Context}. * @param videoEncoderSelector The {@link EncoderSelector}. * @param requestedVideoEncoderSettings The {@link VideoEncoderSettings}. * @param enableFallback Whether to enable fallback. */ public DefaultEncoderFactory( + Context context, EncoderSelector videoEncoderSelector, VideoEncoderSettings requestedVideoEncoderSettings, boolean enableFallback) { + this.context = context; this.videoEncoderSelector = videoEncoderSelector; this.requestedVideoEncoderSettings = requestedVideoEncoderSettings; this.enableFallback = enableFallback; @@ -118,7 +124,12 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory { throw createTransformationException(format); } return new DefaultCodec( - format, mediaFormat, mediaCodecName, /* isDecoder= */ false, /* outputSurface= */ null); + context, + format, + mediaFormat, + mediaCodecName, + /* isDecoder= */ false, + /* outputSurface= */ null); } @Override @@ -208,6 +219,7 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory { } return new DefaultCodec( + context, format, mediaFormat, encoderInfo.getName(), diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Transformer.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Transformer.java index a7919ab28d..07352a3df0 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Transformer.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Transformer.java @@ -92,9 +92,7 @@ public final class Transformer { public static final class Builder { // Mandatory field. - // TODO(huangdarwin): Update @MonotonicNonNull to final after deprecated {@link - // #setContext(Context)} is removed. - private @MonotonicNonNull Context context; + private final Context context; // Optional fields. private MediaSource.@MonotonicNonNull Factory mediaSourceFactory; @@ -111,23 +109,6 @@ public final class Transformer { private Codec.EncoderFactory encoderFactory; private Codec.DecoderFactory decoderFactory; - /** - * @deprecated Use {@link #Builder(Context)} instead. - */ - @Deprecated - public Builder() { - muxerFactory = new FrameworkMuxer.Factory(); - looper = Util.getCurrentOrMainLooper(); - clock = Clock.DEFAULT; - listeners = new ListenerSet<>(looper, clock, (listener, flags) -> {}); - encoderFactory = Codec.EncoderFactory.DEFAULT; - decoderFactory = Codec.DecoderFactory.DEFAULT; - debugViewProvider = DebugViewProvider.NONE; - containerMimeType = MimeTypes.VIDEO_MP4; - transformationRequest = new TransformationRequest.Builder().build(); - videoFrameEffects = ImmutableList.of(); - } - /** * Creates a builder with default values. * @@ -139,8 +120,8 @@ public final class Transformer { looper = Util.getCurrentOrMainLooper(); clock = Clock.DEFAULT; listeners = new ListenerSet<>(looper, clock, (listener, flags) -> {}); - encoderFactory = Codec.EncoderFactory.DEFAULT; - decoderFactory = Codec.DecoderFactory.DEFAULT; + encoderFactory = new DefaultEncoderFactory(this.context); + decoderFactory = new DefaultDecoderFactory(this.context); debugViewProvider = DebugViewProvider.NONE; containerMimeType = MimeTypes.VIDEO_MP4; transformationRequest = new TransformationRequest.Builder().build(); @@ -165,15 +146,6 @@ public final class Transformer { this.clock = transformer.clock; } - /** - * @deprecated Use {@link #Builder(Context)} instead. - */ - @Deprecated - public Builder setContext(Context context) { - this.context = context.getApplicationContext(); - return this; - } - /** * Sets the {@link TransformationRequest} which configures the editing and transcoding options. * @@ -342,7 +314,7 @@ public final class Transformer { /** * Sets the {@link Codec.EncoderFactory} that will be used by the transformer. * - *

The default value is {@link Codec.EncoderFactory#DEFAULT}. + *

The default value is a {@link DefaultEncoderFactory} instance. * * @param encoderFactory The {@link Codec.EncoderFactory} instance. * @return This builder. @@ -355,7 +327,7 @@ public final class Transformer { /** * Sets the {@link Codec.DecoderFactory} that will be used by the transformer. * - *

The default value is {@link Codec.DecoderFactory#DEFAULT}. + *

The default value is a {@link DefaultDecoderFactory} instance. * * @param decoderFactory The {@link Codec.DecoderFactory} instance. * @return This builder. diff --git a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactoryTest.java b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactoryTest.java index 249c231639..3efc65d4ee 100644 --- a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactoryTest.java +++ b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/DefaultEncoderFactoryTest.java @@ -16,9 +16,11 @@ package com.google.android.exoplayer2.transformer; +import static androidx.test.core.app.ApplicationProvider.getApplicationContext; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; +import android.content.Context; import android.media.MediaCodecInfo; import android.media.MediaFormat; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -34,6 +36,7 @@ import org.robolectric.shadows.ShadowMediaCodecList; /** Unit test for {@link DefaultEncoderFactory}. */ @RunWith(AndroidJUnit4.class) public class DefaultEncoderFactoryTest { + private final Context context = getApplicationContext(); @Before public void setUp() { @@ -65,7 +68,7 @@ public class DefaultEncoderFactoryTest { throws Exception { Format requestedVideoFormat = createVideoFormat(MimeTypes.VIDEO_H264, 1920, 1080, 30); Format actualVideoFormat = - new DefaultEncoderFactory() + new DefaultEncoderFactory(context) .createForVideoEncoding( requestedVideoFormat, /* allowedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H264)) @@ -83,7 +86,7 @@ public class DefaultEncoderFactoryTest { throws Exception { Format requestedVideoFormat = createVideoFormat(MimeTypes.VIDEO_H265, 1920, 1080, 30); Format actualVideoFormat = - new DefaultEncoderFactory() + new DefaultEncoderFactory(context) .createForVideoEncoding( requestedVideoFormat, /* allowedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H264)) @@ -101,7 +104,7 @@ public class DefaultEncoderFactoryTest { throws Exception { Format requestedVideoFormat = createVideoFormat(MimeTypes.VIDEO_H264, 3840, 2160, 60); Format actualVideoFormat = - new DefaultEncoderFactory() + new DefaultEncoderFactory(context) .createForVideoEncoding( requestedVideoFormat, /* allowedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H264)) @@ -119,7 +122,7 @@ public class DefaultEncoderFactoryTest { assertThrows( TransformationException.class, () -> - new DefaultEncoderFactory() + new DefaultEncoderFactory(context) .createForVideoEncoding( requestedVideoFormat, /* allowedMimeTypes= */ ImmutableList.of(MimeTypes.VIDEO_H265))); @@ -136,6 +139,7 @@ public class DefaultEncoderFactoryTest { TransformationException.class, () -> new DefaultEncoderFactory( + context, /* videoEncoderSelector= */ mimeType -> ImmutableList.of(), /* enableFallback= */ true) .createForVideoEncoding( diff --git a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerBuilderTest.java b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerBuilderTest.java index e96f136fdd..e134695304 100644 --- a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerBuilderTest.java +++ b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerBuilderTest.java @@ -38,11 +38,6 @@ public class TransformerBuilderTest { () -> new Transformer.Builder(context).setOutputMimeType(MimeTypes.VIDEO_UNKNOWN).build()); } - @Test - public void build_withoutContext_throws() { - assertThrows(NullPointerException.class, () -> new Transformer.Builder().build()); - } - @Test public void build_removeAudioAndVideo_throws() { Context context = ApplicationProvider.getApplicationContext(); diff --git a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java index 2b83257296..05eb5eec2b 100644 --- a/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java +++ b/library/transformer/src/test/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java @@ -750,7 +750,8 @@ public final class TransformerEndToEndTest { return new Transformer.Builder(context) .setClock(clock) .setMuxerFactory(new TestMuxerFactory()) - .setEncoderFactory(new DefaultEncoderFactory(EncoderSelector.DEFAULT, enableFallback)); + .setEncoderFactory( + new DefaultEncoderFactory(context, EncoderSelector.DEFAULT, enableFallback)); } private static void createEncodersAndDecoders() {