diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java index 66a56cf15e..82f09f0b27 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java @@ -367,8 +367,8 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media MimeTypes.AUDIO_RAW.equals(codecInfo.mimeType) && !MimeTypes.AUDIO_RAW.equals(format.sampleMimeType); decryptOnlyCodecFormat = decryptOnlyCodecEnabled ? format : null; - return new MediaCodecAdapter.Configuration( - codecInfo, mediaFormat, format, /* surface= */ null, crypto, /* flags= */ 0); + return MediaCodecAdapter.Configuration.createForAudioDecoding( + codecInfo, mediaFormat, format, crypto); } @Override diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecAdapter.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecAdapter.java index 7dd15954b1..2353baf516 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecAdapter.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecAdapter.java @@ -39,13 +39,109 @@ import java.nio.ByteBuffer; public interface MediaCodecAdapter { /** Configuration parameters for a {@link MediaCodecAdapter}. */ final class Configuration { + + /** + * Creates a configuration for audio decoding. + * + * @param codecInfo See {@link #codecInfo}. + * @param mediaFormat See {@link #mediaFormat}. + * @param format See {@link #format}. + * @param crypto See {@link #crypto}. + * @return The created instance. + */ + public static Configuration createForAudioDecoding( + MediaCodecInfo codecInfo, + MediaFormat mediaFormat, + Format format, + @Nullable MediaCrypto crypto) { + return new Configuration( + codecInfo, + mediaFormat, + format, + /* surface= */ null, + crypto, + /* flags= */ 0, + /* createInputSurface= */ false); + } + + /** + * Creates a configuration for video decoding. + * + * @param codecInfo See {@link #codecInfo}. + * @param mediaFormat See {@link #mediaFormat}. + * @param format See {@link #format}. + * @param surface See {@link #surface}. + * @param crypto See {@link #crypto}. + * @return The created instance. + */ + public static Configuration createForVideoDecoding( + MediaCodecInfo codecInfo, + MediaFormat mediaFormat, + Format format, + @Nullable Surface surface, + @Nullable MediaCrypto crypto) { + return new Configuration( + codecInfo, + mediaFormat, + format, + surface, + crypto, + /* flags= */ 0, + /* createInputSurface= */ false); + } + + /** + * Creates a configuration for audio encoding. + * + * @param codecInfo See {@link #codecInfo}. + * @param mediaFormat See {@link #mediaFormat}. + * @param format See {@link #format}. + * @return The created instance. + */ + public static Configuration createForAudioEncoding( + MediaCodecInfo codecInfo, MediaFormat mediaFormat, Format format) { + return new Configuration( + codecInfo, + mediaFormat, + format, + /* surface= */ null, + /* crypto= */ null, + MediaCodec.CONFIGURE_FLAG_ENCODE, + /* createInputSurface= */ false); + } + + /** + * Creates a configuration for video encoding. + * + * @param codecInfo See {@link #codecInfo}. + * @param mediaFormat See {@link #mediaFormat}. + * @param format See {@link #format}. + * @return The created instance. + */ + @RequiresApi(18) + public static Configuration createForVideoEncoding( + MediaCodecInfo codecInfo, MediaFormat mediaFormat, Format format) { + return new Configuration( + codecInfo, + mediaFormat, + format, + /* surface= */ null, + /* crypto= */ null, + MediaCodec.CONFIGURE_FLAG_ENCODE, + /* createInputSurface= */ true); + } + /** Information about the {@link MediaCodec} being configured. */ public final MediaCodecInfo codecInfo; /** The {@link MediaFormat} for which the codec is being configured. */ public final MediaFormat mediaFormat; /** The {@link Format} for which the codec is being configured. */ public final Format format; - /** For video decoding, the output where the object will render the decoded frames. */ + /** + * For video decoding, the output where the object will render the decoded frames. This must be + * null if the codec is not a video decoder, or if it is configured for {@link ByteBuffer} + * output. + */ @Nullable public final Surface surface; /** For DRM protected playbacks, a {@link MediaCrypto} to use for decryption. */ @Nullable public final MediaCrypto crypto; @@ -61,17 +157,7 @@ public interface MediaCodecAdapter { */ public final boolean createInputSurface; - public Configuration( - MediaCodecInfo codecInfo, - MediaFormat mediaFormat, - Format format, - @Nullable Surface surface, - @Nullable MediaCrypto crypto, - int flags) { - this(codecInfo, mediaFormat, format, surface, crypto, flags, /* createInputSurface= */ false); - } - - public Configuration( + private Configuration( MediaCodecInfo codecInfo, MediaFormat mediaFormat, Format format, diff --git a/library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java index 2640eb3c56..3bb6acee03 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java @@ -640,8 +640,8 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { } surface = dummySurface; } - return new MediaCodecAdapter.Configuration( - codecInfo, mediaFormat, format, surface, crypto, /* flags= */ 0); + return MediaCodecAdapter.Configuration.createForVideoDecoding( + codecInfo, mediaFormat, format, surface, crypto); } @Override diff --git a/library/core/src/test/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecAdapterTest.java b/library/core/src/test/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecAdapterTest.java index a7034dab2e..94410ab11f 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecAdapterTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/mediacodec/AsynchronousMediaCodecAdapterTest.java @@ -41,15 +41,13 @@ public class AsynchronousMediaCodecAdapterTest { @Before public void setUp() throws Exception { - MediaCodecInfo codecInfo = createMediaCodecInfo("h264", "video/mp4"); + MediaCodecInfo codecInfo = createMediaCodecInfo("aac", "audio/aac"); MediaCodecAdapter.Configuration configuration = - new MediaCodecAdapter.Configuration( + MediaCodecAdapter.Configuration.createForAudioDecoding( codecInfo, createMediaFormat("format"), - /* format= */ new Format.Builder().build(), - /* surface= */ null, - /* crypto= */ null, - /* flags= */ 0); + new Format.Builder().build(), + /* crypto= */ null); callbackThread = new HandlerThread("TestCallbackThread"); queueingThread = new HandlerThread("TestQueueingThread"); adapter = diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/MediaCodecAdapterWrapper.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/MediaCodecAdapterWrapper.java index 348d45ad06..3177166e95 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/MediaCodecAdapterWrapper.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/MediaCodecAdapterWrapper.java @@ -67,17 +67,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; private boolean outputStreamEnded; private static class Factory extends SynchronousMediaCodecAdapter.Factory { - private final boolean decoder; - - public Factory(boolean decoder) { - this.decoder = decoder; - } - @Override protected MediaCodec createCodec(Configuration configuration) throws IOException { String sampleMimeType = checkNotNull(configuration.mediaFormat.getString(MediaFormat.KEY_MIME)); - return decoder + boolean isDecoder = (configuration.flags & MediaCodec.CONFIGURE_FLAG_ENCODE) == 0; + return isDecoder ? MediaCodec.createDecoderByType(checkNotNull(sampleMimeType)) : MediaCodec.createEncoderByType(checkNotNull(sampleMimeType)); } @@ -115,15 +110,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; mediaFormat, MediaFormat.KEY_MAX_INPUT_SIZE, format.maxInputSize); MediaFormatUtil.setCsdBuffers(mediaFormat, format.initializationData); adapter = - new Factory(/* decoder= */ true) + new Factory() .createAdapter( - new MediaCodecAdapter.Configuration( - createPlaceholderMediaCodecInfo(), - mediaFormat, - format, - /* surface= */ null, - /* crypto= */ null, - /* flags= */ 0)); + MediaCodecAdapter.Configuration.createForAudioDecoding( + createPlaceholderMediaCodecInfo(), mediaFormat, format, /* crypto= */ null)); return new MediaCodecAdapterWrapper(adapter); } catch (Exception e) { if (adapter != null) { @@ -154,15 +144,14 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; mediaFormat, MediaFormat.KEY_MAX_INPUT_SIZE, format.maxInputSize); MediaFormatUtil.setCsdBuffers(mediaFormat, format.initializationData); adapter = - new Factory(/* decoder= */ true) + new Factory() .createAdapter( - new MediaCodecAdapter.Configuration( + MediaCodecAdapter.Configuration.createForVideoDecoding( createPlaceholderMediaCodecInfo(), mediaFormat, format, surface, - /* crypto= */ null, - /* flags= */ 0)); + /* crypto= */ null)); return new MediaCodecAdapterWrapper(adapter); } catch (Exception e) { if (adapter != null) { @@ -190,15 +179,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; checkNotNull(format.sampleMimeType), format.sampleRate, format.channelCount); mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, format.bitrate); adapter = - new Factory(/* decoder= */ false) + new Factory() .createAdapter( - new MediaCodecAdapter.Configuration( - createPlaceholderMediaCodecInfo(), - mediaFormat, - format, - /* surface= */ null, - /* crypto= */ null, - /* flags= */ MediaCodec.CONFIGURE_FLAG_ENCODE)); + MediaCodecAdapter.Configuration.createForAudioEncoding( + createPlaceholderMediaCodecInfo(), mediaFormat, format)); return new MediaCodecAdapterWrapper(adapter); } catch (Exception e) { if (adapter != null) { @@ -232,16 +216,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 5_000_000); adapter = - new Factory(/* decoder= */ false) + new Factory() .createAdapter( - new MediaCodecAdapter.Configuration( - createPlaceholderMediaCodecInfo(), - mediaFormat, - format, - /* surface= */ null, - /* crypto= */ null, - MediaCodec.CONFIGURE_FLAG_ENCODE, - /* createInputSurface= */ true)); + MediaCodecAdapter.Configuration.createForVideoEncoding( + createPlaceholderMediaCodecInfo(), mediaFormat, format)); return new MediaCodecAdapterWrapper(adapter); } catch (Exception e) { if (adapter != null) {