Skip to content

Commit

Permalink
Select codecs without util methods
Browse files Browse the repository at this point in the history
`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
  • Loading branch information
andrewlewis authored and rohitjoins committed Apr 18, 2023
1 parent e4c8f7f commit 6f2051b
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,7 @@ public static void writeTestSummaryToFile(Context context, String testId, JSONOb
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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,21 @@
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;
Expand All @@ -55,12 +60,14 @@ public Codec createForAudioDecoding(Format format) throws ExportException {
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,
Expand Down Expand Up @@ -89,7 +96,6 @@ public Codec createForVideoDecoding(
}

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.
Expand All @@ -100,6 +106,14 @@ public Codec createForVideoDecoding(
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) {
Expand All @@ -109,12 +123,6 @@ public Codec createForVideoDecoding(
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);
}
Expand All @@ -134,4 +142,17 @@ private static ExportException createExportException(Format format, String reaso
/* 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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -173,18 +173,17 @@ public DefaultEncoderFactory(
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);
}
Expand Down

0 comments on commit 6f2051b

Please sign in to comment.