From 6ac1306ec2164d23747809adfcebd43849c71ef3 Mon Sep 17 00:00:00 2001 From: samrobinson Date: Tue, 10 May 2022 15:08:51 +0100 Subject: [PATCH] Expose the codec name to the analysis files. PiperOrigin-RevId: 447724152 --- .../TransformerAndroidTestRunner.java | 62 ++++++++++++++++++- .../android/exoplayer2/transformer/Codec.java | 3 + .../exoplayer2/transformer/DefaultCodec.java | 21 ++++++- .../exoplayer2/transformer/Transformer.java | 4 +- 4 files changed, 85 insertions(+), 5 deletions(-) diff --git a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/TransformerAndroidTestRunner.java b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/TransformerAndroidTestRunner.java index c04019cc1e..cf4ecabd07 100644 --- a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/TransformerAndroidTestRunner.java +++ b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/TransformerAndroidTestRunner.java @@ -22,16 +22,19 @@ import android.content.Context; import android.net.Uri; import androidx.annotation.Nullable; import androidx.test.platform.app.InstrumentationRegistry; +import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.SystemClock; import java.io.File; import java.io.IOException; +import java.util.List; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicReference; import org.checkerframework.checker.nullness.compatqual.NullableType; +import org.json.JSONException; import org.json.JSONObject; /** An android instrumentation test runner for {@link Transformer}. */ @@ -140,6 +143,7 @@ public class TransformerAndroidTestRunner { } private final Context context; + private final CodecNameForwardingEncoderFactory transformerEncoderFactory; private final Transformer transformer; private final int timeoutSeconds; private final boolean calculateSsim; @@ -154,7 +158,9 @@ public class TransformerAndroidTestRunner { boolean suppressAnalysisExceptions, @Nullable Map inputValues) { this.context = context; - this.transformer = transformer; + this.transformerEncoderFactory = + new CodecNameForwardingEncoderFactory(transformer.encoderFactory); + this.transformer = transformer.buildUpon().setEncoderFactory(transformerEncoderFactory).build(); this.timeoutSeconds = timeoutSeconds; this.calculateSsim = calculateSsim; this.suppressAnalysisExceptions = suppressAnalysisExceptions; @@ -186,6 +192,7 @@ public class TransformerAndroidTestRunner { resultJson.put("exception", AndroidTestUtil.exceptionAsJsonObject(e)); throw e; } finally { + resultJson.put("codecDetails", transformerEncoderFactory.getCodecNamesAsJsonObject()); AndroidTestUtil.writeTestSummaryToFile(context, testId, resultJson); } } @@ -307,4 +314,57 @@ public class TransformerAndroidTestRunner { } return resultBuilder.build(); } + + /** + * A {@link Codec.EncoderFactory} that forwards all methods to another encoder factory, whilst + * providing visibility into the names of last codecs created by it. + */ + private static class CodecNameForwardingEncoderFactory implements Codec.EncoderFactory { + + @Nullable public String audioEncoderName; + @Nullable public String videoEncoderName; + + private final Codec.EncoderFactory encoderFactory; + + public CodecNameForwardingEncoderFactory(Codec.EncoderFactory encoderFactory) { + this.encoderFactory = encoderFactory; + } + + @Override + public Codec createForAudioEncoding(Format format, List allowedMimeTypes) + throws TransformationException { + Codec audioEncoder = encoderFactory.createForAudioEncoding(format, allowedMimeTypes); + audioEncoderName = audioEncoder.getName(); + return audioEncoder; + } + + @Override + public Codec createForVideoEncoding(Format format, List allowedMimeTypes) + throws TransformationException { + Codec videoEncoder = encoderFactory.createForVideoEncoding(format, allowedMimeTypes); + videoEncoderName = videoEncoder.getName(); + return videoEncoder; + } + + @Override + public boolean audioNeedsEncoding() { + return encoderFactory.audioNeedsEncoding(); + } + + @Override + public boolean videoNeedsEncoding() { + return encoderFactory.videoNeedsEncoding(); + } + + public JSONObject getCodecNamesAsJsonObject() throws JSONException { + JSONObject detailsJson = new JSONObject(); + if (audioEncoderName != null) { + detailsJson.put("audioEncoderName", audioEncoderName); + } + if (videoEncoderName != null) { + detailsJson.put("videoEncoderName", videoEncoderName); + } + return detailsJson; + } + } } 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 fddabfdeab..c9a4e67a2b 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 @@ -131,6 +131,9 @@ public interface Codec { */ Format getConfigurationFormat(); + /** Returns the name of the underlying codec. */ + String getName(); + /** * Returns the input {@link Surface} of an underlying video encoder. * 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 7471405482..e9b2165d33 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 @@ -19,6 +19,7 @@ package com.google.android.exoplayer2.transformer; import static com.google.android.exoplayer2.util.Assertions.checkNotNull; 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.media.MediaCodec; import android.media.MediaCodec.BufferInfo; @@ -30,7 +31,6 @@ import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.TraceUtil; -import com.google.android.exoplayer2.util.Util; import com.google.common.base.Ascii; import com.google.common.collect.ImmutableList; import java.io.IOException; @@ -122,7 +122,7 @@ public final class DefaultCodec implements Codec { @Override public int getMaxPendingFrameCount() { - if (Util.SDK_INT < 29) { + 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 @@ -255,6 +255,23 @@ public final class DefaultCodec implements Codec { mediaCodec.release(); } + /** + * {@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)}. + * + * @see MediaCodec#getCanonicalName() + */ + @Override + public String getName() { + if (SDK_INT >= 29) { + return mediaCodec.getCanonicalName(); + } + + return mediaCodec.getName(); + } + /** * Attempts to dequeue an output buffer if there is no output buffer pending. Does nothing * otherwise. 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 291186701d..3f090f0a58 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 @@ -555,10 +555,10 @@ public final class Transformer { private final ImmutableList videoFrameEffects; private final Looper looper; private final Clock clock; - private final Codec.EncoderFactory encoderFactory; - private final Codec.DecoderFactory decoderFactory; private final Transformer.DebugViewProvider debugViewProvider; private final ListenerSet listeners; + private final Codec.DecoderFactory decoderFactory; + @VisibleForTesting /* package */ final Codec.EncoderFactory encoderFactory; @Nullable private MuxerWrapper muxerWrapper; @Nullable private ExoPlayer player;