diff --git a/demos/transformer/src/main/java/androidx/media3/demo/transformer/ConfigurationActivity.java b/demos/transformer/src/main/java/androidx/media3/demo/transformer/ConfigurationActivity.java index b6fd239d2c..3c9cdb1d08 100644 --- a/demos/transformer/src/main/java/androidx/media3/demo/transformer/ConfigurationActivity.java +++ b/demos/transformer/src/main/java/androidx/media3/demo/transformer/ConfigurationActivity.java @@ -96,7 +96,7 @@ public final class ConfigurationActivity extends AppCompatActivity { "H264 video and AAC audio (portrait, H < W, 90\u00B0)", "SEF slow motion with 240 fps", "480p DASH (non-square pixels)", - "HDR (HDR10) H265 video (encoding may fail)", + "HDR (HDR10) H265 limited range video (encoding may fail)", }; private static final String[] DEMO_EFFECTS = { "Dizzy crop", diff --git a/libraries/effect/src/main/assets/shaders/fragment_shader_copy_external_yuv_es3.glsl b/libraries/effect/src/main/assets/shaders/fragment_shader_copy_external_yuv_es3.glsl index 9460a4db17..88559ee80f 100644 --- a/libraries/effect/src/main/assets/shaders/fragment_shader_copy_external_yuv_es3.glsl +++ b/libraries/effect/src/main/assets/shaders/fragment_shader_copy_external_yuv_es3.glsl @@ -18,7 +18,7 @@ // the sampler uses the EXT_YUV_target extension specified at // https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_YUV_target.txt, // 2. Applies a YUV to RGB conversion using the specified color transform -// uColorTransform, yielding HLG BT.2020 RGB, +// uYuvToRgbColorTransform, yielding HLG BT.2020 RGB, // 3. If uApplyHlgOetf is 1, outputs HLG BT.2020 RGB. If 0, outputs // linear BT.2020 RGB for intermediate shaders by applying the HLG OETF. // 4. Copies this converted texture color to the current output. @@ -27,8 +27,7 @@ #extension GL_EXT_YUV_target : require precision mediump float; uniform __samplerExternal2DY2YEXT uTexSampler; -// YUV to RGB conversion matrix. -uniform mat3 uColorTransform; +uniform mat3 uYuvToRgbColorTransform; uniform float uApplyHlgOetf; in vec2 vTexSamplingCoord; out vec4 outColor; @@ -63,8 +62,9 @@ highp vec4 hlgOetf(highp vec4 hlgColor) { /** Convert YUV to RGBA. */ vec4 yuvToRgba(vec3 yuv) { - vec3 yuvOffset = vec3(yuv.x - 0.0625, yuv.y - 0.5, yuv.z - 0.5); - return vec4(uColorTransform * yuvOffset, 1.0); + const vec3 yuvOffset = vec3(0.0625, 0.5, 0.5); + vec3 rgb = uYuvToRgbColorTransform * (yuv - yuvOffset); + return vec4(rgb, 1.0); } void main() { diff --git a/libraries/effect/src/main/java/androidx/media3/effect/MatrixTransformationProcessor.java b/libraries/effect/src/main/java/androidx/media3/effect/MatrixTransformationProcessor.java index e231a39fb1..40c98ee2dd 100644 --- a/libraries/effect/src/main/java/androidx/media3/effect/MatrixTransformationProcessor.java +++ b/libraries/effect/src/main/java/androidx/media3/effect/MatrixTransformationProcessor.java @@ -21,6 +21,7 @@ import android.content.Context; import android.opengl.GLES20; import android.opengl.Matrix; import android.util.Pair; +import androidx.media3.common.C; import androidx.media3.common.ColorInfo; import androidx.media3.common.FrameProcessingException; import androidx.media3.common.util.GlProgram; @@ -64,12 +65,19 @@ import java.util.Arrays; new float[] {-1, 1, 0, 1}, new float[] {1, 1, 0, 1}, new float[] {1, -1, 0, 1}); - // Color transform coefficients from - // https://cs.android.com/android/platform/superproject/+/master:frameworks/av/media/libstagefright/colorconversion/ColorConverter.cpp;l=668-670;drc=487adf977a50cac3929eba15fad0d0f461c7ff0f. - private static final float[] MATRIX_YUV_TO_BT2020_COLOR_TRANSFORM = { - 1.168f, 1.168f, 1.168f, - 0.0f, -0.188f, 2.148f, - 1.683f, -0.652f, 0.0f, + + // YUV to RGB color transform coefficients can be calculated from the BT.2020 specification, by + // inverting the RGB to YUV equations, and scaling for limited range. + // https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.2020-2-201510-I!!PDF-E.pdf + private static final float[] BT2020_FULL_RANGE_YUV_TO_RGB_COLOR_TRANSFORM_MATRIX = { + 1.0000f, 1.0000f, 1.0000f, + 0.0000f, -0.1646f, 1.8814f, + 1.4746f, -0.5714f, 0.0000f + }; + private static final float[] BT2020_LIMITED_RANGE_YUV_TO_RGB_COLOR_TRANSFORM_MATRIX = { + 1.1689f, 1.1689f, 1.1689f, + 0.0000f, -0.1881f, 2.1502f, + 1.6853f, -0.6530f, 0.0000f, }; /** The {@link MatrixTransformation MatrixTransformations} to apply. */ @@ -195,7 +203,12 @@ import java.util.Arrays; throw new FrameProcessingException( "The EXT_YUV_target extension is required for HDR editing input."); } - glProgram.setFloatsUniform("uColorTransform", MATRIX_YUV_TO_BT2020_COLOR_TRANSFORM); + glProgram.setFloatsUniform( + "uYuvToRgbColorTransform", + opticalColorInfo.colorRange == C.COLOR_RANGE_FULL + ? BT2020_FULL_RANGE_YUV_TO_RGB_COLOR_TRANSFORM_MATRIX + : BT2020_LIMITED_RANGE_YUV_TO_RGB_COLOR_TRANSFORM_MATRIX); + // TODO(b/227624622): Implement PQ and gamma TFs, and use an @IntDef to select between HLG, // PQ, and gamma, coming from opticalColorInfo.colorTransfer.