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 f76ca3a504..36f7c4f1c7 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/AndroidTestUtil.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/AndroidTestUtil.java @@ -815,17 +815,18 @@ public final class AndroidTestUtil { * * @param context The {@link Context context}. * @param testId The test ID. - * @param inputFormat The {@link Format format} to decode. + * @param inputFormat The {@link Format format} to decode, or the input is not produced by + * MediaCodec, like an image. * @param outputFormat The {@link Format format} to encode/mux or {@code null} if the output won't * be encoded or muxed. * @throws AssumptionViolatedException If the device does not support the formats. In this case, * the reason for skipping the test is logged. */ public static void assumeFormatsSupported( - Context context, String testId, Format inputFormat, @Nullable Format outputFormat) + Context context, String testId, @Nullable Format inputFormat, @Nullable Format outputFormat) throws IOException, JSONException, MediaCodecUtil.DecoderQueryException { // TODO(b/278657595): Make this capability check match the default codec factory selection code. - boolean canDecode = canDecode(inputFormat); + boolean canDecode = inputFormat == null || canDecode(inputFormat); boolean canEncode = outputFormat == null || canEncode(outputFormat); boolean canMux = outputFormat == null || canMux(outputFormat); diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerMixedInputEndToEndTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerMixedInputEndToEndTest.java index 2c6ba0d108..8679596651 100644 --- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerMixedInputEndToEndTest.java +++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/TransformerMixedInputEndToEndTest.java @@ -41,6 +41,8 @@ import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.common.collect.ImmutableList; import java.io.File; +import java.util.ArrayList; +import java.util.List; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -77,6 +79,8 @@ public class TransformerMixedInputEndToEndTest { testId = testName.getMethodName(); } + // TODO: b/343362776 - Add tests to assert enough silence is generated. + @Test public void videoEditing_withImageThenVideoInputs_completesWithCorrectFrameCount() throws Exception { @@ -133,6 +137,47 @@ public class TransformerMixedInputEndToEndTest { assertThat(new File(result.filePath).length()).isGreaterThan(0); } + @Test + public void videoEditing_withShortAlternatingImages_completesWithCorrectFrameCount() + throws Exception { + Transformer transformer = + new Transformer.Builder(context) + .setEncoderFactory( + new DefaultEncoderFactory.Builder(context).setEnableFallback(false).build()) + .build(); + + EditedMediaItem image1 = + new EditedMediaItem.Builder(MediaItem.fromUri(PNG_ASSET_URI_STRING)) + .setDurationUs(100_000) + .setFrameRate(30) + .build(); + int image1FrameCount = 3; + EditedMediaItem image2 = + new EditedMediaItem.Builder(MediaItem.fromUri(JPG_ASSET_URI_STRING)) + .setDurationUs(200_000) + .setFrameRate(30) + .build(); + int image2FrameCount = 6; + + ArrayList editedMediaItems = new ArrayList<>(100); + for (int i = 0; i < 50; i++) { + editedMediaItems.add(image1); + editedMediaItems.add(image2); + } + + ExportTestResult result = + new TransformerAndroidTestRunner.Builder(context, transformer) + .build() + .run(testId, buildComposition(editedMediaItems)); + + // TODO: b/346289922 - Check frame count with extractors. + assertThat(result.exportResult.videoFrameCount) + .isEqualTo(50 * image1FrameCount + 50 * image2FrameCount); + // 50 100ms-images and 50 200ms-images + assertThat(result.exportResult.durationMs).isEqualTo(14_966); + assertThat(new File(result.filePath).length()).isGreaterThan(0); + } + @Test public void videoEditing_withComplexMixedColorSpaceSdrVideoAndImageInputsEndWithVideo_completesWithCorrectFrameCount() @@ -343,9 +388,8 @@ public class TransformerMixedInputEndToEndTest { .build(); } - private static Composition buildComposition( - EditedMediaItem editedMediaItem, EditedMediaItem... editedMediaItems) { - return new Composition.Builder(new EditedMediaItemSequence(editedMediaItem, editedMediaItems)) + private static Composition buildComposition(List editedMediaItems) { + return new Composition.Builder(new EditedMediaItemSequence(editedMediaItems)) .setEffects( new Effects( /* audioProcessors= */ ImmutableList.of(), @@ -355,4 +399,13 @@ public class TransformerMixedInputEndToEndTest { /* width= */ 480, /* height= */ 360, Presentation.LAYOUT_SCALE_TO_FIT)))) .build(); } + + private static Composition buildComposition( + EditedMediaItem editedMediaItem, EditedMediaItem... editedMediaItems) { + return buildComposition( + new ImmutableList.Builder() + .add(editedMediaItem) + .add(editedMediaItems) + .build()); + } }