Add support to MPEG4 codec in Mp4Muxer.

Add support for MPEG4 codec to enable muxing video encoded with the mp4v-es codec. Use esdsBox method to generate esds box required for Mp4v box.

PiperOrigin-RevId: 651000744
This commit is contained in:
Googler 2024-07-10 06:52:29 -07:00 committed by Copybara-Service
parent cf90d2624d
commit 34a802ef38
6 changed files with 132 additions and 6 deletions

View File

@ -52,6 +52,7 @@ public class Mp4MuxerEndToEndParameterizedAndroidTest {
private static final String H265_WITH_METADATA_TRACK_MP4 = "h265_with_metadata_track.mp4";
private static final String AV1_MP4 = "sample_av1.mp4";
private static final String AMR_WB = "bbb_mono_16kHz_23.05kbps_amrwb.3gp";
private static final String MPEG4_MP4 = "bbb_176x144_192kbps_15fps_mpeg4.mp4";
@Parameters(name = "{0}")
public static ImmutableList<String> mediaSamples() {
@ -62,7 +63,8 @@ public class Mp4MuxerEndToEndParameterizedAndroidTest {
H265_HDR10_MP4,
H265_WITH_METADATA_TRACK_MP4,
AV1_MP4,
AMR_WB);
AMR_WB,
MPEG4_MP4);
}
@Parameter public @MonotonicNonNull String inputFile;

View File

@ -542,6 +542,7 @@ import java.util.List;
String mimeType = checkNotNull(format.sampleMimeType);
switch (mimeType) {
case MimeTypes.AUDIO_AAC:
case MimeTypes.VIDEO_MP4V:
return esdsBox(format);
case MimeTypes.AUDIO_AMR_WB:
return damrBox(/* mode= */ (short) 0x83FF); // mode set: all enabled
@ -1329,6 +1330,8 @@ import java.util.List;
return "hvc1";
case MimeTypes.VIDEO_AV1:
return "av01";
case MimeTypes.VIDEO_MP4V:
return "mp4v-es";
default:
throw new IllegalArgumentException("Unsupported format: " + mimeType);
}
@ -1344,6 +1347,7 @@ import java.util.List;
ByteBuffer csd0ByteBuffer = ByteBuffer.wrap(csd0);
int peakBitrate = format.peakBitrate;
int averageBitrate = format.averageBitrate;
boolean isVideo = MimeTypes.isVideo(format.sampleMimeType);
int csd0Size = csd0ByteBuffer.limit();
ByteBuffer dsiSizeBuffer = getSizeBuffer(csd0Size);
@ -1358,17 +1362,18 @@ import java.util.List;
contents.put(esdSizeBuffer);
contents.putShort((short) 0x0000); // First 16 bits of ES_ID.
contents.put((byte) 0x00); // Last 8 bits of ES_ID.
contents.put(isVideo ? (byte) 0x1f : (byte) 0x00); // Last 8 bits of ES_ID.
contents.put((byte) 0x04); // DecoderConfigDescrTag
contents.put(dcdSizeBuffer);
contents.put((byte) 0x40); // objectTypeIndication
contents.put(isVideo ? (byte) 0x20 : (byte) 0x40); // objectTypeIndication
// streamType (6 bits) | upStream (1 bit) | reserved = 1 (1 bit)
contents.put((byte) ((0x05 << 2) | 0x01)); // streamType AudioStream
contents.put((byte) ((isVideo ? (0x04 << 2) : (0x05 << 2)) | 0x01)); // streamType
contents.putShort((short) 0x03); // First 16 bits of buffer size (0x300).
contents.put((byte) 0x00); // Last 8 bits of buffer size (0x300).
int size = isVideo ? 0x017700 : 0x000300;
contents.putShort((short) ((size >> 8) & 0xFFFF)); // First 16 bits of buffer size.
contents.put((byte) 0x00); // Last 8 bits of buffer size.
contents.putInt(peakBitrate != Format.NO_VALUE ? peakBitrate : 0);
contents.putInt(averageBitrate != Format.NO_VALUE ? averageBitrate : 0);

