Add option to disable encoder fallback.

We use the top priority encoder (sorted by EncoderSelector) and the requested
output format for encoding.

PiperOrigin-RevId: 426191800
This commit is contained in:
claincly 2022-02-03 19:09:56 +00:00 committed by Ian Baker
parent 7507da51a0
commit e2d4bd15cd

View File

@ -18,7 +18,6 @@ package androidx.media3.transformer;
import static androidx.media3.common.util.Assertions.checkArgument;
import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.common.util.Assertions.checkState;
import static androidx.media3.common.util.Assertions.checkStateNotNull;
import static androidx.media3.common.util.Util.SDK_INT;
import static androidx.media3.transformer.CodecFactoryUtil.createCodec;
@ -41,22 +40,32 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
/** A default implementation of {@link Codec.EncoderFactory}. */
@UnstableApi
public final class DefaultEncoderFactory implements Codec.EncoderFactory {
// TODO(b/214973843): Add option to disable fallback.
private static final int DEFAULT_COLOR_FORMAT =
MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface;
private static final int DEFAULT_FRAME_RATE = 60;
private static final int DEFAULT_I_FRAME_INTERVAL_SECS = 1;
@Nullable private final EncoderSelector videoEncoderSelector;
private final boolean disableFallback;
/** Creates a new instance using the {@link EncoderSelector#DEFAULT default encoder selector}. */
/**
* Creates a new instance using the {@link EncoderSelector#DEFAULT default encoder selector}, and
* format fallback enabled.
*
* <p>With format fallback enabled, and when the requested {@link Format} is not supported, {@code
* DefaultEncoderFactory} finds a format that is supported by the device and configures the {@link
* Codec} with it. The fallback process may change the requested {@link Format#sampleMimeType MIME
* type}, resolution, {@link Format#bitrate bitrate}, {@link Format#codecs profile/level}, etc.
*/
public DefaultEncoderFactory() {
this(EncoderSelector.DEFAULT);
this(EncoderSelector.DEFAULT, /* disableFallback= */ false);
}
/** Creates a new instance. */
public DefaultEncoderFactory(EncoderSelector videoEncoderSelector) {
public DefaultEncoderFactory(
@Nullable EncoderSelector videoEncoderSelector, boolean disableFallback) {
this.videoEncoderSelector = videoEncoderSelector;
this.disableFallback = disableFallback;
}
@Override
@ -98,7 +107,8 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
@Nullable
Pair<MediaCodecInfo, Format> encoderAndClosestFormatSupport =
findEncoderWithClosestFormatSupport(format, videoEncoderSelector, allowedMimeTypes);
findEncoderWithClosestFormatSupport(
format, videoEncoderSelector, allowedMimeTypes, disableFallback);
if (encoderAndClosestFormatSupport == null) {
throw createTransformationException(
new IllegalArgumentException(
@ -145,16 +155,24 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
@RequiresNonNull("#1.sampleMimeType")
@Nullable
private static Pair<MediaCodecInfo, Format> findEncoderWithClosestFormatSupport(
Format requestedFormat, EncoderSelector encoderSelector, List<String> allowedMimeTypes) {
Format requestedFormat,
EncoderSelector encoderSelector,
List<String> allowedMimeTypes,
boolean disableFallback) {
String requestedMimeType = requestedFormat.sampleMimeType;
@Nullable
String mimeType =
findFallbackMimeType(encoderSelector, requestedFormat.sampleMimeType, allowedMimeTypes);
if (mimeType == null) {
String mimeType = findFallbackMimeType(encoderSelector, requestedMimeType, allowedMimeTypes);
if (mimeType == null || (disableFallback && !requestedMimeType.equals(mimeType))) {
return null;
}
List<MediaCodecInfo> encodersForMimeType = encoderSelector.selectEncoderInfos(mimeType);
checkState(!encodersForMimeType.isEmpty());
if (encodersForMimeType.isEmpty()) {
return null;
}
if (disableFallback) {
return Pair.create(encodersForMimeType.get(0), requestedFormat);
}
ImmutableList<MediaCodecInfo> filteredEncoders =
filterEncoders(
encodersForMimeType,