From 1b2e391971880538d4b7cf15075b9202e5fb89ec Mon Sep 17 00:00:00 2001 From: sheenachhabra Date: Tue, 14 Jan 2025 10:02:17 -0800 Subject: [PATCH] Change muxer instrumentation tests to robolectric These tests were earlier using `MediaExtractor`, hence they were in androidTest. Now `MediaExtractor` has been replaced with `media3 MediaExtractorCompat` so these test can be robolectric. PiperOrigin-RevId: 715424470 --- libraries/muxer/build.gradle | 2 +- .../media3/muxer/AndroidMuxerTestUtil.java | 75 --------- ...erEndToEndNonParameterizedAndroidTest.java | 143 ------------------ .../FragmentedMp4MuxerEndToEndTest.java} | 16 +- .../Mp4MuxerEndToEndParameterizedTest.java} | 16 +- .../media3/muxer/Mp4MuxerEndToEndTest.java | 84 ++++++++++ .../androidx/media3/muxer/MuxerTestUtil.java | 42 +++++ 7 files changed, 143 insertions(+), 235 deletions(-) delete mode 100644 libraries/muxer/src/androidTest/java/androidx/media3/muxer/AndroidMuxerTestUtil.java delete mode 100644 libraries/muxer/src/androidTest/java/androidx/media3/muxer/Mp4MuxerEndToEndNonParameterizedAndroidTest.java rename libraries/muxer/src/{androidTest/java/androidx/media3/muxer/FragmentedMp4MuxerEndToEndAndroidTest.java => test/java/androidx/media3/muxer/FragmentedMp4MuxerEndToEndTest.java} (89%) rename libraries/muxer/src/{androidTest/java/androidx/media3/muxer/Mp4MuxerEndToEndParameterizedAndroidTest.java => test/java/androidx/media3/muxer/Mp4MuxerEndToEndParameterizedTest.java} (90%) diff --git a/libraries/muxer/build.gradle b/libraries/muxer/build.gradle index 67e4197ffa..151efeaf71 100644 --- a/libraries/muxer/build.gradle +++ b/libraries/muxer/build.gradle @@ -58,12 +58,12 @@ dependencies { testImplementation project(modulePrefix + 'test-data') testImplementation 'org.robolectric:robolectric:' + robolectricVersion testImplementation 'com.google.truth:truth:' + truthVersion + testImplementation project(modulePrefix + 'lib-exoplayer') androidTestImplementation 'junit:junit:' + junitVersion androidTestImplementation 'androidx.test:runner:' + androidxTestRunnerVersion androidTestImplementation 'com.google.truth:truth:' + truthVersion androidTestImplementation project(modulePrefix + 'test-utils') androidTestImplementation project(modulePrefix + 'lib-extractor') - androidTestImplementation project(modulePrefix + 'lib-exoplayer') } ext { diff --git a/libraries/muxer/src/androidTest/java/androidx/media3/muxer/AndroidMuxerTestUtil.java b/libraries/muxer/src/androidTest/java/androidx/media3/muxer/AndroidMuxerTestUtil.java deleted file mode 100644 index b628f6fdd8..0000000000 --- a/libraries/muxer/src/androidTest/java/androidx/media3/muxer/AndroidMuxerTestUtil.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2023 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package androidx.media3.muxer; - -import android.content.Context; -import android.content.res.AssetFileDescriptor; -import android.media.MediaCodec; -import androidx.media3.common.util.MediaFormatUtil; -import androidx.media3.exoplayer.MediaExtractorCompat; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; - -/** Utilities for muxer test cases. */ -/* package */ final class AndroidMuxerTestUtil { - private static final String MP4_FILE_ASSET_DIRECTORY = "media/mp4/"; - private static final String DUMP_FILE_OUTPUT_DIRECTORY = "muxerdumps"; - private static final String DUMP_FILE_EXTENSION = "dump"; - - private AndroidMuxerTestUtil() {} - - public static String getExpectedDumpFilePath(String originalFileName) { - return DUMP_FILE_OUTPUT_DIRECTORY + '/' + originalFileName + '.' + DUMP_FILE_EXTENSION; - } - - public static void feedInputDataToMuxer(Context context, Muxer muxer, String inputFileName) - throws IOException, MuxerException { - MediaExtractorCompat extractor = new MediaExtractorCompat(context); - AssetFileDescriptor fd = - context.getResources().getAssets().openFd(MP4_FILE_ASSET_DIRECTORY + inputFileName); - extractor.setDataSource(fd); - - List addedTracks = new ArrayList<>(); - for (int i = 0; i < extractor.getTrackCount(); i++) { - int trackId = - muxer.addTrack(MediaFormatUtil.createFormatFromMediaFormat(extractor.getTrackFormat(i))); - addedTracks.add(trackId); - extractor.selectTrack(i); - } - - do { - MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo(); - bufferInfo.flags = extractor.getSampleFlags(); - bufferInfo.offset = 0; - bufferInfo.presentationTimeUs = extractor.getSampleTime(); - int sampleSize = (int) extractor.getSampleSize(); - bufferInfo.size = sampleSize; - - ByteBuffer sampleBuffer = ByteBuffer.allocateDirect(sampleSize); - extractor.readSampleData(sampleBuffer, /* offset= */ 0); - - sampleBuffer.rewind(); - - muxer.writeSampleData( - addedTracks.get(extractor.getSampleTrackIndex()), sampleBuffer, bufferInfo); - } while (extractor.advance()); - - extractor.release(); - fd.close(); - } -} diff --git a/libraries/muxer/src/androidTest/java/androidx/media3/muxer/Mp4MuxerEndToEndNonParameterizedAndroidTest.java b/libraries/muxer/src/androidTest/java/androidx/media3/muxer/Mp4MuxerEndToEndNonParameterizedAndroidTest.java deleted file mode 100644 index 1e197d16ec..0000000000 --- a/libraries/muxer/src/androidTest/java/androidx/media3/muxer/Mp4MuxerEndToEndNonParameterizedAndroidTest.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 2023 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package androidx.media3.muxer; - -import static androidx.media3.common.util.Assertions.checkNotNull; -import static androidx.media3.muxer.AndroidMuxerTestUtil.feedInputDataToMuxer; - -import android.content.Context; -import androidx.annotation.Nullable; -import androidx.media3.container.Mp4TimestampData; -import androidx.media3.extractor.mp4.Mp4Extractor; -import androidx.media3.extractor.text.DefaultSubtitleParserFactory; -import androidx.media3.test.utils.DumpFileAsserts; -import androidx.media3.test.utils.FakeExtractorOutput; -import androidx.media3.test.utils.TestUtil; -import androidx.test.core.app.ApplicationProvider; -import androidx.test.ext.junit.runners.AndroidJUnit4; -import java.io.FileOutputStream; -import java.io.IOException; -import org.checkerframework.checker.nullness.qual.MonotonicNonNull; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.junit.runner.RunWith; - -/** End to end instrumentation tests for {@link Mp4Muxer}. */ -@RunWith(AndroidJUnit4.class) -public class Mp4MuxerEndToEndNonParameterizedAndroidTest { - private static final String H265_HDR10_MP4 = "hdr10-720p.mp4"; - - @Rule public final TemporaryFolder temporaryFolder = new TemporaryFolder(); - - private final Context context = ApplicationProvider.getApplicationContext(); - private @MonotonicNonNull String outputPath; - private @MonotonicNonNull FileOutputStream outputStream; - - @Before - public void setUp() throws Exception { - outputPath = temporaryFolder.newFile("muxeroutput.mp4").getPath(); - outputStream = new FileOutputStream(outputPath); - } - - @After - public void tearDown() throws IOException { - checkNotNull(outputStream).close(); - } - - @Test - public void createMp4File_muxerNotClosed_createsPartiallyWrittenValidFile() throws Exception { - Mp4Muxer mp4Muxer = new Mp4Muxer.Builder(checkNotNull(outputStream)).build(); - mp4Muxer.addMetadataEntry( - new Mp4TimestampData( - /* creationTimestampSeconds= */ 100_000_000L, - /* modificationTimestampSeconds= */ 500_000_000L)); - feedInputDataToMuxer(context, mp4Muxer, H265_HDR10_MP4); - - // Muxer not closed. - - // Audio sample written = 192 out of 195. - // Video sample written = 125 out of 127. - // Output is still a valid MP4 file. - FakeExtractorOutput fakeExtractorOutput = - TestUtil.extractAllSamplesFromFilePath(new Mp4Extractor(), checkNotNull(outputPath)); - DumpFileAsserts.assertOutput( - context, - fakeExtractorOutput, - AndroidMuxerTestUtil.getExpectedDumpFilePath("partial_" + H265_HDR10_MP4)); - } - - @Test - public void createMp4File_withSampleBatchingDisabled_matchesExpected() throws Exception { - @Nullable Mp4Muxer mp4Muxer = null; - - try { - mp4Muxer = - new Mp4Muxer.Builder(checkNotNull(outputStream)).setSampleBatchingEnabled(false).build(); - mp4Muxer.addMetadataEntry( - new Mp4TimestampData( - /* creationTimestampSeconds= */ 100_000_000L, - /* modificationTimestampSeconds= */ 500_000_000L)); - feedInputDataToMuxer(context, mp4Muxer, checkNotNull(H265_HDR10_MP4)); - } finally { - if (mp4Muxer != null) { - mp4Muxer.close(); - } - } - - FakeExtractorOutput fakeExtractorOutput = - TestUtil.extractAllSamplesFromFilePath( - new Mp4Extractor(new DefaultSubtitleParserFactory()), checkNotNull(outputPath)); - DumpFileAsserts.assertOutput( - context, - fakeExtractorOutput, - AndroidMuxerTestUtil.getExpectedDumpFilePath("sample_batching_disabled_" + H265_HDR10_MP4)); - } - - @Test - public void createMp4File_withSampleBatchingAndAttemptStreamableOutputDisabled_matchesExpected() - throws Exception { - @Nullable Mp4Muxer mp4Muxer = null; - - try { - mp4Muxer = - new Mp4Muxer.Builder(checkNotNull(outputStream)) - .setSampleBatchingEnabled(false) - .setAttemptStreamableOutputEnabled(false) - .build(); - mp4Muxer.addMetadataEntry( - new Mp4TimestampData( - /* creationTimestampSeconds= */ 100_000_000L, - /* modificationTimestampSeconds= */ 500_000_000L)); - feedInputDataToMuxer(context, mp4Muxer, checkNotNull(H265_HDR10_MP4)); - } finally { - if (mp4Muxer != null) { - mp4Muxer.close(); - } - } - - FakeExtractorOutput fakeExtractorOutput = - TestUtil.extractAllSamplesFromFilePath( - new Mp4Extractor(new DefaultSubtitleParserFactory()), checkNotNull(outputPath)); - DumpFileAsserts.assertOutput( - context, - fakeExtractorOutput, - AndroidMuxerTestUtil.getExpectedDumpFilePath( - "sample_batching_and_attempt_streamable_output_disabled_" + H265_HDR10_MP4)); - } -} diff --git a/libraries/muxer/src/androidTest/java/androidx/media3/muxer/FragmentedMp4MuxerEndToEndAndroidTest.java b/libraries/muxer/src/test/java/androidx/media3/muxer/FragmentedMp4MuxerEndToEndTest.java similarity index 89% rename from libraries/muxer/src/androidTest/java/androidx/media3/muxer/FragmentedMp4MuxerEndToEndAndroidTest.java rename to libraries/muxer/src/test/java/androidx/media3/muxer/FragmentedMp4MuxerEndToEndTest.java index bdccfd0d0a..5aa6031f48 100644 --- a/libraries/muxer/src/androidTest/java/androidx/media3/muxer/FragmentedMp4MuxerEndToEndAndroidTest.java +++ b/libraries/muxer/src/test/java/androidx/media3/muxer/FragmentedMp4MuxerEndToEndTest.java @@ -16,7 +16,7 @@ package androidx.media3.muxer; import static androidx.media3.common.util.Assertions.checkNotNull; -import static androidx.media3.muxer.AndroidMuxerTestUtil.feedInputDataToMuxer; +import static androidx.media3.muxer.MuxerTestUtil.feedInputDataToMuxer; import android.content.Context; import androidx.annotation.Nullable; @@ -38,13 +38,13 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameter; -import org.junit.runners.Parameterized.Parameters; +import org.robolectric.ParameterizedRobolectricTestRunner; +import org.robolectric.ParameterizedRobolectricTestRunner.Parameter; +import org.robolectric.ParameterizedRobolectricTestRunner.Parameters; /** End to end instrumentation tests for {@link FragmentedMp4Muxer}. */ -@RunWith(Parameterized.class) -public class FragmentedMp4MuxerEndToEndAndroidTest { +@RunWith(ParameterizedRobolectricTestRunner.class) +public class FragmentedMp4MuxerEndToEndTest { private static final String H264_WITH_PYRAMID_B_FRAMES_MP4 = "bbb_800x640_768kbps_30fps_avc_pyramid_3b.mp4"; private static final String H265_HDR10_MP4 = "hdr10-720p.mp4"; @@ -96,7 +96,7 @@ public class FragmentedMp4MuxerEndToEndAndroidTest { DumpFileAsserts.assertOutput( context, fakeExtractorOutput, - AndroidMuxerTestUtil.getExpectedDumpFilePath(inputFile + "_fragmented")); + MuxerTestUtil.getExpectedDumpFilePath(inputFile + "_fragmented")); } @Test @@ -123,6 +123,6 @@ public class FragmentedMp4MuxerEndToEndAndroidTest { DumpFileAsserts.assertOutput( context, dumpableMp4Box, - AndroidMuxerTestUtil.getExpectedDumpFilePath(H265_HDR10_MP4 + "_fragmented_box_structure")); + MuxerTestUtil.getExpectedDumpFilePath(H265_HDR10_MP4 + "_fragmented_box_structure")); } } diff --git a/libraries/muxer/src/androidTest/java/androidx/media3/muxer/Mp4MuxerEndToEndParameterizedAndroidTest.java b/libraries/muxer/src/test/java/androidx/media3/muxer/Mp4MuxerEndToEndParameterizedTest.java similarity index 90% rename from libraries/muxer/src/androidTest/java/androidx/media3/muxer/Mp4MuxerEndToEndParameterizedAndroidTest.java rename to libraries/muxer/src/test/java/androidx/media3/muxer/Mp4MuxerEndToEndParameterizedTest.java index 2dd530f423..b3a320e05c 100644 --- a/libraries/muxer/src/androidTest/java/androidx/media3/muxer/Mp4MuxerEndToEndParameterizedAndroidTest.java +++ b/libraries/muxer/src/test/java/androidx/media3/muxer/Mp4MuxerEndToEndParameterizedTest.java @@ -16,7 +16,7 @@ package androidx.media3.muxer; import static androidx.media3.common.util.Assertions.checkNotNull; -import static androidx.media3.muxer.AndroidMuxerTestUtil.feedInputDataToMuxer; +import static androidx.media3.muxer.MuxerTestUtil.feedInputDataToMuxer; import android.content.Context; import androidx.annotation.Nullable; @@ -36,13 +36,13 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameter; -import org.junit.runners.Parameterized.Parameters; +import org.robolectric.ParameterizedRobolectricTestRunner; +import org.robolectric.ParameterizedRobolectricTestRunner.Parameter; +import org.robolectric.ParameterizedRobolectricTestRunner.Parameters; -/** End to end parameterized instrumentation tests for {@link Mp4Muxer}. */ -@RunWith(Parameterized.class) -public class Mp4MuxerEndToEndParameterizedAndroidTest { +/** End to end parameterized tests for {@link Mp4Muxer}. */ +@RunWith(ParameterizedRobolectricTestRunner.class) +public class Mp4MuxerEndToEndParameterizedTest { // Video Codecs private static final String H263_3GP = "bbb_176x144_128kbps_15fps_h263.3gp"; private static final String H264_MP4 = "sample_no_bframes.mp4"; @@ -126,6 +126,6 @@ public class Mp4MuxerEndToEndParameterizedAndroidTest { FakeExtractorOutput fakeExtractorOutput = TestUtil.extractAllSamplesFromFilePath(new Mp4Extractor(), checkNotNull(outputPath)); DumpFileAsserts.assertOutput( - context, fakeExtractorOutput, AndroidMuxerTestUtil.getExpectedDumpFilePath(inputFile)); + context, fakeExtractorOutput, MuxerTestUtil.getExpectedDumpFilePath(inputFile)); } } diff --git a/libraries/muxer/src/test/java/androidx/media3/muxer/Mp4MuxerEndToEndTest.java b/libraries/muxer/src/test/java/androidx/media3/muxer/Mp4MuxerEndToEndTest.java index 5ac1a197c8..e33ea9630f 100644 --- a/libraries/muxer/src/test/java/androidx/media3/muxer/Mp4MuxerEndToEndTest.java +++ b/libraries/muxer/src/test/java/androidx/media3/muxer/Mp4MuxerEndToEndTest.java @@ -15,9 +15,11 @@ */ package androidx.media3.muxer; +import static androidx.media3.common.util.Assertions.checkNotNull; import static androidx.media3.muxer.Mp4Muxer.LAST_SAMPLE_DURATION_BEHAVIOR_SET_FROM_END_OF_STREAM_BUFFER_OR_DUPLICATE_PREVIOUS; import static androidx.media3.muxer.MuxerTestUtil.FAKE_VIDEO_FORMAT; import static androidx.media3.muxer.MuxerTestUtil.XMP_SAMPLE_DATA; +import static androidx.media3.muxer.MuxerTestUtil.feedInputDataToMuxer; import static androidx.media3.muxer.MuxerTestUtil.getFakeSampleAndSampleInfo; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; @@ -53,6 +55,7 @@ import org.junit.runner.RunWith; public class Mp4MuxerEndToEndTest { @Rule public final TemporaryFolder temporaryFolder = new TemporaryFolder(); + private static final String H265_HDR10_MP4 = "hdr10-720p.mp4"; private final Context context = ApplicationProvider.getApplicationContext(); @Test @@ -117,6 +120,30 @@ public class Mp4MuxerEndToEndTest { assertThat(outputFileBytes).isEmpty(); } + @Test + public void createMp4File_muxerNotClosed_createsPartiallyWrittenValidFile() throws Exception { + String outputPath = temporaryFolder.newFile().getPath(); + Mp4Muxer mp4Muxer = new Mp4Muxer.Builder(new FileOutputStream(outputPath)).build(); + mp4Muxer.addMetadataEntry( + new Mp4TimestampData( + /* creationTimestampSeconds= */ 100_000_000L, + /* modificationTimestampSeconds= */ 500_000_000L)); + feedInputDataToMuxer(context, mp4Muxer, H265_HDR10_MP4); + + // Muxer not closed. + + // Audio sample written = 192 out of 195. + // Video sample written = 125 out of 127. + // Output is still a valid MP4 file. + FakeExtractorOutput fakeExtractorOutput = + TestUtil.extractAllSamplesFromFilePath( + new Mp4Extractor(new DefaultSubtitleParserFactory()), checkNotNull(outputPath)); + DumpFileAsserts.assertOutput( + context, + fakeExtractorOutput, + MuxerTestUtil.getExpectedDumpFilePath("partial_" + H265_HDR10_MP4)); + } + @Test public void createMp4File_withSameTracksOffset_matchesExpected() throws Exception { String outputFilePath = temporaryFolder.newFile().getPath(); @@ -813,6 +840,63 @@ public class Mp4MuxerEndToEndTest { assertThat(fakeExtractorOutput.seekMap.getDurationUs()).isEqualTo(400L); } + @Test + public void createMp4File_withSampleBatchingDisabled_matchesExpected() throws Exception { + String outputPath = temporaryFolder.newFile().getPath(); + + Mp4Muxer mp4Muxer = + new Mp4Muxer.Builder(new FileOutputStream(outputPath)) + .setSampleBatchingEnabled(false) + .build(); + mp4Muxer.addMetadataEntry( + new Mp4TimestampData( + /* creationTimestampSeconds= */ 100_000_000L, + /* modificationTimestampSeconds= */ 500_000_000L)); + try { + feedInputDataToMuxer(context, mp4Muxer, checkNotNull(H265_HDR10_MP4)); + } finally { + mp4Muxer.close(); + } + + FakeExtractorOutput fakeExtractorOutput = + TestUtil.extractAllSamplesFromFilePath( + new Mp4Extractor(new DefaultSubtitleParserFactory()), checkNotNull(outputPath)); + DumpFileAsserts.assertOutput( + context, + fakeExtractorOutput, + MuxerTestUtil.getExpectedDumpFilePath("sample_batching_disabled_" + H265_HDR10_MP4)); + } + + @Test + public void createMp4File_withSampleBatchingAndAttemptStreamableOutputDisabled_matchesExpected() + throws Exception { + String outputPath = temporaryFolder.newFile().getPath(); + + Mp4Muxer mp4Muxer = + new Mp4Muxer.Builder(new FileOutputStream(outputPath)) + .setSampleBatchingEnabled(false) + .setAttemptStreamableOutputEnabled(false) + .build(); + mp4Muxer.addMetadataEntry( + new Mp4TimestampData( + /* creationTimestampSeconds= */ 100_000_000L, + /* modificationTimestampSeconds= */ 500_000_000L)); + try { + feedInputDataToMuxer(context, mp4Muxer, checkNotNull(H265_HDR10_MP4)); + } finally { + mp4Muxer.close(); + } + + FakeExtractorOutput fakeExtractorOutput = + TestUtil.extractAllSamplesFromFilePath( + new Mp4Extractor(new DefaultSubtitleParserFactory()), checkNotNull(outputPath)); + DumpFileAsserts.assertOutput( + context, + fakeExtractorOutput, + MuxerTestUtil.getExpectedDumpFilePath( + "sample_batching_and_attempt_streamable_output_disabled_" + H265_HDR10_MP4)); + } + private static void writeFakeSamples(Mp4Muxer muxer, int trackId, int sampleCount) throws MuxerException { for (int i = 0; i < sampleCount; i++) { diff --git a/libraries/muxer/src/test/java/androidx/media3/muxer/MuxerTestUtil.java b/libraries/muxer/src/test/java/androidx/media3/muxer/MuxerTestUtil.java index 7123b4dbab..ff37e729c4 100644 --- a/libraries/muxer/src/test/java/androidx/media3/muxer/MuxerTestUtil.java +++ b/libraries/muxer/src/test/java/androidx/media3/muxer/MuxerTestUtil.java @@ -18,13 +18,20 @@ package androidx.media3.muxer; import static androidx.media3.common.MimeTypes.AUDIO_AAC; import static androidx.media3.common.MimeTypes.VIDEO_H264; +import android.content.Context; import android.media.MediaCodec; import android.media.MediaCodec.BufferInfo; +import android.net.Uri; import android.util.Pair; import androidx.media3.common.Format; +import androidx.media3.common.util.MediaFormatUtil; +import androidx.media3.exoplayer.MediaExtractorCompat; import com.google.common.collect.ImmutableList; import com.google.common.io.BaseEncoding; +import java.io.IOException; import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; /** Utilities for muxer test cases. */ /* package */ class MuxerTestUtil { @@ -53,6 +60,7 @@ import java.nio.ByteBuffer; .decode( "0000000167F4000A919B2BF3CB3640000003004000000C83C48965800000000168EBE3C448000001658884002BFFFEF5DBF32CAE4A43FF"); + private static final String MP4_FILE_ASSET_DIRECTORY = "asset:///media/mp4/"; private static final String DUMP_FILE_OUTPUT_DIRECTORY = "muxerdumps"; private static final String DUMP_FILE_EXTENSION = "dump"; @@ -73,5 +81,39 @@ import java.nio.ByteBuffer; return new Pair<>(sampleDirectBuffer, bufferInfo); } + public static void feedInputDataToMuxer(Context context, Muxer muxer, String inputFileName) + throws IOException, MuxerException { + MediaExtractorCompat extractor = new MediaExtractorCompat(context); + Uri fileUri = Uri.parse(MP4_FILE_ASSET_DIRECTORY + inputFileName); + extractor.setDataSource(fileUri, /* offset= */ 0); + + List addedTracks = new ArrayList<>(); + for (int i = 0; i < extractor.getTrackCount(); i++) { + int trackId = + muxer.addTrack(MediaFormatUtil.createFormatFromMediaFormat(extractor.getTrackFormat(i))); + addedTracks.add(trackId); + extractor.selectTrack(i); + } + + do { + MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo(); + bufferInfo.flags = extractor.getSampleFlags(); + bufferInfo.offset = 0; + bufferInfo.presentationTimeUs = extractor.getSampleTime(); + int sampleSize = (int) extractor.getSampleSize(); + bufferInfo.size = sampleSize; + + ByteBuffer sampleBuffer = ByteBuffer.allocateDirect(sampleSize); + extractor.readSampleData(sampleBuffer, /* offset= */ 0); + + sampleBuffer.rewind(); + + muxer.writeSampleData( + addedTracks.get(extractor.getSampleTrackIndex()), sampleBuffer, bufferInfo); + } while (extractor.advance()); + + extractor.release(); + } + private MuxerTestUtil() {} }