mirror of
https://github.com/samsonjs/media.git
synced 2026-04-16 13:05:46 +00:00
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
This commit is contained in:
parent
23b1cab56c
commit
990f7ef5b5
4 changed files with 41 additions and 18 deletions
|
|
@ -97,6 +97,8 @@
|
|||
* Fix a bug where transformation could get stuck (leading to muxer
|
||||
timeout) if the end of the video stream was signaled at the moment when
|
||||
an input frame was pending processing.
|
||||
* Query codecs via `MediaCodecList` instead of using
|
||||
`findDecoder/EncoderForFormat` utilities, to expand support.
|
||||
* DASH:
|
||||
* Fix handling of empty segment timelines
|
||||
([#11014](https://github.com/google/ExoPlayer/issues/11014)).
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -30,14 +30,19 @@ import androidx.annotation.Nullable;
|
|||
import androidx.media3.common.ColorInfo;
|
||||
import androidx.media3.common.Format;
|
||||
import androidx.media3.common.MimeTypes;
|
||||
import androidx.media3.common.util.Log;
|
||||
import androidx.media3.common.util.MediaFormatUtil;
|
||||
import androidx.media3.common.util.Util;
|
||||
import androidx.media3.exoplayer.mediacodec.MediaCodecInfo;
|
||||
import androidx.media3.exoplayer.mediacodec.MediaCodecUtil;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -175,18 +175,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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue