一、MP4格式介绍
参考:https://zhuanlan.zhihu.com/p/457888765
参考:https://blog.51cto.com/u_13861442/5169957
mp4或称MPEG-4 Part 14,是一种多媒体容器格式,扩展名为.mp4。
MP4 文件格式又被称为 MPEG-4 Part 14,出自 MPEG-4 标准第 14 部分 。它是一种多媒体格式容器,广泛用于包装视频和音频数据流、海报、字幕和元数据等
MP4文件由许多box组成,每个box包含不同的信息, 这些box以树形结构的方式组织。以下是主要box的简要说明:
根节点之下,主要包含三个节点:ftyp、moov、mdat。
ftyp:文件类型
moov box:媒体的metadata信息
mdat:具体的媒体数据
二、MP4-BOX解析
mp4文件由若干个box组成,下面是box结构的一个示意图,每个box的前4个字节为box的长度
通过media4info打开一个MP4格式的文件,可以看到,该MP4包含4个box,ftyp、free、mdat、moov 4个box
注意:box内部也可以包含多个box,如下图
三、FTYP-BOX解析
ftyp-box 00 00 00 20表示box-size 32byte,包含长度标识块,整个文件有且仅有一个ftyp类型的box
ftyp-box各个字段的解释如下
字段 |
占用byte |
描述 |
box-size |
4 |
整个box块的长度,包含长度字段,这里是32 |
box-type |
4 |
box块的类型,fyyp |
major-brand |
4 |
iscm的ascii码 |
minor-version |
4 |
iscm版本号 |
compatibled_brands |
16 |
本文件兼容的协议,iscm、iso2、avc1、mp41 |
major_brand:比如常见的 isom、mp41、mp42、avc1、qt等。它表示“最好”基于哪种格式来解析当前的文件。举例,major_brand 是 A,compatible_brands 是 A1,当解码器同时支持 A、A1 规范时,最好使用A规范来解码当前媒体文件
四、FREE-BOX解析
free-box中的内容是无关紧要的,可以被忽略
五、MDAT-BOX解析
MP4的媒体信息和数据是分开存放的,获得数据之前必须要解析出每个帧数据所在的位置,帧信息的放在stbl-box,而真实的数据放在mdat中
六、MOOV-BOX解析(较复杂,子BOX较多)
moov-box,整个文件仅有一个moov类型的box,moov-box中包含1个mvhd-box和多个track
1、moov子box,mvhd-box解析
moov为header box,mvhd-box作为moov-box的第一个子box出现,其具体的字段定义如下图
字段 |
占用byte |
描述 |
box-size |
4 |
整个box块的长度,包含长度字段 |
box-type |
4 |
box块的类型 |
version |
1 |
0或1,一般为0 |
flags |
3 |
|
creation time |
4 |
创建时间 |
modification time |
4 |
修改时间 |
time scale |
4 |
时间缩放因子,1000, |
duration |
4 |
视频时长,单位ms |
rate |
4 |
推荐播放速率,高16位和低16位分别表示整数部分和小数部分,1.0表示正常播放 |
volume |
2 |
高8位和低16位分别表示整数部分和小数部分,1.0表示最大音量 |
reserved |
10 |
保留位 |
matrix |
36 |
视频变换矩阵 |
pre-defined |
24 |
|
next-track id |
4 |
下一个track使用的ID |
2、moov子box,track-box解析
一个mp4有多个track,每个track-box必须有一个tkhd-box和mdia-box,其中tkhd-box信息如下
字段 |
占用byte |
描述 |
box-size |
4 |
整个box块的长度,包含长度字段 |
box-type |
4 |
box块的类型 |
version |
1 |
0或1,一般为0 |
flags |
3 |
按位或操作结果值,预定义如下:0X000001 track_enabled,否则该track不被播放;0X000002 track_in_movie 表示该track在播放中被引用;0X000004 track_in_preview 表示该track在预览时被引用;一般情况下该值为7,如果一个媒体的所有track均没有设置track_in_movie和track_in_preview,将被理解为所有track均被设置了这两项 |
creation time |
4 |
创建时间 |
modification time |
4 |
修改时间 |
track_id |
4 |
指定track的id号,不能重复且不能为0 |
reserved |
4 |
保留位 |
duration |
4 |
指定track的时间长度 |
reserved |
8 |
保留位 |
layer |
2 |
指定视频层,默认为0,值小的在上层 |
alternate_group |
2 |
指定rack分组信息,默认为0表示该track未与其他track有群组关系 |
volume |
2 |
高8位和低16位分别表示整数部分和小数部分,1.0表示最大音量 |
reserved |
2 |
保留位 |
matrix |
36 |
视频变换矩阵 |
width |
4 |
宽,为 [16.16] 格式值,与sample描述中的实际画面大小比值,用于播放时的展示宽高 |
height |
4 |
高 |
edts-box,Edit atoms 定义了创建movie 中一个track 的一部分媒体。所有的edit 都在一个表里面,包括每一部分的时间偏移量和长度。Edit atoms 的类型是'edts'。如果没有该表,则此track 会被立即播放。elst全称Edit List Box,来映射movie 的时间到此track media 的时间,mp4文件中不一定都含有这个box,该box作用是使某个track的时间戳产生偏移
mdia-box,包含多个子box,较复杂,树状图如下
mdia-box定义了track媒体类型以及sample数据,描述sample信息。一般“mdia”包含一个“mdhd”,一个“hdlr”和 一个“minf”,其中“mdhd”为media header box,“hdlr”为handler reference box,“minf”为media information box。下面依次看一下这几个box的结构
mdhd各个字段定义如下图
字段 |
占用byte |
描述 |
box-size |
4 |
box大小 |
box-type |
4 |
mdhd |
version |
1 |
box版本,0或1,一般为0 |
flags |
3 |
|
creation time |
4 |
创建时间 |
modification time |
4 |
修改时间 |
time scale |
4 |
时间缩放因子,1000, |
duration |
4 |
视频时长,单位ms |
language |
2 |
媒体语言码。最高位为0,后面15位为3个字符(见ISO 639-2/T标准中定义) |
pre-defined |
2 |
hdlr解释了媒体的播放过程信息,hdlr各个字段定义如下图
字段 |
占用byte |
描述 |
box size |
4 |
box大小 |
box type |
4 |
box类型 |
version |
1 |
box版本,0或1,一般为0。(以下字节数均按version=0) |
flags |
3 |
|
pre-defined |
4 |
|
handler type |
4 |
在media box中,该值为4个字符: “vide”— video track “soun”— audio track “hint”— hint track |
reserved |
12 |
|
name |
不定 |
track type name,以‘\0’结尾的字符串 |
minf存储了解释track媒体数据的handler-specific信息,media handler用这些信息将媒体时间映射到媒体数据并进行处理
vmhd字段定义如下
字段 |
占用byte |
描述 |
box size |
4 |
box大小 |
box type |
4 |
box类型 |
version |
1 |
box版本,0或1,一般为0。(以下字节数均按version=0) |
flags |
3 |
|
graphics mode |
4 |
视频合成模式,为0时拷贝原始图像,否则与opcolor进行合成 |
opcolor |
2×3 |
{red,green,blue} |
dinf解释如何定位媒体信息,是一个container box。“dinf”一般包含一个“dref”,即data reference box;“dref”下会包含若干个“url”或“urn”,这些box组成一个表,用来定位track数据。简单的说,track可以被分成若干段,每 一段都可以根据“url”或“urn”指向的地址来获取数据,sample描述中会用这些片段的序号将这些片段组成一个完整的track。一般情况下,当 数据被完全包含在文件中时,“url”或“urn”中的定位字符串是空的。
dref各个字段定义如下
字段 |
占用byte |
描述 |
box size |
4 |
box大小 |
box type |
4 |
box类型 |
version |
1 |
box版本,0或1,一般为0。(以下字节数均按version=0) |
flags |
3 |
|
entry count |
4 |
“url”或“urn”表的元素个数 |
“url”或“urn”列表 |
不定 |
url字段,表示
字段 |
占用byte |
描述 |
box size |
4 |
box大小 |
box type |
4 |
box类型 |
box-flag |
4 |
0001,表示url为空,track包含在文件中 |
stbl解析,stbl” 包含了关于track中sample所有时间和位置的信息,以及sample的编解码等信息。利用这个表,可以解释sample的时序、类型、大小以及在 各自存储容器中的位置
stsd box给出视频、音频的编码、宽高、音量等信息,以及每个sample中包含多少个frame;stsd box的子box用于保存该流的编码类型,如是audio还是video数据的编码类型,这是avc1表示video数据信息,mp4a表示是audio数据信息
avc1-box各个字段描述
字段 |
占用byte |
描述 |
box size |
4 |
box长度 |
box type |
4 |
box类型 |
reserved |
6 |
保留位默认0x00 |
data reference ID |
2 |
引用参考Dref Box |
code stream version |
4 |
一般都是默认值0 |
reserver |
12 |
保留位一般都是默认值0 |
width |
2 |
图像宽度 |
heigth |
2 |
图像高度 |
horizontal resolution |
4 |
默认值一般都是72dpi(前两个字节整数部分,后面两个字节小数部分) |
vertical resolution |
4 |
默认值一般都是72dpi(前两个字节整数部分,后面两个字节小数部分) |
reserved |
4 |
保留位一般都是默认值0 |
frame count |
2 |
默认值一般是0x00 01 每采样点图像的帧数,一般为1,有些情况下,每个采样点有多帧 |
compressorname |
32 |
默认填充32字节0即可 |
depth |
2 |
两个字节默认值是0x00 0x18 即24 |
reserver |
2 |
两个字节默认值是0xFF0xFF |
avcC-box指定了该流的编码类型为H264,存储解码所需的SPS、PPS信息
mp4a-box各个字段描述
字段 |
占用byte |
描述 |
box size |
4 |
box长度 |
box type |
4 |
box类型 |
reserved |
6 |
保留位默认0x00 |
data reference ID |
2 |
引用参考Dref Box |
version |
2 |
一般都是默认值0 |
revision level |
2 |
一般都是默认值0 |
reserved |
4 |
保留位一般都是默认值0 |
channel count |
2 |
音频通道个数 |
sample size |
2 |
音频采样个数 |
pre_define |
2 |
一般为0 |
reserved |
2 |
一般为0 |
sanple rate |
4 |
音频采样率,需要移位16bit |
stco:thunk在文件中的偏移;
stsc:每个thunk中包含几个sample;
stsz:每个sample的size(单位是字节);
stts:每个sample的时长;
stss:哪些sample是关键帧;
ctts:帧解码到渲染的时间差值,通常用在B帧的场景;
未完待续,后续分析stco、stsc、stsz、stts、stss、ctts