From ba8c85a277057f2b9249e3758b50c991be5c129b Mon Sep 17 00:00:00 2001 From: huangdarwin Date: Fri, 22 Sep 2023 08:48:48 -0700 Subject: [PATCH] Compositor: Add VideoCompositorSettings to Composition. This allows apps using Transformer to customize how a Composition is used. PiperOrigin-RevId: 567633129 --- ...WithVideoCompositorSettings_succeeds_0.png | Bin 0 -> 63806 bytes ...ansformerMultiSequenceCompositionTest.java | 83 ++++++++++++++++-- .../media3/transformer/Composition.java | 31 ++++++- .../transformer/MultipleInputVideoGraph.java | 7 +- .../transformer/SingleInputVideoGraph.java | 12 +++ .../transformer/TransformerInternal.java | 1 + .../TransformerSingleInputVideoGraph.java | 5 ++ .../transformer/TransformerVideoGraph.java | 5 ++ .../transformer/VideoSampleExporter.java | 5 ++ 9 files changed, 141 insertions(+), 8 deletions(-) create mode 100644 libraries/test_data/src/test/assets/media/bitmap/transformer_multi_sequence_composition_test/export_withTwoSequencesWithVideoCompositorSettings_succeeds_0.png diff --git a/libraries/test_data/src/test/assets/media/bitmap/transformer_multi_sequence_composition_test/export_withTwoSequencesWithVideoCompositorSettings_succeeds_0.png b/libraries/test_data/src/test/assets/media/bitmap/transformer_multi_sequence_composition_test/export_withTwoSequencesWithVideoCompositorSettings_succeeds_0.png new file mode 100644 index 0000000000000000000000000000000000000000..b8dc88a75e5ea7d6d7de1155863cb84eb12fa204 GIT binary patch literal 63806 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 CUjIV? literal 0 HcmV?d00001 diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerMultiSequenceCompositionTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerMultiSequenceCompositionTest.java index 956ee7421d..321e3b50df 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerMultiSequenceCompositionTest.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerMultiSequenceCompositionTest.java @@ -32,11 +32,14 @@ import android.content.Context; import android.graphics.Bitmap; import androidx.media3.common.Effect; import androidx.media3.common.MediaItem; +import androidx.media3.common.util.Size; import androidx.media3.common.util.Util; import androidx.media3.effect.AlphaScale; import androidx.media3.effect.Contrast; +import androidx.media3.effect.OverlaySettings; import androidx.media3.effect.Presentation; import androidx.media3.effect.ScaleAndRotateTransformation; +import androidx.media3.effect.VideoCompositorSettings; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.common.collect.ImmutableList; @@ -49,6 +52,9 @@ import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) 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 = "media/bitmap/transformer_multi_sequence_composition_test"; @@ -86,7 +92,8 @@ public final class TransformerMultiSequenceCompositionTest { .build()))), /* secondSequenceMediaItems= */ ImmutableList.of( editedMediaItemByClippingVideo( - MP4_ASSET_URI_STRING, /* effects= */ ImmutableList.of()))); + MP4_ASSET_URI_STRING, /* effects= */ ImmutableList.of())), + VideoCompositorSettings.DEFAULT); ExportTestResult result = new TransformerAndroidTestRunner.Builder(context, new Transformer.Builder(context).build()) @@ -125,7 +132,70 @@ public final class TransformerMultiSequenceCompositionTest { .build()))), /* secondSequenceMediaItems= */ ImmutableList.of( 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 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 = new TransformerAndroidTestRunner.Builder(context, new Transformer.Builder(context).build()) @@ -165,7 +235,8 @@ public final class TransformerMultiSequenceCompositionTest { private static Composition createComposition( List compositionEffects, List firstSequenceMediaItems, - List secondSequenceMediaItems) { + List secondSequenceMediaItems, + VideoCompositorSettings videoCompositorSettings) { return new Composition.Builder( ImmutableList.of( @@ -174,6 +245,7 @@ public final class TransformerMultiSequenceCompositionTest { .setEffects( new Effects( /* audioProcessors= */ ImmutableList.of(), /* videoEffects= */ compositionEffects)) + .setVideoCompositorSettings(videoCompositorSettings) .build(); } @@ -181,12 +253,11 @@ public final class TransformerMultiSequenceCompositionTest { throws IOException { for (int i = 0; i < actualBitmaps.size(); i++) { Bitmap actualBitmap = actualBitmaps.get(i); + maybeSaveTestBitmap( + testId, /* bitmapLabel= */ String.valueOf(i), actualBitmap, /* path= */ null); String subTestId = testId + "_" + i; Bitmap expectedBitmap = readBitmap(Util.formatInvariant("%s/%s.png", PNG_ASSET_BASE_PATH, subTestId)); - - maybeSaveTestBitmap( - testId, /* bitmapLabel= */ String.valueOf(i), actualBitmap, /* path= */ null); float averagePixelAbsoluteDifference = getBitmapAveragePixelAbsoluteDifferenceArgb8888(expectedBitmap, actualBitmap, subTestId); assertThat(averagePixelAbsoluteDifference) diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/Composition.java b/libraries/transformer/src/main/java/androidx/media3/transformer/Composition.java index 8f8c051b14..9e80b538d4 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/Composition.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/Composition.java @@ -23,6 +23,7 @@ import androidx.annotation.IntDef; import androidx.media3.common.MediaItem; import androidx.media3.common.audio.AudioProcessor; import androidx.media3.common.util.UnstableApi; +import androidx.media3.effect.VideoCompositorSettings; import com.google.common.collect.ImmutableList; import com.google.errorprone.annotations.CanIgnoreReturnValue; import java.lang.annotation.Documented; @@ -43,6 +44,7 @@ public final class Composition { public static final class Builder { private ImmutableList sequences; + private VideoCompositorSettings videoCompositorSettings; private Effects effects; private boolean forceAudioTrack; private boolean transmuxAudio; @@ -69,12 +71,14 @@ public final class Composition { !sequences.isEmpty(), "The composition must contain at least one EditedMediaItemSequence."); this.sequences = ImmutableList.copyOf(sequences); + videoCompositorSettings = VideoCompositorSettings.DEFAULT; effects = Effects.EMPTY; } /** Creates a new instance to build upon the provided {@link Composition}. */ private Builder(Composition composition) { sequences = composition.sequences; + videoCompositorSettings = composition.videoCompositorSettings; effects = composition.effects; forceAudioTrack = composition.forceAudioTrack; transmuxAudio = composition.transmuxAudio; @@ -82,6 +86,20 @@ public final class Composition { hdrMode = composition.hdrMode; } + /** + * Sets the {@link VideoCompositorSettings} to apply to the {@link Composition}. + * + *

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}. * @@ -207,7 +225,13 @@ public final class Composition { /** Builds a {@link Composition} instance. */ public Composition build() { 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 sequences; + /** The {@link VideoCompositorSettings} to apply to the composition. */ + public final VideoCompositorSettings videoCompositorSettings; + /** The {@link Effects} to apply to the composition. */ public final Effects effects; @@ -347,6 +374,7 @@ public final class Composition { private Composition( List sequences, + VideoCompositorSettings videoCompositorSettings, Effects effects, boolean forceAudioTrack, boolean transmuxAudio, @@ -356,6 +384,7 @@ public final class Composition { !transmuxAudio || !forceAudioTrack, "Audio transmuxing and audio track forcing are not allowed together."); this.sequences = ImmutableList.copyOf(sequences); + this.videoCompositorSettings = videoCompositorSettings; this.effects = effects; this.transmuxAudio = transmuxAudio; this.transmuxVideo = transmuxVideo; diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/MultipleInputVideoGraph.java b/libraries/transformer/src/main/java/androidx/media3/transformer/MultipleInputVideoGraph.java index cecfa85f66..6fedfce7a5 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/MultipleInputVideoGraph.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/MultipleInputVideoGraph.java @@ -72,6 +72,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; DebugViewProvider debugViewProvider, Listener listener, Executor listenerExecutor, + VideoCompositorSettings videoCompositorSettings, List compositionEffects, long initialTimestampOffsetUs) { return new MultipleInputVideoGraph( @@ -81,6 +82,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; debugViewProvider, listener, listenerExecutor, + videoCompositorSettings, compositionEffects, initialTimestampOffsetUs); } @@ -99,6 +101,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; private final DebugViewProvider debugViewProvider; private final Listener listener; private final Executor listenerExecutor; + private final VideoCompositorSettings videoCompositorSettings; private final List compositionEffects; private final List preProcessingWrappers; @@ -128,6 +131,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; DebugViewProvider debugViewProvider, Listener listener, Executor listenerExecutor, + VideoCompositorSettings videoCompositorSettings, List compositionEffects, long initialTimestampOffsetUs) { this.context = context; @@ -136,6 +140,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; this.debugViewProvider = debugViewProvider; this.listener = listener; this.listenerExecutor = listenerExecutor; + this.videoCompositorSettings = videoCompositorSettings; this.compositionEffects = new ArrayList<>(compositionEffects); this.initialTimestampOffsetUs = initialTimestampOffsetUs; lastRenderedPresentationTimeUs = C.TIME_UNSET; @@ -219,7 +224,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; new DefaultVideoCompositor( context, glObjectsProvider, - VideoCompositorSettings.DEFAULT, + videoCompositorSettings, sharedExecutorService, new VideoCompositor.Listener() { // All of this listener's methods are called on the sharedExecutorService. diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/SingleInputVideoGraph.java b/libraries/transformer/src/main/java/androidx/media3/transformer/SingleInputVideoGraph.java index b8dce37abb..4934956ef6 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/SingleInputVideoGraph.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/SingleInputVideoGraph.java @@ -17,6 +17,7 @@ package androidx.media3.transformer; 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 android.content.Context; @@ -30,6 +31,7 @@ import androidx.media3.common.VideoFrameProcessingException; import androidx.media3.common.VideoFrameProcessor; import androidx.media3.common.VideoGraph; import androidx.media3.effect.Presentation; +import androidx.media3.effect.VideoCompositorSettings; import java.util.List; import java.util.concurrent.Executor; @@ -52,6 +54,11 @@ import java.util.concurrent.Executor; private boolean released; private volatile boolean hasProducedFrameWithTimestampZero; + /** + * Creates an instance. + * + *

{@code videoCompositorSettings} must be {@link VideoCompositorSettings#DEFAULT}. + */ public SingleInputVideoGraph( Context context, VideoFrameProcessor.Factory videoFrameProcessorFactory, @@ -60,9 +67,14 @@ import java.util.concurrent.Executor; Listener listener, DebugViewProvider debugViewProvider, Executor listenerExecutor, + VideoCompositorSettings videoCompositorSettings, boolean renderFramesAutomatically, @Nullable Presentation presentation, long initialTimestampOffsetUs) { + checkState( + VideoCompositorSettings.DEFAULT.equals(videoCompositorSettings), + "SingleInputVideoGraph does not use VideoCompositor, and therefore cannot apply" + + " VideoCompositorSettings"); this.context = context; this.videoFrameProcessorFactory = videoFrameProcessorFactory; this.inputColorInfo = inputColorInfo; diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerInternal.java b/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerInternal.java index 5bb443d11c..5a70e7d50b 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerInternal.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerInternal.java @@ -582,6 +582,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; context, firstAssetLoaderInputFormat, transformationRequest, + composition.videoCompositorSettings, composition.effects.videoEffects, videoFrameProcessorFactory, encoderFactory, diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerSingleInputVideoGraph.java b/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerSingleInputVideoGraph.java index cc5c7619b0..e8c97c7401 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerSingleInputVideoGraph.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerSingleInputVideoGraph.java @@ -23,6 +23,7 @@ import androidx.media3.common.DebugViewProvider; import androidx.media3.common.Effect; import androidx.media3.common.VideoFrameProcessor; import androidx.media3.effect.Presentation; +import androidx.media3.effect.VideoCompositorSettings; import java.util.List; import java.util.concurrent.Executor; @@ -46,6 +47,7 @@ import java.util.concurrent.Executor; DebugViewProvider debugViewProvider, Listener listener, Executor listenerExecutor, + VideoCompositorSettings videoCompositorSettings, List compositionEffects, long initialTimestampOffsetUs) { @Nullable Presentation presentation = null; @@ -63,6 +65,7 @@ import java.util.concurrent.Executor; listener, debugViewProvider, listenerExecutor, + videoCompositorSettings, /* renderFramesAutomatically= */ true, presentation, initialTimestampOffsetUs); @@ -77,6 +80,7 @@ import java.util.concurrent.Executor; Listener listener, DebugViewProvider debugViewProvider, Executor listenerExecutor, + VideoCompositorSettings videoCompositorSettings, boolean renderFramesAutomatically, @Nullable Presentation presentation, long initialTimestampOffsetUs) { @@ -88,6 +92,7 @@ import java.util.concurrent.Executor; listener, debugViewProvider, listenerExecutor, + videoCompositorSettings, renderFramesAutomatically, presentation, initialTimestampOffsetUs); diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerVideoGraph.java b/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerVideoGraph.java index f85598b474..97e2dcd164 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerVideoGraph.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerVideoGraph.java @@ -23,6 +23,7 @@ import androidx.media3.common.Effect; import androidx.media3.common.VideoFrameProcessingException; import androidx.media3.common.VideoFrameProcessor; import androidx.media3.common.VideoGraph; +import androidx.media3.effect.VideoCompositorSettings; import java.util.List; import java.util.concurrent.Executor; @@ -40,7 +41,10 @@ import java.util.concurrent.Executor; * @param debugViewProvider A {@link DebugViewProvider}. * @param listener A {@link Listener}. * @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 initialTimestampOffsetUs The timestamp offset for the first frame, in microseconds. * @return A new instance. * @throws VideoFrameProcessingException If a problem occurs while creating the {@link * VideoFrameProcessor}. @@ -52,6 +56,7 @@ import java.util.concurrent.Executor; DebugViewProvider debugViewProvider, Listener listener, Executor listenerExecutor, + VideoCompositorSettings videoCompositorSettings, List compositionEffects, long initialTimestampOffsetUs) throws VideoFrameProcessingException; diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoSampleExporter.java b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoSampleExporter.java index 75e8f34723..24f95794f1 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/VideoSampleExporter.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/VideoSampleExporter.java @@ -48,6 +48,7 @@ import androidx.media3.common.util.Log; import androidx.media3.common.util.Util; import androidx.media3.decoder.DecoderInputBuffer; import androidx.media3.effect.DebugTraceUtil; +import androidx.media3.effect.VideoCompositorSettings; import androidx.media3.exoplayer.mediacodec.MediaCodecUtil; import com.google.common.collect.ImmutableList; import com.google.common.util.concurrent.MoreExecutors; @@ -78,6 +79,7 @@ import org.checkerframework.dataflow.qual.Pure; Context context, Format firstInputFormat, TransformationRequest transformationRequest, + VideoCompositorSettings videoCompositorSettings, List compositionEffects, VideoFrameProcessor.Factory videoFrameProcessorFactory, Codec.EncoderFactory encoderFactory, @@ -151,6 +153,7 @@ import org.checkerframework.dataflow.qual.Pure; videoGraphOutputColor, errorConsumer, debugViewProvider, + videoCompositorSettings, compositionEffects); videoGraph.initialize(); } catch (VideoFrameProcessingException e) { @@ -477,6 +480,7 @@ import org.checkerframework.dataflow.qual.Pure; ColorInfo videoFrameProcessorOutputColor, Consumer errorConsumer, DebugViewProvider debugViewProvider, + VideoCompositorSettings videoCompositorSettings, List compositionEffects) throws VideoFrameProcessingException { this.errorConsumer = errorConsumer; @@ -493,6 +497,7 @@ import org.checkerframework.dataflow.qual.Pure; debugViewProvider, /* listener= */ thisRef, /* listenerExecutor= */ MoreExecutors.directExecutor(), + videoCompositorSettings, compositionEffects, initialTimestampOffsetUs); }