mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Apply video composition effects in preview
PiperOrigin-RevId: 678207818
This commit is contained in:
parent
c19d910f6b
commit
d8dc513431
@ -121,6 +121,7 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
|
|||||||
|
|
||||||
private VideoFrameProcessor.@MonotonicNonNull Factory videoFrameProcessorFactory;
|
private VideoFrameProcessor.@MonotonicNonNull Factory videoFrameProcessorFactory;
|
||||||
private PreviewingVideoGraph.@MonotonicNonNull Factory previewingVideoGraphFactory;
|
private PreviewingVideoGraph.@MonotonicNonNull Factory previewingVideoGraphFactory;
|
||||||
|
private List<Effect> compositionEffects;
|
||||||
private Clock clock;
|
private Clock clock;
|
||||||
private boolean built;
|
private boolean built;
|
||||||
|
|
||||||
@ -128,6 +129,7 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
|
|||||||
public Builder(Context context, VideoFrameReleaseControl videoFrameReleaseControl) {
|
public Builder(Context context, VideoFrameReleaseControl videoFrameReleaseControl) {
|
||||||
this.context = context.getApplicationContext();
|
this.context = context.getApplicationContext();
|
||||||
this.videoFrameReleaseControl = videoFrameReleaseControl;
|
this.videoFrameReleaseControl = videoFrameReleaseControl;
|
||||||
|
compositionEffects = ImmutableList.of();
|
||||||
clock = Clock.DEFAULT;
|
clock = Clock.DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,6 +166,18 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the {@linkplain Effect effects} to apply after compositing the sinks' data.
|
||||||
|
*
|
||||||
|
* @param compositionEffects The composition {@linkplain Effect effects}.
|
||||||
|
* @return This builder, for convenience.
|
||||||
|
*/
|
||||||
|
@CanIgnoreReturnValue
|
||||||
|
public Builder setCompositionEffects(List<Effect> compositionEffects) {
|
||||||
|
this.compositionEffects = compositionEffects;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the {@link Clock} that will be used.
|
* Sets the {@link Clock} that will be used.
|
||||||
*
|
*
|
||||||
@ -217,6 +231,8 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
|
|||||||
private final VideoFrameReleaseControl videoFrameReleaseControl;
|
private final VideoFrameReleaseControl videoFrameReleaseControl;
|
||||||
private final VideoFrameRenderControl videoFrameRenderControl;
|
private final VideoFrameRenderControl videoFrameRenderControl;
|
||||||
private final PreviewingVideoGraph.Factory previewingVideoGraphFactory;
|
private final PreviewingVideoGraph.Factory previewingVideoGraphFactory;
|
||||||
|
|
||||||
|
private final List<Effect> compositionEffects;
|
||||||
private final Clock clock;
|
private final Clock clock;
|
||||||
private final CopyOnWriteArraySet<PlaybackVideoGraphWrapper.Listener> listeners;
|
private final CopyOnWriteArraySet<PlaybackVideoGraphWrapper.Listener> listeners;
|
||||||
|
|
||||||
@ -244,6 +260,7 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
|
|||||||
videoFrameRenderControl =
|
videoFrameRenderControl =
|
||||||
new VideoFrameRenderControl(new FrameRendererImpl(), videoFrameReleaseControl);
|
new VideoFrameRenderControl(new FrameRendererImpl(), videoFrameReleaseControl);
|
||||||
previewingVideoGraphFactory = checkStateNotNull(builder.previewingVideoGraphFactory);
|
previewingVideoGraphFactory = checkStateNotNull(builder.previewingVideoGraphFactory);
|
||||||
|
compositionEffects = builder.compositionEffects;
|
||||||
listeners = new CopyOnWriteArraySet<>();
|
listeners = new CopyOnWriteArraySet<>();
|
||||||
state = STATE_CREATED;
|
state = STATE_CREATED;
|
||||||
addListener(videoSinkImpl);
|
addListener(videoSinkImpl);
|
||||||
@ -642,6 +659,7 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
|
|||||||
public void setPendingVideoEffects(List<Effect> videoEffects) {
|
public void setPendingVideoEffects(List<Effect> videoEffects) {
|
||||||
this.videoEffects.clear();
|
this.videoEffects.clear();
|
||||||
this.videoEffects.addAll(videoEffects);
|
this.videoEffects.addAll(videoEffects);
|
||||||
|
this.videoEffects.addAll(compositionEffects);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -376,4 +376,42 @@ public class CompositionPlaybackTest {
|
|||||||
|
|
||||||
assertThat(inputTimestampRecordingShaderProgram.getInputTimestampsUs()).isEmpty();
|
assertThat(inputTimestampRecordingShaderProgram.getInputTimestampsUs()).isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void playback_withCompositionEffect_effectIsApplied() throws Exception {
|
||||||
|
EditedMediaItem editedMediaItem =
|
||||||
|
new EditedMediaItem.Builder(VIDEO_MEDIA_ITEM).setDurationUs(VIDEO_DURATION_US).build();
|
||||||
|
InputTimestampRecordingShaderProgram inputTimestampRecordingShaderProgram =
|
||||||
|
new InputTimestampRecordingShaderProgram();
|
||||||
|
Effect videoEffect = (GlEffect) (context, useHdr) -> inputTimestampRecordingShaderProgram;
|
||||||
|
Composition composition =
|
||||||
|
new Composition.Builder(
|
||||||
|
new EditedMediaItemSequence.Builder(editedMediaItem, editedMediaItem).build())
|
||||||
|
.setEffects(
|
||||||
|
new Effects(
|
||||||
|
/* audioProcessors= */ ImmutableList.of(),
|
||||||
|
/* videoEffects= */ ImmutableList.of(videoEffect)))
|
||||||
|
.build();
|
||||||
|
ImmutableList<Long> expectedTimestampsUs =
|
||||||
|
new ImmutableList.Builder<Long>()
|
||||||
|
.addAll(VIDEO_TIMESTAMPS_US)
|
||||||
|
.addAll(
|
||||||
|
Iterables.transform(
|
||||||
|
VIDEO_TIMESTAMPS_US, timestampUs -> (VIDEO_DURATION_US + timestampUs)))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
getInstrumentation()
|
||||||
|
.runOnMainSync(
|
||||||
|
() -> {
|
||||||
|
player = new CompositionPlayer.Builder(context).build();
|
||||||
|
player.addListener(playerTestListener);
|
||||||
|
player.setComposition(composition);
|
||||||
|
player.prepare();
|
||||||
|
player.play();
|
||||||
|
});
|
||||||
|
playerTestListener.waitUntilPlayerEnded();
|
||||||
|
|
||||||
|
assertThat(inputTimestampRecordingShaderProgram.getInputTimestampsUs())
|
||||||
|
.isEqualTo(expectedTimestampsUs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -673,6 +673,7 @@ public final class CompositionPlayer extends SimpleBasePlayer
|
|||||||
PlaybackVideoGraphWrapper playbackVideoGraphWrapper =
|
PlaybackVideoGraphWrapper playbackVideoGraphWrapper =
|
||||||
new PlaybackVideoGraphWrapper.Builder(context, videoFrameReleaseControl)
|
new PlaybackVideoGraphWrapper.Builder(context, videoFrameReleaseControl)
|
||||||
.setPreviewingVideoGraphFactory(checkNotNull(previewingVideoGraphFactory))
|
.setPreviewingVideoGraphFactory(checkNotNull(previewingVideoGraphFactory))
|
||||||
|
.setCompositionEffects(composition.effects.videoEffects)
|
||||||
.setClock(clock)
|
.setClock(clock)
|
||||||
.build();
|
.build();
|
||||||
playbackVideoGraphWrapper.addListener(this);
|
playbackVideoGraphWrapper.addListener(this);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user