Commit 6f2051b3 by andrewlewis Committed by Rohit Singh

Select codecs without util methods

`findDecoder/EncoderForFormat` seem to be more restrictive than querying
`MediaCodecList` as done for playback, and it's not clear that the cases where
no codec is found correspond to actual cases that would fail given that it
seems this returns an empty string for many cases in production.

Switch to using `MediaCodecUtil` and `EncoderUtil` for querying codecs instead.

PiperOrigin-RevId: 525078321
parent e4c8f7fc
...@@ -642,6 +642,7 @@ public final class AndroidTestUtil { ...@@ -642,6 +642,7 @@ public final class AndroidTestUtil {
public static boolean skipAndLogIfFormatsUnsupported( public static boolean skipAndLogIfFormatsUnsupported(
Context context, String testId, Format inputFormat, @Nullable Format outputFormat) Context context, String testId, Format inputFormat, @Nullable Format outputFormat)
throws IOException, JSONException { throws IOException, JSONException {
// TODO(b/278657595): Make this capability check match the default codec factory selection code.
boolean canDecode = canDecode(inputFormat); boolean canDecode = canDecode(inputFormat);
boolean canEncode = outputFormat == null || canEncode(outputFormat); boolean canEncode = outputFormat == null || canEncode(outputFormat);
......
...@@ -28,16 +28,21 @@ import android.util.Pair; ...@@ -28,16 +28,21 @@ import android.util.Pair;
import android.view.Surface; import android.view.Surface;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.mediacodec.MediaCodecInfo;
import com.google.android.exoplayer2.mediacodec.MediaCodecUtil; import com.google.android.exoplayer2.mediacodec.MediaCodecUtil;
import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.MediaFormatUtil; import com.google.android.exoplayer2.util.MediaFormatUtil;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.ColorInfo; import com.google.android.exoplayer2.video.ColorInfo;
import java.util.List;
import org.checkerframework.checker.nullness.qual.RequiresNonNull; import org.checkerframework.checker.nullness.qual.RequiresNonNull;
/** A default implementation of {@link Codec.DecoderFactory}. */ /** A default implementation of {@link Codec.DecoderFactory}. */
/* package */ final class DefaultDecoderFactory implements Codec.DecoderFactory { /* package */ final class DefaultDecoderFactory implements Codec.DecoderFactory {
private static final String TAG = "DefaultDecoderFactory";
private final Context context; private final Context context;
private final boolean decoderSupportsKeyAllowFrameDrop; private final boolean decoderSupportsKeyAllowFrameDrop;
...@@ -55,12 +60,14 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -55,12 +60,14 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
checkNotNull(format.sampleMimeType); checkNotNull(format.sampleMimeType);
MediaFormat mediaFormat = createMediaFormatFromFormat(format); MediaFormat mediaFormat = createMediaFormatFromFormat(format);
@Nullable String mediaCodecName;
String mediaCodecName = EncoderUtil.findCodecForFormat(mediaFormat, /* isDecoder= */ true); try {
if (mediaCodecName == null) { mediaCodecName = getMediaCodecNameForDecoding(format);
throw createExportException( } catch (MediaCodecUtil.DecoderQueryException e) {
format, /* reason= */ "The requested decoding format is not supported."); Log.e(TAG, "Error querying decoders", e);
throw createExportException(format, /* reason= */ "Querying codecs failed.");
} }
return new DefaultCodec( return new DefaultCodec(
context, context,
format, format,
...@@ -89,7 +96,6 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -89,7 +96,6 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
} }
MediaFormat mediaFormat = createMediaFormatFromFormat(format); MediaFormat mediaFormat = createMediaFormatFromFormat(format);
if (decoderSupportsKeyAllowFrameDrop) { if (decoderSupportsKeyAllowFrameDrop) {
// This key ensures no frame dropping when the decoder's output surface is full. This allows // This key ensures no frame dropping when the decoder's output surface is full. This allows
// transformer to decode as many frames as possible in one render cycle. // transformer to decode as many frames as possible in one render cycle.
...@@ -100,6 +106,14 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -100,6 +106,14 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
MediaFormat.KEY_COLOR_TRANSFER_REQUEST, MediaFormat.COLOR_TRANSFER_SDR_VIDEO); MediaFormat.KEY_COLOR_TRANSFER_REQUEST, MediaFormat.COLOR_TRANSFER_SDR_VIDEO);
} }
String mediaCodecName;
try {
mediaCodecName = getMediaCodecNameForDecoding(format);
} catch (MediaCodecUtil.DecoderQueryException e) {
Log.e(TAG, "Error querying decoders", e);
throw createExportException(format, /* reason= */ "Querying codecs failed");
}
@Nullable @Nullable
Pair<Integer, Integer> codecProfileAndLevel = MediaCodecUtil.getCodecProfileAndLevel(format); Pair<Integer, Integer> codecProfileAndLevel = MediaCodecUtil.getCodecProfileAndLevel(format);
if (codecProfileAndLevel != null) { if (codecProfileAndLevel != null) {
...@@ -109,12 +123,6 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -109,12 +123,6 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
mediaFormat, MediaFormat.KEY_LEVEL, codecProfileAndLevel.second); mediaFormat, MediaFormat.KEY_LEVEL, codecProfileAndLevel.second);
} }
@Nullable
String mediaCodecName = EncoderUtil.findCodecForFormat(mediaFormat, /* isDecoder= */ true);
if (mediaCodecName == null) {
throw createExportException(
format, /* reason= */ "The requested video decoding format is not supported.");
}
return new DefaultCodec( return new DefaultCodec(
context, format, mediaFormat, mediaCodecName, /* isDecoder= */ true, outputSurface); context, format, mediaFormat, mediaCodecName, /* isDecoder= */ true, outputSurface);
} }
...@@ -134,4 +142,17 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -134,4 +142,17 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
/* isDecoder= */ true, /* isDecoder= */ true,
format); format);
} }
private static String getMediaCodecNameForDecoding(Format format)
throws MediaCodecUtil.DecoderQueryException, ExportException {
List<MediaCodecInfo> decoderInfos =
MediaCodecUtil.getDecoderInfosSortedByFormatSupport(
MediaCodecUtil.getDecoderInfos(
checkNotNull(format.sampleMimeType), /* secure= */ false, /* tunneling= */ false),
format);
if (decoderInfos.isEmpty()) {
throw createExportException(format, /* reason= */ "No decoders for format");
}
return decoderInfos.get(0).name;
}
} }
...@@ -173,18 +173,17 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory { ...@@ -173,18 +173,17 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
public DefaultCodec createForAudioEncoding(Format format) throws ExportException { public DefaultCodec createForAudioEncoding(Format format) throws ExportException {
checkNotNull(format.sampleMimeType); checkNotNull(format.sampleMimeType);
MediaFormat mediaFormat = createMediaFormatFromFormat(format); MediaFormat mediaFormat = createMediaFormatFromFormat(format);
@Nullable @Nullable
String mediaCodecName = EncoderUtil.findCodecForFormat(mediaFormat, /* isDecoder= */ false); ImmutableList<MediaCodecInfo> mediaCodecInfos =
if (mediaCodecName == null) { EncoderUtil.getSupportedEncoders(format.sampleMimeType);
throw createExportException( if (mediaCodecInfos.isEmpty()) {
format, /* errorString= */ "The requested audio encoding format is not supported."); throw createExportException(format, "No audio media codec found");
} }
return new DefaultCodec( return new DefaultCodec(
context, context,
format, format,
mediaFormat, mediaFormat,
mediaCodecName, mediaCodecInfos.get(0).getName(),
/* isDecoder= */ false, /* isDecoder= */ false,
/* outputSurface= */ null); /* outputSurface= */ null);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment