Add Effect marker interface.

This allows non-GL effects to be passed to custom FrameProcessor
implementations.

PiperOrigin-RevId: 463696384
(cherry picked from commit 66dde42989dbc8fedeee59897a05644d86240cf6)
This commit is contained in:
Googler 2022-07-27 22:40:20 +00:00 committed by microkatz
parent 3fa0ce7faf
commit 5c7dcf42a0
9 changed files with 95 additions and 59 deletions

View File

@ -41,6 +41,7 @@ import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.transformer.Contrast; import com.google.android.exoplayer2.transformer.Contrast;
import com.google.android.exoplayer2.transformer.DebugViewProvider; import com.google.android.exoplayer2.transformer.DebugViewProvider;
import com.google.android.exoplayer2.transformer.DefaultEncoderFactory; import com.google.android.exoplayer2.transformer.DefaultEncoderFactory;
import com.google.android.exoplayer2.transformer.Effect;
import com.google.android.exoplayer2.transformer.GlEffect; import com.google.android.exoplayer2.transformer.GlEffect;
import com.google.android.exoplayer2.transformer.GlTextureProcessor; import com.google.android.exoplayer2.transformer.GlTextureProcessor;
import com.google.android.exoplayer2.transformer.ProgressHolder; import com.google.android.exoplayer2.transformer.ProgressHolder;
@ -265,7 +266,7 @@ public final class TransformerActivity extends AppCompatActivity {
.setEnableFallback(bundle.getBoolean(ConfigurationActivity.ENABLE_FALLBACK)) .setEnableFallback(bundle.getBoolean(ConfigurationActivity.ENABLE_FALLBACK))
.build()); .build());
ImmutableList.Builder<GlEffect> effects = new ImmutableList.Builder<>(); ImmutableList.Builder<Effect> effects = new ImmutableList.Builder<>();
@Nullable @Nullable
boolean[] selectedEffects = boolean[] selectedEffects =
bundle.getBooleanArray(ConfigurationActivity.DEMO_EFFECTS_SELECTIONS); bundle.getBooleanArray(ConfigurationActivity.DEMO_EFFECTS_SELECTIONS);
@ -281,43 +282,45 @@ public final class TransformerActivity extends AppCompatActivity {
clazz.getConstructor( clazz.getConstructor(
Context.class, Boolean.class, String.class, String.class, String.class); Context.class, Boolean.class, String.class, String.class, String.class);
effects.add( effects.add(
(Context context, boolean useHdr) -> { (GlEffect)
try { (Context context, boolean useHdr) -> {
return (GlTextureProcessor) try {
constructor.newInstance( return (GlTextureProcessor)
context, constructor.newInstance(
useHdr, context,
/* graphName= */ "edge_detector_mediapipe_graph.binarypb", useHdr,
/* inputStreamName= */ "input_video", /* graphName= */ "edge_detector_mediapipe_graph.binarypb",
/* outputStreamName= */ "output_video"); /* inputStreamName= */ "input_video",
} catch (Exception e) { /* outputStreamName= */ "output_video");
runOnUiThread(() -> showToast(R.string.no_media_pipe_error)); } catch (Exception e) {
throw new RuntimeException("Failed to load MediaPipe processor", e); runOnUiThread(() -> showToast(R.string.no_media_pipe_error));
} throw new RuntimeException("Failed to load MediaPipe processor", e);
}); }
});
} catch (Exception e) { } catch (Exception e) {
showToast(R.string.no_media_pipe_error); showToast(R.string.no_media_pipe_error);
} }
} }
if (selectedEffects[2]) { if (selectedEffects[2]) {
effects.add( effects.add(
(Context context, boolean useHdr) -> (GlEffect)
new PeriodicVignetteProcessor( (Context context, boolean useHdr) ->
context, new PeriodicVignetteProcessor(
useHdr, context,
bundle.getFloat(ConfigurationActivity.PERIODIC_VIGNETTE_CENTER_X), useHdr,
bundle.getFloat(ConfigurationActivity.PERIODIC_VIGNETTE_CENTER_Y), bundle.getFloat(ConfigurationActivity.PERIODIC_VIGNETTE_CENTER_X),
/* minInnerRadius= */ bundle.getFloat( bundle.getFloat(ConfigurationActivity.PERIODIC_VIGNETTE_CENTER_Y),
ConfigurationActivity.PERIODIC_VIGNETTE_INNER_RADIUS), /* minInnerRadius= */ bundle.getFloat(
/* maxInnerRadius= */ bundle.getFloat( ConfigurationActivity.PERIODIC_VIGNETTE_INNER_RADIUS),
ConfigurationActivity.PERIODIC_VIGNETTE_OUTER_RADIUS), /* maxInnerRadius= */ bundle.getFloat(
bundle.getFloat(ConfigurationActivity.PERIODIC_VIGNETTE_OUTER_RADIUS))); ConfigurationActivity.PERIODIC_VIGNETTE_OUTER_RADIUS),
bundle.getFloat(ConfigurationActivity.PERIODIC_VIGNETTE_OUTER_RADIUS)));
} }
if (selectedEffects[3]) { if (selectedEffects[3]) {
effects.add(MatrixTransformationFactory.createSpin3dEffect()); effects.add(MatrixTransformationFactory.createSpin3dEffect());
} }
if (selectedEffects[4]) { if (selectedEffects[4]) {
effects.add(BitmapOverlayProcessor::new); effects.add((GlEffect) BitmapOverlayProcessor::new);
} }
if (selectedEffects[5]) { if (selectedEffects[5]) {
effects.add(MatrixTransformationFactory.createZoomInTransition()); effects.add(MatrixTransformationFactory.createZoomInTransition());

View File

@ -295,7 +295,7 @@ public final class GlEffectsFrameProcessorPixelTest {
"processData_withManyComposedMatrixTransformations_producesSameOutputAsCombinedTransformation"; "processData_withManyComposedMatrixTransformations_producesSameOutputAsCombinedTransformation";
Crop centerCrop = Crop centerCrop =
new Crop(/* left= */ -0.5f, /* right= */ 0.5f, /* bottom= */ -0.5f, /* top= */ 0.5f); new Crop(/* left= */ -0.5f, /* right= */ 0.5f, /* bottom= */ -0.5f, /* top= */ 0.5f);
ImmutableList.Builder<GlEffect> full10StepRotationAndCenterCrop = new ImmutableList.Builder<>(); ImmutableList.Builder<Effect> full10StepRotationAndCenterCrop = new ImmutableList.Builder<>();
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
full10StepRotationAndCenterCrop.add(new Rotation(/* degrees= */ 36)); full10StepRotationAndCenterCrop.add(new Rotation(/* degrees= */ 36));
} }
@ -336,7 +336,7 @@ public final class GlEffectsFrameProcessorPixelTest {
setUpAndPrepareFirstFrame(pixelWidthHeightRatio, asList(effects)); setUpAndPrepareFirstFrame(pixelWidthHeightRatio, asList(effects));
} }
private void setUpAndPrepareFirstFrame(float pixelWidthHeightRatio, List<GlEffect> effects) private void setUpAndPrepareFirstFrame(float pixelWidthHeightRatio, List<Effect> effects)
throws Exception { throws Exception {
// Set up the extractor to read the first video frame and get its format. // Set up the extractor to read the first video frame and get its format.
MediaExtractor mediaExtractor = new MediaExtractor(); MediaExtractor mediaExtractor = new MediaExtractor();

View File

@ -0,0 +1,20 @@
/*
* Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.transformer;
/** Marker interface for a video frame effect. */
public interface Effect {}

View File

@ -23,7 +23,7 @@ import java.util.List;
/** /**
* Interface for a frame processor that applies changes to individual video frames. * Interface for a frame processor that applies changes to individual video frames.
* *
* <p>The changes are specified by {@link GlEffect} instances passed to the {@link Factory}. * <p>The changes are specified by {@link Effect} instances passed to the {@link Factory}.
* *
* <p>The frame processor manages its input {@link Surface} which can be accessed via {@link * <p>The frame processor manages its input {@link Surface} which can be accessed via {@link
* #getInputSurface()}. The output {@link Surface} must be set by the caller using {@link * #getInputSurface()}. The output {@link Surface} must be set by the caller using {@link
@ -42,7 +42,7 @@ public interface FrameProcessor {
* *
* @param context A {@link Context}. * @param context A {@link Context}.
* @param listener A {@link Listener}. * @param listener A {@link Listener}.
* @param effects The {@link GlEffect} instances to apply to each frame. * @param effects The {@link Effect} instances 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.
* @return A new instance. * @return A new instance.
@ -52,7 +52,7 @@ public interface FrameProcessor {
FrameProcessor create( FrameProcessor create(
Context context, Context context,
FrameProcessor.Listener listener, FrameProcessor.Listener listener,
List<GlEffect> effects, List<Effect> effects,
DebugViewProvider debugViewProvider, DebugViewProvider debugViewProvider,
boolean useHdr) boolean useHdr)
throws FrameProcessingException; throws FrameProcessingException;

View File

@ -24,7 +24,7 @@ import android.content.Context;
* #toGlTextureProcessor(Context, boolean) converted} to a {@link GlTextureProcessor} which applies * #toGlTextureProcessor(Context, boolean) converted} to a {@link GlTextureProcessor} which applies
* the effect. * the effect.
*/ */
public interface GlEffect { public interface GlEffect extends Effect {
/** /**
* Returns a {@link SingleFrameGlTextureProcessor} that applies the effect. * Returns a {@link SingleFrameGlTextureProcessor} that applies the effect.

View File

@ -15,6 +15,7 @@
*/ */
package com.google.android.exoplayer2.transformer; package com.google.android.exoplayer2.transformer;
import static com.google.android.exoplayer2.util.Assertions.checkArgument;
import static com.google.android.exoplayer2.util.Assertions.checkState; import static com.google.android.exoplayer2.util.Assertions.checkState;
import static com.google.android.exoplayer2.util.Assertions.checkStateNotNull; import static com.google.android.exoplayer2.util.Assertions.checkStateNotNull;
import static com.google.common.collect.Iterables.getLast; import static com.google.common.collect.Iterables.getLast;
@ -51,13 +52,15 @@ public final class GlEffectsFrameProcessor implements FrameProcessor {
/** /**
* {@inheritDoc} * {@inheritDoc}
* *
* <p>All {@link Effect} instances must be {@link GlEffect} instances.
*
* <p>Using HDR requires the {@code EXT_YUV_target} OpenGL extension. * <p>Using HDR requires the {@code EXT_YUV_target} OpenGL extension.
*/ */
@Override @Override
public GlEffectsFrameProcessor create( public GlEffectsFrameProcessor create(
Context context, Context context,
FrameProcessor.Listener listener, FrameProcessor.Listener listener,
List<GlEffect> effects, List<Effect> effects,
DebugViewProvider debugViewProvider, DebugViewProvider debugViewProvider,
boolean useHdr) boolean useHdr)
throws FrameProcessingException { throws FrameProcessingException {
@ -91,6 +94,8 @@ public final class GlEffectsFrameProcessor implements FrameProcessor {
* GlTextureProcessor} instances corresponding to the {@link GlEffect} instances, and returns a * GlTextureProcessor} instances corresponding to the {@link GlEffect} instances, and returns a
* new {@code GlEffectsFrameProcessor}. * new {@code GlEffectsFrameProcessor}.
* *
* <p>All {@link Effect} instances must be {@link GlEffect} instances.
*
* <p>This method must be executed using the {@code singleThreadExecutorService}, as later OpenGL * <p>This method must be executed using the {@code singleThreadExecutorService}, as later OpenGL
* commands will be called on that thread. * commands will be called on that thread.
*/ */
@ -98,7 +103,7 @@ public final class GlEffectsFrameProcessor implements FrameProcessor {
private static GlEffectsFrameProcessor createOpenGlObjectsAndFrameProcessor( private static GlEffectsFrameProcessor createOpenGlObjectsAndFrameProcessor(
Context context, Context context,
FrameProcessor.Listener listener, FrameProcessor.Listener listener,
List<GlEffect> effects, List<Effect> effects,
DebugViewProvider debugViewProvider, DebugViewProvider debugViewProvider,
boolean useHdr, boolean useHdr,
ExecutorService singleThreadExecutorService) ExecutorService singleThreadExecutorService)
@ -140,13 +145,15 @@ public final class GlEffectsFrameProcessor implements FrameProcessor {
* MatrixTransformationProcessor} and converts all other {@link GlEffect} instances to separate * MatrixTransformationProcessor} and converts all other {@link GlEffect} instances to separate
* {@link GlTextureProcessor} instances. * {@link GlTextureProcessor} instances.
* *
* <p>All {@link Effect} instances must be {@link GlEffect} instances.
*
* @return A non-empty list of {@link GlTextureProcessor} instances to apply in the given order. * @return A non-empty list of {@link GlTextureProcessor} instances to apply in the given order.
* The first is an {@link ExternalTextureProcessor} and the last is a {@link * The first is an {@link ExternalTextureProcessor} and the last is a {@link
* FinalMatrixTransformationProcessorWrapper}. * FinalMatrixTransformationProcessorWrapper}.
*/ */
private static ImmutableList<GlTextureProcessor> getGlTextureProcessorsForGlEffects( private static ImmutableList<GlTextureProcessor> getGlTextureProcessorsForGlEffects(
Context context, Context context,
List<GlEffect> effects, List<Effect> effects,
EGLDisplay eglDisplay, EGLDisplay eglDisplay,
EGLContext eglContext, EGLContext eglContext,
FrameProcessor.Listener listener, FrameProcessor.Listener listener,
@ -159,9 +166,11 @@ public final class GlEffectsFrameProcessor implements FrameProcessor {
new ImmutableList.Builder<>(); new ImmutableList.Builder<>();
boolean sampleFromExternalTexture = true; boolean sampleFromExternalTexture = true;
for (int i = 0; i < effects.size(); i++) { for (int i = 0; i < effects.size(); i++) {
GlEffect effect = effects.get(i); Effect effect = effects.get(i);
if (effect instanceof GlMatrixTransformation) { checkArgument(effect instanceof GlEffect, "GlEffectsFrameProcessor only supports GlEffects");
matrixTransformationListBuilder.add((GlMatrixTransformation) effect); GlEffect glEffect = (GlEffect) effect;
if (glEffect instanceof GlMatrixTransformation) {
matrixTransformationListBuilder.add((GlMatrixTransformation) glEffect);
continue; continue;
} }
ImmutableList<GlMatrixTransformation> matrixTransformations = ImmutableList<GlMatrixTransformation> matrixTransformations =
@ -177,7 +186,7 @@ public final class GlEffectsFrameProcessor implements FrameProcessor {
matrixTransformationListBuilder = new ImmutableList.Builder<>(); matrixTransformationListBuilder = new ImmutableList.Builder<>();
sampleFromExternalTexture = false; sampleFromExternalTexture = false;
} }
textureProcessorListBuilder.add(effect.toGlTextureProcessor(context, useHdr)); textureProcessorListBuilder.add(glEffect.toGlTextureProcessor(context, useHdr));
} }
textureProcessorListBuilder.add( textureProcessorListBuilder.add(
new FinalMatrixTransformationProcessorWrapper( new FinalMatrixTransformationProcessorWrapper(

View File

@ -101,7 +101,7 @@ public final class Transformer {
private boolean removeVideo; private boolean removeVideo;
private String containerMimeType; private String containerMimeType;
private TransformationRequest transformationRequest; private TransformationRequest transformationRequest;
private ImmutableList<GlEffect> videoEffects; private ImmutableList<Effect> videoEffects;
private FrameProcessor.Factory frameProcessorFactory; private FrameProcessor.Factory frameProcessorFactory;
private ListenerSet<Transformer.Listener> listeners; private ListenerSet<Transformer.Listener> listeners;
private DebugViewProvider debugViewProvider; private DebugViewProvider debugViewProvider;
@ -166,32 +166,36 @@ public final class Transformer {
} }
/** /**
* Sets the {@linkplain GlEffect effects} to apply to each video frame. * Sets the {@link Effect} instances to apply to each video frame.
* *
* <p>The {@linkplain GlEffect effects} are applied before any {@linkplain * <p>The {@link Effect} instances are applied before any {@linkplain
* TransformationRequest.Builder#setScale(float, float) scale}, {@linkplain * TransformationRequest.Builder#setScale(float, float) scale}, {@linkplain
* TransformationRequest.Builder#setRotationDegrees(float) rotation}, or {@linkplain * TransformationRequest.Builder#setRotationDegrees(float) rotation}, or {@linkplain
* TransformationRequest.Builder#setResolution(int) resolution} changes specified in the {@link * TransformationRequest.Builder#setResolution(int) resolution} changes specified in the {@link
* #setTransformationRequest(TransformationRequest) TransformationRequest} but after {@linkplain * #setTransformationRequest(TransformationRequest) TransformationRequest} but after {@linkplain
* TransformationRequest.Builder#setFlattenForSlowMotion(boolean) slow-motion flattening}. * TransformationRequest.Builder#setFlattenForSlowMotion(boolean) slow-motion flattening}.
* *
* @param effects The {@linkplain GlEffect effects} to apply to each video frame. * <p>The default {@link FrameProcessor} only supports {@link GlEffect} instances. To use other
* effects, call {@link #setFrameProcessorFactory(FrameProcessor.Factory)} with a custom {@link
* FrameProcessor.Factory}.
*
* @param effects The {@link Effect} instances to apply to each video frame.
* @return This builder. * @return This builder.
*/ */
@CanIgnoreReturnValue @CanIgnoreReturnValue
public Builder setVideoEffects(List<GlEffect> effects) { public Builder setVideoEffects(List<Effect> effects) {
this.videoEffects = ImmutableList.copyOf(effects); this.videoEffects = ImmutableList.copyOf(effects);
return this; return this;
} }
/** /**
* Sets the {@link FrameProcessor.Factory} for the {@link FrameProcessor} to use when applying * Sets the {@link FrameProcessor.Factory} for the {@link FrameProcessor} to use when applying
* {@linkplain GlEffect effects} to the video frames. * {@linkplain Effect effects} to the video frames.
* *
* <p>This factory will be used to create the {@link FrameProcessor} used for applying the * <p>This factory will be used to create the {@link FrameProcessor} used for applying the
* {@link GlEffect} instances passed to {@link #setVideoEffects(List<GlEffect>)} and any * {@link Effect} instances passed to {@link #setVideoEffects(List<Effect>)} and any additional
* additional {@link GlMatrixTransformation} instances derived from the {@link * {@link GlMatrixTransformation} instances derived from the {@link TransformationRequest} set
* TransformationRequest} set using {@link #setTransformationRequest(TransformationRequest)}. * using {@link #setTransformationRequest(TransformationRequest)}.
* *
* <p>The default is {@link GlEffectsFrameProcessor.Factory}. * <p>The default is {@link GlEffectsFrameProcessor.Factory}.
* *
@ -569,7 +573,7 @@ public final class Transformer {
private final boolean removeVideo; private final boolean removeVideo;
private final String containerMimeType; private final String containerMimeType;
private final TransformationRequest transformationRequest; private final TransformationRequest transformationRequest;
private final ImmutableList<GlEffect> videoEffects; private final ImmutableList<Effect> videoEffects;
private final FrameProcessor.Factory frameProcessorFactory; private final FrameProcessor.Factory frameProcessorFactory;
private final Looper looper; private final Looper looper;
private final Clock clock; private final Clock clock;
@ -591,7 +595,7 @@ public final class Transformer {
boolean removeVideo, boolean removeVideo,
String containerMimeType, String containerMimeType,
TransformationRequest transformationRequest, TransformationRequest transformationRequest,
ImmutableList<GlEffect> videoEffects, ImmutableList<Effect> videoEffects,
FrameProcessor.Factory frameProcessorFactory, FrameProcessor.Factory frameProcessorFactory,
ListenerSet<Transformer.Listener> listeners, ListenerSet<Transformer.Listener> listeners,
Looper looper, Looper looper,
@ -872,7 +876,7 @@ public final class Transformer {
private final boolean removeVideo; private final boolean removeVideo;
private final TransformationRequest transformationRequest; private final TransformationRequest transformationRequest;
private final boolean clippingStartsAtKeyFrame; private final boolean clippingStartsAtKeyFrame;
private final ImmutableList<GlEffect> videoEffects; private final ImmutableList<Effect> videoEffects;
private final FrameProcessor.Factory frameProcessorFactory; private final FrameProcessor.Factory frameProcessorFactory;
private final Codec.EncoderFactory encoderFactory; private final Codec.EncoderFactory encoderFactory;
private final Codec.DecoderFactory decoderFactory; private final Codec.DecoderFactory decoderFactory;
@ -887,7 +891,7 @@ public final class Transformer {
boolean removeVideo, boolean removeVideo,
TransformationRequest transformationRequest, TransformationRequest transformationRequest,
boolean clippingStartsAtKeyFrame, boolean clippingStartsAtKeyFrame,
ImmutableList<GlEffect> videoEffects, ImmutableList<Effect> videoEffects,
FrameProcessor.Factory frameProcessorFactory, FrameProcessor.Factory frameProcessorFactory,
Codec.EncoderFactory encoderFactory, Codec.EncoderFactory encoderFactory,
Codec.DecoderFactory decoderFactory, Codec.DecoderFactory decoderFactory,

View File

@ -38,7 +38,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
private final Context context; private final Context context;
private final boolean clippingStartsAtKeyFrame; private final boolean clippingStartsAtKeyFrame;
private final ImmutableList<GlEffect> effects; private final ImmutableList<Effect> effects;
private final FrameProcessor.Factory frameProcessorFactory; private final FrameProcessor.Factory frameProcessorFactory;
private final Codec.EncoderFactory encoderFactory; private final Codec.EncoderFactory encoderFactory;
private final Codec.DecoderFactory decoderFactory; private final Codec.DecoderFactory decoderFactory;
@ -53,7 +53,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
TransformerMediaClock mediaClock, TransformerMediaClock mediaClock,
TransformationRequest transformationRequest, TransformationRequest transformationRequest,
boolean clippingStartsAtKeyFrame, boolean clippingStartsAtKeyFrame,
ImmutableList<GlEffect> effects, ImmutableList<Effect> effects,
FrameProcessor.Factory frameProcessorFactory, FrameProcessor.Factory frameProcessorFactory,
Codec.EncoderFactory encoderFactory, Codec.EncoderFactory encoderFactory,
Codec.DecoderFactory decoderFactory, Codec.DecoderFactory decoderFactory,

View File

@ -57,7 +57,7 @@ import org.checkerframework.dataflow.qual.Pure;
Format inputFormat, Format inputFormat,
long streamOffsetUs, long streamOffsetUs,
TransformationRequest transformationRequest, TransformationRequest transformationRequest,
ImmutableList<GlEffect> effects, ImmutableList<Effect> effects,
FrameProcessor.Factory frameProcessorFactory, FrameProcessor.Factory frameProcessorFactory,
Codec.DecoderFactory decoderFactory, Codec.DecoderFactory decoderFactory,
Codec.EncoderFactory encoderFactory, Codec.EncoderFactory encoderFactory,
@ -78,8 +78,8 @@ import org.checkerframework.dataflow.qual.Pure;
int decodedHeight = int decodedHeight =
(inputFormat.rotationDegrees % 180 == 0) ? inputFormat.height : inputFormat.width; (inputFormat.rotationDegrees % 180 == 0) ? inputFormat.height : inputFormat.width;
ImmutableList.Builder<GlEffect> effectsListBuilder = ImmutableList.Builder<Effect> effectsListBuilder =
new ImmutableList.Builder<GlEffect>().addAll(effects); new ImmutableList.Builder<Effect>().addAll(effects);
if (transformationRequest.scaleX != 1f if (transformationRequest.scaleX != 1f
|| transformationRequest.scaleY != 1f || transformationRequest.scaleY != 1f
|| transformationRequest.rotationDegrees != 0f) { || transformationRequest.rotationDegrees != 0f) {
@ -136,7 +136,7 @@ import org.checkerframework.dataflow.qual.Pure;
debugViewProvider, debugViewProvider,
// HDR is only used if the MediaCodec encoder supports FEATURE_HdrEditing. This // 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 // implies that the OpenGL EXT_YUV_target extension is supported and hence the
// GlEffectsFrameProcessor also supports HDR. // default FrameProcessor, GlEffectsFrameProcessor, also supports HDR.
/* useHdr= */ encoderWrapper.isHdrEditingEnabled()); /* useHdr= */ encoderWrapper.isHdrEditingEnabled());
} catch (FrameProcessingException e) { } catch (FrameProcessingException e) {
throw TransformationException.createForFrameProcessingException( throw TransformationException.createForFrameProcessingException(