From d5dcbf4a12bddbcf26e02fdfb29105f5c288ef5d Mon Sep 17 00:00:00 2001 From: shahddaghash Date: Mon, 24 Mar 2025 02:15:23 -0700 Subject: [PATCH] Extract CodecInfo from CodecImpl and expose default CodecInfo configs This is a step towards unifying ShadowMediaCodecConfig structure to accommodate both ExoPlayer and Transcoding codecs configuration. This change abstracts the codec information to a separate `CodecInfo` class. This allows having codecs with the same information configured with different configurations (passthrough/frame-dropping, decoder/encoder). It also does the following: * Replaces the map of default codecs with public static final CodecInfo constants for each codec. * Modifies the ShadowMediaCodecConfig constructor to accept a set of CodecImpls instead of mime types. * Updates factory methods to reflect the constructor change. * Updates addSupportedMimeTypes to addDecoder, taking a CodecInfo instead of a mimeType. This is a non-functional change. PiperOrigin-RevId: 739857883 --- .../audio/AudioCapabilitiesEndToEndTest.java | 12 +- .../robolectric/ShadowMediaCodecConfig.java | 374 ++++++++++-------- 2 files changed, 207 insertions(+), 179 deletions(-) diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/audio/AudioCapabilitiesEndToEndTest.java b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/audio/AudioCapabilitiesEndToEndTest.java index bf0b9e1547..cfd0c48e44 100644 --- a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/audio/AudioCapabilitiesEndToEndTest.java +++ b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/audio/AudioCapabilitiesEndToEndTest.java @@ -19,6 +19,8 @@ import static android.media.AudioFormat.CHANNEL_OUT_5POINT1; import static android.media.AudioFormat.CHANNEL_OUT_STEREO; import static android.media.AudioFormat.ENCODING_AC3; import static androidx.media3.common.util.Assertions.checkNotNull; +import static androidx.media3.test.utils.robolectric.ShadowMediaCodecConfig.CODEC_INFO_AAC; +import static androidx.media3.test.utils.robolectric.ShadowMediaCodecConfig.CODEC_INFO_AC3; import static androidx.media3.test.utils.robolectric.TestPlayerRunHelper.advance; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.mock; @@ -124,7 +126,7 @@ public class AudioCapabilitiesEndToEndTest { @Config(minSdk = 29) public void playAc3WithDirectPlayback_directPlaybackNotSupportMidPlayback_recoversToAac() throws Exception { - shadowMediaCodecConfig.addSupportedMimeTypes(MimeTypes.AUDIO_AAC); + shadowMediaCodecConfig.addDecoders(CODEC_INFO_AAC); setupDefaultPcmSupport(); addDirectPlaybackSupportForAC3(); setUiModeToTv(); @@ -189,7 +191,7 @@ public class AudioCapabilitiesEndToEndTest { public void playAc3WithDirectPlayback_directPlaybackNotSupportMidPlaybackButDeviceHasAc3Codec_recoversToAc3() throws Throwable { - shadowMediaCodecConfig.addSupportedMimeTypes(MimeTypes.AUDIO_AAC, MimeTypes.AUDIO_AC3); + shadowMediaCodecConfig.addDecoders(CODEC_INFO_AAC, CODEC_INFO_AC3); setupDefaultPcmSupport(); addDirectPlaybackSupportForAC3(); setUiModeToTv(); @@ -249,7 +251,7 @@ public class AudioCapabilitiesEndToEndTest { final AtomicBoolean directPlaybackSupportAddedReference = new AtomicBoolean(); setupDefaultPcmSupport(); - shadowMediaCodecConfig.addSupportedMimeTypes(MimeTypes.AUDIO_AAC); + shadowMediaCodecConfig.addDecoders(CODEC_INFO_AAC); setUiModeToTv(); RenderersFactory renderersFactory = createRenderersFactory( @@ -323,7 +325,7 @@ public class AudioCapabilitiesEndToEndTest { final AtomicBoolean directPlaybackSupportAddedReference = new AtomicBoolean(); setupDefaultPcmSupport(); - shadowMediaCodecConfig.addSupportedMimeTypes(MimeTypes.AUDIO_AAC, MimeTypes.AUDIO_AC3); + shadowMediaCodecConfig.addDecoders(CODEC_INFO_AAC, CODEC_INFO_AC3); setUiModeToTv(); RenderersFactory renderersFactory = createRenderersFactory( @@ -396,7 +398,7 @@ public class AudioCapabilitiesEndToEndTest { throws Throwable { final AtomicBoolean directPlaybackSupportAddedReference = new AtomicBoolean(); - shadowMediaCodecConfig.addSupportedMimeTypes(MimeTypes.AUDIO_AAC); + shadowMediaCodecConfig.addDecoders(CODEC_INFO_AAC); setupDefaultPcmSupport(); setUiModeToTv(); RenderersFactory renderersFactory = diff --git a/libraries/test_utils_robolectric/src/main/java/androidx/media3/test/utils/robolectric/ShadowMediaCodecConfig.java b/libraries/test_utils_robolectric/src/main/java/androidx/media3/test/utils/robolectric/ShadowMediaCodecConfig.java index 28b7933639..dd10d5d6b3 100644 --- a/libraries/test_utils_robolectric/src/main/java/androidx/media3/test/utils/robolectric/ShadowMediaCodecConfig.java +++ b/libraries/test_utils_robolectric/src/main/java/androidx/media3/test/utils/robolectric/ShadowMediaCodecConfig.java @@ -15,9 +15,6 @@ */ package androidx.media3.test.utils.robolectric; -import static androidx.media3.common.util.Assertions.checkArgument; -import static androidx.media3.common.util.Assertions.checkState; -import static androidx.media3.common.util.Assertions.checkStateNotNull; import static androidx.media3.exoplayer.mediacodec.MediaCodecUtil.createCodecProfileLevel; import android.media.MediaCodecInfo; @@ -27,40 +24,191 @@ import androidx.media3.common.MimeTypes; import androidx.media3.common.util.UnstableApi; import androidx.media3.exoplayer.mediacodec.MediaCodecUtil; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.primitives.Ints; import java.nio.ByteBuffer; -import java.util.HashSet; -import java.util.Set; import org.junit.rules.ExternalResource; import org.robolectric.shadows.MediaCodecInfoBuilder; import org.robolectric.shadows.ShadowMediaCodec; import org.robolectric.shadows.ShadowMediaCodecList; /** - * A JUnit @Rule to configure Roboelectric's {@link ShadowMediaCodec}. + * A JUnit @Rule to configure Robolectric's {@link ShadowMediaCodec}. * *

Registers a {@link org.robolectric.shadows.ShadowMediaCodec.CodecConfig} for each audio/video * MIME type known by ExoPlayer. */ @UnstableApi public final class ShadowMediaCodecConfig extends ExternalResource { - private static final ImmutableMap ALL_SUPPORTED_CODECS = - createAllSupportedCodecs(); - public static ShadowMediaCodecConfig forAllSupportedMimeTypes() { - return new ShadowMediaCodecConfig(ALL_SUPPORTED_CODECS.keySet()); + /** Class that holds information about a {@link CodecImpl} configuration. */ + public static final class CodecInfo { + public final String codecName; + public final String mimeType; + public final ImmutableList profileLevels; + public final ImmutableList colorFormats; + + /** + * Creates an instance. + * + *

This method is equivalent to {@code CodecInfo(codecName, mimeType, ImmutableList.of(), + * ImmutableList.of()}. + * + * @param codecName The name of the codec. + * @param mimeType The MIME type of the codec. + */ + public CodecInfo(String codecName, String mimeType) { + this( + codecName, + mimeType, + /* profileLevels= */ ImmutableList.of(), + /* colorFormats= */ ImmutableList.of()); + } + + /** + * Creates an instance. + * + * @param codecName The name of the codec. + * @param mimeType The MIME type of the codec. + * @param profileLevels A list of profiles and levels supported by the codec. + * @param colorFormats A list of color formats supported by the codec. + */ + public CodecInfo( + String codecName, + String mimeType, + ImmutableList profileLevels, + ImmutableList colorFormats) { + this.codecName = codecName; + this.mimeType = mimeType; + this.profileLevels = profileLevels; + this.colorFormats = colorFormats; + } } + public static final CodecInfo CODEC_INFO_AVC = + new CodecInfo( + /* codecName= */ "exotest.video.avc", + MimeTypes.VIDEO_H264, + /* profileLevels= */ ImmutableList.of( + createCodecProfileLevel( + CodecProfileLevel.AVCProfileHigh, CodecProfileLevel.AVCLevel62)), + /* colorFormats= */ ImmutableList.of( + MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible)); + public static final CodecInfo CODEC_INFO_HEVC = + new CodecInfo( + /* codecName= */ "exotest.video.hevc", + MimeTypes.VIDEO_H265, + /* profileLevels= */ ImmutableList.of( + createCodecProfileLevel( + CodecProfileLevel.HEVCProfileMain, CodecProfileLevel.HEVCMainTierLevel61)), + /* colorFormats= */ ImmutableList.of( + MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible)); + public static final CodecInfo CODEC_INFO_MPEG2 = + new CodecInfo( + /* codecName= */ "exotest.video.mpeg2", + MimeTypes.VIDEO_MPEG2, + /* profileLevels= */ ImmutableList.of( + createCodecProfileLevel( + CodecProfileLevel.MPEG2ProfileMain, CodecProfileLevel.MPEG2LevelML)), + /* colorFormats= */ ImmutableList.of( + MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible)); + public static final CodecInfo CODEC_INFO_VP9 = + new CodecInfo( + /* codecName= */ "exotest.video.vp9", + MimeTypes.VIDEO_VP9, + /* profileLevels= */ ImmutableList.of(), + /* colorFormats= */ ImmutableList.of( + MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible)); + public static final CodecInfo CODEC_INFO_AV1 = + new CodecInfo( + /* codecName= */ "exotest.video.av1", + MimeTypes.VIDEO_AV1, + /* profileLevels= */ ImmutableList.of(), + /* colorFormats= */ ImmutableList.of( + MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible)); + public static final CodecInfo CODEC_INFO_AAC = + new CodecInfo(/* codecName= */ "exotest.audio.aac", MimeTypes.AUDIO_AAC); + public static final CodecInfo CODEC_INFO_AC3 = + new CodecInfo(/* codecName= */ "exotest.audio.ac3", MimeTypes.AUDIO_AC3); + public static final CodecInfo CODEC_INFO_AC4 = + new CodecInfo(/* codecName= */ "exotest.audio.ac4", MimeTypes.AUDIO_AC4); + public static final CodecInfo CODEC_INFO_E_AC3 = + new CodecInfo(/* codecName= */ "exotest.audio.eac3", MimeTypes.AUDIO_E_AC3); + public static final CodecInfo CODEC_INFO_E_AC3_JOC = + new CodecInfo(/* codecName= */ "exotest.audio.eac3joc", MimeTypes.AUDIO_E_AC3_JOC); + public static final CodecInfo CODEC_INFO_FLAC = + new CodecInfo(/* codecName= */ "exotest.audio.flac", MimeTypes.AUDIO_FLAC); + public static final CodecInfo CODEC_INFO_MPEG = + new CodecInfo(/* codecName= */ "exotest.audio.mpeg", MimeTypes.AUDIO_MPEG); + public static final CodecInfo CODEC_INFO_MPEG_L2 = + new CodecInfo(/* codecName= */ "exotest.audio.mpegl2", MimeTypes.AUDIO_MPEG_L2); + public static final CodecInfo CODEC_INFO_OPUS = + new CodecInfo(/* codecName= */ "exotest.audio.opus", MimeTypes.AUDIO_OPUS); + public static final CodecInfo CODEC_INFO_VORBIS = + new CodecInfo(/* codecName= */ "exotest.audio.vorbis", MimeTypes.AUDIO_VORBIS); + // In ExoPlayer, raw audio should use a bypass mode and never need this codec. However, to easily + // assert failures of the bypass mode we want to detect when the raw audio is decoded by this + public static final CodecInfo CODEC_INFO_RAW = + new CodecInfo(/* codecName= */ "exotest.audio.raw", MimeTypes.AUDIO_RAW); + + private static final ImmutableSet ALL_SUPPORTED_CODECS = + ImmutableSet.of( + CODEC_INFO_AVC, + CODEC_INFO_HEVC, + CODEC_INFO_MPEG2, + CODEC_INFO_VP9, + CODEC_INFO_AV1, + CODEC_INFO_AAC, + CODEC_INFO_AC3, + CODEC_INFO_AC4, + CODEC_INFO_E_AC3, + CODEC_INFO_E_AC3_JOC, + CODEC_INFO_FLAC, + CODEC_INFO_MPEG, + CODEC_INFO_MPEG_L2, + CODEC_INFO_OPUS, + CODEC_INFO_VORBIS, + CODEC_INFO_RAW); + + /** + * @deprecated Use {@link ShadowMediaCodecConfig#withAllDefaultSupportedCodecs()} instead. + */ + // TODO(b/399861060): Remove in Media3 1.8. + @Deprecated + public static ShadowMediaCodecConfig forAllSupportedMimeTypes() { + return withAllDefaultSupportedCodecs(); + } + + /** + * Returns a {@link ShadowMediaCodecConfig} instance populated with a default list of supported + * decoders using a default codec configuration. + * + *

The default codec configuration drops all samples on audio decoders and works as passthrough + * on video decoders. + */ + public static ShadowMediaCodecConfig withAllDefaultSupportedCodecs() { + return new ShadowMediaCodecConfig( + createDecoders(ALL_SUPPORTED_CODECS.asList(), /* forcePassthrough= */ false)); + } + + /** + * @deprecated Use {@link ShadowMediaCodecConfig#withNoDefaultSupportedCodecs()} instead. + */ + // TODO(b/399861060): Remove in Media3 1.8. + @Deprecated public static ShadowMediaCodecConfig withNoDefaultSupportedMimeTypes() { + return withNoDefaultSupportedCodecs(); + } + + /** Returns a {@link ShadowMediaCodecConfig} instance populated with no shadow codecs. */ + public static ShadowMediaCodecConfig withNoDefaultSupportedCodecs() { return new ShadowMediaCodecConfig(ImmutableSet.of()); } - private final Set supportedMimeTypes; + private final ImmutableSet defaultCodecs; - private ShadowMediaCodecConfig(Set mimeTypes) { - supportedMimeTypes = new HashSet<>(mimeTypes); + private ShadowMediaCodecConfig(ImmutableSet defaultCodecs) { + this.defaultCodecs = defaultCodecs; } /** @@ -106,140 +254,44 @@ public final class ShadowMediaCodecConfig extends ExternalResource { } } - public void addSupportedMimeTypes(String... mimeTypes) { - for (String mimeType : mimeTypes) { - checkState(!supportedMimeTypes.contains(mimeType), "MIME type already added: " + mimeType); - checkArgument( - ALL_SUPPORTED_CODECS.containsKey(mimeType), "MIME type not supported: " + mimeType); + /** + * Configures and publishes {@linkplain ShadowMediaCodec shadow decoders} based on {@code + * decoders}. + * + *

This method configures frame-dropping decoders. + */ + public void addDecoders(CodecInfo... decoders) { + for (CodecInfo decoderInfo : decoders) { + CodecImpl decoder = CodecImpl.createFrameDroppingDecoder(decoderInfo); + decoder.configure(); } - ImmutableSet addedMimeTypes = ImmutableSet.copyOf(mimeTypes); - supportedMimeTypes.addAll(addedMimeTypes); - configureCodecs(addedMimeTypes); } @Override protected void before() throws Throwable { - configureCodecs(supportedMimeTypes); + for (CodecImpl codec : this.defaultCodecs) { + codec.configure(); + } } @Override protected void after() { - supportedMimeTypes.clear(); MediaCodecUtil.clearDecoderInfoCache(); ShadowMediaCodecList.reset(); ShadowMediaCodec.clearCodecs(); } - private void configureCodecs(Set mimeTypes) { - for (String mimeType : mimeTypes) { - checkStateNotNull(ALL_SUPPORTED_CODECS.get(mimeType)).configure(); + private static ImmutableSet createDecoders( + ImmutableList decoderInfos, boolean forcePassthrough) { + ImmutableSet.Builder builder = new ImmutableSet.Builder<>(); + for (CodecInfo info : decoderInfos) { + if (!forcePassthrough && MimeTypes.isAudio(info.mimeType)) { + builder.add(CodecImpl.createFrameDroppingDecoder(info)); + } else { + builder.add(CodecImpl.createPassthroughDecoder(info)); + } } - } - - private static ImmutableMap createAllSupportedCodecs() { - ImmutableMap.Builder codecs = new ImmutableMap.Builder<>(); - // Video codecs - codecs.put( - MimeTypes.VIDEO_H264, - new CodecImpl( - /* codecName= */ "exotest.video.avc", - /* mimeType= */ MimeTypes.VIDEO_H264, - /* profileLevels= */ ImmutableList.of( - createCodecProfileLevel( - MediaCodecInfo.CodecProfileLevel.AVCProfileHigh, - MediaCodecInfo.CodecProfileLevel.AVCLevel62)), - /* colorFormats= */ ImmutableList.of( - MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible), - /* isPassthrough= */ true, - /* isEncoder= */ false)); - codecs.put( - MimeTypes.VIDEO_H265, - new CodecImpl( - /* codecName= */ "exotest.video.hevc", - /* mimeType= */ MimeTypes.VIDEO_H265, - /* profileLevels= */ ImmutableList.of( - createCodecProfileLevel( - CodecProfileLevel.HEVCProfileMain, CodecProfileLevel.HEVCMainTierLevel61)), - /* colorFormats= */ ImmutableList.of( - MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible), - /* isPassthrough= */ true, - /* isEncoder= */ false)); - codecs.put( - MimeTypes.VIDEO_MPEG2, - new CodecImpl( - /* codecName= */ "exotest.video.mpeg2", - /* mimeType= */ MimeTypes.VIDEO_MPEG2, - /* profileLevels= */ ImmutableList.of( - createCodecProfileLevel( - MediaCodecInfo.CodecProfileLevel.MPEG2ProfileMain, - MediaCodecInfo.CodecProfileLevel.MPEG2LevelML)), - /* colorFormats= */ ImmutableList.of( - MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible), - /* isPassthrough= */ true, - /* isEncoder= */ false)); - codecs.put( - MimeTypes.VIDEO_VP9, - new CodecImpl( - /* codecName= */ "exotest.video.vp9", - /* mimeType= */ MimeTypes.VIDEO_VP9, - /* profileLevels= */ ImmutableList.of(), - /* colorFormats= */ ImmutableList.of( - MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible), - /* isPassthrough= */ true, - /* isEncoder= */ false)); - codecs.put( - MimeTypes.VIDEO_AV1, - new CodecImpl( - /* codecName= */ "exotest.video.av1", - /* mimeType= */ MimeTypes.VIDEO_AV1, - /* profileLevels= */ ImmutableList.of(), - /* colorFormats= */ ImmutableList.of( - MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible), - /* isPassthrough= */ true, - /* isEncoder= */ false)); - - // Frame-dropping audio decoders. - codecs.put( - MimeTypes.AUDIO_AAC, - new CodecImpl(/* codecName= */ "exotest.audio.aac", /* mimeType= */ MimeTypes.AUDIO_AAC)); - codecs.put( - MimeTypes.AUDIO_AC3, - new CodecImpl(/* codecName= */ "exotest.audio.ac3", /* mimeType= */ MimeTypes.AUDIO_AC3)); - codecs.put( - MimeTypes.AUDIO_AC4, - new CodecImpl(/* codecName= */ "exotest.audio.ac4", /* mimeType= */ MimeTypes.AUDIO_AC4)); - codecs.put( - MimeTypes.AUDIO_E_AC3, - new CodecImpl( - /* codecName= */ "exotest.audio.eac3", /* mimeType= */ MimeTypes.AUDIO_E_AC3)); - codecs.put( - MimeTypes.AUDIO_E_AC3_JOC, - new CodecImpl( - /* codecName= */ "exotest.audio.eac3joc", /* mimeType= */ MimeTypes.AUDIO_E_AC3_JOC)); - codecs.put( - MimeTypes.AUDIO_FLAC, - new CodecImpl(/* codecName= */ "exotest.audio.flac", /* mimeType= */ MimeTypes.AUDIO_FLAC)); - codecs.put( - MimeTypes.AUDIO_MPEG, - new CodecImpl(/* codecName= */ "exotest.audio.mpeg", /* mimeType= */ MimeTypes.AUDIO_MPEG)); - codecs.put( - MimeTypes.AUDIO_MPEG_L2, - new CodecImpl( - /* codecName= */ "exotest.audio.mpegl2", /* mimeType= */ MimeTypes.AUDIO_MPEG_L2)); - codecs.put( - MimeTypes.AUDIO_OPUS, - new CodecImpl(/* codecName= */ "exotest.audio.opus", /* mimeType= */ MimeTypes.AUDIO_OPUS)); - codecs.put( - MimeTypes.AUDIO_VORBIS, - new CodecImpl( - /* codecName= */ "exotest.audio.vorbis", /* mimeType= */ MimeTypes.AUDIO_VORBIS)); - // Raw audio should use a bypass mode and never need this codec. However, to easily assert - // failures of the bypass mode we want to detect when the raw audio is decoded by this - codecs.put( - MimeTypes.AUDIO_RAW, - new CodecImpl(/* codecName= */ "exotest.audio.raw", /* mimeType= */ MimeTypes.AUDIO_RAW)); - - return codecs.buildOrThrow(); + return builder.build(); } /** @@ -248,55 +300,29 @@ public final class ShadowMediaCodecConfig extends ExternalResource { */ private static final class CodecImpl implements ShadowMediaCodec.CodecConfig.Codec { - private final String codecName; - private final String mimeType; - private final ImmutableList profileLevels; - private final ImmutableList colorFormats; + private final CodecInfo codecInfo; private final boolean isPassthrough; private final boolean isEncoder; - /** - * Creates a frame dropping decoder with the specified {@code codecName} and {@code mimeType}. - * - *

This method is equivalent to {@code new CodecImpl(codecName, mimeType, ImmutableList.of(), - * ImmutableList.of(), false, false)}. - * - * @param codecName The name of the codec. - * @param mimeType The MIME type of the codec. - */ - public CodecImpl(String codecName, String mimeType) { - this( - codecName, - mimeType, - /* profileLevels= */ ImmutableList.of(), - /* colorFormats= */ ImmutableList.of(), - /* isPassthrough= */ false, - /* isEncoder= */ false); + public static CodecImpl createFrameDroppingDecoder(CodecInfo codecInfo) { + return new CodecImpl(codecInfo, /* isPassthrough= */ false, /* isEncoder= */ false); + } + + public static CodecImpl createPassthroughDecoder(CodecInfo codecInfo) { + return new CodecImpl(codecInfo, /* isPassthrough= */ true, /* isEncoder= */ false); } /** * Creates an instance. * - * @param codecName The name of the codec. - * @param mimeType The MIME type of the codec. - * @param profileLevels A list of profiles and levels supported by the codec. - * @param colorFormats A list of color formats supported by the codec. + * @param codecInfo The {@link CodecInfo} that holds the codec information. * @param isPassthrough If {@code true}, the codec acts as a pass-through codec, directly * copying input data to the output. If {@code false}, the codec drops frames. * @param isEncoder If {@code true}, the codec is an encoder. If {@code false}, the codec is a * decoder. */ - public CodecImpl( - String codecName, - String mimeType, - ImmutableList profileLevels, - ImmutableList colorFormats, - boolean isPassthrough, - boolean isEncoder) { - this.codecName = codecName; - this.mimeType = mimeType; - this.profileLevels = profileLevels; - this.colorFormats = colorFormats; + private CodecImpl(CodecInfo codecInfo, boolean isPassthrough, boolean isEncoder) { + this.codecInfo = codecInfo; this.isPassthrough = isPassthrough; this.isEncoder = isEncoder; } @@ -304,13 +330,13 @@ public final class ShadowMediaCodecConfig extends ExternalResource { public void configure() { // TODO: Update ShadowMediaCodec to consider the MediaFormat.KEY_MAX_INPUT_SIZE value passed // to configure() so we don't have to specify large buffers here. - int bufferSize = mimeType.equals(MimeTypes.VIDEO_H265) ? 250_000 : 150_000; + int bufferSize = codecInfo.mimeType.equals(MimeTypes.VIDEO_H265) ? 250_000 : 150_000; configureShadowMediaCodec( - codecName, - mimeType, + codecInfo.codecName, + codecInfo.mimeType, isEncoder, - profileLevels, - colorFormats, + codecInfo.profileLevels, + codecInfo.colorFormats, new ShadowMediaCodec.CodecConfig( /* inputBufferSize= */ bufferSize, /* outputBufferSize= */ bufferSize,