From 7684949fa40d39e780f5f25dcd7d5c77d17d400c Mon Sep 17 00:00:00 2001 From: huangdarwin Date: Fri, 3 Feb 2023 18:30:49 +0000 Subject: [PATCH] HDR: Move codec errors from VideoSamplePipeline It doesn't actually make sense for them to be placed in the Transformer, because the error's root causes are actually only in codecs. Also, a few codec errors were repeated, so deduplicate these instances PiperOrigin-RevId: 506937695 --- .../transformer/mh/HdrEditingTest.java | 16 ++++----- .../ToneMapHdrToSdrUsingMediaCodecTest.java | 16 +++------ .../transformer/DefaultDecoderFactory.java | 34 +++++++++++++++++-- .../transformer/VideoSamplePipeline.java | 25 -------------- 4 files changed, 43 insertions(+), 48 deletions(-) diff --git a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/HdrEditingTest.java b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/HdrEditingTest.java index d9c164d912..aa18398897 100644 --- a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/HdrEditingTest.java +++ b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/HdrEditingTest.java @@ -87,7 +87,9 @@ public class HdrEditingTest { Log.i(TAG, checkNotNull(exception.getCause()).toString()); assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class); assertThat(exception.errorCode) - .isEqualTo(TransformationException.ERROR_CODE_HDR_ENCODING_UNSUPPORTED); + .isAnyOf( + TransformationException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED, + TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED); } } @@ -110,7 +112,9 @@ public class HdrEditingTest { Log.i(TAG, checkNotNull(exception.getCause()).toString()); assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class); assertThat(exception.errorCode) - .isEqualTo(TransformationException.ERROR_CODE_HDR_ENCODING_UNSUPPORTED); + .isAnyOf( + TransformationException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED, + TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED); } } @@ -213,9 +217,7 @@ public class HdrEditingTest { Log.i(TAG, checkNotNull(exception.getCause()).toString()); assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class); assertThat(exception.errorCode) - .isAnyOf( - TransformationException.ERROR_CODE_HDR_ENCODING_UNSUPPORTED, - TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED); + .isEqualTo(TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED); assertThat(isFallbackListenerInvoked.get()).isFalse(); } } @@ -269,9 +271,7 @@ public class HdrEditingTest { Log.i(TAG, checkNotNull(exception.getCause()).toString()); assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class); assertThat(exception.errorCode) - .isAnyOf( - TransformationException.ERROR_CODE_HDR_ENCODING_UNSUPPORTED, - TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED); + .isEqualTo(TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED); assertThat(isFallbackListenerInvoked.get()).isFalse(); } } diff --git a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/ToneMapHdrToSdrUsingMediaCodecTest.java b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/ToneMapHdrToSdrUsingMediaCodecTest.java index 24207e13c6..3981e2ca95 100644 --- a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/ToneMapHdrToSdrUsingMediaCodecTest.java +++ b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/ToneMapHdrToSdrUsingMediaCodecTest.java @@ -88,9 +88,7 @@ public class ToneMapHdrToSdrUsingMediaCodecTest { Log.i(TAG, checkNotNull(exception.getCause()).toString()); assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class); assertThat(exception.errorCode) - .isAnyOf( - TransformationException.ERROR_CODE_HDR_ENCODING_UNSUPPORTED, - TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED); + .isEqualTo(TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED); } } @@ -132,9 +130,7 @@ public class ToneMapHdrToSdrUsingMediaCodecTest { Log.i(TAG, checkNotNull(exception.getCause()).toString()); assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class); assertThat(exception.errorCode) - .isAnyOf( - TransformationException.ERROR_CODE_HDR_ENCODING_UNSUPPORTED, - TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED); + .isEqualTo(TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED); } } @@ -181,9 +177,7 @@ public class ToneMapHdrToSdrUsingMediaCodecTest { Log.i(TAG, checkNotNull(exception.getCause()).toString()); assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class); assertThat(exception.errorCode) - .isAnyOf( - TransformationException.ERROR_CODE_HDR_ENCODING_UNSUPPORTED, - TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED); + .isEqualTo(TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED); } } @@ -230,9 +224,7 @@ public class ToneMapHdrToSdrUsingMediaCodecTest { Log.i(TAG, checkNotNull(exception.getCause()).toString()); assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class); assertThat(exception.errorCode) - .isAnyOf( - TransformationException.ERROR_CODE_HDR_ENCODING_UNSUPPORTED, - TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED); + .isEqualTo(TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED); } } } diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultDecoderFactory.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultDecoderFactory.java index 44679dfa5d..5fc3732aa4 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultDecoderFactory.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultDecoderFactory.java @@ -22,6 +22,7 @@ import static com.google.android.exoplayer2.util.Util.SDK_INT; import android.annotation.SuppressLint; import android.content.Context; import android.media.MediaFormat; +import android.os.Build; import android.util.Pair; import android.view.Surface; import androidx.annotation.Nullable; @@ -29,6 +30,8 @@ import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.mediacodec.MediaCodecUtil; 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 org.checkerframework.checker.nullness.qual.RequiresNonNull; /** A default implementation of {@link Codec.DecoderFactory}. */ @@ -74,9 +77,20 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; public Codec createForVideoDecoding( Format format, Surface outputSurface, boolean requestSdrToneMapping) throws TransformationException { + checkNotNull(format.sampleMimeType); + if (ColorInfo.isTransferHdr(format.colorInfo)) { + if (requestSdrToneMapping && (SDK_INT < 31 || deviceNeedsNoToneMappingWorkaround())) { + throw createTransformationException( + format, /* reason= */ "Tone-mapping HDR is not supported."); + } + if (SDK_INT < 29) { + // TODO(b/266837571, b/267171669): Remove API version restriction after fixing linked bugs. + throw createTransformationException(format, /* reason= */ "Decoding HDR is not supported."); + } + } + MediaFormat mediaFormat = - MediaFormat.createVideoFormat( - checkNotNull(format.sampleMimeType), format.width, format.height); + MediaFormat.createVideoFormat(format.sampleMimeType, format.width, format.height); MediaFormatUtil.maybeSetInteger(mediaFormat, MediaFormat.KEY_ROTATION, format.rotationDegrees); MediaFormatUtil.maybeSetInteger( mediaFormat, MediaFormat.KEY_MAX_INPUT_SIZE, format.maxInputSize); @@ -108,10 +122,24 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; context, format, mediaFormat, mediaCodecName, /* isDecoder= */ true, outputSurface); } + private static boolean deviceNeedsNoToneMappingWorkaround() { + // Pixel build ID prefix does not support tone mapping. See http://b/249297370#comment8. + return Util.MANUFACTURER.equals("Google") + && ( + /* Pixel 6 */ Build.ID.startsWith("TP1A") + || Build.ID.startsWith(/* Pixel Watch */ "rwd9.220429.053")); + } + @RequiresNonNull("#1.sampleMimeType") private static TransformationException createTransformationException(Format format) { + return createTransformationException(format, "The requested decoding format is not supported."); + } + + @RequiresNonNull("#1.sampleMimeType") + private static TransformationException createTransformationException( + Format format, String reason) { return TransformationException.createForCodec( - new IllegalArgumentException("The requested decoding format is not supported."), + new IllegalArgumentException(reason), TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED, MimeTypes.isVideo(format.sampleMimeType), /* isDecoder= */ true, diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoSamplePipeline.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoSamplePipeline.java index e5736fd9c7..c5dfa62233 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoSamplePipeline.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoSamplePipeline.java @@ -26,7 +26,6 @@ import static com.google.android.exoplayer2.util.Util.SDK_INT; import android.content.Context; import android.media.MediaCodec; -import android.os.Build; import android.view.Surface; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; @@ -97,23 +96,7 @@ import org.checkerframework.dataflow.qual.Pure; firstInputFormat = firstInputFormat.buildUpon().setColorInfo(ColorInfo.SDR_BT709_LIMITED).build(); } else if (transformationRequest.hdrMode == HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL) { - if (SDK_INT < 29) { - throw TransformationException.createForCodec( - new IllegalArgumentException( - "OpenGL-based HDR to SDR tone mapping is not supported."), - TransformationException.ERROR_CODE_HDR_DECODING_UNSUPPORTED, - /* isVideo= */ true, - /* isDecoder= */ true, - firstInputFormat); - } isGlToneMapping = true; - } else if (SDK_INT < 31 || deviceNeedsNoToneMappingWorkaround()) { - throw TransformationException.createForCodec( - new IllegalArgumentException("HDR editing and tone mapping is not supported."), - TransformationException.ERROR_CODE_HDR_ENCODING_UNSUPPORTED, - /* isVideo= */ true, - /* isDecoder= */ false, - firstInputFormat); } } @@ -332,14 +315,6 @@ import org.checkerframework.dataflow.qual.Pure; return supportedRequestBuilder.build(); } - private static boolean deviceNeedsNoToneMappingWorkaround() { - // Pixel build ID prefix does not support tone mapping. See http://b/249297370#comment8. - return Util.MANUFACTURER.equals("Google") - && ( - /* Pixel 6 */ Build.ID.startsWith("TP1A") - || Build.ID.startsWith(/* Pixel Watch */ "rwd9.220429.053")); - } - /** * Wraps an {@linkplain Codec encoder} and provides its input {@link Surface}. *