Effect: Add EGL_EXT_gl_colorspace_bt2020_hlg support, on API 34+
Confirmed that the HLG extension displays properly on Pixel 7 Pro, API 34 and Samsung S24, API 34. On these devices, this fixes the washed out HLG preview issue on API 34, where the PQ ext had a washed out look, and where the HLG ext is supported (this bug didn't occur on API 33, only 34). More info on manual tests done to sanity-check: * Test cases: Transformer debug SurfaceView and ExoPlayer.setVideoEffects * Test inputs: HLG and PQ * Test devices: Pixel 7 Pro (API 33 & 34), Samsung Galaxy S24 (API 34) * Added debugging: Logging colorInfo used in GlUtil.createEglSurface No regressions were seen. HLG extension is used more in API 34, and behavior stays the same on API 33. Only human-visible change without logging is that HLG content looks better on API 34, for Samsung S24 and Pixel 7 Pro. PiperOrigin-RevId: 616131192
This commit is contained in:
parent
c0ffc94d15
commit
b126bae93d
@ -73,6 +73,9 @@
|
||||
* Support multiple speed changes within the same `EditedMediaItem` or
|
||||
`Composition` in `SpeedChangeEffect`.
|
||||
* Support for HLG and PQ output from ultra HDR bitmap input.
|
||||
* Add support for EGL_GL_COLORSPACE_BT2020_HLG_EXT, which improves HLG
|
||||
surface output in ExoPlayer.setVideoEffect and Transformer's Debug
|
||||
SurfaceView.
|
||||
* Muxers:
|
||||
* IMA extension:
|
||||
* Session:
|
||||
|
@ -96,6 +96,7 @@ public final class GlUtil {
|
||||
private static final String EXTENSION_YUV_TARGET = "GL_EXT_YUV_target";
|
||||
// https://registry.khronos.org/EGL/extensions/EXT/EGL_EXT_gl_colorspace_bt2020_linear.txt
|
||||
private static final String EXTENSION_COLORSPACE_BT2020_PQ = "EGL_EXT_gl_colorspace_bt2020_pq";
|
||||
private static final String EXTENSION_COLORSPACE_BT2020_HLG = "EGL_EXT_gl_colorspace_bt2020_hlg";
|
||||
// https://registry.khronos.org/EGL/extensions/KHR/EGL_KHR_gl_colorspace.txt
|
||||
private static final int EGL_GL_COLORSPACE_KHR = 0x309D;
|
||||
// https://registry.khronos.org/EGL/extensions/EXT/EGL_EXT_gl_colorspace_bt2020_linear.txt
|
||||
@ -104,6 +105,11 @@ public final class GlUtil {
|
||||
new int[] {
|
||||
EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_BT2020_PQ_EXT, EGL14.EGL_NONE, EGL14.EGL_NONE
|
||||
};
|
||||
private static final int EGL_GL_COLORSPACE_BT2020_HLG_EXT = 0x3540;
|
||||
private static final int[] EGL_WINDOW_SURFACE_ATTRIBUTES_BT2020_HLG =
|
||||
new int[] {
|
||||
EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_BT2020_HLG_EXT, EGL14.EGL_NONE, EGL14.EGL_NONE
|
||||
};
|
||||
private static final int[] EGL_WINDOW_SURFACE_ATTRIBUTES_NONE = new int[] {EGL14.EGL_NONE};
|
||||
|
||||
/** Class only contains static methods. */
|
||||
@ -221,7 +227,14 @@ public final class GlUtil {
|
||||
|
||||
/** Returns whether {@link #EXTENSION_COLORSPACE_BT2020_PQ} is supported. */
|
||||
public static boolean isBt2020PqExtensionSupported() {
|
||||
return isExtensionSupported(EXTENSION_COLORSPACE_BT2020_PQ);
|
||||
// On API<33, the system cannot display PQ content correctly regardless of whether BT2020 PQ
|
||||
// GL extension is supported. Context: http://b/252537203#comment5.
|
||||
return Util.SDK_INT >= 33 && isExtensionSupported(EXTENSION_COLORSPACE_BT2020_PQ);
|
||||
}
|
||||
|
||||
/** Returns whether {@link #EXTENSION_COLORSPACE_BT2020_HLG} is supported. */
|
||||
public static boolean isBt2020HlgExtensionSupported() {
|
||||
return isExtensionSupported(EXTENSION_COLORSPACE_BT2020_HLG);
|
||||
}
|
||||
|
||||
/** Returns an initialized default {@link EGLDisplay}. */
|
||||
@ -301,7 +314,7 @@ public final class GlUtil {
|
||||
* @param surface The surface to wrap; must be a surface, surface texture or surface holder.
|
||||
* @param colorTransfer The {@linkplain C.ColorTransfer color transfer characteristics} to which
|
||||
* the {@code surface} is configured. The only accepted values are {@link
|
||||
* C#COLOR_TRANSFER_SDR}, {@link C#COLOR_TRANSFER_HLG} and {@link C#COLOR_TRANSFER_ST2084}.
|
||||
* C#COLOR_TRANSFER_SDR}, {@link C#COLOR_TRANSFER_HLG}, and {@link C#COLOR_TRANSFER_ST2084}.
|
||||
* @param isEncoderInputSurface Whether the {@code surface} is the input surface of an encoder.
|
||||
*/
|
||||
public static EGLSurface createEglSurface(
|
||||
@ -315,22 +328,28 @@ public final class GlUtil {
|
||||
if (colorTransfer == C.COLOR_TRANSFER_SDR || colorTransfer == C.COLOR_TRANSFER_GAMMA_2_2) {
|
||||
configAttributes = EGL_CONFIG_ATTRIBUTES_RGBA_8888;
|
||||
windowAttributes = EGL_WINDOW_SURFACE_ATTRIBUTES_NONE;
|
||||
} else if (colorTransfer == C.COLOR_TRANSFER_ST2084) {
|
||||
} else if (colorTransfer == C.COLOR_TRANSFER_HLG || colorTransfer == C.COLOR_TRANSFER_ST2084) {
|
||||
configAttributes = EGL_CONFIG_ATTRIBUTES_RGBA_1010102;
|
||||
// !isEncoderInputSurface means outputting to a display surface. HDR display surfaces
|
||||
// require EGL_GL_COLORSPACE_BT2020_PQ_EXT or EGL_GL_COLORSPACE_BT2020_HLG_EXT.
|
||||
if (isEncoderInputSurface) {
|
||||
// Outputting BT2020 PQ with EGL_WINDOW_SURFACE_ATTRIBUTES_BT2020_PQ to an encoder causes
|
||||
// the encoder to incorrectly switch to full range color, even if the encoder is configured
|
||||
// with limited range color, because EGL_WINDOW_SURFACE_ATTRIBUTES_BT2020_PQ sets full range
|
||||
// color output, and GL windowAttributes overrides encoder settings.
|
||||
// Outputting BT2020 PQ or HLG with EGL_WINDOW_SURFACE_ATTRIBUTES_BT2020_PQ to an encoder
|
||||
// causes the encoder to incorrectly switch to full range color, even if the encoder is
|
||||
// configured with limited range color, because EGL_WINDOW_SURFACE_ATTRIBUTES_BT2020_PQ sets
|
||||
// full range color output, and GL windowAttributes overrides encoder settings.
|
||||
windowAttributes = EGL_WINDOW_SURFACE_ATTRIBUTES_NONE;
|
||||
} else {
|
||||
// TODO(b/262259999): HDR10 PQ content looks dark on the screen.
|
||||
} else if (colorTransfer == C.COLOR_TRANSFER_ST2084) {
|
||||
if (!isBt2020PqExtensionSupported()) {
|
||||
throw new GlException("BT.2020 PQ OpenGL output isn't supported.");
|
||||
}
|
||||
// TODO(b/262259999): HDR10 PQ content looks dark on the screen, on API 33.
|
||||
windowAttributes = EGL_WINDOW_SURFACE_ATTRIBUTES_BT2020_PQ;
|
||||
} else {
|
||||
if (!isBt2020HlgExtensionSupported()) {
|
||||
throw new GlException("BT.2020 HLG OpenGL output isn't supported.");
|
||||
}
|
||||
windowAttributes = EGL_WINDOW_SURFACE_ATTRIBUTES_BT2020_HLG;
|
||||
}
|
||||
} else if (colorTransfer == C.COLOR_TRANSFER_HLG) {
|
||||
checkArgument(isEncoderInputSurface, "Outputting HLG to the screen is not supported.");
|
||||
configAttributes = EGL_CONFIG_ATTRIBUTES_RGBA_1010102;
|
||||
windowAttributes = EGL_WINDOW_SURFACE_ATTRIBUTES_NONE;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsupported color transfer: " + colorTransfer);
|
||||
}
|
||||
|
@ -247,9 +247,8 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor {
|
||||
*
|
||||
* <p>Using HDR {@code outputColorInfo} requires OpenGL ES 3.0.
|
||||
*
|
||||
* <p>If outputting HDR content to a display, {@code EGL_GL_COLORSPACE_BT2020_PQ_EXT} is
|
||||
* required, and {@link ColorInfo#colorTransfer outputColorInfo.colorTransfer} must be {@link
|
||||
* C#COLOR_TRANSFER_ST2084}.
|
||||
* <p>If outputting HDR content to a display, {@code EGL_GL_COLORSPACE_BT2020_PQ_EXT} or {@code
|
||||
* EGL_GL_COLORSPACE_BT2020_HLG_EXT} is required.
|
||||
*
|
||||
* <p>{@code outputColorInfo}'s {@link ColorInfo#colorRange} values are currently ignored, in
|
||||
* favor of {@link C#COLOR_RANGE_FULL}.
|
||||
@ -678,18 +677,6 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor {
|
||||
EGLContext eglContext =
|
||||
createFocusedEglContextWithFallback(glObjectsProvider, eglDisplay, configAttributes);
|
||||
|
||||
// Not renderFramesAutomatically means outputting to a display surface. HDR display surfaces
|
||||
// require the BT2020 PQ GL extension.
|
||||
if (!renderFramesAutomatically && ColorInfo.isTransferHdr(outputColorInfo)) {
|
||||
// Display hardware supports PQ only.
|
||||
checkArgument(outputColorInfo.colorTransfer == C.COLOR_TRANSFER_ST2084);
|
||||
if (SDK_INT < 33 || !GlUtil.isBt2020PqExtensionSupported()) {
|
||||
GlUtil.destroyEglContext(eglDisplay, eglContext);
|
||||
// On API<33, the system cannot display PQ content correctly regardless of whether BT2020 PQ
|
||||
// GL extension is supported.
|
||||
throw new VideoFrameProcessingException("BT.2020 PQ OpenGL output isn't supported.");
|
||||
}
|
||||
}
|
||||
ColorInfo linearColorInfo =
|
||||
outputColorInfo
|
||||
.buildUpon()
|
||||
|
@ -588,9 +588,11 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
@C.ColorTransfer int outputColorTransfer) {
|
||||
this.eglDisplay = eglDisplay;
|
||||
this.eglContext = eglContext;
|
||||
// Screen output supports only BT.2020 PQ (ST2084) for HDR.
|
||||
// PQ SurfaceView output is supported from API 33, but HLG output is supported from API 34.
|
||||
// Therefore, convert HLG to PQ below API 34, so that HLG input can be displayed properly on
|
||||
// API 33.
|
||||
this.outputColorTransfer =
|
||||
outputColorTransfer == C.COLOR_TRANSFER_HLG
|
||||
outputColorTransfer == C.COLOR_TRANSFER_HLG && Util.SDK_INT < 34
|
||||
? C.COLOR_TRANSFER_ST2084
|
||||
: outputColorTransfer;
|
||||
surfaceView.getHolder().addCallback(this);
|
||||
|
@ -252,8 +252,10 @@ public final class CompositingVideoSinkProvider
|
||||
|
||||
ColorInfo inputColorInfo = getAdjustedInputColorInfo(sourceFormat.colorInfo);
|
||||
ColorInfo outputColorInfo = inputColorInfo;
|
||||
if (inputColorInfo.colorTransfer == C.COLOR_TRANSFER_HLG) {
|
||||
// SurfaceView only supports BT2020 PQ input. Therefore, convert HLG to PQ.
|
||||
if (inputColorInfo.colorTransfer == C.COLOR_TRANSFER_HLG && Util.SDK_INT < 34) {
|
||||
// PQ SurfaceView output is supported from API 33, but HLG output is supported from API 34.
|
||||
// Therefore, convert HLG to PQ below API 34, so that HLG input can be displayed properly on
|
||||
// API 33.
|
||||
outputColorInfo =
|
||||
inputColorInfo.buildUpon().setColorTransfer(C.COLOR_TRANSFER_ST2084).build();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user