diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/AndroidTestUtil.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/AndroidTestUtil.java index 5de5d9c7dd..19447a8ed5 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/AndroidTestUtil.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/AndroidTestUtil.java @@ -71,6 +71,9 @@ public final class AndroidTestUtil { public static final String JPG_PORTRAIT_ASSET_URI_STRING = "asset:///media/bitmap/input_images/tokyo.jpg"; + public static final String MP4_TRIM_OPTIMIZATION_URI_STRING = + "asset:///media/mp4/internal_emulator_transformer_output.mp4"; + public static final String MP4_ASSET_URI_STRING = "asset:///media/mp4/sample.mp4"; public static final Format MP4_ASSET_FORMAT = new Format.Builder() 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 0cf00b3fa0..4af37d478a 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerEndToEndTest.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerEndToEndTest.java @@ -24,6 +24,7 @@ import static androidx.media3.transformer.AndroidTestUtil.MP4_ASSET_URI_STRING; import static androidx.media3.transformer.AndroidTestUtil.MP4_ASSET_WITH_INCREASING_TIMESTAMPS_320W_240H_15S_FORMAT; import static androidx.media3.transformer.AndroidTestUtil.MP4_ASSET_WITH_INCREASING_TIMESTAMPS_320W_240H_15S_URI_STRING; import static androidx.media3.transformer.AndroidTestUtil.MP4_ASSET_WITH_INCREASING_TIMESTAMPS_URI_STRING; +import static androidx.media3.transformer.AndroidTestUtil.MP4_TRIM_OPTIMIZATION_URI_STRING; import static androidx.media3.transformer.AndroidTestUtil.PNG_ASSET_URI_STRING; import static androidx.media3.transformer.AndroidTestUtil.createOpenGlObjects; import static androidx.media3.transformer.AndroidTestUtil.generateTextureFromBitmap; @@ -567,7 +568,7 @@ public class TransformerEndToEndTest { new Transformer.Builder(context).experimentalSetTrimOptimizationEnabled(true).build(); MediaItem mediaItem = new MediaItem.Builder() - .setUri("asset:///media/mp4/internal_emulator_transformer_output.mp4") + .setUri(MP4_TRIM_OPTIMIZATION_URI_STRING) .setClippingConfiguration( new MediaItem.ClippingConfiguration.Builder() .setStartPositionMs(500) @@ -585,6 +586,39 @@ public class TransformerEndToEndTest { assertThat(result.exportResult.durationMs).isAtMost(2000); } + @Test + public void clippedMedia_trimOptimizationEnabled_audioRemoved_completesWithOptimizationApplied() + throws Exception { + String testId = "clippedMedia_trimOptimizationEnabled_completesWithOptimizationApplied"; + if (!isRunningOnEmulator() || Util.SDK_INT != 33) { + // The trim optimization is only guaranteed to work on emulator for this (emulator-transcoded) + // file. + recordTestSkipped(context, testId, /* reason= */ "SDK 33 Emulator only test"); + assumeTrue(false); + } + Transformer transformer = + new Transformer.Builder(context).experimentalSetTrimOptimizationEnabled(true).build(); + MediaItem mediaItem = + new MediaItem.Builder() + .setUri(MP4_TRIM_OPTIMIZATION_URI_STRING) + .setClippingConfiguration( + new MediaItem.ClippingConfiguration.Builder() + .setStartPositionMs(500) + .setEndPositionMs(2500) + .build()) + .build(); + EditedMediaItem editedMediaItem = + new EditedMediaItem.Builder(mediaItem).setRemoveAudio(true).build(); + + ExportTestResult result = + new TransformerAndroidTestRunner.Builder(context, transformer) + .build() + .run(testId, editedMediaItem); + + assertThat(result.exportResult.optimizationResult).isEqualTo(OPTIMIZATION_SUCCEEDED); + assertThat(result.exportResult.durationMs).isAtMost(2000); + } + @Test public void videoEditing_trimOptimizationEnabled_fallbackToNormalExport() throws Exception { String testId = "videoEditing_trimOptimizationEnabled_fallbackToNormalExport"; @@ -598,7 +632,7 @@ public class TransformerEndToEndTest { } MediaItem mediaItem = new MediaItem.Builder() - .setUri("asset:///media/mp4/internal_emulator_transformer_output.mp4") + .setUri(MP4_TRIM_OPTIMIZATION_URI_STRING) .setClippingConfiguration( new MediaItem.ClippingConfiguration.Builder() .setStartPositionMs(500) diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerTrimOptimizationProgressTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerTrimOptimizationProgressTest.java index cdddc2526e..69ba5038a6 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerTrimOptimizationProgressTest.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerTrimOptimizationProgressTest.java @@ -16,6 +16,7 @@ package androidx.media3.transformer; import static androidx.media3.common.util.Util.isRunningOnEmulator; +import static androidx.media3.transformer.AndroidTestUtil.MP4_TRIM_OPTIMIZATION_URI_STRING; import static androidx.media3.transformer.Transformer.PROGRESS_STATE_AVAILABLE; import static androidx.media3.transformer.Transformer.PROGRESS_STATE_NOT_STARTED; import static androidx.media3.transformer.Transformer.PROGRESS_STATE_UNAVAILABLE; @@ -78,7 +79,7 @@ public class TransformerTrimOptimizationProgressTest { new Transformer.Builder(context).experimentalSetTrimOptimizationEnabled(true).build(); MediaItem mediaItem = new MediaItem.Builder() - .setUri("asset:///media/mp4/internal_emulator_transformer_output.mp4") + .setUri(MP4_TRIM_OPTIMIZATION_URI_STRING) .setClippingConfiguration( new MediaItem.ClippingConfiguration.Builder() .setStartPositionMs(500) @@ -158,7 +159,7 @@ public class TransformerTrimOptimizationProgressTest { new Transformer.Builder(context).experimentalSetTrimOptimizationEnabled(true).build(); MediaItem mediaItem = new MediaItem.Builder() - .setUri("asset:///media/mp4/internal_emulator_transformer_output.mp4") + .setUri(MP4_TRIM_OPTIMIZATION_URI_STRING) .setClippingConfiguration( new MediaItem.ClippingConfiguration.Builder() .setStartPositionMs(500) diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/Transformer.java b/libraries/transformer/src/main/java/androidx/media3/transformer/Transformer.java index d237d8302d..53ad7ce317 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/Transformer.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/Transformer.java @@ -1460,19 +1460,19 @@ public final class Transformer { } private void remuxRemainingMedia() { - Mp4Info mediaItemInfo = checkNotNull(this.mediaItemInfo); transformerState = TRANSFORMER_STATE_REMUX_REMAINING_MEDIA; - if (!doesFormatsMatch()) { + EditedMediaItem firstEditedMediaItem = + checkNotNull(composition).sequences.get(0).editedMediaItems.get(0); + Mp4Info mediaItemInfo = checkNotNull(this.mediaItemInfo); + if (!doesFormatsMatch(mediaItemInfo, firstEditedMediaItem)) { remuxingMuxerWrapper = null; transformerInternal = null; exportResultBuilder.setOptimizationResult(OPTIMIZATION_FAILED_FORMAT_MISMATCH); processFullInput(); return; } - MediaItem firstMediaItem = - checkNotNull(composition).sequences.get(0).editedMediaItems.get(0).mediaItem; - long trimStartTimeUs = firstMediaItem.clippingConfiguration.startPositionUs; - long trimEndTimeUs = firstMediaItem.clippingConfiguration.endPositionUs; + long trimStartTimeUs = firstEditedMediaItem.mediaItem.clippingConfiguration.startPositionUs; + long trimEndTimeUs = firstEditedMediaItem.mediaItem.clippingConfiguration.endPositionUs; Composition transmuxComposition = buildNewCompositionWithClipTimes( composition, @@ -1490,14 +1490,14 @@ public final class Transformer { - trimStartTimeUs); } - private boolean doesFormatsMatch() { - Mp4Info mediaItemInfo = checkNotNull(this.mediaItemInfo); + private boolean doesFormatsMatch(Mp4Info mediaItemInfo, EditedMediaItem firstMediaItem) { boolean videoFormatMatches = checkNotNull(remuxingMuxerWrapper) .getTrackFormat(C.TRACK_TYPE_VIDEO) .initializationDataEquals(checkNotNull(mediaItemInfo.videoFormat)); boolean audioFormatMatches = mediaItemInfo.audioFormat == null + || firstMediaItem.removeAudio || mediaItemInfo.audioFormat.initializationDataEquals( checkNotNull(remuxingMuxerWrapper).getTrackFormat(C.TRACK_TYPE_AUDIO)); return videoFormatMatches && audioFormatMatches;