
本文共 16655 字,大约阅读时间需要 55 分钟。
【网络通信 -- 直播】音视频常见封装格式 -- MP4
【1】简介
MP4 起源于 QuickTime,全名是 MPEG-4 Part 14,属于 MPEG-4 的一部分;这部分内容主要规定了多媒体容器的格式,后来成为 ”ISO/IEC 14996-14” 国际标准, 其中 MP4 就是对这种标准的一种具体实现,基于这个标准进行扩展或者裁剪还产生了像 M4V、F4V 等封装格式;MP4 目前在移动端的 Androids 和 IOS 可以播放,也可以在 FlashPlayer 播放,跨平台和兼容性最好,MP4 可以实现快进快放,边下载边播放的效果;
mp4 ⽂件格式基于 Apple 公司的 QuickTime 格式,因此, 可以作为研究 mp4 的重要参考;
【2】术语
- Box:起源于 QuickTime 中的 atom,即 MP4 文件就是由一个个 Box 组成的,可以将其理解为一个数据块,它由 Header + Data 组成,Data 可以存储媒体元数据和实际的音视频码流数据;Box 里面可以直接存储数据块,也可以包含其它类型的 Box,该类型的 Box 又称为 container box;
- Sample:简单理解为采样,对于视频可理解为一帧数据,对于音频可理解为一段固定时间的音频数据,可以由多个 Sample 数据组成,存储媒体数据的单位是 sample;
- Track:表示一些 sample 的集合,对于媒体数据而言就是一个视频序列或者音频序列,除了 Video Track 和 Audio Track 还可以有非媒体数据,比如 Hint Track,这种类型的 Track 不包含媒体数据,可以包含一些将其他数据打包成媒体数据的指示信息或者字幕信息;Track 是电影中可以独立操作的媒体单位;
- Chunk:一个 track 的连续几个 sample 组成的单元被称为 chunk,每个 chunk 在文件中有一个偏移量,整个偏移量从文件头算起,在这个 chunk 内,sample 是连续存储的;
注,MP4 文件里面有多个 Track,一个 Track 由多个 Chunk 组成,每个 Chunk 里面包含着一组连续的 Sample;
【3】封装格式分析
【3.1】MP4 文件特点
mp4 ⽂件由 box 组成,每个 box 分为 Header 和 Data;其中 Header 部分包含了 box 的类型和⼤⼩,Data 包含了子 box 或者数据,box 可以嵌套子 box;
- 1. MP4 文件就是由一个个 Box 组成,其中 Box 还可以相互嵌套,排列紧凑没有多的冗余数据;
- 2. 一个 MP4 文件中实际包含的 Box 类型并不多,主要是由必须的 ftyb、mdat、moov,以及 free、udta 等非必须 box 组成;
- 3. Moov 一般存储媒体元数据,比较复杂嵌套层次比较深;
MP4 文件的基本结构图示
【3.2】Box 的结构
- 其中在 Box 的 Header 头部,size 指定了该 Box 所占用的大小,包括了 Header 部分,一般的头部大小为 8 字节,但是若 Box 很大,超过了 uint32 的最大数值,则 size 被置为 1,并用接下来的 8 字节 uint64 来表示该 Box 的大小,这样头部大小就变成 16 字节;
- 正常情况 Box 不会太大,但是当 box 承载的音视频数据(特别是 I 帧)时,有可能 Box 会很大;
- 除了 mdat box,其它的 Box 都很小;
【3.3】基本 MP4 完整结构
【4】典型 Box 分析
【4.1】第一层 Box : Ftyp、Moov、Mdat、Free
【4.1.1】Ftyp Box
【4.1.1.1】简介
ftyp 是 MP4 文件的第一个 Box,包含了视频文件使用的编码格式、标准等,这个 Box 为 MP4 封装格式的标识,在一份 MP4 文件中只有一个这样的 Box;ftyp box 通常放在文件的开始,通过对该 box 解析可以知道应该使用哪种协议对这该文件解析,是后续解读文件基础;
【4.1.1.2】格式
字段 | 长度 | 含义 | 说明 |
Box length | 4 | 表示该 Box 的长度,包含 Box 的 header 长度 | |
Box type | 4 | 固定值 ”ftyp” 的 ASCII 码,为该 Box 的标识 | |
Major brand | 4 | 主商标 | MP4 这种格式基于 QuickTime,然后成为 ISO 国标,还有其它厂家基于该标准自己扩展的格式如 F4V、M4V 等,因此不同厂商要实现这种规范都要向 ISO 注册一个四字节的标识码 |
Minor version | 4 | 商标版本号 | 表示 Major brand 的版本号 |
Compatible brand | 12 | 兼容其他的版本号 | 表示可以兼容和遵从那些协议标准,是一个列表 |
【4.1.2】Moov Box
【4.1.2.1】简介
Moov Box 是 MP4 文件中必须有但是只存在一个的 Box,该 Box 里面一般存放的是媒体文件的元数据,该 Box 是一种 Container Box,里面的数据是子 Box,本身类似一个分界标识;所谓的媒体元数据主要包含类似 SPS、PPS 的编解码参数信息,音视频的时间戳等信息;对于 MP4 的采样表 stbl 信息,这里面定义了采样 Sample、Chunk、Track 的映射关系,是 MP4 能够进行随机拖动和播放的关键;
【4.1.2.2】格式
字段 | 长度 | 含义 | 说明 |
Box length | 4 | 表示该 Box 的长度,包含 Box 的 header 长度 | |
Box type | 4 | 固定值 ”ftyp” 的 ASCII 码,为该 Box 的标识 | |
Box Data | 该 Box 是 Container Box,里面还有好几层子 Box |
【4.1.3】Mdat Box
【4.1.3.1】简介
Mdat Box 是存储音视频数据的 Box,可以从该 Box 解封装出真实的媒体数据,该 Box 一般都会存在,但不是必须的;
- H264 的基本结构是由一系列的 NALU 组成,Start code + NALU header + NALU payload
- 在 MP4 格式文件中,H264 slice 并不是以 00 00 00 01 Start Code 来进行分割,而是存储在 Mdat Box 的 Data 中;
【4.1.3.2】格式
- Box header + Box Data;
- Box length + Box Type + NALU length + NALU header + Nalu Data....... NALU length + NALU header + Nalu Data
注意点
- 1. Mdat Box 基本由头部和数据两部分组成,注意若 Box length 长度不够时,要用后面 8 字节的扩展长度字段,Box Type 是 “mdat” 的 ASCII 码值;
- 2. 真实的数据字段是一个个 NALU header + NALU Data,但是没有用 NALU 的分解符 00 00 00 01,而是在每个 NALU 前面加了长度字段;
- 3. 这里的 NLAU 一般不再包含 SPS PPS 等数据,这些数据已经放到 Moov Box 里面了,此处 NALU 类型是 I\B\P 帧数据以及 SEI 用户增强信息;
【4.2】第二层 Box : Moov Box 的 Mvhd、Trck、Iods 等
【4.2.1】Mvhd Box
【4.2.1.1】简介
该 Box 是全文件唯一的一个 Box,一般处于 Moov Box 的第一个子 Box,该 Box 对整个媒体文件所包含的媒体数据(包含 Video track 和 Audio Track 等)进行全面的描述,其中包含了媒体的创建和修改时间,默认音量、色域、时长等信息;
【4.2.1.2】格式
Box Header
字段 | 长度 | 说明 |
box size | 4 byte | box 大小 |
box type | 4 byte | box 类型 |
version | 1 byte | box 版本,0 或 1,一般为 0 |
flags | 3 byte | 根据各个 box 类型定义是 0 还是 1 |
Box Data
字段 | 长度 | 说明 |
creation time | 4 byte | 创建时间(相对于 UTC 时间 1904-01-01 零点的秒数) |
modification time | 4 byte | 修改时间(相对于 UTC 时间 1904-01-01 零点的秒数) |
time scale | 4 byte | 文件媒体在 1 秒时间内的刻度值,可以理解为 1 秒长度的时间单元数,该值只用来计算该 Mp4 文件的长度,没有参与 PTS 和 DTS 的计算 |
duration | 4 byte | 该影片的播放时长,该值除以 time scale 字段即可以得到该影片的总时长单位秒 s |
rate | 4 byte | 推荐播放速率,高 16 位和低 16 位分别为小数点整数部分和小数部分,即 [16.16] 格式,该值为 1.0(0x00010000)表示正常前向播放 |
volume | 2 byte | 与 rate 类似,[8.8] 格式,1.0(0x0100)表示最大音量 |
reserved | 10 byte | 保留位 |
matrix | 36 byte | 视频变换矩阵,实际填写都是默认值 |
pre-defined | 24 byte | 预览相关的信息,一般都是填充 0 |
next track id | 4 byte | 下一个 Track 使用的 id 号,通过该值减去 1 可以判断当前文件的 Track 数量 |
【4.2.2】Iods Box
【4.2.2.1】简介
该 Box 是非必须的 Box,实际是 24 字节的固定值,解析时可以直接跳过;封装直接给填写固定 24 字节,注意该 Box 是 Full Box 即 Header 里面有 1 字节的 Version 和 3 字节的 Flag 字段;定义的内容是 Audio 和 Video ProfileLevel 方面的描述;
【4.2.3】Trak Box
【4.2.3.1】简介
Trak Box 定义了媒体文件中媒体中一个 Track 的信息,视频为 Video Track,音频为 Audio Track,媒体文件中可以有多个 Track,每个 Track 具有自己独立的时间和空间的信息,可以进行独立操作;每个 Track Box 都需要有一个 Tkhd Box 和 Mdia Box,其它的 Box 都是可选择的;
【4.3】第三层 Box : Trak Box 的 Tkhd Box、Mdia Box 等
【4.3.1】Tkhd Box
【4.3.1.1】简介
该 Box 描述了该 Track 的媒体整体信息包括时长、图像的宽度和高度等,该 Box 是 Full Box 即 Box Header 后面有 Box Header Version (1 byte) 和 Box Header Flag (3 byte);
【4.3.1.2】格式
视频的 Tkhd
音频的 Tkhd
Box Header
字段 | 长度 | 说明 |
box size | 4 byte | box 大小 |
box type | 4 byte | box 类型 |
version | 1 byte | box 版本,0 或 1,一般为 0 |
flags | 3 byte |
Box Data
字段 | 长度 | 说明 |
creation time | 4 byte | 创建时间(相对于 UTC 时间 1904-01-01 零点的秒数) |
modification time | 4 byte | 修改时间(相对于 UTC 时间 1904-01-01 零点的秒数) |
track ID | 4 byte | 唯一标识该 Track 的一个非零值 |
reserve | 4 byte | 保留位 |
duration | 4 byte | 该 Track 的播放时长,需要和时间戳进行一起计算,然后得到播放的时间坐标 |
reserver | 8 byte | 保留位 |
layer | 2 byte | 视频层,值小的在上层 |
alternate group | 2 byte | track 分组信息,一般默认为 0,表示该 track 和其它 track 没有建立群组关系 |
volume | 2 byte | 播放此 track 的音量,1.0 为正常音量 |
reserver | 2 byte | 默认值 0 |
matrix | 36 byte | 视频变换矩阵 |
width | 4 byte | 如果该 Track 为 Video Track,则表示图像的宽度(16.16 浮点表示) |
height | 4 byte | 如果该 Track 为 Video Track,则表示图像的高度(16.16 浮点表示) |
【4.3.2】Mdia Box
【4.3.2.1】简介
该 Box 是 Container Box,里面包含子 Box,一般必须有 Mdhd Box、Hdlr Box、Minf Box;基本为当前 Track 媒体头信息和媒体句柄以及媒体信息;该 Box 自身就是一个标识,复杂的还是里面包含的子 Box;
【4.3.2.2】格式
Box Header
字段 | 长度 | 说明 |
box size | 4 byte | box 大小 |
box type | 4 byte | box 类型 |
【4.4】第四层 Box : Mdia Box 的 Mdhd、Hdlr、Minf 等
【4.4.1】Mdhd Box
【4.4.1.1】简介
该 Box 是Full Box,意味着 Box Header 有 Version 和 Flag字段,该 Box 里面主要定义了该 Track 的媒体头信息,其中 Time scale 和 Duration 字段分别表示了该 Track 的时间戳和时长信息,该时间戳信息是 PTS 和 DTS 的单位;
【4.4.1.2】格式
视频 mdhd
音频 mdhd
Box Header
字段 | 长度 | 说明 |
box size | 4 byte | box 大小 |
box type | 4 byte | box 类型 |
version | 1 byte | box 版本,0 或 1,一般为 0 |
flags | 3 byte | 该 box 该字段填充 0 |
Box Data
字段 | 长度 | 说明 |
creation time | 4 byte | 创建时间(相对于 UTC 时间 1904-01-01 零点的秒数) |
modification time | 4 byte | 修改时间(相对于 UTC 时间 1904-01-01 零点的秒数) |
timescale | 4 byte | 当前 Track 的时间计算单位 |
duration | 4 byte | 该 Track 的播放时长,需要参考前面的 timescale 计算 |
language | 2 byte | 媒体语言码,参考其他标准 |
qualiiy | 2 byte | 媒体的回放质量 |
【4.4.2】Hdlr Box
【4.4.2.1】简介
该 Box 是Full Box,意味着 Box Header 有 Version 和 Flag 字段,该 Box 解释了媒体的播放过程信息,用来设置不同 Track 的处理方式,标识了该 Track 的类型;
【4.4.2.2】格式
视频 hdlr
音频 hdlr
Box Header
字段 | 长度 | 说明 |
box size | 4 byte | box 大小 |
box type | 4 byte | box 类型 |
version | 1 byte | box 版本,0 或 1,一般为 0 |
flags | 3 byte | 该 box 该字段填充 0 |
Box Data
字段 | 长度 | 说明 |
handle type | 4 byte | Handle 的类型 ‘mhlr’,media handle ‘dhlr’,data handle 实际处理时默认为 0 即可 |
hand sub type | 4 byte | 视频,‘vide’ 音频,‘soun’ |
reserved | 12 byte | 保留字段,默认为 0 |
component name | 可变 | 该 component 的名字,其实是给该 Track 起的名字,打包时填写一个有意义字符串即可 |
【4.4.3】Minf Box
【4.4.3.1】简介
该 Box 内部还有子 Box,该 Box 建立了时间到真实音视频 Sample 的映射关系,对于音视频数据操作时很有帮助;该 Box 是 Container Box,一般含有三大必须的子 Box;
- 媒体信息头 Box,Vmhd Box 或者 Smhd Box;
- 数据信息 Box,Dinf Box;
- 采样表 Box,Stbl Box;
minf 作为 Container Box,即临界符,仅仅包含 8 字节的头部数据;
【4.5】第五层 Box : Minf Box 的 Vmhd、Smhd、Dinf、Stbl 等
【4.5.1】Vmhd Box
【4.5.1.1】简介
该 Box 的大小是固定的,如果是 Vmhd 则大小就是 24 字节,如果是 Smhd 则大小是 16 字节,一般都是用默认值填充;该 Box 为 Full Box 意味着 Box Header 多了四字节的 version 和 Flag 字段;
【4.5.1.2】格式
vmhd
smhd
Box Header
字段 | 长度 | 说明 |
box size | 4 byte | box 大小 |
box type | 4 byte | box 类型 |
version | 1 byte | box 版本,0 或 1,一般为 0 |
flags | 3 byte | 该 box 该字段填充 0 |
Box Data
字段 | 长度 | 说明 |
raphics mode | 2 byte | 视频合成模式,为 0 时拷贝原始图像,否则与 opcolor 进行合成 一般默认 0x00 00 即可 |
Opcolor | 6 byte (2 * 3) | 颜色值,RGB 颜色值,{red,green,blue} 一般默认 0x00 00 00 00 00 00 |
【4.5.2】Dinf Box
【4.5.2.1】简介
该 Box 是一个 container box,一般用来定位媒体信息;一般会包含一个 Dref Box 即 data reference box,Dref 下面会有若干个 Url Box 或者 Urn Box,这些 Box 组成一个表,用来定位 Track 的数据;Track 可以被分成若干个段,每一段都可以根据 Url 或者 Urn 指向的地址来获取数据,sample 描述中会用这些片段的序号将这些片段组成一个完整的 track,一般情况下当数据完全包含在文件中,Url 和 Urn Box 的字符串是空的;该 Box 存在的意义是允许 MP4 文件的媒体数据分开最后还能进行恢复合并操作;
【4.5.3】Dref Box
【4.5.3.1】简介
由于 Track 可以分为多个段,该 Box 是用来定义当前 Track 各个段的 URl;
【4.5.3.2】格式
Box Header
字段 | 长度 | 说明 |
box size | 4 byte | box 大小 |
box type | 4 byte | box 类型 |
version | 1 byte | box 版本,0 或 1,一般为 0 |
flags | 3 byte | 标记 |
Box Data
字段 | 长度 | 说明 |
entry count | 4 byte | Data reference 数目 |
url or urn list | 4 byte | url 或者 urn Box |
【4.5.4】Stbl Box
【4.5.4.1】简介
Sample 是媒体数据的存储单元,其存储在 Media 的 chunk 中;
其中每个 Sample 的时间和位置、编解码信息、和 chunk 关系等都由 Stbl Box 来描述,该 Box 又称为采样参数列表即 Sample Table;
Stbl Box 包含了 Track 中 media 媒体的所有时间和索引,利用该容器的 Sample 信息,可以定位 Sample 的媒体时间、类型、大小以及和其相邻的 Sample;同时该 Box 是必须存在于 Trak Box 中;
其一般要包含下列子 Box
- 采样描述容器,Sample Description 即 Stsd Box;
- 采样时间容器,Time To Sample 即 Stts Box;
- 采样同步容器,Sync Sample 即 Stss;
- Chunk 采样容器,Sample To Chunk 即 Stsc;
- 采样大小容器,Sample Size 即 Stsz;
- Chunk 偏移容器,Chunk Offest 即 Stco;
Stbl Box 是 Container Box,此处仅仅是 8 字节的分解符;
【4.6】第六层 Box : Stbl Box 的 Stsd、Stts、Ctts、Stss、Stsc、Stsz、Stco 等
【4.6.1】Stsd Box
【4.6.1.1】简介
该 Box 存储了编码类型和初始化解码器需要的信息,与特定的 Track Type 有关,根据不同的 Track 使用不同的编码标准;
【4.6.1.2】格式
box header 和 version 字段后有一个 entry count 字段,根据 entry 的个数,每个 entry 会有 type 信息,如 “vide”、“sund” 等,根据 type 不同 sample description 会提供不同的信息,例如对于 video track,会有 “VisualSampleEntry” 类型信息,对于 audio track 会有 “AudioSampleEntry” 类型信息;视频的编码类型、宽高、长度,音频的声道、采样等信息都会出现在该 box 中;该 Box 是 Full Box,对于 Video Track 而言,H264 的 SPS PPS 就存在于该 Box 里面,对于解码非常重要;
视频的 stsd
Box Header
字段 | 长度 | 说明 |
box size | 4 byte | box 大小 |
box type | 4 byte | box 类型 |
version | 1 byte | box 版本,0 或 1,一般为 0 |
flags | 3 byte | 标记 |
Box Data
字段 | 长度 | 说明 |
sample description entry count | 4 byte | sample description 数目,同时不同的 Track 有不同的 sample description (以 Box 描述); |
sample description entry | 不定 | Sample description 的实际内容 |
Stsd Box 中视频相关的 Box
【4.6.1 - 1】Avc1 Box
Box Header
字段 | 长度 | 说明 |
box size | 4 byte | box 大小 |
box type | 4 byte | box 类型 |
Box Data
字段 | 长度 | 说明 |
reserved | 4 byte | 保留位默认 0x00 |
reserver | 2 byte | 保留位默认 0x00 |
data reference ID | 2 byte | 引用参考 Dref Box |
code stream version | 4 byte | 一般都是默认值 0 |
code stream version | 4 byte | 一般都是默认值 0 |
reserver | 12 byte | 保留位一般都是默认值 0 |
width | 2 byte | 图像宽度(前一个字节整数部分,后面一个字节小数部分) |
heigth | 2 byte | 图像高度(前一个字节整数部分,后面一个字节小数部分) |
horizontal resolution | 4 byte | 默认值一般都是 72dpi (前两个字节整数部分,后面两个字节小数部分) |
vertical resolution | 4 byte | 默认值一般都是 72dpi (前两个字节整数部分,后面两个字节小数部分) |
reserver | 4 byte | 保留位一般都是默认值 0 |
frame count | 2 byte | 默认值一般是 0x00 01 每采样点图像的帧数,一般为 1,有些情况下,每个采样点有多帧 |
compressorname | 32 byte | 默认填充 32 字节 0 即可 |
depth | 2 byte | 两个字节默认值是 0x00 0x18 即 24 |
reserver | 2 byte | 两个字节默认值是 0xFF 0xFF |
avcc/esds/hvcc | 可变 | 根据视频编码格式,这里填充不同的 Box 如果是 avc/h.264 编码则构造 Avcc Box 如果是 MPEG-4 编码则构造 Esds Box 如果是 MPEG-4 编码则构造 Hvcc Box |
btrt | 20 byte | 描述了解码器需要的 Buffer 大小和码率相关信息 |
【4.6.1 - 2】AVCC Box
【4.6.1 - 2.1】简介
该 Box 包含了真实的 SPS PPS 等信息,包含着音视频编解码参数;
【4.6.1 - 2.2】格式
Box Header
字段 | 长度 | 说明 |
box size | 4 byte | box 大小 |
box type | 4 byte | box 类型 |
Box Data
字段 | 长度 | 说明 |
configuration version | 1 byte | 保留位默认 0x01 |
avc profile indication | 1 byte | 保留位默认 0x00 H.264 编码配置 0x64 即 100 表示 Baseline 0x4D 即 77 表示 Main |
profile compatibility | 1 byte | |
avc level indication | 1 byte | H.264 编码级别 |
reserved | 6 bit | 默认填 1 |
length size minus one | 2 bit | 读出的每个 packet 的前几字节代表数据大小 |
reserved | 3 bit | 默认填 1 |
number of sps | 5 bit | sps 的个数,一般情况是 1 |
reserved | 3 bit | 默认填 1 |
sps length | 2 byte | sps 长度 |
sps | sps length | sps 实际内容 |
reserved | 3 bit | 默认填 0 |
number of pps | 5 bit | sps 的个数,一般情况是 1 |
pps length | 2 byte | pps 长度 |
pps | pps length | pps 实际内容 |
【4.6.1 - 3】Btrt Box
【4.6.1 - 3.1】简介
该 Box 是非必须 Box,描述了解码器需要的缓存空间大小和码率描述信息,解码器如果收到该 Box,可以在解码时作为参考;
【4.6.1 - 3.2】格式
Box Data
字段 | 长度 | 说明 |
buffer size db | 4 byte | 告知 decoder 开辟缓冲区大小 |
max bitrate | 4 byte | 该路视频的最大码率 |
avg bitrate | 4 byte | 该路视频的平均码率 |
Stsd Box 中音频相关的 Box
【4.6.1 - 4】mp4a Box
Box Data
字段 | 长度 | 说明 |
channelcount | 2 byte | 音频通道个数 |
samplesize | 2 byte | 音频采样 sample 的大小 |
samplerate | 4 byte | 音频采样率 |
【4.6.1 - 5】Esds Box
【4.6.1 - 5.1】简介
该 Box 主要存放音频的编码信息和音频码率信息;
【4.6.1 - 5.2】格式
Box Header
字段 | 长度 | 说明 |
box size | 4 byte | box 大小 |
box type | 4 byte | box 类型 |
version | 1 byte | box 版本,0 或 1,一般为 0 |
flags | 3 byte |
Box Data
字段 | 长度 | 说明 |
es description(ed) tag | 1 byte | 基本流描述标记,默认 0x03 |
ed tag szie | 1 byte | 长度 |
ed track id | 2 byte | es id 原始音频流的 id |
ed flag | 1 byte | 一般默认 00 : 0x00 : 00000000 其中每个 bit 还代表是否后面有相应的字段 第一 bit 为 1,则有 16 bit 的 depend On_ES_IS 字段; 第二 bit 为 1,则有 8 bit 的 URL ing 字段; 第三 bit 为 1,则有 16 bit 的 OCR_ES_ID 字段; 最后 5 bit 代表 streamPriority |
decoder config descriptor(dcd) tag | 1 byte | 解码配置参数描述标记,默认0x04 |
dcd tag size | 1 byte | Length Field 长度 |
dcd mepg-4 audio | 1 byte | 如果是 mp4 则计算得到:0x40 |
dcd audio stream | 1 byte | 计算得到默认值:0x15 |
dcd buffersize db | 3 byte | 建议的解码器缓存大小 |
dcd max bitrate | 4 byte | 音频数据最大码率 |
dcd avg bitrate | 4 byte | 音频数据平均码率 |
decoder specific info description(dsid) tag | 1 byte | 解码规格标记,默认值:0x05 |
dsid tag szie | 1 byte | 解码规格标记及其后面值大小 |
dsid audio specific config(asc) | 2 byte | 音频规格数据 |
asc object type | 5 bit | MPEG-4 Audio Object Types: 0: Null 1: AAC Main 2: AAC LC (Low Complexity) 3: AAC SSR (Scalable Sample Rate) |
asc frequency index | 4 bit | 0: 96000 Hz 1: 88200 Hz 2: 64000 Hz 3: 48000 Hz 4: 44100 Hz 5: 32000 Hz 6: 24000 Hz 7: 22050 Hz 8: 16000 Hz 9: 12000 Hz 10: 11025 Hz 11: 8000 Hz 12: 7350 Hz 13: Reserved 14: Reserved 15: frequency is written explictly |
asc channel configuration | 1 bit | 0:Each packet contains 1024 samples 1: Each packet contains 960 samples |
asc depends on core coder | 1 bit | |
asc extesion flag | 1 bit |
【4.6.2】Stts Box
【4.6.2.1】简介
该 Box 是 sample number 和解码时间 DTS 之间的映射表,通过该表格,可以找到任何时间的 sample;Stts Box 表格有两项值,其中一项是连续的样点数目,即 sample count 和样点相对时间差值,即 sample delta;表格中每个条目提供了在同一个时间偏移量里面连续的 sample 序号以及 sample 偏移量;当然这里的相对时间差单位是由该 Track 的 Mdhd Box 描述的时间单位;该表格只能找到当前时间的 sample 的序号,该 sample 的长度和指针还要靠其它表格获取;
Sample delta 可以理解为采样点 sample 的 duration,因此 duration 相加应该为总的 Track 的时长;
计算公式:DT(n+1) = DT(n) + STTS(n)
【4.6.2.2】格式
视频 stts
音频 stts
Box Header
字段 | 长度 | 说明 |
box size | 4 byte | box 大小 |
box type | 4 byte | box 类型 |
version | 1 byte | box 版本,0 或 1,一般为 0 |
flags | 3 byte |
Box Data
字段 | 长度 | 说明 |
entry count | 4 byte | 描述了 sample conut 和 sample delta 组成的二元组信息个数 |
sample count | 4 byte | 连续相同时间长度 sample delta 的 sample 个数 |
sample delta | 4 byte | 每个 sample delta 即以 timescale 为单位的时间长度 如果所有的 sample delta 值相同则说明该视频文件是固定帧率 |
【4.6.3】Ctts Box
【4.6.3.1】简介
该 Box 保存了每个 sample 的 composition time 和 decode time 之间的差值,通过 Composition Time 就可以计算出 Sample 的 PTS;
【4.6.3.2】格式
Box Header
字段 | 长度 | 说明 |
box size | 4 byte | box 大小 |
box type | 4 byte | box 类型 |
version | 1 byte | box 版本,0 或 1,一般为 0 |
flags | 3 byte |
Box Data
字段 | 长度 | 说明 |
entry count | 4 byte | 描述了 sample conut 和 sample delta 组成的二元组信息个数 |
sample count | 4 byte | 连续相同 offset 的 sample 个数 |
sample offset | 4 byte | CT 和 DT 之间的 offset |
【4.6.4】Stss Box
【4.6.4.1】简介
该 Box 就是存储了哪些 Sample 是 I 关键帧;
【4.6.4.2】格式
布局
Box Header
字段 | 长度 | 说明 |
box size | 4 byte | box 大小 |
box type | 4 byte | box 类型 |
version | 1 byte | box 版本,0 或 1,一般为 0 |
flags | 3 byte |
Box Data
字段 | 长度 | 说明 |
entry count | 4 byte | 关键帧的 sample 个数 |
sample count | 4 byte | 关键帧 sample 序号 |
【4.6.5】Stsc Box
【4.6.5.1】简介
MP4 中存在 Track-Chunk-Sample 概念,该 Box 用于说明哪些 Sample 可以划分为一个 Chunk;
媒体数据被分为若干个 chunk,chunk 可以有不同的大小,同一个 chunk 中的样点 sample 也可以有不同的大小;通过本表可以定位一个样点的 chunk 位置;
该 Box 里面的 Box Data 里面有三个字段,分别是 first chunk、sample per chunk、sample description index;
- 1. fist chunk:具有相同采样点 sample 和 sample_description_index 的 chunk 中,第一个 chunk 的索引值,即该 chunk 索引值直到下一个索引值之间的所有 chunk 都具有相同的 sample 个数,同时这些 sample 的描述 description 也一样;
- 2. samples per chunk:上面所有 chunk 的 sample 个数;
- 3. sample description index:描述采样点的采样描述项的索引值,范围为 1 到样本描述表中的表项数目;
这 3 个字段实际上决定了一个 MP4 中有多少个 chunks,每个 chunks 有多少个 samples;
【4.6.5.2】格式
Box Data
字段 | 长度 | 说明 |
entry count | 4 byte | 三元组信息的个数 |
first chunk | 4 byte | 每一个 entry 开始的 chunk 位置 |
sample per chunk | 4 byte | 每一个 chunk 里面包含多少的 sample |
sample description index | 4 byte | 每一个 sample 的描述,一般可以默认设置为 1 |
【4.6.6】Stsz Box
【4.6.6.1】简介
该 Box 给出每个 Sample 的 Size 即包含的字节数,包含了媒体中全部 sample 的数目和一张给出每个 sample 大小的表;
【4.6.6.2】格式
布局
Box Header
字段 | 长度 | 说明 |
box size | 4 byte | box 大小 |
box type | 4 byte | box 类型 |
version | 1 byte | box 版本,0 或 1,一般为 0 |
flags | 3 byte |
Box Data
字段 | 长度 | 说明 |
sample size | 4 byte | 指定默认的 sample 大小,如果每个 sample 大小不相等,则这个字段值为 0,每个 sample 大小存在下表中 |
sample count | 4 byte | 该 track 中所有 sample 的数量 |
entry size | 4 byte | 每个 sample 的大小 |
【4.6.7】Stco Box
【4.6.7.1】简介
该 Box 存储了 Chunk Offset,表示每个 Chunk 在文件中的位置,从而确定 chunk 在文件的偏移量,然后根据其它表的关联关系就可以读取每个 Sample 的大小;
【4.6.7.2】格式
布局
Box Header
字段 | 长度 | 说明 |
box size | 4 byte | box 大小 |
box type | 4 byte | box 类型 |
version | 1 byte | box 版本,0 或 1,一般为 0 |
flags | 3 byte |
Box Data
字段 | 长度 | 说明 |
entry count | 4 byte | chunk 的总个数 |
chunk offset | 4 byte | 每个 chunk 在文件中的位置 |
【5】H.264 打包 MP4
1. 构造 Ftyp Box,这是 MP4 文件的基本标识,按照规范构造即可;
2. 构造 Mdat Box,其中是音视频媒体数据,将 NALU 数据封装成一个个 Sample,从上到下排列起来即可;
3. 构造 Moov Box,先构造除了 stbl 的其它 Box,这样从子 Box,一直按照层次构造上来,这些 Box 的基本信息是明确的,个别信息通过解析 SPS、PPS 获取;
4. 构造 Moov Box 的 Stbl 部分,这部分要封装:
- SPS、PPS 的 NALU 数据
- 时间戳 PTS 和 DTS 信息
- Sample 的大小和数量
- Chunk 的数量和在文件偏移量
- Sample 和 Chunk 的映射关系
5. 其中 Moov 到底是放到 Mdat Box 前面还是后面,需要在封装打包前确定;
6. 填充一些感兴趣的非必要的 Box,至此组装成整个 MP4 文件完毕;
【6】计算 sample 偏移位置
获取某⼀个 pts 对应的 sample 在⽂件中的位置的方法;
大体步骤
- 1. 将 pts 转换到媒体对应的时间坐标系
- 2. 根据 stts ((decoding) time-to-sample) 计算某个 pts 对应的 sample 序号
- 3. 根据 stsc (sample-to-chunk) 计算 sample 序号存放在哪个 chunk 中
- 4. 根据 stco (chunk offset) 获取对应 chunk 在⽂件中的偏移位置
- 5. 根据 stsz 获取 sample 在 chunk 内的偏移位置并加上第 4 步获取的偏移,计算出 sample 在⽂件中的偏移
参考致谢
本博客为博主的学习实践总结,并参考了众多博主的博文,在此表示感谢,博主若有不足之处,请批评指正。
【1】
【2】
【3】
【4】
发表评论
最新留言
关于作者
