diff --git a/RELEASENOTES.md b/RELEASENOTES.md index ac24640427..983fb0cbd6 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -10,6 +10,10 @@ error during initialization of the next media item ([#2229](https://github.com/androidx/media/issues/2229)). * Transformer: + * Filling an initial gap (added via `addGap()`) with silent audio now + requires explicitly setting `setForceAudioTrack(true)` in + `EditedMediaItemSequence.Builder`. If the gap is in the middle of the + sequence, then this flag is not required. * Track Selection: * Extractors: * MP3: Use duration and data size from unseekable Xing, VBRI and similar diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerEndToEndTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerEndToEndTest.java index 326a844300..7732d5ace0 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerEndToEndTest.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerEndToEndTest.java @@ -1887,6 +1887,7 @@ public class TransformerEndToEndTest { new EditedMediaItemSequence.Builder() .addGap(100_000) .addItem(editedMediaItem) + .setForceAudioTrack(true) .build(), new EditedMediaItemSequence.Builder(editedMediaItem).build()) .build(); diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerGapsTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerGapsTest.java index eb91308f64..fea77ab6a7 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerGapsTest.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerGapsTest.java @@ -149,8 +149,12 @@ public class TransformerGapsTest { TransformerAndroidTestRunner transformerAndroidTestRunner = new TransformerAndroidTestRunner.Builder(context, transformer).build(); + // An IllegalStateException is thrown instead of an ExportException because the exception is + // thrown very early in the setup phase and its not caught. + // TODO: b/391111085 - Throw exception when the sequence without force audio/video flag is + // built. assertThrows( - ExportException.class, () -> transformerAndroidTestRunner.run(testId, composition)); + IllegalStateException.class, () -> transformerAndroidTestRunner.run(testId, composition)); } @Test @@ -234,8 +238,12 @@ public class TransformerGapsTest { TransformerAndroidTestRunner transformerAndroidTestRunner = new TransformerAndroidTestRunner.Builder(context, transformer).build(); + // An IllegalStateException is thrown instead of an ExportException because the exception is + // thrown very early in the setup phase and its not caught. + // TODO: b/391111085 - Throw exception when the sequence without force audio/video flag is + // built. assertThrows( - ExportException.class, () -> transformerAndroidTestRunner.run(testId, composition)); + IllegalStateException.class, () -> transformerAndroidTestRunner.run(testId, composition)); } @Test diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/SequenceAssetLoader.java b/libraries/transformer/src/main/java/androidx/media3/transformer/SequenceAssetLoader.java index 56067d209c..4a654cb2f7 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/SequenceAssetLoader.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/SequenceAssetLoader.java @@ -137,7 +137,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; Looper looper) { editedMediaItems = sequence.editedMediaItems; isLooping = sequence.isLooping; - this.forceAudioTrack = sequence.forceAudioTrack || sequence.editedMediaItems.get(0).isGap(); + this.forceAudioTrack = sequence.forceAudioTrack; this.assetLoaderFactory = new GapInterceptingAssetLoaderFactory(assetLoaderFactory); this.compositionSettings = compositionSettings; sequenceAssetLoaderListener = listener; diff --git a/libraries/transformer/src/test/java/androidx/media3/transformer/CompositionExportTest.java b/libraries/transformer/src/test/java/androidx/media3/transformer/CompositionExportTest.java index 55d5a015b5..f7bd452c4f 100644 --- a/libraries/transformer/src/test/java/androidx/media3/transformer/CompositionExportTest.java +++ b/libraries/transformer/src/test/java/androidx/media3/transformer/CompositionExportTest.java @@ -481,7 +481,10 @@ public class CompositionExportTest { new EditedMediaItem.Builder(MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_RAW)).build(); Composition composition = new Composition.Builder( - new EditedMediaItemSequence.Builder().addGap(1_000_000).build(), + new EditedMediaItemSequence.Builder() + .addGap(1_000_000) + .setForceAudioTrack(true) + .build(), new EditedMediaItemSequence.Builder(audioItem1000ms).build()) .build(); @@ -512,6 +515,7 @@ public class CompositionExportTest { new EditedMediaItemSequence.Builder() .addGap(100_000) .addItem(audioEditedMediaItem) + .setForceAudioTrack(true) .build(), new EditedMediaItemSequence.Builder(otherAudioEditedMediaItem).build()) .build(); @@ -591,6 +595,7 @@ public class CompositionExportTest { new EditedMediaItemSequence.Builder() .addGap(200_000) .addItem(audioEditedMediaItem) + .setForceAudioTrack(true) .build()) .setTransmuxVideo(true) .build(); @@ -716,7 +721,10 @@ public class CompositionExportTest { Composition composition = new Composition.Builder( new EditedMediaItemSequence.Builder(audioItem1000ms).build(), - new EditedMediaItemSequence.Builder().addGap(1_000_000).build()) + new EditedMediaItemSequence.Builder() + .addGap(1_000_000) + .setForceAudioTrack(true) + .build()) .build(); transformer.start(composition, outputDir.newFile().getPath()); @@ -733,8 +741,14 @@ public class CompositionExportTest { new TestTransformerBuilder(context).setMuxerFactory(muxerFactory).build(); Composition composition = new Composition.Builder( - new EditedMediaItemSequence.Builder().addGap(500_000).build(), - new EditedMediaItemSequence.Builder().addGap(500_000).build()) + new EditedMediaItemSequence.Builder() + .addGap(500_000) + .setForceAudioTrack(true) + .build(), + new EditedMediaItemSequence.Builder() + .addGap(500_000) + .setForceAudioTrack(true) + .build()) .build(); transformer.start(composition, outputDir.newFile().getPath()); diff --git a/libraries/transformer/src/test/java/androidx/media3/transformer/MediaItemExportTest.java b/libraries/transformer/src/test/java/androidx/media3/transformer/MediaItemExportTest.java index f323ffee87..16a62d4c1f 100644 --- a/libraries/transformer/src/test/java/androidx/media3/transformer/MediaItemExportTest.java +++ b/libraries/transformer/src/test/java/androidx/media3/transformer/MediaItemExportTest.java @@ -148,7 +148,7 @@ public final class MediaItemExportTest { new TestTransformerBuilder(context).setMuxerFactory(muxerFactory).build(); EditedMediaItemSequence gapSequence = - new EditedMediaItemSequence.Builder().addGap(500_000).build(); + new EditedMediaItemSequence.Builder().addGap(500_000).setForceAudioTrack(true).build(); transformer.start(new Composition.Builder(gapSequence).build(), outputDir.newFile().getPath()); ExportResult result = TransformerTestRunner.runLooper(transformer); diff --git a/libraries/transformer/src/test/java/androidx/media3/transformer/SequenceExportTest.java b/libraries/transformer/src/test/java/androidx/media3/transformer/SequenceExportTest.java index 1e83e1612b..6bc6f6cb94 100644 --- a/libraries/transformer/src/test/java/androidx/media3/transformer/SequenceExportTest.java +++ b/libraries/transformer/src/test/java/androidx/media3/transformer/SequenceExportTest.java @@ -551,7 +551,11 @@ public final class SequenceExportTest { new EditedMediaItem.Builder(MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_RAW_VIDEO)) .build(); EditedMediaItemSequence sequence = - new EditedMediaItemSequence.Builder().addGap(500_000).addItem(audioVideoItem).build(); + new EditedMediaItemSequence.Builder() + .addGap(500_000) + .addItem(audioVideoItem) + .setForceAudioTrack(true) + .build(); Composition composition = new Composition.Builder(sequence).build(); transformer.start(composition, outputDir.newFile().getPath()); @@ -567,7 +571,11 @@ public final class SequenceExportTest { Transformer transformer = new TestTransformerBuilder(context).setMuxerFactory(muxerFactory).build(); EditedMediaItemSequence sequence = - new EditedMediaItemSequence.Builder().addGap(300_000).addGap(200_000).build(); + new EditedMediaItemSequence.Builder() + .addGap(300_000) + .addGap(200_000) + .setForceAudioTrack(true) + .build(); Composition composition = new Composition.Builder(sequence).build(); transformer.start(composition, outputDir.newFile().getPath()); @@ -614,6 +622,7 @@ public final class SequenceExportTest { .addGap(200_000) .addGap(500_000) .addItem(audioItem) + .setForceAudioTrack(true) .build(); Composition composition = new Composition.Builder(sequence).build(); @@ -709,6 +718,7 @@ public final class SequenceExportTest { .addItem(firstAudioItem) .addGap(200_000) .addItem(secondAudioItem) + .setForceAudioTrack(true) .build(); Composition composition = new Composition.Builder(sequence).build();