Disable video only on the sequence that has items that disable video

This means we need a custom track selector for each SequencePlayer.

PiperOrigin-RevId: 678779216
This commit is contained in:
claincly 2024-09-25 11:25:21 -07:00 committed by Copybara-Service
parent 5879426c07
commit 0ea63e3fa6
2 changed files with 85 additions and 49 deletions

View File

@ -374,6 +374,44 @@ public class CompositionPlaybackTest {
assertThat(inputTimestampRecordingShaderProgram.getInputTimestampsUs()).isEmpty();
}
@Test
public void playback_compositionWithSecondSequenceRemoveVideo_rendersVideoFromFirstSequence()
throws Exception {
InputTimestampRecordingShaderProgram inputTimestampRecordingShaderProgram =
new InputTimestampRecordingShaderProgram();
EditedMediaItem videoEditedMediaItem =
new EditedMediaItem.Builder(VIDEO_MEDIA_ITEM)
.setDurationUs(VIDEO_DURATION_US)
.setEffects(
new Effects(
/* audioProcessors= */ ImmutableList.of(),
/* videoEffects= */ ImmutableList.of(
(GlEffect) (context, useHdr) -> inputTimestampRecordingShaderProgram)))
.build();
EditedMediaItem videoEditedMediaItemRemoveVideo =
videoEditedMediaItem.buildUpon().setRemoveVideo(true).build();
Composition composition =
new Composition.Builder(
new EditedMediaItemSequence.Builder(videoEditedMediaItem).build(),
new EditedMediaItemSequence.Builder(videoEditedMediaItemRemoveVideo).build())
.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(VIDEO_TIMESTAMPS_US);
}
@Test
public void playback_withCompositionEffect_effectIsApplied() throws Exception {
EditedMediaItem editedMediaItem =

View File

@ -682,7 +682,6 @@ public final class CompositionPlayer extends SimpleBasePlayer
long primarySequenceDurationUs =
getSequenceDurationUs(checkNotNull(composition.sequences.get(0)));
// Video playback is disabled when one EditedMediaItem removes video.
boolean disableVideoPlayback = shouldDisableVideoPlayback(composition);
for (int i = 0; i < composition.sequences.size(); i++) {
EditedMediaItemSequence editedMediaItemSequence = composition.sequences.get(i);
SequenceRenderersFactory sequenceRenderersFactory =
@ -704,9 +703,15 @@ public final class CompositionPlayer extends SimpleBasePlayer
.setHandleAudioBecomingNoisy(true)
.setClock(clock);
if (i == 0) {
playerBuilder.setTrackSelector(new CompositionTrackSelector(context, disableVideoPlayback));
boolean disableVideoPlayback = false;
for (int j = 0; j < editedMediaItemSequence.editedMediaItems.size(); j++) {
if (editedMediaItemSequence.editedMediaItems.get(j).removeVideo) {
disableVideoPlayback = true;
break;
}
}
playerBuilder.setTrackSelector(
new CompositionTrackSelector(context, /* sequenceIndex= */ i, disableVideoPlayback));
ExoPlayer player = playerBuilder.build();
player.addListener(new PlayerListener(i));
@ -992,19 +997,6 @@ public final class CompositionPlayer extends SimpleBasePlayer
return compositionDurationUs;
}
private static boolean shouldDisableVideoPlayback(Composition composition) {
for (int i = 0; i < composition.sequences.size(); i++) {
EditedMediaItemSequence editedMediaItemSequence = composition.sequences.get(i);
for (int j = 0; j < editedMediaItemSequence.editedMediaItems.size(); j++) {
EditedMediaItem editedMediaItem = editedMediaItemSequence.editedMediaItems.get(j);
if (editedMediaItem.removeVideo) {
return true;
}
}
}
return false;
}
/**
* A {@link VideoFrameReleaseControl.FrameTimingEvaluator} for composition frames.
*
@ -1095,10 +1087,13 @@ public final class CompositionPlayer extends SimpleBasePlayer
private static final class CompositionTrackSelector extends DefaultTrackSelector {
private static final String SILENCE_AUDIO_TRACK_GROUP_ID = "1:";
private final int sequenceIndex;
private final boolean disableVideoPlayback;
public CompositionTrackSelector(Context context, boolean disableVideoPlayback) {
public CompositionTrackSelector(
Context context, int sequenceIndex, boolean disableVideoPlayback) {
super(context);
this.sequenceIndex = sequenceIndex;
this.disableVideoPlayback = disableVideoPlayback;
}
@ -1110,6 +1105,8 @@ public final class CompositionPlayer extends SimpleBasePlayer
@RendererCapabilities.AdaptiveSupport int[] rendererMixedMimeTypeAdaptationSupports,
Parameters params)
throws ExoPlaybackException {
if (sequenceIndex == 0) {
// Currently silence is only generated for the zero-indexed sequence.
int audioRenderIndex = C.INDEX_UNSET;
for (int i = 0; i < mappedTrackInfo.getRendererCount(); i++) {
if (mappedTrackInfo.getRendererType(i) == C.TRACK_TYPE_AUDIO) {
@ -1147,6 +1144,7 @@ public final class CompositionPlayer extends SimpleBasePlayer
RendererCapabilities.create(C.FORMAT_UNSUPPORTED_TYPE);
}
}
}
return super.selectAudioTrack(
mappedTrackInfo, rendererFormatSupports, rendererMixedMimeTypeAdaptationSupports, params);