Use WORKING_COLOR_SPACE_DEFAULT in multi-sequence compositions

Build upon Transformer.videoFrameProcessorFactory in MultipleInputVideoGraph
Check that Transformer.videoFrameProcessorFactory is DefaultVideoFrameProcessor
for multi-input video

Fixes https://github.com/androidx/media/issues/1509

PiperOrigin-RevId: 655232381
This commit is contained in:
dancho 2024-07-23 11:11:03 -07:00 committed by Copybara-Service
parent 9a42d03466
commit 7103f21da9
11 changed files with 46 additions and 18 deletions

View File

@ -17,6 +17,7 @@
package androidx.media3.effect;
import static androidx.media3.common.VideoFrameProcessor.INPUT_TYPE_TEXTURE_ID;
import static androidx.media3.common.util.Assertions.checkArgument;
import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.common.util.Assertions.checkState;
import static androidx.media3.common.util.Assertions.checkStateNotNull;
@ -25,7 +26,6 @@ import static androidx.media3.common.util.Util.newSingleThreadScheduledExecutor;
import static androidx.media3.effect.DebugTraceUtil.COMPONENT_COMPOSITOR;
import static androidx.media3.effect.DebugTraceUtil.COMPONENT_VFP;
import static androidx.media3.effect.DebugTraceUtil.EVENT_OUTPUT_TEXTURE_RENDERED;
import static androidx.media3.effect.DefaultVideoFrameProcessor.WORKING_COLOR_SPACE_LINEAR;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import android.content.Context;
@ -99,6 +99,7 @@ public abstract class MultipleInputVideoGraph implements VideoGraph {
protected MultipleInputVideoGraph(
Context context,
VideoFrameProcessor.Factory videoFrameProcessorFactory,
ColorInfo outputColorInfo,
DebugViewProvider debugViewProvider,
Listener listener,
@ -106,6 +107,7 @@ public abstract class MultipleInputVideoGraph implements VideoGraph {
VideoCompositorSettings videoCompositorSettings,
List<Effect> compositionEffects,
long initialTimestampOffsetUs) {
checkArgument(videoFrameProcessorFactory instanceof DefaultVideoFrameProcessor.Factory);
this.context = context;
this.outputColorInfo = outputColorInfo;
this.debugViewProvider = debugViewProvider;
@ -118,10 +120,10 @@ public abstract class MultipleInputVideoGraph implements VideoGraph {
preProcessors = new SparseArray<>();
sharedExecutorService = newSingleThreadScheduledExecutor(SHARED_EXECUTOR_NAME);
glObjectsProvider = new SingleContextGlObjectsProvider();
// TODO - b/289986435: Support injecting VideoFrameProcessor.Factory.
videoFrameProcessorFactory =
new DefaultVideoFrameProcessor.Factory.Builder()
.setSdrWorkingColorSpace(WORKING_COLOR_SPACE_LINEAR)
// TODO - b/289986435: Support injecting arbitrary VideoFrameProcessor.Factory.
this.videoFrameProcessorFactory =
((DefaultVideoFrameProcessor.Factory) videoFrameProcessorFactory)
.buildUpon()
.setGlObjectsProvider(glObjectsProvider)
.setExecutorService(sharedExecutorService)
.build();

View File

@ -43,7 +43,6 @@ 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;
import java.io.File;
import java.io.IOException;
@ -53,9 +52,12 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
/** Tests for using multiple {@link EditedMediaItemSequence} in a composition. */
@RunWith(AndroidJUnit4.class)
@RunWith(Parameterized.class)
public final class TransformerMultiSequenceCompositionTest {
// Bitmaps are generated on a Pixel 6 or 7 Pro instead of an emulator, due to an emulator bug.
@ -69,11 +71,18 @@ public final class TransformerMultiSequenceCompositionTest {
private static final int EXPORT_WIDTH = 360;
private static final int EXPORT_HEIGHT = 240;
@Parameters(name = "{0}")
public static ImmutableList<Boolean> workingColorSpaceLinear() {
return ImmutableList.of(false, true);
}
private final Context context = ApplicationProvider.getApplicationContext();
@Rule public final TestName testName = new TestName();
private String testId;
@Parameter public boolean workingColorSpaceLinear;
@Before
public void setUpTestId() {
testId = testName.getMethodName();
@ -106,7 +115,7 @@ public final class TransformerMultiSequenceCompositionTest {
VideoCompositorSettings.DEFAULT);
ExportTestResult result =
new TransformerAndroidTestRunner.Builder(context, getLinearColorSpaceTransformer())
new TransformerAndroidTestRunner.Builder(context, buildTransformer())
.build()
.run(testId, composition);
@ -142,7 +151,7 @@ public final class TransformerMultiSequenceCompositionTest {
VideoCompositorSettings.DEFAULT);
ExportTestResult result =
new TransformerAndroidTestRunner.Builder(context, getLinearColorSpaceTransformer())
new TransformerAndroidTestRunner.Builder(context, buildTransformer())
.build()
.run(testId, composition);
@ -200,7 +209,7 @@ public final class TransformerMultiSequenceCompositionTest {
pictureInPictureVideoCompositorSettings);
ExportTestResult result =
new TransformerAndroidTestRunner.Builder(context, getLinearColorSpaceTransformer())
new TransformerAndroidTestRunner.Builder(context, buildTransformer())
.build()
.run(testId, composition);
@ -209,14 +218,16 @@ public final class TransformerMultiSequenceCompositionTest {
extractBitmapsFromVideo(context, checkNotNull(result.filePath)), testId);
}
private Transformer getLinearColorSpaceTransformer() {
private Transformer buildTransformer() {
// Use linear color space for grayscale effects.
return new Transformer.Builder(context)
.setVideoFrameProcessorFactory(
new DefaultVideoFrameProcessor.Factory.Builder()
.setSdrWorkingColorSpace(DefaultVideoFrameProcessor.WORKING_COLOR_SPACE_LINEAR)
.build())
.build();
Transformer.Builder builder = new Transformer.Builder(context);
if (workingColorSpaceLinear) {
builder.setVideoFrameProcessorFactory(
new DefaultVideoFrameProcessor.Factory.Builder()
.setSdrWorkingColorSpace(DefaultVideoFrameProcessor.WORKING_COLOR_SPACE_LINEAR)
.build());
}
return builder.build();
}
private static EditedMediaItem editedMediaItemByClippingVideo(String uri, List<Effect> effects) {

View File

@ -463,6 +463,10 @@ public final class Transformer {
* <p>If passing in a {@link DefaultVideoFrameProcessor.Factory}, the caller must not {@link
* DefaultVideoFrameProcessor.Factory.Builder#setTextureOutput set the texture output}.
*
* <p>If exporting a {@link Composition} with multiple video {@linkplain EditedMediaItemSequence
* sequences}, the {@link VideoFrameProcessor.Factory} must be a {@link
* DefaultVideoFrameProcessor.Factory}.
*
* @param videoFrameProcessorFactory A {@link VideoFrameProcessor.Factory}.
* @return This builder.
*/

View File

@ -21,6 +21,7 @@ import androidx.media3.common.ColorInfo;
import androidx.media3.common.DebugViewProvider;
import androidx.media3.common.Effect;
import androidx.media3.common.VideoFrameProcessingException;
import androidx.media3.common.VideoFrameProcessor;
import androidx.media3.common.VideoGraph;
import androidx.media3.effect.MultipleInputVideoGraph;
import androidx.media3.effect.VideoCompositorSettings;
@ -36,6 +37,13 @@ import java.util.concurrent.Executor;
/** A factory for creating {@link TransformerMultipleInputVideoGraph} instances. */
public static final class Factory implements TransformerVideoGraph.Factory {
private final VideoFrameProcessor.Factory videoFrameProcessorFactory;
public Factory(VideoFrameProcessor.Factory videoFrameProcessorFactory) {
this.videoFrameProcessorFactory = videoFrameProcessorFactory;
}
@Override
public TransformerMultipleInputVideoGraph create(
Context context,
@ -48,6 +56,7 @@ import java.util.concurrent.Executor;
long initialTimestampOffsetUs) {
return new TransformerMultipleInputVideoGraph(
context,
videoFrameProcessorFactory,
outputColorInfo,
debugViewProvider,
listener,
@ -60,6 +69,7 @@ import java.util.concurrent.Executor;
private TransformerMultipleInputVideoGraph(
Context context,
VideoFrameProcessor.Factory videoFrameProcessorFactory,
ColorInfo outputColorInfo,
DebugViewProvider debugViewProvider,
Listener listener,
@ -69,6 +79,7 @@ import java.util.concurrent.Executor;
long initialTimestampOffsetUs) {
super(
context,
videoFrameProcessorFactory,
outputColorInfo,
debugViewProvider,
listener,

View File

@ -136,7 +136,7 @@ import org.checkerframework.dataflow.qual.Pure;
new VideoGraphWrapper(
context,
hasMultipleInputs
? new TransformerMultipleInputVideoGraph.Factory()
? new TransformerMultipleInputVideoGraph.Factory(videoFrameProcessorFactory)
: new TransformerSingleInputVideoGraph.Factory(videoFrameProcessorFactory),
videoGraphOutputColor,
errorConsumer,