Follow practices/guidance in Muxer tests around:

* @Before and @After usage. [1].
* static fields before non-static. [2].

@Before method should typically be paired with an @After method,
focused on ensuring that the component is released regardless of what
the test does.

In tests, inlining final class variables is preferrable [1]. In general
things like the file path should be part of the test (the @Rule means
we don't need before/after) if only used once.

Statically importing values and using them directly is preferable to
having a variable declared as non-final that's effectively final,
because from a readability perspective someone can see (the caps) that
the value is final static and immutable, so doesn't have to check if
it's changed/reassigned.

PiperOrigin-RevId: 586697887
This commit is contained in:
samrobinson 2023-11-30 09:26:50 -08:00 committed by Copybara-Service
parent 5b3491082b
commit fe272d3c49
5 changed files with 90 additions and 117 deletions

View File

@ -17,6 +17,10 @@ package androidx.media3.muxer;
import static androidx.media3.muxer.Mp4Muxer.LAST_FRAME_DURATION_BEHAVIOR_DUPLICATE_PREV_DURATION; import static androidx.media3.muxer.Mp4Muxer.LAST_FRAME_DURATION_BEHAVIOR_DUPLICATE_PREV_DURATION;
import static androidx.media3.muxer.Mp4Muxer.LAST_FRAME_DURATION_BEHAVIOR_INSERT_SHORT_FRAME; import static androidx.media3.muxer.Mp4Muxer.LAST_FRAME_DURATION_BEHAVIOR_INSERT_SHORT_FRAME;
import static androidx.media3.muxer.MuxerTestUtil.FAKE_AUDIO_FORMAT;
import static androidx.media3.muxer.MuxerTestUtil.FAKE_CSD_0;
import static androidx.media3.muxer.MuxerTestUtil.FAKE_CSD_1;
import static androidx.media3.muxer.MuxerTestUtil.FAKE_VIDEO_FORMAT;
import static androidx.media3.muxer.MuxerTestUtil.getExpectedDumpFilePath; import static androidx.media3.muxer.MuxerTestUtil.getExpectedDumpFilePath;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertThrows;
@ -57,15 +61,13 @@ public class BoxesTest {
@Test @Test
public void createTkhdBox_forVideoTrack_matchesExpected() throws IOException { public void createTkhdBox_forVideoTrack_matchesExpected() throws IOException {
Format videoFormat = MuxerTestUtil.getFakeVideoFormat();
ByteBuffer tkhdBox = ByteBuffer tkhdBox =
Boxes.tkhd( Boxes.tkhd(
/* trackId= */ 1, /* trackId= */ 1,
/* trackDurationVu= */ 5_000_000, /* trackDurationVu= */ 5_000_000,
/* modificationTimestampSeconds= */ 1_000_000_000, /* modificationTimestampSeconds= */ 1_000_000_000,
/* orientation= */ 90, /* orientation= */ 90,
videoFormat); FAKE_VIDEO_FORMAT);
DumpableMp4Box dumpableBox = new DumpableMp4Box(tkhdBox); DumpableMp4Box dumpableBox = new DumpableMp4Box(tkhdBox);
DumpFileAsserts.assertOutput( DumpFileAsserts.assertOutput(
@ -74,15 +76,13 @@ public class BoxesTest {
@Test @Test
public void createTkhdBox_forAudioTrack_matchesExpected() throws IOException { public void createTkhdBox_forAudioTrack_matchesExpected() throws IOException {
Format audioFormat = MuxerTestUtil.getFakeAudioFormat();
ByteBuffer tkhdBox = ByteBuffer tkhdBox =
Boxes.tkhd( Boxes.tkhd(
/* trackId= */ 1, /* trackId= */ 1,
/* trackDurationVu= */ 5_000_000, /* trackDurationVu= */ 5_000_000,
/* modificationTimestampSeconds= */ 1_000_000_000, /* modificationTimestampSeconds= */ 1_000_000_000,
/* orientation= */ 90, /* orientation= */ 90,
audioFormat); FAKE_AUDIO_FORMAT);
DumpableMp4Box dumpableBox = new DumpableMp4Box(tkhdBox); DumpableMp4Box dumpableBox = new DumpableMp4Box(tkhdBox);
DumpFileAsserts.assertOutput( DumpFileAsserts.assertOutput(
@ -315,11 +315,7 @@ public class BoxesTest {
.setMaxInputSize(39) .setMaxInputSize(39)
.setFrameRate(25) .setFrameRate(25)
.setHeight(12) .setHeight(12)
.setInitializationData( .setInitializationData(ImmutableList.of(FAKE_CSD_0, FAKE_CSD_1))
ImmutableList.of(
BaseEncoding.base16()
.decode("0000000167F4000A919B2BF3CB3640000003004000000C83C4896580"),
BaseEncoding.base16().decode("0000000168EBE3C448")))
.build(); .build();
ByteBuffer videoSampleEntryBox = Boxes.videoSampleEntry(format); ByteBuffer videoSampleEntryBox = Boxes.videoSampleEntry(format);

View File

@ -15,12 +15,11 @@
*/ */
package androidx.media3.muxer; package androidx.media3.muxer;
import static androidx.media3.muxer.MuxerTestUtil.FAKE_VIDEO_FORMAT;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.media.MediaCodec.BufferInfo; import android.media.MediaCodec.BufferInfo;
import android.util.Pair; import android.util.Pair;
import androidx.media3.common.Format;
import androidx.media3.extractor.mp4.Mp4Extractor; import androidx.media3.extractor.mp4.Mp4Extractor;
import androidx.media3.muxer.Mp4Muxer.TrackToken; import androidx.media3.muxer.Mp4Muxer.TrackToken;
import androidx.media3.test.utils.DumpFileAsserts; import androidx.media3.test.utils.DumpFileAsserts;
@ -31,7 +30,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TemporaryFolder; import org.junit.rules.TemporaryFolder;
@ -42,24 +40,13 @@ import org.junit.runner.RunWith;
public class Mp4MuxerEndToEndTest { public class Mp4MuxerEndToEndTest {
@Rule public final TemporaryFolder temporaryFolder = new TemporaryFolder(); @Rule public final TemporaryFolder temporaryFolder = new TemporaryFolder();
private Format format;
private String outputFilePath;
private FileOutputStream outputFileStream;
@Before
public void setUp() throws IOException {
outputFilePath = temporaryFolder.newFile("output.mp4").getPath();
outputFileStream = new FileOutputStream(outputFilePath);
format = MuxerTestUtil.getFakeVideoFormat();
}
@Test @Test
public void createMp4File_addTrackAndMetadataButNoSamples_createsEmptyFile() throws IOException { public void createMp4File_addTrackAndMetadataButNoSamples_createsEmptyFile() throws IOException {
Mp4Muxer mp4Muxer = new Mp4Muxer.Builder(outputFileStream).build(); String outputFilePath = temporaryFolder.newFile().getPath();
Mp4Muxer mp4Muxer = new Mp4Muxer.Builder(new FileOutputStream(outputFilePath)).build();
try { try {
mp4Muxer.addTrack(/* sortKey= */ 0, format); mp4Muxer.addTrack(/* sortKey= */ 0, FAKE_VIDEO_FORMAT);
mp4Muxer.setOrientation(90); mp4Muxer.setOrientation(90);
mp4Muxer.addMetadata("key", "value"); mp4Muxer.addMetadata("key", "value");
} finally { } finally {
@ -72,8 +59,8 @@ public class Mp4MuxerEndToEndTest {
@Test @Test
public void createMp4File_withSameTracksOffset_matchesExpected() throws IOException { public void createMp4File_withSameTracksOffset_matchesExpected() throws IOException {
Context context = ApplicationProvider.getApplicationContext(); String outputFilePath = temporaryFolder.newFile().getPath();
Mp4Muxer mp4Muxer = new Mp4Muxer.Builder(outputFileStream).build(); Mp4Muxer mp4Muxer = new Mp4Muxer.Builder(new FileOutputStream(outputFilePath)).build();
mp4Muxer.setModificationTime(/* timestampMs= */ 500_000_000L); mp4Muxer.setModificationTime(/* timestampMs= */ 500_000_000L);
Pair<ByteBuffer, BufferInfo> track1Sample1 = Pair<ByteBuffer, BufferInfo> track1Sample1 =
@ -87,12 +74,12 @@ public class Mp4MuxerEndToEndTest {
MuxerTestUtil.getFakeSampleAndSampleInfo(/* presentationTimeUs= */ 300L); MuxerTestUtil.getFakeSampleAndSampleInfo(/* presentationTimeUs= */ 300L);
try { try {
TrackToken track1 = mp4Muxer.addTrack(/* sortKey= */ 0, format); TrackToken track1 = mp4Muxer.addTrack(/* sortKey= */ 0, FAKE_VIDEO_FORMAT);
mp4Muxer.writeSampleData(track1, track1Sample1.first, track1Sample1.second); mp4Muxer.writeSampleData(track1, track1Sample1.first, track1Sample1.second);
mp4Muxer.writeSampleData(track1, track1Sample2.first, track1Sample2.second); mp4Muxer.writeSampleData(track1, track1Sample2.first, track1Sample2.second);
// Add same track again but with different samples. // Add same track again but with different samples.
TrackToken track2 = mp4Muxer.addTrack(/* sortKey= */ 1, format); TrackToken track2 = mp4Muxer.addTrack(/* sortKey= */ 1, FAKE_VIDEO_FORMAT);
mp4Muxer.writeSampleData(track2, track2Sample1.first, track2Sample1.second); mp4Muxer.writeSampleData(track2, track2Sample1.first, track2Sample1.second);
mp4Muxer.writeSampleData(track2, track2Sample2.first, track2Sample2.second); mp4Muxer.writeSampleData(track2, track2Sample2.first, track2Sample2.second);
} finally { } finally {
@ -107,15 +94,15 @@ public class Mp4MuxerEndToEndTest {
FakeExtractorOutput fakeExtractorOutput = FakeExtractorOutput fakeExtractorOutput =
TestUtil.extractAllSamplesFromFilePath(new Mp4Extractor(), outputFilePath); TestUtil.extractAllSamplesFromFilePath(new Mp4Extractor(), outputFilePath);
DumpFileAsserts.assertOutput( DumpFileAsserts.assertOutput(
context, ApplicationProvider.getApplicationContext(),
fakeExtractorOutput, fakeExtractorOutput,
MuxerTestUtil.getExpectedDumpFilePath("mp4_with_same_tracks_offset.mp4")); MuxerTestUtil.getExpectedDumpFilePath("mp4_with_same_tracks_offset.mp4"));
} }
@Test @Test
public void createMp4File_withDifferentTracksOffset_matchesExpected() throws IOException { public void createMp4File_withDifferentTracksOffset_matchesExpected() throws IOException {
Context context = ApplicationProvider.getApplicationContext(); String outputFilePath = temporaryFolder.newFile().getPath();
Mp4Muxer mp4Muxer = new Mp4Muxer.Builder(outputFileStream).build(); Mp4Muxer mp4Muxer = new Mp4Muxer.Builder(new FileOutputStream(outputFilePath)).build();
mp4Muxer.setModificationTime(/* timestampMs= */ 500_000_000L); mp4Muxer.setModificationTime(/* timestampMs= */ 500_000_000L);
Pair<ByteBuffer, BufferInfo> track1Sample1 = Pair<ByteBuffer, BufferInfo> track1Sample1 =
@ -129,12 +116,12 @@ public class Mp4MuxerEndToEndTest {
MuxerTestUtil.getFakeSampleAndSampleInfo(/* presentationTimeUs= */ 200L); MuxerTestUtil.getFakeSampleAndSampleInfo(/* presentationTimeUs= */ 200L);
try { try {
TrackToken track1 = mp4Muxer.addTrack(/* sortKey= */ 0, format); TrackToken track1 = mp4Muxer.addTrack(/* sortKey= */ 0, FAKE_VIDEO_FORMAT);
mp4Muxer.writeSampleData(track1, track1Sample1.first, track1Sample1.second); mp4Muxer.writeSampleData(track1, track1Sample1.first, track1Sample1.second);
mp4Muxer.writeSampleData(track1, track1Sample2.first, track1Sample2.second); mp4Muxer.writeSampleData(track1, track1Sample2.first, track1Sample2.second);
// Add same track again but with different samples. // Add same track again but with different samples.
TrackToken track2 = mp4Muxer.addTrack(/* sortKey= */ 1, format); TrackToken track2 = mp4Muxer.addTrack(/* sortKey= */ 1, FAKE_VIDEO_FORMAT);
mp4Muxer.writeSampleData(track2, track2Sample1.first, track2Sample1.second); mp4Muxer.writeSampleData(track2, track2Sample1.first, track2Sample1.second);
mp4Muxer.writeSampleData(track2, track2Sample2.first, track2Sample2.second); mp4Muxer.writeSampleData(track2, track2Sample2.first, track2Sample2.second);
} finally { } finally {
@ -145,7 +132,7 @@ public class Mp4MuxerEndToEndTest {
FakeExtractorOutput fakeExtractorOutput = FakeExtractorOutput fakeExtractorOutput =
TestUtil.extractAllSamplesFromFilePath(new Mp4Extractor(), outputFilePath); TestUtil.extractAllSamplesFromFilePath(new Mp4Extractor(), outputFilePath);
DumpFileAsserts.assertOutput( DumpFileAsserts.assertOutput(
context, ApplicationProvider.getApplicationContext(),
fakeExtractorOutput, fakeExtractorOutput,
MuxerTestUtil.getExpectedDumpFilePath("mp4_with_different_tracks_offset.mp4")); MuxerTestUtil.getExpectedDumpFilePath("mp4_with_different_tracks_offset.mp4"));
} }

View File

@ -15,10 +15,11 @@
*/ */
package androidx.media3.muxer; package androidx.media3.muxer;
import static androidx.media3.muxer.MuxerTestUtil.FAKE_VIDEO_FORMAT;
import android.content.Context; import android.content.Context;
import android.media.MediaCodec.BufferInfo; import android.media.MediaCodec.BufferInfo;
import android.util.Pair; import android.util.Pair;
import androidx.media3.common.Format;
import androidx.media3.extractor.mp4.Mp4Extractor; import androidx.media3.extractor.mp4.Mp4Extractor;
import androidx.media3.muxer.Mp4Muxer.TrackToken; import androidx.media3.muxer.Mp4Muxer.TrackToken;
import androidx.media3.test.utils.DumpFileAsserts; import androidx.media3.test.utils.DumpFileAsserts;
@ -29,7 +30,6 @@ import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TemporaryFolder; import org.junit.rules.TemporaryFolder;
@ -43,30 +43,18 @@ public class Mp4MuxerMetadataTest {
// Input files. // Input files.
private static final String XMP_SAMPLE_DATA = "media/xmp/sample_datetime_xmp.xmp"; private static final String XMP_SAMPLE_DATA = "media/xmp/sample_datetime_xmp.xmp";
private Context context; private final Context context = ApplicationProvider.getApplicationContext();
private String outputFilePath; private final Pair<ByteBuffer, BufferInfo> sampleAndSampleInfo =
private FileOutputStream outputFileStream; MuxerTestUtil.getFakeSampleAndSampleInfo(/* presentationTimeUs= */ 0L);
private Format format;
private Pair<ByteBuffer, BufferInfo> sampleAndSampleInfo;
@Before
public void setUp() throws Exception {
context = ApplicationProvider.getApplicationContext();
outputFilePath = temporaryFolder.newFile("output.mp4").getPath();
outputFileStream = new FileOutputStream(outputFilePath);
format = MuxerTestUtil.getFakeVideoFormat();
sampleAndSampleInfo = MuxerTestUtil.getFakeSampleAndSampleInfo(/* presentationTimeUs= */ 0L);
}
@Test @Test
public void writeMp4File_orientationNotSet_setsOrientationTo0() throws Exception { public void writeMp4File_orientationNotSet_setsOrientationTo0() throws Exception {
Mp4Muxer muxer = new Mp4Muxer.Builder(outputFileStream).build(); String outputFilePath = temporaryFolder.newFile().getPath();
Mp4Muxer muxer = new Mp4Muxer.Builder(new FileOutputStream(outputFilePath)).build();
try { try {
muxer.setModificationTime(/* timestampMs= */ 5_000_000L); muxer.setModificationTime(/* timestampMs= */ 5_000_000L);
TrackToken token = muxer.addTrack(/* sortKey= */ 0, format); TrackToken token = muxer.addTrack(/* sortKey= */ 0, FAKE_VIDEO_FORMAT);
muxer.writeSampleData(token, sampleAndSampleInfo.first, sampleAndSampleInfo.second); muxer.writeSampleData(token, sampleAndSampleInfo.first, sampleAndSampleInfo.second);
} finally { } finally {
muxer.close(); muxer.close();
@ -83,11 +71,12 @@ public class Mp4MuxerMetadataTest {
@Test @Test
public void writeMp4File_setOrientationTo90_setsOrientationTo90() throws Exception { public void writeMp4File_setOrientationTo90_setsOrientationTo90() throws Exception {
Mp4Muxer muxer = new Mp4Muxer.Builder(outputFileStream).build(); String outputFilePath = temporaryFolder.newFile().getPath();
Mp4Muxer muxer = new Mp4Muxer.Builder(new FileOutputStream(outputFilePath)).build();
try { try {
muxer.setModificationTime(/* timestampMs= */ 5_000_000L); muxer.setModificationTime(/* timestampMs= */ 5_000_000L);
TrackToken token = muxer.addTrack(/* sortKey= */ 0, format); TrackToken token = muxer.addTrack(/* sortKey= */ 0, FAKE_VIDEO_FORMAT);
muxer.writeSampleData(token, sampleAndSampleInfo.first, sampleAndSampleInfo.second); muxer.writeSampleData(token, sampleAndSampleInfo.first, sampleAndSampleInfo.second);
muxer.setOrientation(90); muxer.setOrientation(90);
@ -106,11 +95,12 @@ public class Mp4MuxerMetadataTest {
@Test @Test
public void writeMp4File_setOrientationTo180_setsOrientationTo180() throws Exception { public void writeMp4File_setOrientationTo180_setsOrientationTo180() throws Exception {
Mp4Muxer muxer = new Mp4Muxer.Builder(outputFileStream).build(); String outputFilePath = temporaryFolder.newFile().getPath();
Mp4Muxer muxer = new Mp4Muxer.Builder(new FileOutputStream(outputFilePath)).build();
try { try {
muxer.setModificationTime(/* timestampMs= */ 5_000_000L); muxer.setModificationTime(/* timestampMs= */ 5_000_000L);
TrackToken token = muxer.addTrack(/* sortKey= */ 0, format); TrackToken token = muxer.addTrack(/* sortKey= */ 0, FAKE_VIDEO_FORMAT);
muxer.writeSampleData(token, sampleAndSampleInfo.first, sampleAndSampleInfo.second); muxer.writeSampleData(token, sampleAndSampleInfo.first, sampleAndSampleInfo.second);
muxer.setOrientation(180); muxer.setOrientation(180);
@ -129,11 +119,12 @@ public class Mp4MuxerMetadataTest {
@Test @Test
public void writeMp4File_setOrientationTo270_setsOrientationTo270() throws Exception { public void writeMp4File_setOrientationTo270_setsOrientationTo270() throws Exception {
Mp4Muxer muxer = new Mp4Muxer.Builder(outputFileStream).build(); String outputFilePath = temporaryFolder.newFile().getPath();
Mp4Muxer muxer = new Mp4Muxer.Builder(new FileOutputStream(outputFilePath)).build();
try { try {
muxer.setModificationTime(/* timestampMs= */ 5_000_000L); muxer.setModificationTime(/* timestampMs= */ 5_000_000L);
TrackToken token = muxer.addTrack(/* sortKey= */ 0, format); TrackToken token = muxer.addTrack(/* sortKey= */ 0, FAKE_VIDEO_FORMAT);
muxer.writeSampleData(token, sampleAndSampleInfo.first, sampleAndSampleInfo.second); muxer.writeSampleData(token, sampleAndSampleInfo.first, sampleAndSampleInfo.second);
muxer.setOrientation(270); muxer.setOrientation(270);
@ -152,11 +143,12 @@ public class Mp4MuxerMetadataTest {
@Test @Test
public void writeMp4File_setLocation_setsSameLocation() throws Exception { public void writeMp4File_setLocation_setsSameLocation() throws Exception {
Mp4Muxer muxer = new Mp4Muxer.Builder(outputFileStream).build(); String outputFilePath = temporaryFolder.newFile().getPath();
Mp4Muxer muxer = new Mp4Muxer.Builder(new FileOutputStream(outputFilePath)).build();
try { try {
muxer.setModificationTime(/* timestampMs= */ 5_000_000L); muxer.setModificationTime(/* timestampMs= */ 5_000_000L);
TrackToken token = muxer.addTrack(/* sortKey= */ 0, format); TrackToken token = muxer.addTrack(/* sortKey= */ 0, FAKE_VIDEO_FORMAT);
muxer.writeSampleData(token, sampleAndSampleInfo.first, sampleAndSampleInfo.second); muxer.writeSampleData(token, sampleAndSampleInfo.first, sampleAndSampleInfo.second);
muxer.setLocation(33.0f, -120f); muxer.setLocation(33.0f, -120f);
} finally { } finally {
@ -174,11 +166,12 @@ public class Mp4MuxerMetadataTest {
@Test @Test
public void writeMp4File_locationNotSet_setsLocationToNull() throws Exception { public void writeMp4File_locationNotSet_setsLocationToNull() throws Exception {
Mp4Muxer muxer = new Mp4Muxer.Builder(outputFileStream).build(); String outputFilePath = temporaryFolder.newFile().getPath();
Mp4Muxer muxer = new Mp4Muxer.Builder(new FileOutputStream(outputFilePath)).build();
try { try {
muxer.setModificationTime(/* timestampMs= */ 5_000_000L); muxer.setModificationTime(/* timestampMs= */ 5_000_000L);
TrackToken token = muxer.addTrack(/* sortKey= */ 0, format); TrackToken token = muxer.addTrack(/* sortKey= */ 0, FAKE_VIDEO_FORMAT);
muxer.writeSampleData(token, sampleAndSampleInfo.first, sampleAndSampleInfo.second); muxer.writeSampleData(token, sampleAndSampleInfo.first, sampleAndSampleInfo.second);
} finally { } finally {
muxer.close(); muxer.close();
@ -195,12 +188,13 @@ public class Mp4MuxerMetadataTest {
@Test @Test
public void writeMp4File_setFrameRate_setsSameFrameRate() throws Exception { public void writeMp4File_setFrameRate_setsSameFrameRate() throws Exception {
Mp4Muxer muxer = new Mp4Muxer.Builder(outputFileStream).build(); String outputFilePath = temporaryFolder.newFile().getPath();
Mp4Muxer muxer = new Mp4Muxer.Builder(new FileOutputStream(outputFilePath)).build();
try { try {
muxer.setModificationTime(/* timestampMs= */ 5_000_000L); muxer.setModificationTime(/* timestampMs= */ 5_000_000L);
muxer.setCaptureFps(120.0f); muxer.setCaptureFps(120.0f);
TrackToken token = muxer.addTrack(/* sortKey= */ 0, format); TrackToken token = muxer.addTrack(/* sortKey= */ 0, FAKE_VIDEO_FORMAT);
muxer.writeSampleData(token, sampleAndSampleInfo.first, sampleAndSampleInfo.second); muxer.writeSampleData(token, sampleAndSampleInfo.first, sampleAndSampleInfo.second);
} finally { } finally {
muxer.close(); muxer.close();
@ -217,12 +211,13 @@ public class Mp4MuxerMetadataTest {
@Test @Test
public void writeMp4File_addStringMetadata_matchesExpected() throws Exception { public void writeMp4File_addStringMetadata_matchesExpected() throws Exception {
Mp4Muxer muxer = new Mp4Muxer.Builder(outputFileStream).build(); String outputFilePath = temporaryFolder.newFile().getPath();
Mp4Muxer muxer = new Mp4Muxer.Builder(new FileOutputStream(outputFilePath)).build();
try { try {
muxer.setModificationTime(/* timestampMs= */ 5_000_000L); muxer.setModificationTime(/* timestampMs= */ 5_000_000L);
muxer.addMetadata("SomeStringKey", "Some Random String"); muxer.addMetadata("SomeStringKey", "Some Random String");
TrackToken token = muxer.addTrack(/* sortKey= */ 0, format); TrackToken token = muxer.addTrack(/* sortKey= */ 0, FAKE_VIDEO_FORMAT);
muxer.writeSampleData(token, sampleAndSampleInfo.first, sampleAndSampleInfo.second); muxer.writeSampleData(token, sampleAndSampleInfo.first, sampleAndSampleInfo.second);
} finally { } finally {
muxer.close(); muxer.close();
@ -239,12 +234,13 @@ public class Mp4MuxerMetadataTest {
@Test @Test
public void writeMp4File_addFloatMetadata_matchesExpected() throws Exception { public void writeMp4File_addFloatMetadata_matchesExpected() throws Exception {
Mp4Muxer muxer = new Mp4Muxer.Builder(outputFileStream).build(); String outputFilePath = temporaryFolder.newFile().getPath();
Mp4Muxer muxer = new Mp4Muxer.Builder(new FileOutputStream(outputFilePath)).build();
try { try {
muxer.setModificationTime(/* timestampMs= */ 5_000_000L); muxer.setModificationTime(/* timestampMs= */ 5_000_000L);
muxer.addMetadata("SomeStringKey", 10.0f); muxer.addMetadata("SomeStringKey", 10.0f);
TrackToken token = muxer.addTrack(/* sortKey= */ 0, format); TrackToken token = muxer.addTrack(/* sortKey= */ 0, FAKE_VIDEO_FORMAT);
muxer.writeSampleData(token, sampleAndSampleInfo.first, sampleAndSampleInfo.second); muxer.writeSampleData(token, sampleAndSampleInfo.first, sampleAndSampleInfo.second);
} finally { } finally {
muxer.close(); muxer.close();
@ -261,7 +257,8 @@ public class Mp4MuxerMetadataTest {
@Test @Test
public void writeMp4File_addXmp_matchesExpected() throws Exception { public void writeMp4File_addXmp_matchesExpected() throws Exception {
Mp4Muxer muxer = new Mp4Muxer.Builder(outputFileStream).build(); String outputFilePath = temporaryFolder.newFile().getPath();
Mp4Muxer muxer = new Mp4Muxer.Builder(new FileOutputStream(outputFilePath)).build();
try { try {
muxer.setModificationTime(/* timestampMs= */ 5_000_000L); muxer.setModificationTime(/* timestampMs= */ 5_000_000L);
@ -270,7 +267,7 @@ public class Mp4MuxerMetadataTest {
ByteBuffer xmp = ByteBuffer.wrap(xmpBytes); ByteBuffer xmp = ByteBuffer.wrap(xmpBytes);
muxer.addXmp(xmp); muxer.addXmp(xmp);
xmp.rewind(); xmp.rewind();
TrackToken token = muxer.addTrack(0, format); TrackToken token = muxer.addTrack(0, FAKE_VIDEO_FORMAT);
muxer.writeSampleData(token, sampleAndSampleInfo.first, sampleAndSampleInfo.second); muxer.writeSampleData(token, sampleAndSampleInfo.first, sampleAndSampleInfo.second);
} finally { } finally {
muxer.close(); muxer.close();

View File

@ -15,6 +15,9 @@
*/ */
package androidx.media3.muxer; package androidx.media3.muxer;
import static androidx.media3.common.MimeTypes.AUDIO_AAC;
import static androidx.media3.common.MimeTypes.VIDEO_H264;
import android.media.MediaCodec; import android.media.MediaCodec;
import android.media.MediaCodec.BufferInfo; import android.media.MediaCodec.BufferInfo;
import android.util.Pair; import android.util.Pair;
@ -25,9 +28,24 @@ import java.nio.ByteBuffer;
/** Utilities for muxer test cases. */ /** Utilities for muxer test cases. */
/* package */ class MuxerTestUtil { /* package */ class MuxerTestUtil {
private static final byte[] FAKE_CSD_0 =
public static final byte[] FAKE_CSD_0 =
BaseEncoding.base16().decode("0000000167F4000A919B2BF3CB3640000003004000000C83C4896580"); BaseEncoding.base16().decode("0000000167F4000A919B2BF3CB3640000003004000000C83C4896580");
private static final byte[] FAKE_CSD_1 = BaseEncoding.base16().decode("0000000168EBE3C448"); public static final byte[] FAKE_CSD_1 = BaseEncoding.base16().decode("0000000168EBE3C448");
public static final Format FAKE_AUDIO_FORMAT =
new Format.Builder()
.setSampleMimeType(AUDIO_AAC)
.setSampleRate(40000)
.setChannelCount(2)
.build();
public static final Format FAKE_VIDEO_FORMAT =
new Format.Builder()
.setSampleMimeType(VIDEO_H264)
.setWidth(12)
.setHeight(10)
.setInitializationData(ImmutableList.of(FAKE_CSD_0, FAKE_CSD_1))
.build();
private static final byte[] FAKE_H264_SAMPLE = private static final byte[] FAKE_H264_SAMPLE =
BaseEncoding.base16() BaseEncoding.base16()
.decode( .decode(
@ -40,23 +58,6 @@ import java.nio.ByteBuffer;
return DUMP_FILE_OUTPUT_DIRECTORY + '/' + originalFileName + '.' + DUMP_FILE_EXTENSION; return DUMP_FILE_OUTPUT_DIRECTORY + '/' + originalFileName + '.' + DUMP_FILE_EXTENSION;
} }
public static Format getFakeVideoFormat() {
return new Format.Builder()
.setSampleMimeType("video/avc")
.setWidth(12)
.setHeight(10)
.setInitializationData(ImmutableList.of(FAKE_CSD_0, FAKE_CSD_1))
.build();
}
public static Format getFakeAudioFormat() {
return new Format.Builder()
.setSampleMimeType("audio/mp4a-latm")
.setSampleRate(40000)
.setChannelCount(2)
.build();
}
public static Pair<ByteBuffer, BufferInfo> getFakeSampleAndSampleInfo(long presentationTimeUs) { public static Pair<ByteBuffer, BufferInfo> getFakeSampleAndSampleInfo(long presentationTimeUs) {
ByteBuffer sampleDirectBuffer = ByteBuffer.allocateDirect(FAKE_H264_SAMPLE.length); ByteBuffer sampleDirectBuffer = ByteBuffer.allocateDirect(FAKE_H264_SAMPLE.length);
sampleDirectBuffer.put(FAKE_H264_SAMPLE); sampleDirectBuffer.put(FAKE_H264_SAMPLE);

View File

@ -15,6 +15,7 @@
*/ */
package androidx.media3.transformer; package androidx.media3.transformer;
import static androidx.media3.common.MimeTypes.AUDIO_AAC;
import static androidx.media3.common.MimeTypes.VIDEO_H264; import static androidx.media3.common.MimeTypes.VIDEO_H264;
import static androidx.media3.transformer.MuxerWrapper.MUXER_MODE_MUX_PARTIAL_VIDEO; import static androidx.media3.transformer.MuxerWrapper.MUXER_MODE_MUX_PARTIAL_VIDEO;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
@ -25,9 +26,7 @@ import androidx.media3.common.ColorInfo;
import androidx.media3.common.Format; import androidx.media3.common.Format;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TemporaryFolder; import org.junit.rules.TemporaryFolder;
@ -36,8 +35,6 @@ import org.junit.runner.RunWith;
/** Unit tests for {@link MuxerWrapper}. */ /** Unit tests for {@link MuxerWrapper}. */
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
public class MuxerWrapperTest { public class MuxerWrapperTest {
@Rule public final TemporaryFolder temporaryFolder = new TemporaryFolder();
private static final Format FAKE_VIDEO_TRACK_FORMAT = private static final Format FAKE_VIDEO_TRACK_FORMAT =
new Format.Builder() new Format.Builder()
.setSampleMimeType(VIDEO_H264) .setSampleMimeType(VIDEO_H264)
@ -48,25 +45,20 @@ public class MuxerWrapperTest {
.build(); .build();
private static final Format FAKE_AUDIO_TRACK_FORMAT = private static final Format FAKE_AUDIO_TRACK_FORMAT =
new Format.Builder() new Format.Builder()
.setSampleMimeType("audio/mp4a-latm") .setSampleMimeType(AUDIO_AAC)
.setSampleRate(40000) .setSampleRate(40000)
.setChannelCount(2) .setChannelCount(2)
.build(); .build();
private static final ByteBuffer FAKE_SAMPLE = ByteBuffer.wrap(new byte[] {1, 2, 3, 4}); private static final ByteBuffer FAKE_SAMPLE = ByteBuffer.wrap(new byte[] {1, 2, 3, 4});
private String outputFilePath; @Rule public final TemporaryFolder temporaryFolder = new TemporaryFolder();
@Before
public void setUp() throws IOException {
outputFilePath = temporaryFolder.newFile("output.mp4").getPath();
}
@Test @Test
public void changeToAppendVideoMode_afterDefaultMode_throws() { public void changeToAppendVideoMode_afterDefaultMode_throws() throws Exception {
MuxerWrapper muxerWrapper = MuxerWrapper muxerWrapper =
new MuxerWrapper( new MuxerWrapper(
outputFilePath, temporaryFolder.newFile().getPath(),
new DefaultMuxer.Factory(), new DefaultMuxer.Factory(),
new NoOpMuxerListenerImpl(), new NoOpMuxerListenerImpl(),
MuxerWrapper.MUXER_MODE_DEFAULT); MuxerWrapper.MUXER_MODE_DEFAULT);
@ -75,10 +67,10 @@ public class MuxerWrapperTest {
} }
@Test @Test
public void setTrackCount_toTwoInMuxPartialVideoMode_throws() { public void setTrackCount_toTwoInMuxPartialVideoMode_throws() throws Exception {
MuxerWrapper muxerWrapper = MuxerWrapper muxerWrapper =
new MuxerWrapper( new MuxerWrapper(
outputFilePath, temporaryFolder.newFile().getPath(),
new DefaultMuxer.Factory(), new DefaultMuxer.Factory(),
new NoOpMuxerListenerImpl(), new NoOpMuxerListenerImpl(),
MUXER_MODE_MUX_PARTIAL_VIDEO); MUXER_MODE_MUX_PARTIAL_VIDEO);
@ -90,7 +82,7 @@ public class MuxerWrapperTest {
public void setTrackCount_toTwoInAppendVideoMode_throws() throws Exception { public void setTrackCount_toTwoInAppendVideoMode_throws() throws Exception {
MuxerWrapper muxerWrapper = MuxerWrapper muxerWrapper =
new MuxerWrapper( new MuxerWrapper(
outputFilePath, temporaryFolder.newFile().getPath(),
new DefaultMuxer.Factory(), new DefaultMuxer.Factory(),
new NoOpMuxerListenerImpl(), new NoOpMuxerListenerImpl(),
MUXER_MODE_MUX_PARTIAL_VIDEO); MUXER_MODE_MUX_PARTIAL_VIDEO);
@ -105,10 +97,10 @@ public class MuxerWrapperTest {
} }
@Test @Test
public void addTrackFormat_withAudioFormatInMuxPartialVideoMode_throws() { public void addTrackFormat_withAudioFormatInMuxPartialVideoMode_throws() throws Exception {
MuxerWrapper muxerWrapper = MuxerWrapper muxerWrapper =
new MuxerWrapper( new MuxerWrapper(
outputFilePath, temporaryFolder.newFile().getPath(),
new DefaultMuxer.Factory(), new DefaultMuxer.Factory(),
new NoOpMuxerListenerImpl(), new NoOpMuxerListenerImpl(),
MUXER_MODE_MUX_PARTIAL_VIDEO); MUXER_MODE_MUX_PARTIAL_VIDEO);
@ -122,7 +114,7 @@ public class MuxerWrapperTest {
public void addTrackFormat_withSameVideoFormatInAppendVideoMode_doesNotThrow() throws Exception { public void addTrackFormat_withSameVideoFormatInAppendVideoMode_doesNotThrow() throws Exception {
MuxerWrapper muxerWrapper = MuxerWrapper muxerWrapper =
new MuxerWrapper( new MuxerWrapper(
outputFilePath, temporaryFolder.newFile().getPath(),
new DefaultMuxer.Factory(), new DefaultMuxer.Factory(),
new NoOpMuxerListenerImpl(), new NoOpMuxerListenerImpl(),
MUXER_MODE_MUX_PARTIAL_VIDEO); MUXER_MODE_MUX_PARTIAL_VIDEO);
@ -141,7 +133,7 @@ public class MuxerWrapperTest {
public void addTrackFormat_withDifferentVideoFormatInAppendVideoMode_throws() throws Exception { public void addTrackFormat_withDifferentVideoFormatInAppendVideoMode_throws() throws Exception {
MuxerWrapper muxerWrapper = MuxerWrapper muxerWrapper =
new MuxerWrapper( new MuxerWrapper(
outputFilePath, temporaryFolder.newFile().getPath(),
new DefaultMuxer.Factory(), new DefaultMuxer.Factory(),
new NoOpMuxerListenerImpl(), new NoOpMuxerListenerImpl(),
MUXER_MODE_MUX_PARTIAL_VIDEO); MUXER_MODE_MUX_PARTIAL_VIDEO);
@ -162,7 +154,7 @@ public class MuxerWrapperTest {
public void isEnded_afterPartialVideoMuxed_returnsTrue() throws Exception { public void isEnded_afterPartialVideoMuxed_returnsTrue() throws Exception {
MuxerWrapper muxerWrapper = MuxerWrapper muxerWrapper =
new MuxerWrapper( new MuxerWrapper(
outputFilePath, temporaryFolder.newFile().getPath(),
new DefaultMuxer.Factory(), new DefaultMuxer.Factory(),
new NoOpMuxerListenerImpl(), new NoOpMuxerListenerImpl(),
MUXER_MODE_MUX_PARTIAL_VIDEO); MUXER_MODE_MUX_PARTIAL_VIDEO);
@ -179,7 +171,7 @@ public class MuxerWrapperTest {
public void isEnded_afterStartingAppendVideo_returnsFalse() throws Exception { public void isEnded_afterStartingAppendVideo_returnsFalse() throws Exception {
MuxerWrapper muxerWrapper = MuxerWrapper muxerWrapper =
new MuxerWrapper( new MuxerWrapper(
outputFilePath, temporaryFolder.newFile().getPath(),
new DefaultMuxer.Factory(), new DefaultMuxer.Factory(),
new NoOpMuxerListenerImpl(), new NoOpMuxerListenerImpl(),
MUXER_MODE_MUX_PARTIAL_VIDEO); MUXER_MODE_MUX_PARTIAL_VIDEO);