diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerUtil.java b/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerUtil.java index b9e0a4d9c9..7dea3d0660 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerUtil.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerUtil.java @@ -17,10 +17,15 @@ package androidx.media3.transformer; import static androidx.media3.common.ColorInfo.SDR_BT709_LIMITED; +import static androidx.media3.common.ColorInfo.isTransferHdr; import static androidx.media3.transformer.Composition.HDR_MODE_KEEP_HDR; +import static androidx.media3.transformer.Composition.HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL; +import static androidx.media3.transformer.EncoderUtil.getSupportedEncodersForHdrEditing; import static java.lang.Math.round; import android.media.MediaCodec; +import android.media.MediaCodecInfo; +import android.util.Pair; import androidx.annotation.Nullable; import androidx.media3.common.C; import androidx.media3.common.ColorInfo; @@ -31,6 +36,7 @@ import androidx.media3.common.MimeTypes; import androidx.media3.effect.GlEffect; import androidx.media3.effect.ScaleAndRotateTransformation; import androidx.media3.extractor.metadata.mp4.SlowMotionData; +import androidx.media3.transformer.Composition.HdrMode; import com.google.common.collect.ImmutableList; /** Utility methods for Transformer. */ @@ -233,4 +239,33 @@ import com.google.common.collect.ImmutableList; } return decoderInputColor; } + + /** + * Calculate what the MIME type and {@link HdrMode} to use, applying fallback measure if + * necessary. + * + * @param hdrMode The {@link HdrMode}. + * @param requestedOutputMimeType The desired output MIME type. + * @param colorInfo The {@link ColorInfo}. + * @return a {@link Pair} of the output MIME type and {@link HdrMode}. + */ + public static Pair getOutputMimeTypeAndHdrModeAfterFallback( + @HdrMode int hdrMode, String requestedOutputMimeType, @Nullable ColorInfo colorInfo) { + // HdrMode fallback is only supported from HDR_MODE_KEEP_HDR to + // HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL. + if (hdrMode == HDR_MODE_KEEP_HDR && isTransferHdr(colorInfo)) { + ImmutableList hdrEncoders = + getSupportedEncodersForHdrEditing(requestedOutputMimeType, colorInfo); + if (hdrEncoders.isEmpty()) { + // Fallback H.265/HEVC codecs for HDR content to avoid tonemapping. + hdrEncoders = getSupportedEncodersForHdrEditing(MimeTypes.VIDEO_H265, colorInfo); + if (!hdrEncoders.isEmpty()) { + requestedOutputMimeType = MimeTypes.VIDEO_H265; + } else { + hdrMode = HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL; + } + } + } + return Pair.create(requestedOutputMimeType, hdrMode); + } } diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoSampleExporter.java b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoSampleExporter.java index 02a557e627..42dcfff3e9 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoSampleExporter.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoSampleExporter.java @@ -26,11 +26,10 @@ import static androidx.media3.common.util.Assertions.checkArgument; import static androidx.media3.common.util.Assertions.checkNotNull; import static androidx.media3.transformer.Composition.HDR_MODE_KEEP_HDR; import static androidx.media3.transformer.Composition.HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL; -import static androidx.media3.transformer.EncoderUtil.getSupportedEncodersForHdrEditing; +import static androidx.media3.transformer.TransformerUtil.getOutputMimeTypeAndHdrModeAfterFallback; import android.content.Context; import android.media.MediaCodec; -import android.media.MediaCodecInfo; import android.util.Pair; import android.view.Surface; import androidx.annotation.IntRange; @@ -51,7 +50,6 @@ import androidx.media3.common.util.Util; import androidx.media3.decoder.DecoderInputBuffer; import androidx.media3.effect.DebugTraceUtil; import androidx.media3.effect.VideoCompositorSettings; -import com.google.common.collect.ImmutableList; import com.google.common.util.concurrent.MoreExecutors; import java.nio.ByteBuffer; import java.util.List; @@ -268,25 +266,8 @@ import org.checkerframework.dataflow.qual.Pure; requestedOutputMimeType = inputSampleMimeType; } - // HdrMode fallback is only supported from HDR_MODE_KEEP_HDR to - // HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL. - @Composition.HdrMode int hdrMode = transformationRequest.hdrMode; - if (hdrMode == HDR_MODE_KEEP_HDR && isTransferHdr(inputFormat.colorInfo)) { - ImmutableList hdrEncoders = - getSupportedEncodersForHdrEditing(requestedOutputMimeType, inputFormat.colorInfo); - if (hdrEncoders.isEmpty()) { - // Fallback H.265/HEVC codecs for HDR content to avoid tonemapping. - hdrEncoders = - getSupportedEncodersForHdrEditing(MimeTypes.VIDEO_H265, inputFormat.colorInfo); - } - if (hdrEncoders.isEmpty()) { - hdrMode = HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL; - } else { - requestedOutputMimeType = MimeTypes.VIDEO_H265; - } - } - - return Pair.create(requestedOutputMimeType, hdrMode); + return getOutputMimeTypeAndHdrModeAfterFallback( + transformationRequest.hdrMode, requestedOutputMimeType, inputFormat.colorInfo); } public @Composition.HdrMode int getHdrModeAfterFallback() {