Make sure that tracks are transcoded/transmuxed consistently

All audio tracks should either all be transcoded or all be transmuxed.
Same for video tracks.

To achieve this, simplify the behaviour of transmuxAudio/Video.

PiperOrigin-RevId: 513809287
This commit is contained in:
kimvde 2023-03-03 14:12:51 +00:00 committed by Rohit Singh
parent 07ba24ab1a
commit 71fb4f9a5c
3 changed files with 18 additions and 20 deletions

View File

@ -122,9 +122,10 @@ public final class Composition {
* audio track will only be transcoded if necessary. * audio track will only be transcoded if necessary.
* *
* <p>If the input {@link Composition} contains multiple {@linkplain MediaItem media items}, all * <p>If the input {@link Composition} contains multiple {@linkplain MediaItem media items}, all
* the audio tracks are transmuxed if {@code transmuxAudio} is {@code true} and exporting the * the audio tracks are transcoded by default. They are all transmuxed if {@code transmuxAudio}
* first {@link MediaItem} doesn't require audio transcoding. Otherwise, they are all * is {@code true}. Transmuxed tracks must be compatible (typically, all the {@link MediaItem}
* transcoded. Transmuxed tracks must be compatible and must not overlap in time. * instances containing the track to transmux are concatenated in a single {@link
* EditedMediaItemSequence} and have the same sample format for that track).
* *
* <p>Requesting audio transmuxing and {@linkplain #experimentalSetForceAudioTrack(boolean) * <p>Requesting audio transmuxing and {@linkplain #experimentalSetForceAudioTrack(boolean)
* forcing an audio track} are not allowed together because generating silence requires * forcing an audio track} are not allowed together because generating silence requires
@ -148,9 +149,10 @@ public final class Composition {
* video track will only be transcoded if necessary. * video track will only be transcoded if necessary.
* *
* <p>If the input {@link Composition} contains multiple {@linkplain MediaItem media items}, all * <p>If the input {@link Composition} contains multiple {@linkplain MediaItem media items}, all
* the video tracks are transmuxed if {@code transmuxVideo} is {@code true} and exporting the * the video tracks are transcoded by default. They are all transmuxed if {@code transmuxVideo}
* first {@link MediaItem} doesn't require video transcoding. Otherwise, they are all * is {@code true}. Transmuxed tracks must be compatible (typically, all the {@link MediaItem}
* transcoded. Transmuxed tracks must be compatible and must not overlap in time. * instances containing the track to transmux are concatenated in a single {@link
* EditedMediaItemSequence} and have the same sample format for that track).
* *
* @param transmuxVideo Whether to transmux the video tracks. * @param transmuxVideo Whether to transmux the video tracks.
* @return This builder. * @return This builder.

View File

@ -582,8 +582,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
} }
private boolean shouldTranscodeAudio(Format inputFormat) { private boolean shouldTranscodeAudio(Format inputFormat) {
if (editedMediaItems.size() > 1 && !composition.transmuxAudio) { if (composition.sequences.size() > 1 || editedMediaItems.size() > 1) {
return true; return !composition.transmuxAudio;
} }
if (encoderFactory.audioNeedsEncoding()) { if (encoderFactory.audioNeedsEncoding()) {
return true; return true;
@ -603,14 +603,13 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
if (!firstEditedMediaItem.effects.audioProcessors.isEmpty()) { if (!firstEditedMediaItem.effects.audioProcessors.isEmpty()) {
return true; return true;
} }
return false; return false;
} }
private boolean shouldTranscodeVideo( private boolean shouldTranscodeVideo(
Format inputFormat, long streamStartPositionUs, long streamOffsetUs) { Format inputFormat, long streamStartPositionUs, long streamOffsetUs) {
if (editedMediaItems.size() > 1 && !composition.transmuxVideo) { if (composition.sequences.size() > 1 || editedMediaItems.size() > 1) {
return true; return !composition.transmuxVideo;
} }
EditedMediaItem firstEditedMediaItem = editedMediaItems.get(0); EditedMediaItem firstEditedMediaItem = editedMediaItems.get(0);
if ((streamStartPositionUs - streamOffsetUs) != 0 if ((streamStartPositionUs - streamOffsetUs) != 0

View File

@ -50,6 +50,7 @@ import androidx.media3.common.audio.AudioProcessor;
import androidx.media3.common.audio.SonicAudioProcessor; import androidx.media3.common.audio.SonicAudioProcessor;
import androidx.media3.common.util.Util; import androidx.media3.common.util.Util;
import androidx.media3.effect.Presentation; import androidx.media3.effect.Presentation;
import androidx.media3.effect.RgbFilter;
import androidx.media3.effect.ScaleAndRotateTransformation; import androidx.media3.effect.ScaleAndRotateTransformation;
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory; import androidx.media3.exoplayer.source.DefaultMediaSourceFactory;
import androidx.media3.exoplayer.source.MediaSource; import androidx.media3.exoplayer.source.MediaSource;
@ -516,15 +517,16 @@ public final class TransformerEndToEndTest {
} }
@Test @Test
public void start_multipleMediaItemsWithEffectsAndTransmux_ignoresTransmux() throws Exception { public void start_multipleMediaItemsAndTransmux_transmux() throws Exception {
Transformer transformer = createTransformerBuilder(/* enableFallback= */ false).build(); Transformer transformer = createTransformerBuilder(/* enableFallback= */ false).build();
MediaItem mediaItem = MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_VIDEO); MediaItem mediaItem = MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_VIDEO);
SonicAudioProcessor sonicAudioProcessor = new SonicAudioProcessor(); SonicAudioProcessor sonicAudioProcessor = new SonicAudioProcessor();
sonicAudioProcessor.setPitch(2f); sonicAudioProcessor.setPitch(2f);
Effect videoEffect = RgbFilter.createGrayscaleFilter();
Effects effects = Effects effects =
new Effects(ImmutableList.of(sonicAudioProcessor), /* videoEffects= */ ImmutableList.of()); new Effects(ImmutableList.of(sonicAudioProcessor), ImmutableList.of(videoEffect));
EditedMediaItem editedMediaItem = EditedMediaItem editedMediaItem =
new EditedMediaItem.Builder(mediaItem).setEffects(effects).setRemoveVideo(true).build(); new EditedMediaItem.Builder(mediaItem).setEffects(effects).build();
EditedMediaItemSequence editedMediaItemSequence = EditedMediaItemSequence editedMediaItemSequence =
new EditedMediaItemSequence(ImmutableList.of(editedMediaItem, editedMediaItem)); new EditedMediaItemSequence(ImmutableList.of(editedMediaItem, editedMediaItem));
Composition composition = Composition composition =
@ -536,13 +538,8 @@ public final class TransformerEndToEndTest {
transformer.start(composition, outputPath); transformer.start(composition, outputPath);
TransformerTestRunner.runLooper(transformer); TransformerTestRunner.runLooper(transformer);
// The inputs should be transcoded even though transmuxing has been requested. This is because
// audio effects have been added to the first MediaItem in the sequence, so the transcoding
// audio sample pipeline should be picked to apply these effects.
DumpFileAsserts.assertOutput( DumpFileAsserts.assertOutput(
context, context, testMuxer, getDumpFileName(FILE_AUDIO_VIDEO + ".concatenated"));
testMuxer,
getDumpFileName(FILE_AUDIO_VIDEO + ".concatenated_with_high_pitch_and_no_video"));
} }
@Test @Test