PiperOrigin-RevId: 711804077
This commit is contained in:
sheenachhabra 2025-01-03 11:15:21 -08:00 committed by Copybara-Service
parent 7ecaebe3d6
commit 750baf2c05
2 changed files with 47 additions and 19 deletions

View file

@ -35,8 +35,10 @@ import android.graphics.Bitmap;
import android.graphics.Bitmap.Config; import android.graphics.Bitmap.Config;
import android.media.Image; import android.media.Image;
import android.media.MediaCodecInfo; import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.opengl.EGLContext; import android.opengl.EGLContext;
import android.opengl.EGLDisplay; import android.opengl.EGLDisplay;
import android.util.Pair;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.media3.common.C; import androidx.media3.common.C;
import androidx.media3.common.ColorInfo; import androidx.media3.common.ColorInfo;
@ -47,6 +49,7 @@ import androidx.media3.common.MimeTypes;
import androidx.media3.common.util.GlRect; import androidx.media3.common.util.GlRect;
import androidx.media3.common.util.GlUtil; import androidx.media3.common.util.GlUtil;
import androidx.media3.common.util.Log; import androidx.media3.common.util.Log;
import androidx.media3.common.util.MediaFormatUtil;
import androidx.media3.common.util.Size; import androidx.media3.common.util.Size;
import androidx.media3.common.util.Util; import androidx.media3.common.util.Util;
import androidx.media3.effect.ByteBufferGlEffect; import androidx.media3.effect.ByteBufferGlEffect;
@ -55,7 +58,6 @@ import androidx.media3.effect.GlEffect;
import androidx.media3.effect.GlShaderProgram; import androidx.media3.effect.GlShaderProgram;
import androidx.media3.effect.PassthroughShaderProgram; import androidx.media3.effect.PassthroughShaderProgram;
import androidx.media3.effect.ScaleAndRotateTransformation; import androidx.media3.effect.ScaleAndRotateTransformation;
import androidx.media3.exoplayer.mediacodec.MediaCodecSelector;
import androidx.media3.exoplayer.mediacodec.MediaCodecUtil; import androidx.media3.exoplayer.mediacodec.MediaCodecUtil;
import androidx.media3.muxer.Muxer; import androidx.media3.muxer.Muxer;
import androidx.media3.test.utils.BitmapPixelTestUtil; import androidx.media3.test.utils.BitmapPixelTestUtil;
@ -67,7 +69,6 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.io.File; import java.io.File;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.util.List;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
@ -1294,6 +1295,7 @@ public final class AndroidTestUtil {
@Nullable Format outputFormat, @Nullable Format outputFormat,
boolean isPortraitEncodingEnabled) boolean isPortraitEncodingEnabled)
throws IOException, JSONException, MediaCodecUtil.DecoderQueryException { 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 canDecode = inputFormat == null || canDecode(inputFormat);
boolean canEncode = outputFormat == null || canEncode(outputFormat, isPortraitEncodingEnabled); boolean canEncode = outputFormat == null || canEncode(outputFormat, isPortraitEncodingEnabled);
@ -1345,28 +1347,21 @@ public final class AndroidTestUtil {
return SDK_INT > 24 ? new DefaultMuxer.Factory() : new InAppMuxer.Factory.Builder().build(); return SDK_INT > 24 ? new DefaultMuxer.Factory() : new InAppMuxer.Factory.Builder().build();
} }
private static boolean canDecode(Format format) throws MediaCodecUtil.DecoderQueryException { private static boolean canDecode(Format format) {
if (MimeTypes.isImage(format.sampleMimeType)) { if (MimeTypes.isImage(format.sampleMimeType)) {
return Util.isBitmapFactorySupportedMimeType(format.sampleMimeType); return Util.isBitmapFactorySupportedMimeType(format.sampleMimeType);
} }
// Check decoding capability in the same way as the default decoder factory. // Check decoding capability in the same way as the default decoder factory.
return findDecoderForFormat(format) != null && !deviceNeedsDisable8kWorkaround(format); MediaFormat mediaFormat = MediaFormatUtil.createMediaFormatFromFormat(format);
} @Nullable
Pair<Integer, Integer> codecProfileAndLevel = MediaCodecUtil.getCodecProfileAndLevel(format);
@Nullable if (codecProfileAndLevel != null) {
private static String findDecoderForFormat(Format format) MediaFormatUtil.maybeSetInteger(
throws MediaCodecUtil.DecoderQueryException { mediaFormat, MediaFormat.KEY_PROFILE, codecProfileAndLevel.first);
List<androidx.media3.exoplayer.mediacodec.MediaCodecInfo> mediaCodecInfoList = }
MediaCodecUtil.getDecoderInfosSortedByFormatSupport( return EncoderUtil.findCodecForFormat(mediaFormat, /* isDecoder= */ true) != null
MediaCodecUtil.getDecoderInfosSoftMatch( && !deviceNeedsDisable8kWorkaround(format);
MediaCodecSelector.DEFAULT,
format,
/* requiresSecureDecoder= */ false,
/* requiresTunnelingDecoder= */ false),
format);
return mediaCodecInfoList.isEmpty() ? null : mediaCodecInfoList.get(0).name;
} }
private static boolean deviceNeedsDisable8kWorkaround(Format format) { private static boolean deviceNeedsDisable8kWorkaround(Format format) {

View file

@ -24,6 +24,7 @@ import android.media.CamcorderProfile;
import android.media.MediaCodec; import android.media.MediaCodec;
import android.media.MediaCodecInfo; import android.media.MediaCodecInfo;
import android.media.MediaCodecList; import android.media.MediaCodecList;
import android.media.MediaFormat;
import android.util.Pair; import android.util.Pair;
import android.util.Range; import android.util.Range;
import android.util.Size; import android.util.Size;
@ -36,6 +37,7 @@ import androidx.media3.common.C.ColorTransfer;
import androidx.media3.common.ColorInfo; import androidx.media3.common.ColorInfo;
import androidx.media3.common.Format; import androidx.media3.common.Format;
import androidx.media3.common.MimeTypes; import androidx.media3.common.MimeTypes;
import androidx.media3.common.util.MediaFormatUtil;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util; import androidx.media3.common.util.Util;
import com.google.common.base.Ascii; import com.google.common.base.Ascii;
@ -325,6 +327,37 @@ public final class EncoderUtil {
return maxSupportedLevel; 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}. */ /** Returns the range of supported bitrates for the given {@linkplain MimeTypes MIME type}. */
public static Range<Integer> getSupportedBitrateRange( public static Range<Integer> getSupportedBitrateRange(
MediaCodecInfo encoderInfo, String mimeType) { MediaCodecInfo encoderInfo, String mimeType) {