mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
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:
parent
76db936d68
commit
951f296851
@ -43,6 +43,7 @@ import org.junit.runners.Parameterized.Parameters;
|
|||||||
/** End to end parameterized instrumentation tests for {@link Mp4Muxer}. */
|
/** End to end parameterized instrumentation tests for {@link Mp4Muxer}. */
|
||||||
@RunWith(Parameterized.class)
|
@RunWith(Parameterized.class)
|
||||||
public class Mp4MuxerEndToEndParameterizedAndroidTest {
|
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_MP4 = "sample_no_bframes.mp4";
|
||||||
private static final String H264_WITH_NON_REFERENCE_B_FRAMES_MP4 =
|
private static final String H264_WITH_NON_REFERENCE_B_FRAMES_MP4 =
|
||||||
"bbb_800x640_768kbps_30fps_avc_non_reference_3b.mp4";
|
"bbb_800x640_768kbps_30fps_avc_non_reference_3b.mp4";
|
||||||
@ -58,6 +59,7 @@ public class Mp4MuxerEndToEndParameterizedAndroidTest {
|
|||||||
@Parameters(name = "{0}")
|
@Parameters(name = "{0}")
|
||||||
public static ImmutableList<String> mediaSamples() {
|
public static ImmutableList<String> mediaSamples() {
|
||||||
return ImmutableList.of(
|
return ImmutableList.of(
|
||||||
|
H263_GPP,
|
||||||
H264_MP4,
|
H264_MP4,
|
||||||
H264_WITH_NON_REFERENCE_B_FRAMES_MP4,
|
H264_WITH_NON_REFERENCE_B_FRAMES_MP4,
|
||||||
H264_WITH_PYRAMID_B_FRAMES_MP4,
|
H264_WITH_PYRAMID_B_FRAMES_MP4,
|
||||||
|
@ -548,6 +548,8 @@ import java.util.List;
|
|||||||
return damrBox(/* mode= */ (short) 0x81FF); // mode set: all enabled for AMR-NB
|
return damrBox(/* mode= */ (short) 0x81FF); // mode set: all enabled for AMR-NB
|
||||||
case MimeTypes.AUDIO_AMR_WB:
|
case MimeTypes.AUDIO_AMR_WB:
|
||||||
return damrBox(/* mode= */ (short) 0x83FF); // mode set: all enabled for AMR-WB
|
return damrBox(/* mode= */ (short) 0x83FF); // mode set: all enabled for AMR-WB
|
||||||
|
case MimeTypes.VIDEO_H263:
|
||||||
|
return d263Box();
|
||||||
case MimeTypes.VIDEO_H264:
|
case MimeTypes.VIDEO_H264:
|
||||||
return avcCBox(format);
|
return avcCBox(format);
|
||||||
case MimeTypes.VIDEO_H265:
|
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. */
|
/** Returns the avcC box as per ISO/IEC 14496-15: 5.3.3.1.2. */
|
||||||
private static ByteBuffer avcCBox(Format format) {
|
private static ByteBuffer avcCBox(Format format) {
|
||||||
checkArgument(
|
checkArgument(
|
||||||
@ -1328,6 +1343,8 @@ import java.util.List;
|
|||||||
return "samr";
|
return "samr";
|
||||||
case MimeTypes.AUDIO_AMR_WB:
|
case MimeTypes.AUDIO_AMR_WB:
|
||||||
return "sawb";
|
return "sawb";
|
||||||
|
case MimeTypes.VIDEO_H263:
|
||||||
|
return "s263";
|
||||||
case MimeTypes.VIDEO_H264:
|
case MimeTypes.VIDEO_H264:
|
||||||
return "avc1";
|
return "avc1";
|
||||||
case MimeTypes.VIDEO_H265:
|
case MimeTypes.VIDEO_H265:
|
||||||
|
@ -35,7 +35,7 @@ import java.nio.ByteBuffer;
|
|||||||
/**
|
/**
|
||||||
* A muxer for creating a fragmented MP4 file.
|
* 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.
|
* <p>All the operations are performed on the caller thread.
|
||||||
*
|
*
|
||||||
|
@ -54,7 +54,7 @@ import org.checkerframework.checker.nullness.qual.EnsuresNonNull;
|
|||||||
/**
|
/**
|
||||||
* A muxer for creating an MP4 container file.
|
* 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.
|
* <p>All the operations are performed on the caller thread.
|
||||||
*
|
*
|
||||||
|
@ -375,6 +375,26 @@ public class BoxesTest {
|
|||||||
MuxerTestUtil.getExpectedDumpFilePath("video_sample_entry_box_h265_hdr10"));
|
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
|
@Test
|
||||||
public void createVideoSampleEntryBox_forH264_matchesExpected() throws Exception {
|
public void createVideoSampleEntryBox_forH264_matchesExpected() throws Exception {
|
||||||
Format format =
|
Format format =
|
||||||
|
Binary file not shown.
@ -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
|
@ -0,0 +1,2 @@
|
|||||||
|
s263 (117 bytes):
|
||||||
|
Data = length 109, hash B820D1F5
|
Loading…
x
Reference in New Issue
Block a user