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 {
public static boolean skipAndLogIfFormatsUnsupported(
Context context, String testId, Format inputFormat, @Nullable Format outputFormat)
throws IOException, JSONException {
// TODO(b/278657595): Make this capability check match the default codec factory selection code.
boolean canDecode = canDecode(inputFormat);
boolean canEncode = outputFormat == null || canEncode(outputFormat);
......
......@@ -28,16 +28,21 @@ import android.util.Pair;
import android.view.Surface;
import androidx.annotation.Nullable;
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.util.Log;
import com.google.android.exoplayer2.util.MediaFormatUtil;
import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.ColorInfo;
import java.util.List;
import org.checkerframework.checker.nullness.qual.RequiresNonNull;
/** A default implementation of {@link Codec.DecoderFactory}. */
/* package */ final class DefaultDecoderFactory implements Codec.DecoderFactory {
private static final String TAG = "DefaultDecoderFactory";
private final Context context;
private final boolean decoderSupportsKeyAllowFrameDrop;
......@@ -55,12 +60,14 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
checkNotNull(format.sampleMimeType);
MediaFormat mediaFormat = createMediaFormatFromFormat(format);
@Nullable
String mediaCodecName = EncoderUtil.findCodecForFormat(mediaFormat, /* isDecoder= */ true);
if (mediaCodecName == null) {
throw createExportException(
format, /* reason= */ "The requested decoding format is not supported.");
String mediaCodecName;
try {
mediaCodecName = getMediaCodecNameForDecoding(format);
} catch (MediaCodecUtil.DecoderQueryException e) {
Log.e(TAG, "Error querying decoders", e);
throw createExportException(format, /* reason= */ "Querying codecs failed.");
}
return new DefaultCodec(
context,
format,
......@@ -89,7 +96,6 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
}
MediaFormat mediaFormat = createMediaFormatFromFormat(format);
if (decoderSupportsKeyAllowFrameDrop) {
// 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.
......@@ -100,6 +106,14 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
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
Pair<Integer, Integer> codecProfileAndLevel = MediaCodecUtil.getCodecProfileAndLevel(format);
if (codecProfileAndLevel != null) {
......@@ -109,12 +123,6 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
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(
context, format, mediaFormat, mediaCodecName, /* isDecoder= */ true, outputSurface);
}
......@@ -134,4 +142,17 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
/* isDecoder= */ true,
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 {
public DefaultCodec createForAudioEncoding(Format format) throws ExportException {
checkNotNull(format.sampleMimeType);
MediaFormat mediaFormat = createMediaFormatFromFormat(format);
@Nullable
String mediaCodecName = EncoderUtil.findCodecForFormat(mediaFormat, /* isDecoder= */ false);
if (mediaCodecName == null) {
throw createExportException(
format, /* errorString= */ "The requested audio encoding format is not supported.");
ImmutableList<MediaCodecInfo> mediaCodecInfos =
EncoderUtil.getSupportedEncoders(format.sampleMimeType);
if (mediaCodecInfos.isEmpty()) {
throw createExportException(format, "No audio media codec found");
}
return new DefaultCodec(
context,
format,
mediaFormat,
mediaCodecName,
mediaCodecInfos.get(0).getName(),
/* isDecoder= */ false,
/* 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