共计 5270 个字符,预计需要花费 14 分钟才能阅读完成。
MP4 文件格式又被称为 MPEG-4 Part 14,出自 MPEG-4 规范第 14 局部。它是一种多媒体格局容器,宽泛用于包装视频和音频数据流、海报、字幕和元数据等。(顺便一提,目前风行的视频编码格局 AVC/H264 定义在 MPEG-4 Part 10)。MP4 文件格式基于 Apple 公司的 QuickTime 格局,因而,QuickTime File Format Specification 也能够作为咱们钻研 MP4 的重要参考。
作者:张武星
审核:泰一
Overview
MP4 文件由 box 组成,每个 box 分为 Header 和 Data。其中 Header 局部蕴含了 box 的类型和大小,Data 蕴含了子 box 或者数据,box 能够嵌套子 box。
下图是一个典型 MP4 文件的根本构造:
图中看到 MP4 文件有几个次要组成部分:
fytp
File Type Box,个别在文件的开始地位,形容的文件的版本、兼容协定等。
moov
Movie Box,蕴含本文件中所有媒体数据的宏观形容信息以及每路媒体轨道的具体信息。个别位于 ftyp 之后,也有的视频放在文件开端。留神,当扭转 moov 地位时,外部一些值须要从新计算。
mdat
Media Data Box,寄存具体的媒体数据。
Moov Insider
MP4 的媒体数据信息次要寄存在 Moov Box 中,是咱们须要剖析的重点。moov 的次要组成部分如下:
mvhd
Movie Header Box,记录整个媒体文件的形容信息,如创立工夫、批改工夫、工夫度量标尺、可播放时长等。
下图示例中,能够获取文件信息如时长为 3.637 秒。
udta
User Data Box,自定义数据。
track
Track Box,记录媒体流信息,文件中能够存在一个或多个 track,它们之间是互相独立的。每个 track 蕴含以下几个组成部分:
tkhd
Track Header Box,蕴含对于媒体流的头信息。
下图示例中,能够看到流信息如视频流宽度 720,长度 1280。
mdia
Media Box,这是一个蕴含 track 媒体数据信息的 container box。子 box 包含:
- mdhd:Media Header Box,寄存视频流创立工夫,长度等信息。
- hdlr:Handler Reference Box,媒体的播放过程信息。
- minf:Media Information Box,解释 track 媒体数据的 handler-specific 信息。minf 同样是个 container box,其外部须要关注的内容是 stbl,这也是 moov 中最简单的局部。
stbl 蕴含了媒体流每一个 sample 在文件中的 offset,pts,duration 等信息。想要播放一个 MP4 文件,必须依据 stbl 正确找到每个 sample 并送给解码器。
mdia 开展如下图所示:
Stbl Insider
Sample Table Box,上文提到 mdia 中最次要的局部是寄存文件中每个 Sample 信息的 stbl。在解析 stbl 前,咱们须要辨别 Chunk 和 Sample 这两个概念。
在 MP4 文件中,Sample 是一个媒体流的根本单元,例如视频流的一个 Sample 代表理论的 nal 数据。Chunk 是数据存储的根本单位,它是一系列 Sample 数据的汇合,一个 Chunk 中能够蕴含一个或多的 Sample。
stbl 用来形容每个 Sample 的信息,蕴含以下几个次要的子 box:
stsd
Sample Description Box,寄存解码必须的形容信息。
下图示例中,对于 h264 的视频流,其具体类型为 avc1
,extensions 中寄存有 sps,pps 等解码必要信息。
stts
Time-to-Sample Box,定义每个 Sample 时长。Time To Sample 的 table entry 布局如下:
- Sample count:sample 个数
- Sample duration:sample 持续时间
持续时间雷同的间断的 Sample 能够放到一个 entry 外面,以达到节俭空间的目标。
下图示例中,第 1 个 Sample 工夫为 33362 微秒,第 2-11 个 Sample 工夫为 33363 微秒:
stss
Sync Sample Box,同步 Sample 表,寄存关键帧列表,关键帧是为了反对随机拜访。
stss 的 table entry 布局如下:
下图示例中,该视频 track 只有一个关键帧即第 1 帧:
stsc
Sample-To-Chunk Box,Sample-Chunk 映射表。上文提到 MP4 通常把 Sample 封装到 Chunk 中,一个 Chunk 可能会蕴含一个或者几个 Sample。Sample-To-Chunk Atom 的 table entry 布局如下图所示:
- First chunk:应用该表项的第一个 chunk 序号。
- Samples per chunk:应用该表项的 chunk 中蕴含有几个 sample。
- Sample description ID:应用该表项的 chunk 参考的 stsd 表项序号。
下图示例中,能够看到该视频 track 一共有两个 stsc 表项,Chunk 序列 1-108,每个 Chunk 蕴含一个 sample,Chunk 序列 109 开始,每个 Chunk 蕴含两个 Sample。
stsz
Sample Size Box,指定了每个 Sample 的 size。Sample Size Atom 蕴含两 Sample 总数和一张蕴含了每个 Sample Size 的表。
Sample Size 表的 entry 布局如下图:
下图示例中,该视频流一共有 110 个 Sample,第 1 个 Sample 大小为 42072 字节,第 2 个 Sample 大小为 7354 个字节。
stco
Chunk Offset Box,指定了每个 Chunk 在文件中的地位,这个表是确定每个 Sample 在文件中地位的要害。该表蕴含了 Chunk 个数和一个蕴含每个 Chunk 在文件中偏移地位的表。每个表项的内存布局如下:
须要留神,这里 stco 只是指定的每个 Chunk 在文件中的偏移地位,并没有给出每个 Sample 在文件中的偏移。想要取得每个 Sample 的偏移地位,须要联合 Sample Size box 和 Sample-To-Chunk 计算后获得。
下图示例中,该视频流第 1 个 Chunk 在文件中的偏移为 4750,第 1 个 Chunk 在文件中的偏移为 47007。
如何计算 Sample 偏移地位
上文提到通过 stco 并不能间接获取某个 Sample 的偏移地位,上面举例说明如何获取某一个 pts 对应的 Sample 在文件中的地位。大体须要以下步骤:
- 将 pts 转换到媒体对应的工夫坐标系。
- 依据 stts 计算某个 pts 对应的 Sample 序号。
- 依据 stsc 计算 Sample 序号寄存在哪个 Chunk 中。
- 依据 stco 获取对应 Chunk 在文件中的偏移地位。
- 依据 stsz 获取 Sample 在 Chunk 内的偏移地位并加上第 4 步获取的偏移,计算出 Sample 在文件中的偏移。
例如,想要获取 3.64 秒视频 Sample 数据在文件中的地位:
- 依据 time scale 参数,将 3.64 秒转换为视频时间轴对应的 3640000。
- 遍历累加下表所示 stts 所有我的项目,计算失去 3640000 位于第 110 个 Sample。
type stts
size 224
flags 0
version 0
sample_counts 1,10,1,1,11,1,1,2,1,25,1,1,1,17,1,10,1,1,1,7,1,1,1,1,10,1
sample_deltas 33362,33363,33362,33364,33363,33362,33364,33363,33362,33363,33362,33364,33362,33363,33362,33363,33362,33364,33362,33363,33362,33364,33363,33362,33363,0
- 查问下表所示 stsc 所有我的项目,计算失去第 110 个 Sample 位于第 109 个 Chunk,并且在该 Chunk 中位于第 2 个 Sample。
type stsc
size 40
flags 0
version 0
first_chunk 1,109
samples_per_chunk 1,2
sample_description_index 1,1
- 查问下表所示 stco 所有我的项目,失去第 109 个 Chunk 在文件中偏移地位为 1710064。
Property name Property value
type stco
size 452
flags 0
version 0
chunk_offsets 4750,47007,54865,61967,75519,88424,105222,117892,133730,149529,165568,182034,194595,210776,225470,240756,255358,270711,285459,300135,315217,330899,347372,363196,376409,394509,407767,424615,438037,455603,469784,487287,505197,519638,536714,553893,567187,584744,599907,615298,630669,645918,662605,678655,693510,708980,724061,738946,754170,771520,787233,800847,816997,832490,847814,862559,877929,898379,911054,925810,943883,956497,974403,991527,1009478,1025198,1041806,1062609,1078401,1091360,1105142,1118748,1132815,1145281,1156966,1171871,1186742,1202760,1218235,1236688,1249330,1263163,1280880,1297903,1313162,1332885,1345726,1359017,1376283,1391401,1405512,1419550,1433644,1452103,1475241,1492689,1511291,1522606,1535368,1559413,1575331,1588853,1609829,1626623,1642798,1658640,1674160,1693972,1710064
- 查问下表所示 stsz 所有我的项目,失去第 109 个 Sample 的 size 为 14808。计算失去 3.64 秒视频 Sample 数据在文件中:
offset:1710064 + 14808 = 1724872
size:17930
type stsz
size 460
flags 0
version 0
sample_sizes 42072,7354,6858,13110,12684,16416,12490,15497,15630,15865,16116,12387,15775,14519,14929,14433,15181,14390,14496,14717,15507,16101,15643,12843,17911,13070,16455,13221,17186,14002,17139,17737,14251,16708,16999,12911,17356,14801,15213,15016,15062,16505,15689,14657,15053,14907,14527,15048,17161,15308,13432,15777,15307,14971,14568,14987,20264,12494,14382,17873,12235,17718,16770,17766,15366,16420,20623,15403,12761,13394,13390,13714,12295,11505,14541,14689,15635,15291,18091,12458,13645,17346,16847,14902,19530,12446,13105,16872,14937,13944,13657,13908,18092,22959,17080,18421,11129,12400,23844,15564,13340,20603,16609,15984,15474,15339,19451,15719,14808,17930
sample_size 0
sample_count 110
- 验证:用编辑器关上 MP4 文件,定位到文件偏移 offset = 1724872 的地位,前 4 字节值为 0x00004606。在 avcc 中一个 Sample 的前 4 个字节代表这个包的大小,转换为十进制是 17926,该值正好等于 size = 17930 减去示意长度的四个字节。
参考资料
在线 MP4 解析工具
QuickTime File Format Specification
「视频云技术」你最值得关注的音视频技术公众号,每周推送来自阿里云一线的实际技术文章,在这里与音视频畛域一流工程师交换切磋。