View File

@ -30,6 +30,7 @@ import android.media.MediaCodec;
import androidx.media3.common.C;
import androidx.media3.common.ColorInfo;
import androidx.media3.common.Format;
import androidx.media3.common.MimeTypes;
import androidx.media3.common.util.Util;
import androidx.media3.container.MdtaMetadataEntry;
import androidx.media3.container.Mp4LocationData;
@ -396,6 +397,35 @@ public class BoxesTest {
context, dumpableBox, MuxerTestUtil.getExpectedDumpFilePath("video_sample_entry_box_av1"));
}
@Test
public void createVideoSampleEntryBox_forMPEG4_matchesExpected() throws IOException {
Format format =
new Format.Builder()
.setId(1)
.setSampleMimeType(MimeTypes.VIDEO_MP4V)
.setAverageBitrate(9200)
.setPeakBitrate(9200)
.setLanguage("und")
.setWidth(10)
.setMaxInputSize(49)
.setFrameRate(25)
.setHeight(12)
.setInitializationData(
ImmutableList.of(
BaseEncoding.base16()
.decode(
"000001B001000001B58913000001000000012000C48D88007D0584121443000001B24C61766335382E35342E313030")))
.build();
ByteBuffer videoSampleEntryBox = Boxes.videoSampleEntry(format);
DumpableMp4Box dumpableBox = new DumpableMp4Box(videoSampleEntryBox);
DumpFileAsserts.assertOutput(
context,
dumpableBox,
MuxerTestUtil.getExpectedDumpFilePath("video_sample_entry_box_mpeg4"));
}
@Test
public void createVideoSampleEntryBox_withUnknownVideoFormat_throws() {
// The video format contains an unknown MIME type.

View File

@ -0,0 +1,87 @@
seekMap:
isSeekable = true
duration = 933300
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=0, position=400052]]
getPosition(466650) = [[timeUs=0, position=400052]]
getPosition(933300) = [[timeUs=0, position=400052]]
numberOfTracks = 1
track 0:
total output bytes = 45694
sample count = 15
format 0:
averageBitrate = 365552
peakBitrate = 365552
id = 1
sampleMimeType = video/mp4v-es
maxInputSize = 9256
width = 176
height = 144
frameRate = 16.072002
colorInfo:
lumaBitdepth = 8
chromaBitdepth = 8
metadata = entries=[Mp4Timestamp: creation time=100000000, modification time=500000000, timescale=10000]
initializationData:
data = length 47, hash DC4DD041
sample 0:
time = 0
flags = 1
data = length 9226, hash 7C636E69
sample 1:
time = 66655
flags = 0
data = length 2560, hash C7A69F47
sample 2:
time = 133322
flags = 0
data = length 1720, hash 32B683D
sample 3:
time = 200000
flags = 0
data = length 2684, hash A77F20B0
sample 4:
time = 266655
flags = 0
data = length 2966, hash CDB6D380
sample 5:
time = 333322
flags = 0
data = length 3160, hash 5A1455FB
sample 6:
time = 400000
flags = 0
data = length 3128, hash 8F3EA8F2
sample 7:
time = 466655
flags = 0
data = length 3164, hash 40A33F45
sample 8:
time = 533322
flags = 0
data = length 3309, hash 4ACFEBD1
sample 9:
time = 600000
flags = 0
data = length 3332, hash 7902F5A6
sample 10:
time = 666655
flags = 0
data = length 3082, hash 57E4EBB9
sample 11:
time = 733322
flags = 0
data = length 3210, hash FDA3CC0F
sample 12:
time = 800000
flags = 0
data = length 981, hash FA98FC90
sample 13:
time = 866655
flags = 0
data = length 1611, hash 3F58EEE9
sample 14:
time = 933322
flags = 536870912
data = length 1561, hash 24FA5A54
tracksEnded = true

View File

@ -0,0 +1,2 @@
mp4v (186 bytes):
Data = length 178, hash DE771E7E