Compositor: Add VideoCompositorSettings to Composition.

This allows apps using Transformer to customize how a Composition is used.

PiperOrigin-RevId: 567633129
This commit is contained in:
huangdarwin 2023-09-22 08:48:48 -07:00 committed by Copybara-Service
parent 42d9879d47
commit ba8c85a277
9 changed files with 141 additions and 8 deletions

View File

@ -32,11 +32,14 @@ import android.content.Context;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import androidx.media3.common.Effect; import androidx.media3.common.Effect;
import androidx.media3.common.MediaItem; import androidx.media3.common.MediaItem;
import androidx.media3.common.util.Size;
import androidx.media3.common.util.Util; import androidx.media3.common.util.Util;
import androidx.media3.effect.AlphaScale; import androidx.media3.effect.AlphaScale;
import androidx.media3.effect.Contrast; import androidx.media3.effect.Contrast;
import androidx.media3.effect.OverlaySettings;
import androidx.media3.effect.Presentation; import androidx.media3.effect.Presentation;
import androidx.media3.effect.ScaleAndRotateTransformation; import androidx.media3.effect.ScaleAndRotateTransformation;
import androidx.media3.effect.VideoCompositorSettings;
import androidx.test.core.app.ApplicationProvider; import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
@ -49,6 +52,9 @@ import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
public final class TransformerMultiSequenceCompositionTest { public final class TransformerMultiSequenceCompositionTest {
// Bitmaps are generated on a Pixel 6 or 7 Pro instead of an emulator, due to an emulator bug.
// TODO: b/301242589 - Fix this test on the crow emulator, and re-generate bitmaps using the crow
// emulator, for consistency with other pixel tests.
private static final String PNG_ASSET_BASE_PATH = private static final String PNG_ASSET_BASE_PATH =
"media/bitmap/transformer_multi_sequence_composition_test"; "media/bitmap/transformer_multi_sequence_composition_test";
@ -86,7 +92,8 @@ public final class TransformerMultiSequenceCompositionTest {
.build()))), .build()))),
/* secondSequenceMediaItems= */ ImmutableList.of( /* secondSequenceMediaItems= */ ImmutableList.of(
editedMediaItemByClippingVideo( editedMediaItemByClippingVideo(
MP4_ASSET_URI_STRING, /* effects= */ ImmutableList.of()))); MP4_ASSET_URI_STRING, /* effects= */ ImmutableList.of())),
VideoCompositorSettings.DEFAULT);
ExportTestResult result = ExportTestResult result =
new TransformerAndroidTestRunner.Builder(context, new Transformer.Builder(context).build()) new TransformerAndroidTestRunner.Builder(context, new Transformer.Builder(context).build())
@ -125,7 +132,70 @@ public final class TransformerMultiSequenceCompositionTest {
.build()))), .build()))),
/* secondSequenceMediaItems= */ ImmutableList.of( /* secondSequenceMediaItems= */ ImmutableList.of(
editedMediaItemOfOneFrameImage( editedMediaItemOfOneFrameImage(
JPG_ASSET_URI_STRING, /* effects= */ ImmutableList.of()))); JPG_ASSET_URI_STRING, /* effects= */ ImmutableList.of())),
VideoCompositorSettings.DEFAULT);
ExportTestResult result =
new TransformerAndroidTestRunner.Builder(context, new Transformer.Builder(context).build())
.build()
.run(testId, composition);
assertThat(result.filePath).isNotNull();
assertBitmapsMatchExpected(
extractBitmapsFromVideo(context, checkNotNull(result.filePath)), testId);
}
@Test
public void export_withTwoSequencesWithVideoCompositorSettings_succeeds() throws Exception {
String testId = "export_withTwoSequencesWithVideoCompositorSettings_succeeds";
if (AndroidTestUtil.skipAndLogIfFormatsUnsupported(
context,
testId,
/* inputFormat= */ MP4_ASSET_FORMAT,
/* outputFormat= */ MP4_ASSET_FORMAT)) {
return;
}
VideoCompositorSettings pictureInPictureVideoCompositorSettings =
new VideoCompositorSettings() {
@Override
public Size getOutputSize(List<Size> inputSizes) {
return inputSizes.get(0);
}
@Override
public OverlaySettings getOverlaySettings(int inputId, long presentationTimeUs) {
if (inputId == 0) {
// This tests all OverlaySettings builder variables.
return new OverlaySettings.Builder()
.setScale(.25f, .25f)
.setOverlayFrameAnchor(1, -1)
.setBackgroundFrameAnchor(.9f, -.7f)
.build();
} else {
return new OverlaySettings.Builder().build();
}
}
};
Composition composition =
createComposition(
/* compositionEffects= */ ImmutableList.of(
new Contrast(0.1f),
Presentation.createForWidthAndHeight(
EXPORT_WIDTH, EXPORT_HEIGHT, Presentation.LAYOUT_SCALE_TO_FIT)),
/* firstSequenceMediaItems= */ ImmutableList.of(
editedMediaItemByClippingVideo(
MP4_ASSET_URI_STRING,
/* effects= */ ImmutableList.of(
new AlphaScale(0.5f),
new ScaleAndRotateTransformation.Builder()
.setRotationDegrees(180)
.build()))),
/* secondSequenceMediaItems= */ ImmutableList.of(
editedMediaItemByClippingVideo(
MP4_ASSET_URI_STRING, /* effects= */ ImmutableList.of())),
pictureInPictureVideoCompositorSettings);
ExportTestResult result = ExportTestResult result =
new TransformerAndroidTestRunner.Builder(context, new Transformer.Builder(context).build()) new TransformerAndroidTestRunner.Builder(context, new Transformer.Builder(context).build())
@ -165,7 +235,8 @@ public final class TransformerMultiSequenceCompositionTest {
private static Composition createComposition( private static Composition createComposition(
List<Effect> compositionEffects, List<Effect> compositionEffects,
List<EditedMediaItem> firstSequenceMediaItems, List<EditedMediaItem> firstSequenceMediaItems,
List<EditedMediaItem> secondSequenceMediaItems) { List<EditedMediaItem> secondSequenceMediaItems,
VideoCompositorSettings videoCompositorSettings) {
return new Composition.Builder( return new Composition.Builder(
ImmutableList.of( ImmutableList.of(
@ -174,6 +245,7 @@ public final class TransformerMultiSequenceCompositionTest {
.setEffects( .setEffects(
new Effects( new Effects(
/* audioProcessors= */ ImmutableList.of(), /* videoEffects= */ compositionEffects)) /* audioProcessors= */ ImmutableList.of(), /* videoEffects= */ compositionEffects))
.setVideoCompositorSettings(videoCompositorSettings)
.build(); .build();
} }
@ -181,12 +253,11 @@ public final class TransformerMultiSequenceCompositionTest {
throws IOException { throws IOException {
for (int i = 0; i < actualBitmaps.size(); i++) { for (int i = 0; i < actualBitmaps.size(); i++) {
Bitmap actualBitmap = actualBitmaps.get(i); Bitmap actualBitmap = actualBitmaps.get(i);
maybeSaveTestBitmap(
testId, /* bitmapLabel= */ String.valueOf(i), actualBitmap, /* path= */ null);
String subTestId = testId + "_" + i; String subTestId = testId + "_" + i;
Bitmap expectedBitmap = Bitmap expectedBitmap =
readBitmap(Util.formatInvariant("%s/%s.png", PNG_ASSET_BASE_PATH, subTestId)); readBitmap(Util.formatInvariant("%s/%s.png", PNG_ASSET_BASE_PATH, subTestId));
maybeSaveTestBitmap(
testId, /* bitmapLabel= */ String.valueOf(i), actualBitmap, /* path= */ null);
float averagePixelAbsoluteDifference = float averagePixelAbsoluteDifference =
getBitmapAveragePixelAbsoluteDifferenceArgb8888(expectedBitmap, actualBitmap, subTestId); getBitmapAveragePixelAbsoluteDifferenceArgb8888(expectedBitmap, actualBitmap, subTestId);
assertThat(averagePixelAbsoluteDifference) assertThat(averagePixelAbsoluteDifference)

View File

@ -23,6 +23,7 @@ import androidx.annotation.IntDef;
import androidx.media3.common.MediaItem; import androidx.media3.common.MediaItem;
import androidx.media3.common.audio.AudioProcessor; import androidx.media3.common.audio.AudioProcessor;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
import androidx.media3.effect.VideoCompositorSettings;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
@ -43,6 +44,7 @@ public final class Composition {
public static final class Builder { public static final class Builder {
private ImmutableList<EditedMediaItemSequence> sequences; private ImmutableList<EditedMediaItemSequence> sequences;
private VideoCompositorSettings videoCompositorSettings;
private Effects effects; private Effects effects;
private boolean forceAudioTrack; private boolean forceAudioTrack;
private boolean transmuxAudio; private boolean transmuxAudio;
@ -69,12 +71,14 @@ public final class Composition {
!sequences.isEmpty(), !sequences.isEmpty(),
"The composition must contain at least one EditedMediaItemSequence."); "The composition must contain at least one EditedMediaItemSequence.");
this.sequences = ImmutableList.copyOf(sequences); this.sequences = ImmutableList.copyOf(sequences);
videoCompositorSettings = VideoCompositorSettings.DEFAULT;
effects = Effects.EMPTY; effects = Effects.EMPTY;
} }
/** Creates a new instance to build upon the provided {@link Composition}. */ /** Creates a new instance to build upon the provided {@link Composition}. */
private Builder(Composition composition) { private Builder(Composition composition) {
sequences = composition.sequences; sequences = composition.sequences;
videoCompositorSettings = composition.videoCompositorSettings;
effects = composition.effects; effects = composition.effects;
forceAudioTrack = composition.forceAudioTrack; forceAudioTrack = composition.forceAudioTrack;
transmuxAudio = composition.transmuxAudio; transmuxAudio = composition.transmuxAudio;
@ -82,6 +86,20 @@ public final class Composition {
hdrMode = composition.hdrMode; hdrMode = composition.hdrMode;
} }
/**
* Sets the {@link VideoCompositorSettings} to apply to the {@link Composition}.
*
* <p>The default value is {@link VideoCompositorSettings#DEFAULT}.
*
* @param videoCompositorSettings The {@link VideoCompositorSettings}.
* @return This builder.
*/
@CanIgnoreReturnValue
public Builder setVideoCompositorSettings(VideoCompositorSettings videoCompositorSettings) {
this.videoCompositorSettings = videoCompositorSettings;
return this;
}
/** /**
* Sets the {@link Effects} to apply to the {@link Composition}. * Sets the {@link Effects} to apply to the {@link Composition}.
* *
@ -207,7 +225,13 @@ public final class Composition {
/** Builds a {@link Composition} instance. */ /** Builds a {@link Composition} instance. */
public Composition build() { public Composition build() {
return new Composition( return new Composition(
sequences, effects, forceAudioTrack, transmuxAudio, transmuxVideo, hdrMode); sequences,
videoCompositorSettings,
effects,
forceAudioTrack,
transmuxAudio,
transmuxVideo,
hdrMode);
} }
/** /**
@ -309,6 +333,9 @@ public final class Composition {
*/ */
public final ImmutableList<EditedMediaItemSequence> sequences; public final ImmutableList<EditedMediaItemSequence> sequences;
/** The {@link VideoCompositorSettings} to apply to the composition. */
public final VideoCompositorSettings videoCompositorSettings;
/** The {@link Effects} to apply to the composition. */ /** The {@link Effects} to apply to the composition. */
public final Effects effects; public final Effects effects;
@ -347,6 +374,7 @@ public final class Composition {
private Composition( private Composition(
List<EditedMediaItemSequence> sequences, List<EditedMediaItemSequence> sequences,
VideoCompositorSettings videoCompositorSettings,
Effects effects, Effects effects,
boolean forceAudioTrack, boolean forceAudioTrack,
boolean transmuxAudio, boolean transmuxAudio,
@ -356,6 +384,7 @@ public final class Composition {
!transmuxAudio || !forceAudioTrack, !transmuxAudio || !forceAudioTrack,
"Audio transmuxing and audio track forcing are not allowed together."); "Audio transmuxing and audio track forcing are not allowed together.");
this.sequences = ImmutableList.copyOf(sequences); this.sequences = ImmutableList.copyOf(sequences);
this.videoCompositorSettings = videoCompositorSettings;
this.effects = effects; this.effects = effects;
this.transmuxAudio = transmuxAudio; this.transmuxAudio = transmuxAudio;
this.transmuxVideo = transmuxVideo; this.transmuxVideo = transmuxVideo;

View File

@ -72,6 +72,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
DebugViewProvider debugViewProvider, DebugViewProvider debugViewProvider,
Listener listener, Listener listener,
Executor listenerExecutor, Executor listenerExecutor,
VideoCompositorSettings videoCompositorSettings,
List<Effect> compositionEffects, List<Effect> compositionEffects,
long initialTimestampOffsetUs) { long initialTimestampOffsetUs) {
return new MultipleInputVideoGraph( return new MultipleInputVideoGraph(
@ -81,6 +82,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
debugViewProvider, debugViewProvider,
listener, listener,
listenerExecutor, listenerExecutor,
videoCompositorSettings,
compositionEffects, compositionEffects,
initialTimestampOffsetUs); initialTimestampOffsetUs);
} }
@ -99,6 +101,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
private final DebugViewProvider debugViewProvider; private final DebugViewProvider debugViewProvider;
private final Listener listener; private final Listener listener;
private final Executor listenerExecutor; private final Executor listenerExecutor;
private final VideoCompositorSettings videoCompositorSettings;
private final List<Effect> compositionEffects; private final List<Effect> compositionEffects;
private final List<VideoFrameProcessingWrapper> preProcessingWrappers; private final List<VideoFrameProcessingWrapper> preProcessingWrappers;
@ -128,6 +131,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
DebugViewProvider debugViewProvider, DebugViewProvider debugViewProvider,
Listener listener, Listener listener,
Executor listenerExecutor, Executor listenerExecutor,
VideoCompositorSettings videoCompositorSettings,
List<Effect> compositionEffects, List<Effect> compositionEffects,
long initialTimestampOffsetUs) { long initialTimestampOffsetUs) {
this.context = context; this.context = context;
@ -136,6 +140,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
this.debugViewProvider = debugViewProvider; this.debugViewProvider = debugViewProvider;
this.listener = listener; this.listener = listener;
this.listenerExecutor = listenerExecutor; this.listenerExecutor = listenerExecutor;
this.videoCompositorSettings = videoCompositorSettings;
this.compositionEffects = new ArrayList<>(compositionEffects); this.compositionEffects = new ArrayList<>(compositionEffects);
this.initialTimestampOffsetUs = initialTimestampOffsetUs; this.initialTimestampOffsetUs = initialTimestampOffsetUs;
lastRenderedPresentationTimeUs = C.TIME_UNSET; lastRenderedPresentationTimeUs = C.TIME_UNSET;
@ -219,7 +224,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
new DefaultVideoCompositor( new DefaultVideoCompositor(
context, context,
glObjectsProvider, glObjectsProvider,
VideoCompositorSettings.DEFAULT, videoCompositorSettings,
sharedExecutorService, sharedExecutorService,
new VideoCompositor.Listener() { new VideoCompositor.Listener() {
// All of this listener's methods are called on the sharedExecutorService. // All of this listener's methods are called on the sharedExecutorService.

View File

@ -17,6 +17,7 @@
package androidx.media3.transformer; package androidx.media3.transformer;
import static androidx.media3.common.util.Assertions.checkNotNull; import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.common.util.Assertions.checkState;
import static androidx.media3.common.util.Assertions.checkStateNotNull; import static androidx.media3.common.util.Assertions.checkStateNotNull;
import android.content.Context; import android.content.Context;
@ -30,6 +31,7 @@ import androidx.media3.common.VideoFrameProcessingException;
import androidx.media3.common.VideoFrameProcessor; import androidx.media3.common.VideoFrameProcessor;
import androidx.media3.common.VideoGraph; import androidx.media3.common.VideoGraph;
import androidx.media3.effect.Presentation; import androidx.media3.effect.Presentation;
import androidx.media3.effect.VideoCompositorSettings;
import java.util.List; import java.util.List;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
@ -52,6 +54,11 @@ import java.util.concurrent.Executor;
private boolean released; private boolean released;
private volatile boolean hasProducedFrameWithTimestampZero; private volatile boolean hasProducedFrameWithTimestampZero;
/**
* Creates an instance.
*
* <p>{@code videoCompositorSettings} must be {@link VideoCompositorSettings#DEFAULT}.
*/
public SingleInputVideoGraph( public SingleInputVideoGraph(
Context context, Context context,
VideoFrameProcessor.Factory videoFrameProcessorFactory, VideoFrameProcessor.Factory videoFrameProcessorFactory,
@ -60,9 +67,14 @@ import java.util.concurrent.Executor;
Listener listener, Listener listener,
DebugViewProvider debugViewProvider, DebugViewProvider debugViewProvider,
Executor listenerExecutor, Executor listenerExecutor,
VideoCompositorSettings videoCompositorSettings,
boolean renderFramesAutomatically, boolean renderFramesAutomatically,
@Nullable Presentation presentation, @Nullable Presentation presentation,
long initialTimestampOffsetUs) { long initialTimestampOffsetUs) {
checkState(
VideoCompositorSettings.DEFAULT.equals(videoCompositorSettings),
"SingleInputVideoGraph does not use VideoCompositor, and therefore cannot apply"
+ " VideoCompositorSettings");
this.context = context; this.context = context;
this.videoFrameProcessorFactory = videoFrameProcessorFactory; this.videoFrameProcessorFactory = videoFrameProcessorFactory;
this.inputColorInfo = inputColorInfo; this.inputColorInfo = inputColorInfo;

View File

@ -582,6 +582,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
context, context,
firstAssetLoaderInputFormat, firstAssetLoaderInputFormat,
transformationRequest, transformationRequest,
composition.videoCompositorSettings,
composition.effects.videoEffects, composition.effects.videoEffects,
videoFrameProcessorFactory, videoFrameProcessorFactory,
encoderFactory, encoderFactory,

View File

@ -23,6 +23,7 @@ import androidx.media3.common.DebugViewProvider;
import androidx.media3.common.Effect; import androidx.media3.common.Effect;
import androidx.media3.common.VideoFrameProcessor; import androidx.media3.common.VideoFrameProcessor;
import androidx.media3.effect.Presentation; import androidx.media3.effect.Presentation;
import androidx.media3.effect.VideoCompositorSettings;
import java.util.List; import java.util.List;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
@ -46,6 +47,7 @@ import java.util.concurrent.Executor;
DebugViewProvider debugViewProvider, DebugViewProvider debugViewProvider,
Listener listener, Listener listener,
Executor listenerExecutor, Executor listenerExecutor,
VideoCompositorSettings videoCompositorSettings,
List<Effect> compositionEffects, List<Effect> compositionEffects,
long initialTimestampOffsetUs) { long initialTimestampOffsetUs) {
@Nullable Presentation presentation = null; @Nullable Presentation presentation = null;
@ -63,6 +65,7 @@ import java.util.concurrent.Executor;
listener, listener,
debugViewProvider, debugViewProvider,
listenerExecutor, listenerExecutor,
videoCompositorSettings,
/* renderFramesAutomatically= */ true, /* renderFramesAutomatically= */ true,
presentation, presentation,
initialTimestampOffsetUs); initialTimestampOffsetUs);
@ -77,6 +80,7 @@ import java.util.concurrent.Executor;
Listener listener, Listener listener,
DebugViewProvider debugViewProvider, DebugViewProvider debugViewProvider,
Executor listenerExecutor, Executor listenerExecutor,
VideoCompositorSettings videoCompositorSettings,
boolean renderFramesAutomatically, boolean renderFramesAutomatically,
@Nullable Presentation presentation, @Nullable Presentation presentation,
long initialTimestampOffsetUs) { long initialTimestampOffsetUs) {
@ -88,6 +92,7 @@ import java.util.concurrent.Executor;
listener, listener,
debugViewProvider, debugViewProvider,
listenerExecutor, listenerExecutor,
videoCompositorSettings,
renderFramesAutomatically, renderFramesAutomatically,
presentation, presentation,
initialTimestampOffsetUs); initialTimestampOffsetUs);

View File

@ -23,6 +23,7 @@ import androidx.media3.common.Effect;
import androidx.media3.common.VideoFrameProcessingException; import androidx.media3.common.VideoFrameProcessingException;
import androidx.media3.common.VideoFrameProcessor; import androidx.media3.common.VideoFrameProcessor;
import androidx.media3.common.VideoGraph; import androidx.media3.common.VideoGraph;
import androidx.media3.effect.VideoCompositorSettings;
import java.util.List; import java.util.List;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
@ -40,7 +41,10 @@ import java.util.concurrent.Executor;
* @param debugViewProvider A {@link DebugViewProvider}. * @param debugViewProvider A {@link DebugViewProvider}.
* @param listener A {@link Listener}. * @param listener A {@link Listener}.
* @param listenerExecutor The {@link Executor} on which the {@code listener} is invoked. * @param listenerExecutor The {@link Executor} on which the {@code listener} is invoked.
* @param videoCompositorSettings The {@link VideoCompositorSettings} to apply to the
* composition.
* @param compositionEffects A list of {@linkplain Effect effects} to apply to the composition. * @param compositionEffects A list of {@linkplain Effect effects} to apply to the composition.
* @param initialTimestampOffsetUs The timestamp offset for the first frame, in microseconds.
* @return A new instance. * @return A new instance.
* @throws VideoFrameProcessingException If a problem occurs while creating the {@link * @throws VideoFrameProcessingException If a problem occurs while creating the {@link
* VideoFrameProcessor}. * VideoFrameProcessor}.
@ -52,6 +56,7 @@ import java.util.concurrent.Executor;
DebugViewProvider debugViewProvider, DebugViewProvider debugViewProvider,
Listener listener, Listener listener,
Executor listenerExecutor, Executor listenerExecutor,
VideoCompositorSettings videoCompositorSettings,
List<Effect> compositionEffects, List<Effect> compositionEffects,
long initialTimestampOffsetUs) long initialTimestampOffsetUs)
throws VideoFrameProcessingException; throws VideoFrameProcessingException;

View File

@ -48,6 +48,7 @@ import androidx.media3.common.util.Log;
import androidx.media3.common.util.Util; import androidx.media3.common.util.Util;
import androidx.media3.decoder.DecoderInputBuffer; import androidx.media3.decoder.DecoderInputBuffer;
import androidx.media3.effect.DebugTraceUtil; import androidx.media3.effect.DebugTraceUtil;
import androidx.media3.effect.VideoCompositorSettings;
import androidx.media3.exoplayer.mediacodec.MediaCodecUtil; import androidx.media3.exoplayer.mediacodec.MediaCodecUtil;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.MoreExecutors; import com.google.common.util.concurrent.MoreExecutors;
@ -78,6 +79,7 @@ import org.checkerframework.dataflow.qual.Pure;
Context context, Context context,
Format firstInputFormat, Format firstInputFormat,
TransformationRequest transformationRequest, TransformationRequest transformationRequest,
VideoCompositorSettings videoCompositorSettings,
List<Effect> compositionEffects, List<Effect> compositionEffects,
VideoFrameProcessor.Factory videoFrameProcessorFactory, VideoFrameProcessor.Factory videoFrameProcessorFactory,
Codec.EncoderFactory encoderFactory, Codec.EncoderFactory encoderFactory,
@ -151,6 +153,7 @@ import org.checkerframework.dataflow.qual.Pure;
videoGraphOutputColor, videoGraphOutputColor,
errorConsumer, errorConsumer,
debugViewProvider, debugViewProvider,
videoCompositorSettings,
compositionEffects); compositionEffects);
videoGraph.initialize(); videoGraph.initialize();
} catch (VideoFrameProcessingException e) { } catch (VideoFrameProcessingException e) {
@ -477,6 +480,7 @@ import org.checkerframework.dataflow.qual.Pure;
ColorInfo videoFrameProcessorOutputColor, ColorInfo videoFrameProcessorOutputColor,
Consumer<ExportException> errorConsumer, Consumer<ExportException> errorConsumer,
DebugViewProvider debugViewProvider, DebugViewProvider debugViewProvider,
VideoCompositorSettings videoCompositorSettings,
List<Effect> compositionEffects) List<Effect> compositionEffects)
throws VideoFrameProcessingException { throws VideoFrameProcessingException {
this.errorConsumer = errorConsumer; this.errorConsumer = errorConsumer;
@ -493,6 +497,7 @@ import org.checkerframework.dataflow.qual.Pure;
debugViewProvider, debugViewProvider,
/* listener= */ thisRef, /* listener= */ thisRef,
/* listenerExecutor= */ MoreExecutors.directExecutor(), /* listenerExecutor= */ MoreExecutors.directExecutor(),
videoCompositorSettings,
compositionEffects, compositionEffects,
initialTimestampOffsetUs); initialTimestampOffsetUs);
} }