diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/AndroidTestUtil.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/AndroidTestUtil.java index f16fdde6bd..06b62dc3c8 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/AndroidTestUtil.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/AndroidTestUtil.java @@ -35,10 +35,8 @@ import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.media.Image; import android.media.MediaCodecInfo; -import android.media.MediaFormat; import android.opengl.EGLContext; import android.opengl.EGLDisplay; -import android.util.Pair; import androidx.annotation.Nullable; import androidx.media3.common.C; import androidx.media3.common.ColorInfo; @@ -49,7 +47,6 @@ import androidx.media3.common.MimeTypes; import androidx.media3.common.util.GlRect; import androidx.media3.common.util.GlUtil; import androidx.media3.common.util.Log; -import androidx.media3.common.util.MediaFormatUtil; import androidx.media3.common.util.Size; import androidx.media3.common.util.Util; import androidx.media3.effect.ByteBufferGlEffect; @@ -58,6 +55,7 @@ import androidx.media3.effect.GlEffect; import androidx.media3.effect.GlShaderProgram; import androidx.media3.effect.PassthroughShaderProgram; import androidx.media3.effect.ScaleAndRotateTransformation; +import androidx.media3.exoplayer.mediacodec.MediaCodecSelector; import androidx.media3.exoplayer.mediacodec.MediaCodecUtil; import androidx.media3.muxer.Muxer; import androidx.media3.test.utils.BitmapPixelTestUtil; @@ -69,6 +67,7 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; import java.io.File; import java.io.FileWriter; import java.io.IOException; +import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.atomic.AtomicInteger; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @@ -1302,7 +1301,6 @@ public final class AndroidTestUtil { @Nullable Format outputFormat, boolean isPortraitEncodingEnabled) throws IOException, JSONException, MediaCodecUtil.DecoderQueryException { - // TODO(b/278657595): Make this capability check match the default codec factory selection code. boolean canDecode = inputFormat == null || canDecode(inputFormat); boolean canEncode = outputFormat == null || canEncode(outputFormat, isPortraitEncodingEnabled); @@ -1390,21 +1388,39 @@ public final class AndroidTestUtil { return SDK_INT > 24 ? new DefaultMuxer.Factory() : new InAppMuxer.Factory.Builder().build(); } - private static boolean canDecode(Format format) { + private static boolean canDecode(Format format) throws MediaCodecUtil.DecoderQueryException { if (MimeTypes.isImage(format.sampleMimeType)) { return Util.isBitmapFactorySupportedMimeType(format.sampleMimeType); } // Check decoding capability in the same way as the default decoder factory. - MediaFormat mediaFormat = MediaFormatUtil.createMediaFormatFromFormat(format); - @Nullable - Pair codecProfileAndLevel = MediaCodecUtil.getCodecProfileAndLevel(format); - if (codecProfileAndLevel != null) { - MediaFormatUtil.maybeSetInteger( - mediaFormat, MediaFormat.KEY_PROFILE, codecProfileAndLevel.first); + return findDecoderForFormat(format) != null && !deviceNeedsDisable8kWorkaround(format); + } + + @Nullable + private static String findDecoderForFormat(Format format) + throws MediaCodecUtil.DecoderQueryException { + List decoderInfoList = + MediaCodecUtil.getDecoderInfosSortedByFormatSupport( + MediaCodecUtil.getDecoderInfosSoftMatch( + MediaCodecSelector.DEFAULT, + format, + /* requiresSecureDecoder= */ false, + /* requiresTunnelingDecoder= */ false), + format); + + for (int i = 0; i < decoderInfoList.size(); i++) { + androidx.media3.exoplayer.mediacodec.MediaCodecInfo decoderInfo = decoderInfoList.get(i); + // On some devices this method can return false even when the format can be decoded. For + // example, Pixel 6a can decode an 8K video but this method returns false. The + // DefaultDecoderFactory does not rely on this method rather it directly initialize the + // decoder. See b/222095724#comment9. + if (decoderInfo.isFormatSupported(format)) { + return decoderInfo.name; + } } - return EncoderUtil.findCodecForFormat(mediaFormat, /* isDecoder= */ true) != null - && !deviceNeedsDisable8kWorkaround(format); + + return null; } private static boolean deviceNeedsDisable8kWorkaround(Format format) { diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/EncoderUtil.java b/libraries/transformer/src/main/java/androidx/media3/transformer/EncoderUtil.java index e54a9770b3..289d0d5949 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/EncoderUtil.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/EncoderUtil.java @@ -24,7 +24,6 @@ import android.media.CamcorderProfile; import android.media.MediaCodec; import android.media.MediaCodecInfo; import android.media.MediaCodecList; -import android.media.MediaFormat; import android.util.Pair; import android.util.Range; import android.util.Size; @@ -37,7 +36,6 @@ import androidx.media3.common.C.ColorTransfer; import androidx.media3.common.ColorInfo; import androidx.media3.common.Format; import androidx.media3.common.MimeTypes; -import androidx.media3.common.util.MediaFormatUtil; import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.Util; import com.google.common.base.Ascii; @@ -327,37 +325,6 @@ public final class EncoderUtil { return maxSupportedLevel; } - /** - * Finds a {@link MediaCodec} that supports the {@link MediaFormat}, or {@code null} if none is - * found. - */ - @Nullable - public static String findCodecForFormat(MediaFormat format, boolean isDecoder) { - MediaCodecList mediaCodecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS); - // Format must not include KEY_FRAME_RATE on API21. - // https://developer.android.com/reference/android/media/MediaCodecList#findDecoderForFormat(android.media.MediaFormat) - float frameRate = Format.NO_VALUE; - if (Util.SDK_INT == 21 && format.containsKey(MediaFormat.KEY_FRAME_RATE)) { - try { - frameRate = format.getFloat(MediaFormat.KEY_FRAME_RATE); - } catch (ClassCastException e) { - frameRate = format.getInteger(MediaFormat.KEY_FRAME_RATE); - } - // Clears the frame rate field. - format.setString(MediaFormat.KEY_FRAME_RATE, null); - } - - String mediaCodecName = - isDecoder - ? mediaCodecList.findDecoderForFormat(format) - : mediaCodecList.findEncoderForFormat(format); - - if (Util.SDK_INT == 21) { - MediaFormatUtil.maybeSetInteger(format, MediaFormat.KEY_FRAME_RATE, round(frameRate)); - } - return mediaCodecName; - } - /** Returns the range of supported bitrates for the given {@linkplain MimeTypes MIME type}. */ public static Range getSupportedBitrateRange( MediaCodecInfo encoderInfo, String mimeType) {