Add support for 3gpp h263 codec in Mp4Muxer.

Implement d263Box to provide support for muxing video encoded with the h263 codec.

PiperOrigin-RevId: 653188633
This commit is contained in:
Googler 2024-07-17 04:50:41 -07:00 committed by Copybara-Service
parent 76db936d68
commit 951f296851
8 changed files with 126 additions and 2 deletions

View File

@ -43,6 +43,7 @@ import org.junit.runners.Parameterized.Parameters;
/** End to end parameterized instrumentation tests for {@link Mp4Muxer}. */
@RunWith(Parameterized.class)
public class Mp4MuxerEndToEndParameterizedAndroidTest {
private static final String H263_GPP = "bbb_176x144_128kbps_15fps_h263.3gp";
private static final String H264_MP4 = "sample_no_bframes.mp4";
private static final String H264_WITH_NON_REFERENCE_B_FRAMES_MP4 =
"bbb_800x640_768kbps_30fps_avc_non_reference_3b.mp4";
@ -58,6 +59,7 @@ public class Mp4MuxerEndToEndParameterizedAndroidTest {
@Parameters(name = "{0}")
public static ImmutableList<String> mediaSamples() {
return ImmutableList.of(
H263_GPP,
H264_MP4,
H264_WITH_NON_REFERENCE_B_FRAMES_MP4,
H264_WITH_PYRAMID_B_FRAMES_MP4,

View File

@ -548,6 +548,8 @@ import java.util.List;
return damrBox(/* mode= */ (short) 0x81FF); // mode set: all enabled for AMR-NB
case MimeTypes.AUDIO_AMR_WB:
return damrBox(/* mode= */ (short) 0x83FF); // mode set: all enabled for AMR-WB
case MimeTypes.VIDEO_H263:
return d263Box();
case MimeTypes.VIDEO_H264:
return avcCBox(format);
case MimeTypes.VIDEO_H265:
@ -1095,6 +1097,19 @@ import java.util.List;
}
}
/** Returns the d263Box box as per 3GPP ETSI TS 126 244: 6.8. */
private static ByteBuffer d263Box() {
ByteBuffer d263Box = ByteBuffer.allocate(7);
d263Box.put(" ".getBytes(UTF_8)); // 4 spaces (vendor)
d263Box.put((byte) 0x00); // decoder version
// TODO: b/352000778 - Get profile and level from format.
d263Box.put((byte) 0x10); // level
d263Box.put((byte) 0x00); // profile
d263Box.flip();
return BoxUtils.wrapIntoBox("d263", d263Box);
}
/** Returns the avcC box as per ISO/IEC 14496-15: 5.3.3.1.2. */
private static ByteBuffer avcCBox(Format format) {
checkArgument(
@ -1328,6 +1343,8 @@ import java.util.List;
return "samr";
case MimeTypes.AUDIO_AMR_WB:
return "sawb";
case MimeTypes.VIDEO_H263:
return "s263";
case MimeTypes.VIDEO_H264:
return "avc1";
case MimeTypes.VIDEO_H265:

View File

@ -35,7 +35,7 @@ import java.nio.ByteBuffer;
/**
* A muxer for creating a fragmented MP4 file.
*
* <p>The muxer supports writing H264, H265 and AV1 video, AAC audio and metadata.
* <p>The muxer supports writing H263, H264, H265 and AV1 video, AAC audio and metadata.
*
* <p>All the operations are performed on the caller thread.
*

View File

@ -54,7 +54,7 @@ import org.checkerframework.checker.nullness.qual.EnsuresNonNull;
/**
* A muxer for creating an MP4 container file.
*
* <p>The muxer supports writing H264, H265 and AV1 video, AAC audio and metadata.
* <p>The muxer supports writing H263, H264, H265 and AV1 video, AAC audio and metadata.
*
* <p>All the operations are performed on the caller thread.
*

View File

@ -375,6 +375,26 @@ public class BoxesTest {
MuxerTestUtil.getExpectedDumpFilePath("video_sample_entry_box_h265_hdr10"));
}
@Test
public void createVideoSampleEntryBox_forH263_matchesExpected() throws Exception {
Format format =
new Format.Builder()
.setId(1)
.setSampleMimeType(MimeTypes.VIDEO_H263)
.setLanguage("und")
.setWidth(10)
.setMaxInputSize(39)
.setFrameRate(25)
.setHeight(12)
.build();
ByteBuffer videoSampleEntryBox = Boxes.videoSampleEntry(format);
DumpableMp4Box dumpableBox = new DumpableMp4Box(videoSampleEntryBox);
DumpFileAsserts.assertOutput(
context, dumpableBox, MuxerTestUtil.getExpectedDumpFilePath("video_sample_entry_box_h263"));
}
@Test
public void createVideoSampleEntryBox_forH264_matchesExpected() throws Exception {
Format format =

View File

@ -0,0 +1,83 @@
seekMap:
isSeekable = true
duration = 933300
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=0, position=400052], [timeUs=533322, position=428455]]
getPosition(466650) = [[timeUs=0, position=400052], [timeUs=533322, position=428455]]
getPosition(933300) = [[timeUs=533322, position=428455]]
numberOfTracks = 1
track 0:
total output bytes = 50100
sample count = 15
format 0:
id = 1
sampleMimeType = video/3gpp
maxInputSize = 10464
width = 176
height = 144
frameRate = 16.072002
colorInfo:
lumaBitdepth = 8
chromaBitdepth = 8
metadata = entries=[Mp4Timestamp: creation time=100000000, modification time=500000000, timescale=10000]
sample 0:
time = 0
flags = 1
data = length 10434, hash AE44B225
sample 1:
time = 66655
flags = 0
data = length 2615, hash A0DA11FE
sample 2:
time = 133322
flags = 0
data = length 1812, hash 7088FD15
sample 3:
time = 200000
flags = 0
data = length 2812, hash C8A9745F
sample 4:
time = 266655
flags = 0
data = length 3127, hash 15B392C5
sample 5:
time = 333322
flags = 0
data = length 3362, hash 77B8F06A
sample 6:
time = 400000
flags = 0
data = length 3295, hash 24A31310
sample 7:
time = 466655
flags = 0
data = length 946, hash B1E4247C
sample 8:
time = 533322
flags = 1
data = length 10399, hash 65BB0623
sample 9:
time = 600000
flags = 0
data = length 3373, hash 6884A84C
sample 10:
time = 666655
flags = 0
data = length 878, hash BFC0DD04
sample 11:
time = 733322
flags = 0
data = length 1530, hash 55CB846F
sample 12:
time = 800000
flags = 0
data = length 1834, hash ECF4E9AA
sample 13:
time = 866655
flags = 0
data = length 1776, hash 63A892E4
sample 14:
time = 933322
flags = 536870912
data = length 1907, hash 99D43466
tracksEnded = true

View File

@ -0,0 +1,2 @@
s263 (117 bytes):
Data = length 109, hash B820D1F5