Commit cf61e219 by huangdarwin Committed by Ian Baker

HDR: Add effect interface support for different in/out color transfers

Modify FrameProcessor and MatrixTextureProcessor interfaces to support
different input and output color transfers. Does not implement conversion between
color ranges (ex. HDR and SDR), but should allow for conversion between color
transfers of the same color range (ex. HLG and PQ).

This supports in-app tone mapping, where we need a single FrameProcessor to
input HDR color transfers (ex. HLG/PQ) and output SDR (ex. gamma2.2). This also
supports previewing, where we need a single FrameProcessor to be able to input HLG
and output PQ.

Manually tested by confirming colors still look right on SDR and HDR videos
with a rotation and color affect applied.

PiperOrigin-RevId: 493108678
parent 88a7d67f
...@@ -44,9 +44,11 @@ public interface FrameProcessor { ...@@ -44,9 +44,11 @@ public interface FrameProcessor {
* Creates a new {@link FrameProcessor} instance. * Creates a new {@link FrameProcessor} instance.
* *
* @param context A {@link Context}. * @param context A {@link Context}.
* @param effects The {@link Effect} instances to apply to each frame. * @param effects The {@link Effect} instances to apply to each frame. Applied on the {@code
* outputColorInfo}'s color space.
* @param debugViewProvider A {@link DebugViewProvider}. * @param debugViewProvider A {@link DebugViewProvider}.
* @param colorInfo The {@link ColorInfo} for input and output frames. * @param inputColorInfo The {@link ColorInfo} for input frames.
* @param outputColorInfo The {@link ColorInfo} for output frames.
* @param releaseFramesAutomatically If {@code true}, the {@link FrameProcessor} will render * @param releaseFramesAutomatically If {@code true}, the {@link FrameProcessor} will render
* output frames to the {@linkplain #setOutputSurfaceInfo(SurfaceInfo) output surface} * output frames to the {@linkplain #setOutputSurfaceInfo(SurfaceInfo) output surface}
* automatically as {@link FrameProcessor} is done processing them. If {@code false}, the * automatically as {@link FrameProcessor} is done processing them. If {@code false}, the
...@@ -62,7 +64,8 @@ public interface FrameProcessor { ...@@ -62,7 +64,8 @@ public interface FrameProcessor {
Context context, Context context,
List<Effect> effects, List<Effect> effects,
DebugViewProvider debugViewProvider, DebugViewProvider debugViewProvider,
ColorInfo colorInfo, ColorInfo inputColorInfo,
ColorInfo outputColorInfo,
boolean releaseFramesAutomatically, boolean releaseFramesAutomatically,
Executor executor, Executor executor,
Listener listener) Listener listener)
......
...@@ -286,7 +286,8 @@ public final class GlEffectsFrameProcessorFrameReleaseTest { ...@@ -286,7 +286,8 @@ public final class GlEffectsFrameProcessorFrameReleaseTest {
(context, useHdr) -> (context, useHdr) ->
new BlankFrameProducer(inputPresentationTimesUs, useHdr)), new BlankFrameProducer(inputPresentationTimesUs, useHdr)),
DebugViewProvider.NONE, DebugViewProvider.NONE,
ColorInfo.SDR_BT709_LIMITED, /* inputColorInfo= */ ColorInfo.SDR_BT709_LIMITED,
/* outputColorInfo= */ ColorInfo.SDR_BT709_LIMITED,
releaseFramesAutomatically, releaseFramesAutomatically,
MoreExecutors.directExecutor(), MoreExecutors.directExecutor(),
new FrameProcessor.Listener() { new FrameProcessor.Listener() {
......
...@@ -418,7 +418,8 @@ public final class GlEffectsFrameProcessorPixelTest { ...@@ -418,7 +418,8 @@ public final class GlEffectsFrameProcessorPixelTest {
getApplicationContext(), getApplicationContext(),
effects, effects,
DebugViewProvider.NONE, DebugViewProvider.NONE,
ColorInfo.SDR_BT709_LIMITED, /* inputColorInfo= */ ColorInfo.SDR_BT709_LIMITED,
/* outputColorInfo= */ ColorInfo.SDR_BT709_LIMITED,
/* releaseFramesAutomatically= */ true, /* releaseFramesAutomatically= */ true,
MoreExecutors.directExecutor(), MoreExecutors.directExecutor(),
new FrameProcessor.Listener() { new FrameProcessor.Listener() {
......
...@@ -23,9 +23,10 @@ ...@@ -23,9 +23,10 @@
// 3. Applies an EOTF based on uEotfColorTransfer, yielding optical linear // 3. Applies an EOTF based on uEotfColorTransfer, yielding optical linear
// BT.2020 RGB. // BT.2020 RGB.
// 4. Applies a 4x4 RGB color matrix to change the pixel colors. // 4. Applies a 4x4 RGB color matrix to change the pixel colors.
// 5. If uOetfColorTransfer is COLOR_TRANSFER_LINEAR, outputs linear colors as // 5. Output as requested by uOetfColorTransfer. Use COLOR_TRANSFER_LINEAR for
// is to intermediate shaders. Otherwise, applies the HLG or PQ OETF, based // outputting to intermediate shaders, or COLOR_TRANSFER_ST2084 /
// on uOetfColorTransfer, to provide the corresponding output electrical color. // COLOR_TRANSFER_HLG to output electrical colors via an OETF (e.g. to an
// encoder).
// The output will be red if an error has occurred. // The output will be red if an error has occurred.
#extension GL_OES_EGL_image_external : require #extension GL_OES_EGL_image_external : require
......
...@@ -20,15 +20,18 @@ ...@@ -20,15 +20,18 @@
// 2. Transforms the electrical colors to optical colors using the SMPTE 170M // 2. Transforms the electrical colors to optical colors using the SMPTE 170M
// EOTF. // EOTF.
// 3. Applies a 4x4 RGB color matrix to change the pixel colors. // 3. Applies a 4x4 RGB color matrix to change the pixel colors.
// 4. Transforms the optical colors back to electrical ones if uApplyOetf == 1 // 4. Output as requested by uOetfColorTransfer. Use COLOR_TRANSFER_LINEAR for
// using the SMPTE 170M OETF. // outputting to intermediate shaders, or COLOR_TRANSFER_SDR_VIDEO to output
// electrical colors via an OETF (e.g. to an encoder).
#extension GL_OES_EGL_image_external : require #extension GL_OES_EGL_image_external : require
precision mediump float; precision mediump float;
uniform samplerExternalOES uTexSampler; uniform samplerExternalOES uTexSampler;
uniform mat4 uRgbMatrix; uniform mat4 uRgbMatrix;
varying vec2 vTexSamplingCoord; varying vec2 vTexSamplingCoord;
uniform int uApplyOetf; // C.java#ColorTransfer value.
// Only COLOR_TRANSFER_LINEAR and COLOR_TRANSFER_SDR_VIDEO are allowed.
uniform int uOetfColorTransfer;
const float inverseGamma = 0.4500; const float inverseGamma = 0.4500;
const float gamma = 1.0 / inverseGamma; const float gamma = 1.0 / inverseGamma;
...@@ -61,12 +64,26 @@ float sdrOetfSingleChannel(float opticalChannel) { ...@@ -61,12 +64,26 @@ float sdrOetfSingleChannel(float opticalChannel) {
// Transforms optical SDR colors to electrical SDR using the SMPTE 170M OETF. // Transforms optical SDR colors to electrical SDR using the SMPTE 170M OETF.
vec3 sdrOetf(vec3 opticalColor) { vec3 sdrOetf(vec3 opticalColor) {
return uApplyOetf == 1 return vec3(
? vec3(
sdrOetfSingleChannel(opticalColor.r), sdrOetfSingleChannel(opticalColor.r),
sdrOetfSingleChannel(opticalColor.g), sdrOetfSingleChannel(opticalColor.g),
sdrOetfSingleChannel(opticalColor.b)) sdrOetfSingleChannel(opticalColor.b));
: opticalColor; }
// Applies the appropriate OETF to convert linear optical signals to nonlinear
// electrical signals. Input and output are both normalized to [0, 1].
highp vec3 applyOetf(highp vec3 linearColor) {
// LINT.IfChange(color_transfer_oetf)
const int COLOR_TRANSFER_LINEAR = 1;
const int COLOR_TRANSFER_SDR_VIDEO = 3;
if (uOetfColorTransfer == COLOR_TRANSFER_LINEAR) {
return linearColor;
} else if(uOetfColorTransfer == COLOR_TRANSFER_SDR_VIDEO) {
return sdrOetf(linearColor);
} else {
// Output red as an obviously visible error.
return vec3(1.0, 0.0, 0.0);
}
} }
void main() { void main() {
...@@ -75,5 +92,5 @@ void main() { ...@@ -75,5 +92,5 @@ void main() {
vec4 transformedColors = uRgbMatrix * vec4(linearInputColor, 1); vec4 transformedColors = uRgbMatrix * vec4(linearInputColor, 1);
gl_FragColor = vec4(sdrOetf(transformedColors.rgb), inputColor.a); gl_FragColor = vec4(applyOetf(transformedColors.rgb), inputColor.a);
} }
...@@ -70,7 +70,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -70,7 +70,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
private final EGLContext eglContext; private final EGLContext eglContext;
private final DebugViewProvider debugViewProvider; private final DebugViewProvider debugViewProvider;
private final boolean sampleFromExternalTexture; private final boolean sampleFromExternalTexture;
private final ColorInfo colorInfo; private final ColorInfo inputColorInfo;
private final ColorInfo outputColorInfo;
private final boolean releaseFramesAutomatically; private final boolean releaseFramesAutomatically;
private final Executor frameProcessorListenerExecutor; private final Executor frameProcessorListenerExecutor;
private final FrameProcessor.Listener frameProcessorListener; private final FrameProcessor.Listener frameProcessorListener;
...@@ -104,7 +105,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -104,7 +105,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
ImmutableList<RgbMatrix> rgbMatrices, ImmutableList<RgbMatrix> rgbMatrices,
DebugViewProvider debugViewProvider, DebugViewProvider debugViewProvider,
boolean sampleFromExternalTexture, boolean sampleFromExternalTexture,
ColorInfo colorInfo, ColorInfo inputColorInfo,
ColorInfo outputColorInfo,
boolean releaseFramesAutomatically, boolean releaseFramesAutomatically,
Executor frameProcessorListenerExecutor, Executor frameProcessorListenerExecutor,
FrameProcessor.Listener frameProcessorListener) { FrameProcessor.Listener frameProcessorListener) {
...@@ -115,7 +117,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -115,7 +117,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
this.eglContext = eglContext; this.eglContext = eglContext;
this.debugViewProvider = debugViewProvider; this.debugViewProvider = debugViewProvider;
this.sampleFromExternalTexture = sampleFromExternalTexture; this.sampleFromExternalTexture = sampleFromExternalTexture;
this.colorInfo = colorInfo; this.inputColorInfo = inputColorInfo;
this.outputColorInfo = outputColorInfo;
this.releaseFramesAutomatically = releaseFramesAutomatically; this.releaseFramesAutomatically = releaseFramesAutomatically;
this.frameProcessorListenerExecutor = frameProcessorListenerExecutor; this.frameProcessorListenerExecutor = frameProcessorListenerExecutor;
this.frameProcessorListener = frameProcessorListener; this.frameProcessorListener = frameProcessorListener;
...@@ -336,13 +339,13 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -336,13 +339,13 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
SurfaceInfo outputSurfaceInfo = this.outputSurfaceInfo; SurfaceInfo outputSurfaceInfo = this.outputSurfaceInfo;
@Nullable EGLSurface outputEglSurface = this.outputEglSurface; @Nullable EGLSurface outputEglSurface = this.outputEglSurface;
if (outputEglSurface == null) { if (outputEglSurface == null) {
boolean colorInfoIsHdr = ColorInfo.isTransferHdr(colorInfo); boolean outputTransferIsHdr = ColorInfo.isTransferHdr(outputColorInfo);
outputEglSurface = outputEglSurface =
GlUtil.createEglSurface( GlUtil.createEglSurface(
eglDisplay, eglDisplay,
outputSurfaceInfo.surface, outputSurfaceInfo.surface,
colorInfoIsHdr outputTransferIsHdr
? GlUtil.EGL_CONFIG_ATTRIBUTES_RGBA_1010102 ? GlUtil.EGL_CONFIG_ATTRIBUTES_RGBA_1010102
: GlUtil.EGL_CONFIG_ATTRIBUTES_RGBA_8888); : GlUtil.EGL_CONFIG_ATTRIBUTES_RGBA_8888);
...@@ -352,7 +355,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -352,7 +355,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
outputSurfaceInfo.width, outputSurfaceInfo.height); outputSurfaceInfo.width, outputSurfaceInfo.height);
if (debugSurfaceView != null && !Util.areEqual(this.debugSurfaceView, debugSurfaceView)) { if (debugSurfaceView != null && !Util.areEqual(this.debugSurfaceView, debugSurfaceView)) {
debugSurfaceViewWrapper = debugSurfaceViewWrapper =
new SurfaceViewWrapper(eglDisplay, eglContext, colorInfoIsHdr, debugSurfaceView); new SurfaceViewWrapper(eglDisplay, eglContext, outputTransferIsHdr, debugSurfaceView);
} }
this.debugSurfaceView = debugSurfaceView; this.debugSurfaceView = debugSurfaceView;
} }
...@@ -390,12 +393,16 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -390,12 +393,16 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
matrixTransformationListBuilder.build(); matrixTransformationListBuilder.build();
if (sampleFromExternalTexture) { if (sampleFromExternalTexture) {
matrixTextureProcessor = matrixTextureProcessor =
MatrixTextureProcessor.createWithExternalSamplerApplyingEotfThenOetf( MatrixTextureProcessor.createWithExternalSampler(
context, expandedMatrixTransformations, rgbMatrices, colorInfo); context,
expandedMatrixTransformations,
rgbMatrices,
/* inputColorInfo= */ inputColorInfo,
/* outputColorInfo= */ outputColorInfo);
} else { } else {
matrixTextureProcessor = matrixTextureProcessor =
MatrixTextureProcessor.createApplyingOetf( MatrixTextureProcessor.createApplyingOetf(
context, expandedMatrixTransformations, rgbMatrices, colorInfo); context, expandedMatrixTransformations, rgbMatrices, outputColorInfo);
} }
matrixTextureProcessor.setTextureTransformMatrix(textureTransformMatrix); matrixTextureProcessor.setTextureTransformMatrix(textureTransformMatrix);
......
...@@ -68,12 +68,24 @@ public final class GlEffectsFrameProcessor implements FrameProcessor { ...@@ -68,12 +68,24 @@ public final class GlEffectsFrameProcessor implements FrameProcessor {
Context context, Context context,
List<Effect> effects, List<Effect> effects,
DebugViewProvider debugViewProvider, DebugViewProvider debugViewProvider,
ColorInfo colorInfo, ColorInfo inputColorInfo,
ColorInfo outputColorInfo,
boolean releaseFramesAutomatically, boolean releaseFramesAutomatically,
Executor listenerExecutor, Executor listenerExecutor,
Listener listener) Listener listener)
throws FrameProcessingException { throws FrameProcessingException {
// TODO(b/261188041) Add tests to verify the Listener is invoked on the given Executor. // TODO(b/261188041) Add tests to verify the Listener is invoked on the given Executor.
// TODO(b/239735341): Reduce the scope of these checks by implementing GL tone-mapping.
checkArgument(
inputColorInfo.colorSpace == outputColorInfo.colorSpace,
"Conversion between HDR and SDR color spaces is not yet supported.");
checkArgument(
ColorInfo.isTransferHdr(inputColorInfo) == ColorInfo.isTransferHdr(outputColorInfo),
"Conversion between HDR and SDR color transfers is not yet supported.");
checkArgument(inputColorInfo.colorTransfer != C.COLOR_TRANSFER_LINEAR);
checkArgument(outputColorInfo.colorTransfer != C.COLOR_TRANSFER_LINEAR);
ExecutorService singleThreadExecutorService = Util.newSingleThreadExecutor(THREAD_NAME); ExecutorService singleThreadExecutorService = Util.newSingleThreadExecutor(THREAD_NAME);
Future<GlEffectsFrameProcessor> glFrameProcessorFuture = Future<GlEffectsFrameProcessor> glFrameProcessorFuture =
...@@ -83,7 +95,8 @@ public final class GlEffectsFrameProcessor implements FrameProcessor { ...@@ -83,7 +95,8 @@ public final class GlEffectsFrameProcessor implements FrameProcessor {
context, context,
effects, effects,
debugViewProvider, debugViewProvider,
colorInfo, inputColorInfo,
outputColorInfo,
releaseFramesAutomatically, releaseFramesAutomatically,
singleThreadExecutorService, singleThreadExecutorService,
listenerExecutor, listenerExecutor,
...@@ -115,7 +128,8 @@ public final class GlEffectsFrameProcessor implements FrameProcessor { ...@@ -115,7 +128,8 @@ public final class GlEffectsFrameProcessor implements FrameProcessor {
Context context, Context context,
List<Effect> effects, List<Effect> effects,
DebugViewProvider debugViewProvider, DebugViewProvider debugViewProvider,
ColorInfo colorInfo, ColorInfo inputColorInfo,
ColorInfo outputColorInfo,
boolean releaseFramesAutomatically, boolean releaseFramesAutomatically,
ExecutorService singleThreadExecutorService, ExecutorService singleThreadExecutorService,
Executor executor, Executor executor,
...@@ -125,10 +139,11 @@ public final class GlEffectsFrameProcessor implements FrameProcessor { ...@@ -125,10 +139,11 @@ public final class GlEffectsFrameProcessor implements FrameProcessor {
// TODO(b/237674316): Delay initialization of things requiring the colorInfo, to // TODO(b/237674316): Delay initialization of things requiring the colorInfo, to
// configure based on the color info from the decoder output media format instead. // configure based on the color info from the decoder output media format instead.
boolean useHdr = ColorInfo.isTransferHdr(colorInfo);
EGLDisplay eglDisplay = GlUtil.createEglDisplay(); EGLDisplay eglDisplay = GlUtil.createEglDisplay();
int[] configAttributes = int[] configAttributes =
useHdr ? GlUtil.EGL_CONFIG_ATTRIBUTES_RGBA_1010102 : GlUtil.EGL_CONFIG_ATTRIBUTES_RGBA_8888; ColorInfo.isTransferHdr(outputColorInfo)
? GlUtil.EGL_CONFIG_ATTRIBUTES_RGBA_1010102
: GlUtil.EGL_CONFIG_ATTRIBUTES_RGBA_8888;
EGLContext eglContext = GlUtil.createEglContext(eglDisplay, configAttributes); EGLContext eglContext = GlUtil.createEglContext(eglDisplay, configAttributes);
GlUtil.createFocusedPlaceholderEglSurface(eglContext, eglDisplay, configAttributes); GlUtil.createFocusedPlaceholderEglSurface(eglContext, eglDisplay, configAttributes);
...@@ -139,7 +154,8 @@ public final class GlEffectsFrameProcessor implements FrameProcessor { ...@@ -139,7 +154,8 @@ public final class GlEffectsFrameProcessor implements FrameProcessor {
eglDisplay, eglDisplay,
eglContext, eglContext,
debugViewProvider, debugViewProvider,
colorInfo, inputColorInfo,
outputColorInfo,
releaseFramesAutomatically, releaseFramesAutomatically,
executor, executor,
listener); listener);
...@@ -173,7 +189,8 @@ public final class GlEffectsFrameProcessor implements FrameProcessor { ...@@ -173,7 +189,8 @@ public final class GlEffectsFrameProcessor implements FrameProcessor {
EGLDisplay eglDisplay, EGLDisplay eglDisplay,
EGLContext eglContext, EGLContext eglContext,
DebugViewProvider debugViewProvider, DebugViewProvider debugViewProvider,
ColorInfo colorInfo, ColorInfo inputColorInfo,
ColorInfo outputColorInfo,
boolean releaseFramesAutomatically, boolean releaseFramesAutomatically,
Executor executor, Executor executor,
Listener listener) Listener listener)
...@@ -184,6 +201,9 @@ public final class GlEffectsFrameProcessor implements FrameProcessor { ...@@ -184,6 +201,9 @@ public final class GlEffectsFrameProcessor implements FrameProcessor {
new ImmutableList.Builder<>(); new ImmutableList.Builder<>();
ImmutableList.Builder<RgbMatrix> rgbMatrixListBuilder = new ImmutableList.Builder<>(); ImmutableList.Builder<RgbMatrix> rgbMatrixListBuilder = new ImmutableList.Builder<>();
boolean sampleFromExternalTexture = true; boolean sampleFromExternalTexture = true;
ColorInfo linearColorInfo =
new ColorInfo(
inputColorInfo.colorSpace, inputColorInfo.colorRange, C.COLOR_TRANSFER_LINEAR, null);
for (int i = 0; i < effects.size(); i++) { for (int i = 0; i < effects.size(); i++) {
Effect effect = effects.get(i); Effect effect = effects.get(i);
checkArgument(effect instanceof GlEffect, "GlEffectsFrameProcessor only supports GlEffects"); checkArgument(effect instanceof GlEffect, "GlEffectsFrameProcessor only supports GlEffects");
...@@ -203,24 +223,28 @@ public final class GlEffectsFrameProcessor implements FrameProcessor { ...@@ -203,24 +223,28 @@ public final class GlEffectsFrameProcessor implements FrameProcessor {
ImmutableList<GlMatrixTransformation> matrixTransformations = ImmutableList<GlMatrixTransformation> matrixTransformations =
matrixTransformationListBuilder.build(); matrixTransformationListBuilder.build();
ImmutableList<RgbMatrix> rgbMatrices = rgbMatrixListBuilder.build(); ImmutableList<RgbMatrix> rgbMatrices = rgbMatrixListBuilder.build();
boolean isOutputTransferHdr = ColorInfo.isTransferHdr(outputColorInfo);
if (!matrixTransformations.isEmpty() || !rgbMatrices.isEmpty() || sampleFromExternalTexture) { if (!matrixTransformations.isEmpty() || !rgbMatrices.isEmpty() || sampleFromExternalTexture) {
MatrixTextureProcessor matrixTextureProcessor; MatrixTextureProcessor matrixTextureProcessor;
if (sampleFromExternalTexture) { if (sampleFromExternalTexture) {
matrixTextureProcessor = matrixTextureProcessor =
MatrixTextureProcessor.createWithExternalSamplerApplyingEotf( MatrixTextureProcessor.createWithExternalSampler(
context, matrixTransformations, rgbMatrices, colorInfo); context,
matrixTransformations,
rgbMatrices,
/* inputColorInfo= */ inputColorInfo,
/* outputColorInfo= */ linearColorInfo);
} else { } else {
matrixTextureProcessor = matrixTextureProcessor =
MatrixTextureProcessor.create( MatrixTextureProcessor.create(
context, matrixTransformations, rgbMatrices, ColorInfo.isTransferHdr(colorInfo)); context, matrixTransformations, rgbMatrices, isOutputTransferHdr);
} }
textureProcessorListBuilder.add(matrixTextureProcessor); textureProcessorListBuilder.add(matrixTextureProcessor);
matrixTransformationListBuilder = new ImmutableList.Builder<>(); matrixTransformationListBuilder = new ImmutableList.Builder<>();
rgbMatrixListBuilder = new ImmutableList.Builder<>(); rgbMatrixListBuilder = new ImmutableList.Builder<>();
sampleFromExternalTexture = false; sampleFromExternalTexture = false;
} }
textureProcessorListBuilder.add( textureProcessorListBuilder.add(glEffect.toGlTextureProcessor(context, isOutputTransferHdr));
glEffect.toGlTextureProcessor(context, ColorInfo.isTransferHdr(colorInfo)));
} }
textureProcessorListBuilder.add( textureProcessorListBuilder.add(
...@@ -232,7 +256,8 @@ public final class GlEffectsFrameProcessor implements FrameProcessor { ...@@ -232,7 +256,8 @@ public final class GlEffectsFrameProcessor implements FrameProcessor {
rgbMatrixListBuilder.build(), rgbMatrixListBuilder.build(),
debugViewProvider, debugViewProvider,
sampleFromExternalTexture, sampleFromExternalTexture,
colorInfo, /* inputColorInfo= */ sampleFromExternalTexture ? inputColorInfo : linearColorInfo,
outputColorInfo,
releaseFramesAutomatically, releaseFramesAutomatically,
executor, executor,
listener)); listener));
......
...@@ -155,17 +155,19 @@ import org.checkerframework.dataflow.qual.Pure; ...@@ -155,17 +155,19 @@ import org.checkerframework.dataflow.qual.Pure;
transformationRequest, transformationRequest,
fallbackListener); fallbackListener);
// HDR colors are only used if the MediaCodec encoder supports FEATURE_HdrEditing.
// This implies that the OpenGL EXT_YUV_target extension is supported and hence the
// default FrameProcessor, GlEffectsFrameProcessor, also supports HDR. Otherwise, tone
// mapping is applied, which ensures the decoder outputs SDR output for an HDR input.
ColorInfo encoderSupportedInputColor = encoderWrapper.getSupportedInputColor();
try { try {
frameProcessor = frameProcessor =
frameProcessorFactory.create( frameProcessorFactory.create(
context, context,
effectsListBuilder.build(), effectsListBuilder.build(),
debugViewProvider, debugViewProvider,
// HDR colors are only used if the MediaCodec encoder supports FEATURE_HdrEditing. /* inputColorInfo= */ encoderSupportedInputColor,
// This implies that the OpenGL EXT_YUV_target extension is supported and hence the /* outputColorInfo= */ encoderSupportedInputColor,
// default FrameProcessor, GlEffectsFrameProcessor, also supports HDR. Otherwise, tone
// mapping is applied, which ensures the decoder outputs SDR output for an HDR input.
encoderWrapper.getSupportedInputColor(),
/* releaseFramesAutomatically= */ true, /* releaseFramesAutomatically= */ true,
MoreExecutors.directExecutor(), MoreExecutors.directExecutor(),
new FrameProcessor.Listener() { new FrameProcessor.Listener() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment