diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/mh/ForceInterpretHdrVideoAsSdrTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/mh/ForceInterpretHdrVideoAsSdrTest.java index c279bc16c6..d57ae6d621 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/mh/ForceInterpretHdrVideoAsSdrTest.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/mh/ForceInterpretHdrVideoAsSdrTest.java @@ -15,18 +15,22 @@ */ package androidx.media3.transformer.mh; +import static androidx.media3.common.util.Util.SDK_INT; import static androidx.media3.transformer.AndroidTestUtil.MP4_ASSET_1080P_4_SECOND_HDR10; import static androidx.media3.transformer.AndroidTestUtil.MP4_ASSET_1080P_4_SECOND_HDR10_FORMAT; import static androidx.media3.transformer.AndroidTestUtil.MP4_ASSET_1080P_5_SECOND_HLG10; import static androidx.media3.transformer.AndroidTestUtil.MP4_ASSET_1080P_5_SECOND_HLG10_FORMAT; +import static androidx.media3.transformer.AndroidTestUtil.recordTestSkipped; +import static androidx.media3.transformer.AndroidTestUtil.skipAndLogIfFormatsUnsupported; import static androidx.media3.transformer.mh.FileUtil.maybeAssertFileHasColorTransfer; import android.content.Context; import android.net.Uri; +import android.util.Log; import androidx.media3.common.C; +import androidx.media3.common.ColorInfo; +import androidx.media3.common.Format; import androidx.media3.common.MediaItem; -import androidx.media3.common.util.Log; -import androidx.media3.transformer.AndroidTestUtil; import androidx.media3.transformer.ExportException; import androidx.media3.transformer.ExportTestResult; import androidx.media3.transformer.TransformationRequest; @@ -51,11 +55,21 @@ public class ForceInterpretHdrVideoAsSdrTest { String testId = "forceInterpretHdrVideoAsSdrTest_hdr10File_transformsOrThrows"; Context context = ApplicationProvider.getApplicationContext(); - if (AndroidTestUtil.skipAndLogIfFormatsUnsupported( - context, - testId, - /* inputFormat= */ MP4_ASSET_1080P_4_SECOND_HDR10_FORMAT, - /* outputFormat= */ null)) { + if (SDK_INT < 29) { + // TODO(b/269759013): Fix failures under API 29 to expand confidence on all API versions. + recordTestSkipped( + context, testId, /* reason= */ "Under API 29, this API is considered best-effort."); + return; + } + + // Force interpret HDR as SDR signals SDR input to the decoder, even if the actual input is HDR. + Format decoderInputFormat = + MP4_ASSET_1080P_4_SECOND_HDR10_FORMAT + .buildUpon() + .setColorInfo(ColorInfo.SDR_BT709_LIMITED) + .build(); + if (skipAndLogIfFormatsUnsupported( + context, testId, decoderInputFormat, /* outputFormat= */ null)) { return; } @@ -76,7 +90,9 @@ public class ForceInterpretHdrVideoAsSdrTest { maybeAssertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR); Log.i(TAG, "Transformed."); } catch (ExportException exception) { - if (exception.errorCode != ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED) { + String message = getMessageOrEmptyString(exception); + Log.i(TAG, "Exception: " + message); + if (!message.equals("The requested video decoding format is not supported.")) { throw exception; } } @@ -87,11 +103,21 @@ public class ForceInterpretHdrVideoAsSdrTest { String testId = "forceInterpretHdrVideoAsSdrTest_hlg10File_transformsOrThrows"; Context context = ApplicationProvider.getApplicationContext(); - if (AndroidTestUtil.skipAndLogIfFormatsUnsupported( - context, - testId, - /* inputFormat= */ MP4_ASSET_1080P_5_SECOND_HLG10_FORMAT, - /* outputFormat= */ null)) { + if (SDK_INT < 29) { + // TODO(b/269759013): Fix failures under API 29 to expand confidence on all API versions. + recordTestSkipped( + context, testId, /* reason= */ "Under API 29, this API is considered best-effort."); + return; + } + + // Force interpret HDR as SDR signals SDR input to the decoder, even if the actual input is HDR. + Format decoderInputFormat = + MP4_ASSET_1080P_5_SECOND_HLG10_FORMAT + .buildUpon() + .setColorInfo(ColorInfo.SDR_BT709_LIMITED) + .build(); + if (skipAndLogIfFormatsUnsupported( + context, testId, decoderInputFormat, /* outputFormat= */ null)) { return; } @@ -112,9 +138,22 @@ public class ForceInterpretHdrVideoAsSdrTest { maybeAssertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR); Log.i(TAG, "Transformed."); } catch (ExportException exception) { - if (exception.errorCode != ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED) { + String message = getMessageOrEmptyString(exception); + Log.i(TAG, "Exception: " + message); + if (!message.equals("The requested video decoding format is not supported.")) { throw exception; } } } + + private String getMessageOrEmptyString(Exception exception) { + if (exception.getCause() == null) { + return ""; + } + String message = exception.getCause().getMessage(); + if (message == null) { + return ""; + } + return message; + } } diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/ExoAssetLoaderBaseRenderer.java b/libraries/transformer/src/main/java/androidx/media3/transformer/ExoAssetLoaderBaseRenderer.java index da00c98a12..a55fcef32b 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/ExoAssetLoaderBaseRenderer.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/ExoAssetLoaderBaseRenderer.java @@ -136,7 +136,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; } /** Overrides the {@code inputFormat}. */ - protected Format overrideFormat(Format inputFormat) throws ExportException { + protected Format overrideFormat(Format inputFormat) { return inputFormat; } diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/ExoAssetLoaderVideoRenderer.java b/libraries/transformer/src/main/java/androidx/media3/transformer/ExoAssetLoaderVideoRenderer.java index a9f7db53f6..45961e1239 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/ExoAssetLoaderVideoRenderer.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/ExoAssetLoaderVideoRenderer.java @@ -16,7 +16,6 @@ package androidx.media3.transformer; import static androidx.media3.common.util.Assertions.checkNotNull; -import static androidx.media3.common.util.Util.SDK_INT; import android.media.MediaCodec; import androidx.annotation.Nullable; @@ -61,17 +60,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; } @Override - protected Format overrideFormat(Format inputFormat) throws ExportException { + protected Format overrideFormat(Format inputFormat) { if (forceInterpretHdrAsSdr && ColorInfo.isTransferHdr(inputFormat.colorInfo)) { - if (SDK_INT < 29) { - throw ExportException.createForCodec( - new IllegalArgumentException( - "Interpreting HDR video as SDR is not supported on this device."), - ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED, - /* isVideo= */ true, - /* isDecoder= */ true, - inputFormat); - } return inputFormat.buildUpon().setColorInfo(ColorInfo.SDR_BT709_LIMITED).build(); } return inputFormat; diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/TransformationRequest.java b/libraries/transformer/src/main/java/androidx/media3/transformer/TransformationRequest.java index 53d763c53a..aa36d97d14 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/TransformationRequest.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/TransformationRequest.java @@ -90,13 +90,13 @@ public final class TransformationRequest { /** * Interpret HDR input as SDR, likely with a washed out look. * - *

Supported on API 29+. - * *

This is much more widely supported than {@link #HDR_MODE_KEEP_HDR} and {@link * #HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_MEDIACODEC}. However, as HDR transfer functions and * metadata will be ignored, contents will be displayed incorrectly, likely with a washed out * look. * + *

Using this API may lead to codec errors before API 29, per b/269759013. + * *

Use of this flag may result in {@code ERROR_CODE_DECODING_FORMAT_UNSUPPORTED}. * *

This field is experimental, and will be renamed or removed in a future release.