mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
HDR: Check whether EXT_YUV_target extension is supported.
This extension is needed for editing HDR input with OpenGL, as the ExternalTextureProcessor samples raw YUV values from the external texture for HDR and converts them to RGB itself rather than relying on the OpenGL driver to do this automatically as for SDR. PiperOrigin-RevId: 460424154
This commit is contained in:
parent
30fbc3a27d
commit
a5ff4ef17f
@ -63,6 +63,8 @@ public final class GlUtil {
|
|||||||
private static final String EXTENSION_PROTECTED_CONTENT = "EGL_EXT_protected_content";
|
private static final String EXTENSION_PROTECTED_CONTENT = "EGL_EXT_protected_content";
|
||||||
// https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_surfaceless_context.txt
|
// https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_surfaceless_context.txt
|
||||||
private static final String EXTENSION_SURFACELESS_CONTEXT = "EGL_KHR_surfaceless_context";
|
private static final String EXTENSION_SURFACELESS_CONTEXT = "EGL_KHR_surfaceless_context";
|
||||||
|
// https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_YUV_target.txt
|
||||||
|
private static final String EXTENSION_YUV_TARGET = "GL_EXT_YUV_target";
|
||||||
|
|
||||||
private static final int[] EGL_WINDOW_SURFACE_ATTRIBUTES_NONE = new int[] {EGL14.EGL_NONE};
|
private static final int[] EGL_WINDOW_SURFACE_ATTRIBUTES_NONE = new int[] {EGL14.EGL_NONE};
|
||||||
private static final int[] EGL_CONFIG_ATTRIBUTES_RGBA_8888 =
|
private static final int[] EGL_CONFIG_ATTRIBUTES_RGBA_8888 =
|
||||||
@ -170,6 +172,41 @@ public final class GlUtil {
|
|||||||
return eglExtensions != null && eglExtensions.contains(EXTENSION_SURFACELESS_CONTEXT);
|
return eglExtensions != null && eglExtensions.contains(EXTENSION_SURFACELESS_CONTEXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the {@value #EXTENSION_YUV_TARGET} extension is supported.
|
||||||
|
*
|
||||||
|
* <p>This extension allows sampling raw YUV values from an external texture, which is required
|
||||||
|
* for HDR.
|
||||||
|
*/
|
||||||
|
public static boolean isYuvTargetExtensionSupported() {
|
||||||
|
if (Util.SDK_INT < 17) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable String glExtensions;
|
||||||
|
if (Util.areEqual(EGL14.eglGetCurrentContext(), EGL14.EGL_NO_CONTEXT)) {
|
||||||
|
// Create a placeholder context and make it current to allow calling GLES20.glGetString().
|
||||||
|
try {
|
||||||
|
EGLDisplay eglDisplay = createEglDisplay();
|
||||||
|
EGLContext eglContext = createEglContext(eglDisplay);
|
||||||
|
if (GlUtil.isSurfacelessContextExtensionSupported()) {
|
||||||
|
focusEglSurface(
|
||||||
|
eglDisplay, eglContext, EGL14.EGL_NO_SURFACE, /* width= */ 1, /* height= */ 1);
|
||||||
|
} else {
|
||||||
|
focusPlaceholderEglSurface(eglContext, eglDisplay);
|
||||||
|
}
|
||||||
|
glExtensions = GLES20.glGetString(GLES20.GL_EXTENSIONS);
|
||||||
|
destroyEglContext(eglDisplay, eglContext);
|
||||||
|
} catch (GlException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
glExtensions = GLES20.glGetString(GLES20.GL_EXTENSIONS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return glExtensions != null && glExtensions.contains(EXTENSION_YUV_TARGET);
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns an initialized default {@link EGLDisplay}. */
|
/** Returns an initialized default {@link EGLDisplay}. */
|
||||||
@RequiresApi(17)
|
@RequiresApi(17)
|
||||||
public static EGLDisplay createEglDisplay() throws GlException {
|
public static EGLDisplay createEglDisplay() throws GlException {
|
||||||
|
@ -53,7 +53,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
* @param listener A {@link Listener}.
|
* @param listener A {@link Listener}.
|
||||||
* @param effects The {@link GlEffect GlEffects} to apply to each frame.
|
* @param effects The {@link GlEffect GlEffects} to apply to each frame.
|
||||||
* @param debugViewProvider A {@link DebugViewProvider}.
|
* @param debugViewProvider A {@link DebugViewProvider}.
|
||||||
* @param useHdr Whether to process the input as an HDR signal.
|
* @param useHdr Whether to process the input as an HDR signal. Using HDR requires the {@code
|
||||||
|
* EXT_YUV_target} OpenGL extension.
|
||||||
* @return A new instance.
|
* @return A new instance.
|
||||||
* @throws FrameProcessingException If reading shader files fails, or an OpenGL error occurs while
|
* @throws FrameProcessingException If reading shader files fails, or an OpenGL error occurs while
|
||||||
* creating and configuring the OpenGL components.
|
* creating and configuring the OpenGL components.
|
||||||
|
@ -109,7 +109,7 @@ import java.util.Arrays;
|
|||||||
context,
|
context,
|
||||||
ImmutableList.of(matrixTransformation),
|
ImmutableList.of(matrixTransformation),
|
||||||
/* sampleFromExternalTexture= */ false,
|
/* sampleFromExternalTexture= */ false,
|
||||||
/* enableExperimentalHdrEditing= */ false);
|
/* useHdr= */ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -126,7 +126,7 @@ import java.util.Arrays;
|
|||||||
context,
|
context,
|
||||||
ImmutableList.of(matrixTransformation),
|
ImmutableList.of(matrixTransformation),
|
||||||
/* sampleFromExternalTexture= */ false,
|
/* sampleFromExternalTexture= */ false,
|
||||||
/* enableExperimentalHdrEditing= */ false);
|
/* useHdr= */ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -138,15 +138,22 @@ import java.util.Arrays;
|
|||||||
* @param sampleFromExternalTexture Whether the input will be provided using an external texture.
|
* @param sampleFromExternalTexture Whether the input will be provided using an external texture.
|
||||||
* If {@code true}, the caller should use {@link #setTextureTransformMatrix(float[])} to
|
* If {@code true}, the caller should use {@link #setTextureTransformMatrix(float[])} to
|
||||||
* provide the transformation matrix associated with the external texture.
|
* provide the transformation matrix associated with the external texture.
|
||||||
* @param enableExperimentalHdrEditing Whether to attempt to process the input as an HDR signal.
|
* @param useHdr Whether to process the input as an HDR signal. Using HDR requires the {@code
|
||||||
* @throws FrameProcessingException If a problem occurs while reading shader files.
|
* EXT_YUV_target} OpenGL extension.
|
||||||
|
* @throws FrameProcessingException If a problem occurs while reading shader files or an OpenGL
|
||||||
|
* operation fails or is unsupported.
|
||||||
*/
|
*/
|
||||||
public MatrixTransformationProcessor(
|
public MatrixTransformationProcessor(
|
||||||
Context context,
|
Context context,
|
||||||
ImmutableList<GlMatrixTransformation> matrixTransformations,
|
ImmutableList<GlMatrixTransformation> matrixTransformations,
|
||||||
boolean sampleFromExternalTexture,
|
boolean sampleFromExternalTexture,
|
||||||
boolean enableExperimentalHdrEditing)
|
boolean useHdr)
|
||||||
throws FrameProcessingException {
|
throws FrameProcessingException {
|
||||||
|
if (sampleFromExternalTexture && useHdr && !GlUtil.isYuvTargetExtensionSupported()) {
|
||||||
|
throw new FrameProcessingException(
|
||||||
|
"The EXT_YUV_target extension is required for HDR editing.");
|
||||||
|
}
|
||||||
|
|
||||||
this.matrixTransformations = matrixTransformations;
|
this.matrixTransformations = matrixTransformations;
|
||||||
|
|
||||||
transformationMatrixCache = new float[matrixTransformations.size()][16];
|
transformationMatrixCache = new float[matrixTransformations.size()][16];
|
||||||
@ -159,13 +166,9 @@ import java.util.Arrays;
|
|||||||
String fragmentShaderFilePath;
|
String fragmentShaderFilePath;
|
||||||
if (sampleFromExternalTexture) {
|
if (sampleFromExternalTexture) {
|
||||||
vertexShaderFilePath =
|
vertexShaderFilePath =
|
||||||
enableExperimentalHdrEditing
|
useHdr ? VERTEX_SHADER_TRANSFORMATION_ES3_PATH : VERTEX_SHADER_TRANSFORMATION_PATH;
|
||||||
? VERTEX_SHADER_TRANSFORMATION_ES3_PATH
|
|
||||||
: VERTEX_SHADER_TRANSFORMATION_PATH;
|
|
||||||
fragmentShaderFilePath =
|
fragmentShaderFilePath =
|
||||||
enableExperimentalHdrEditing
|
useHdr ? FRAGMENT_SHADER_COPY_EXTERNAL_YUV_ES3_PATH : FRAGMENT_SHADER_COPY_EXTERNAL_PATH;
|
||||||
? FRAGMENT_SHADER_COPY_EXTERNAL_YUV_ES3_PATH
|
|
||||||
: FRAGMENT_SHADER_COPY_EXTERNAL_PATH;
|
|
||||||
} else {
|
} else {
|
||||||
vertexShaderFilePath = VERTEX_SHADER_TRANSFORMATION_PATH;
|
vertexShaderFilePath = VERTEX_SHADER_TRANSFORMATION_PATH;
|
||||||
fragmentShaderFilePath = FRAGMENT_SHADER_COPY_PATH;
|
fragmentShaderFilePath = FRAGMENT_SHADER_COPY_PATH;
|
||||||
@ -177,7 +180,7 @@ import java.util.Arrays;
|
|||||||
throw new FrameProcessingException(e);
|
throw new FrameProcessingException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enableExperimentalHdrEditing && sampleFromExternalTexture) {
|
if (useHdr && sampleFromExternalTexture) {
|
||||||
// In HDR editing mode the decoder output is sampled in YUV.
|
// In HDR editing mode the decoder output is sampled in YUV.
|
||||||
glProgram.setFloatsUniform("uColorTransform", MATRIX_YUV_TO_BT2020_COLOR_TRANSFORM);
|
glProgram.setFloatsUniform("uColorTransform", MATRIX_YUV_TO_BT2020_COLOR_TRANSFORM);
|
||||||
}
|
}
|
||||||
|
@ -111,8 +111,6 @@ import org.checkerframework.dataflow.qual.Pure;
|
|||||||
boolean useHdr =
|
boolean useHdr =
|
||||||
transformationRequest.enableHdrEditing && ColorInfo.isHdr(inputFormat.colorInfo);
|
transformationRequest.enableHdrEditing && ColorInfo.isHdr(inputFormat.colorInfo);
|
||||||
if (useHdr && !encoderWrapper.supportsHdr()) {
|
if (useHdr && !encoderWrapper.supportsHdr()) {
|
||||||
// TODO(b/236316454): Also check whether GlEffectsFrameProcessor supports HDR, i.e., whether
|
|
||||||
// EXT_YUV_target is supported.
|
|
||||||
useHdr = false;
|
useHdr = false;
|
||||||
enableRequestSdrToneMapping = true;
|
enableRequestSdrToneMapping = true;
|
||||||
encoderWrapper.signalFallbackToSdr();
|
encoderWrapper.signalFallbackToSdr();
|
||||||
@ -152,6 +150,9 @@ import org.checkerframework.dataflow.qual.Pure;
|
|||||||
streamOffsetUs,
|
streamOffsetUs,
|
||||||
effectsListBuilder.build(),
|
effectsListBuilder.build(),
|
||||||
debugViewProvider,
|
debugViewProvider,
|
||||||
|
// HDR is only used if the MediaCodec encoder supports FEATURE_HdrEditing. This
|
||||||
|
// implies that the OpenGL EXT_YUV_target extension is supported and hence the
|
||||||
|
// GlEffectsFrameProcessor also supports HDR.
|
||||||
useHdr);
|
useHdr);
|
||||||
} catch (FrameProcessingException e) {
|
} catch (FrameProcessingException e) {
|
||||||
throw TransformationException.createForFrameProcessingException(
|
throw TransformationException.createForFrameProcessingException(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user