MP4视频文件封装格式是基于QuickTime容器格式定义的,所以参考QuickTime的格式定义对理解MP4文件格式颇有帮助。MP4文件格式是一个十分开放的容器,几乎能够用来描述全部的媒体结构,MP4文件中的媒体描述与媒体数据是分开的,而且媒体数据的组织也很自由,不必定要按照时间顺序排列,甚至媒体数据能够直接引用其余文件。同时,MP4也支持流媒体。MP4目前被普遍用于封装h.264视频和AAC音频,是高清视频的表明。数组
MP4文件中的全部数据都装在box(QuickTime中为atom)中,也就是说MP4文件由若干个box组成,每一个box有类型和长度,能够将box理解为一个数据对象块。box中能够包含另外一个box,这种box称为container box。一个MP4文件首先会有且只有一个“ftyp”类型的box,做为MP4格式的标志并包含关于文件的一些信息;以后会有且只有一个“moov”类型的box(Movie Box),它是一种container box,子box包含了媒体的metadata信息;MP4文件的媒体数据包含在“mdat”类型的box(Midia Data Box)中,该类型的box也是container box,能够有多个,也能够没有(当媒体数据所有引用其余文件时),媒体数据的结构由metadata进行描述。网络
首先须要说明的是,box中的字节序为网络字节序,也就是大端字节序(Big-Endian),简单的说,就是一个32位的4字节整数存储方式为高位字节在内存的低端。Box由header和body组成,其中header统一指明box的大小和类型,body根据类型有不一样的意义和格式。数据结构
标准的box开头的4个字节(32位)为box size,该大小包括box header和box body整个box的大小,这样咱们就能够在文件中定位各个box。若是size为1,则表示这个box的大小为large size,真正的size值要在largesize域上获得。(实际上只有“mdat”类型的box才有可能用到large size。)若是size为0,表示该box为文件的最后一个box,文件结尾即为该box结尾。(一样只存在于“mdat”类型的box中。)
size后面紧跟的32位为box type,通常是4个字符,如“ftyp”、“moov”等,这些box type都是已经预约义好的,分别表示固定的意义。若是是“uuid”,表示该box为用户扩展类型。若是box type是未定义的,应该将其忽略。ide
Base Box{ BoxHead{ box_size 4byte; box_type 4byte; }; BoxBody };
接下来咱们看看真正的Boxui
该box有且只有1个,而且只能被包含在文件层,而不能被其余box包含。该box应该被放在文件的最开始,指示该MP4文件应用的相关信息。atom
"ftyp" body依次包括1个32位的major brand(4个字符),1个32位的minor version(整数)和1个以32位(4个字符)为单位元素的数组compatible brands。这些都是用来指示文件应用级别的信息。该box的字节实例以下:spa
struct mov_ftyp_t { uint32_t major_brand; uint32_t minor_version; uint32_t compatible_brands[N_BRAND]; size_t brands_count; };
该box包含了文件媒体的metadata信息,moov是一个container box,具体内容信息由子box诠释。同File Type Box同样,该box有且只有一个,且只被包含在文件层。通常状况下,moov会紧随ftyp出现。
通常状况下(限于篇幅,本文只讲解常见的MP4文件结构),moov中会包含1个mvhd和若干个trak。其中mvhd为header box,通常做为moov的第一个子box出现(对于其余container box来讲,header box都应做为首个子box出现)。trak包含了一个track的相关信息,是一个container box。下图为部分moov的字节实例,其中红色部分为box header,绿色为mvhd,黄色为一部分trak。code
字段 | 字节数 | 说明 |
---|---|---|
box size | 4 | box 的大小 |
box type | 4 | box 的类型 |
version | 1 | box 的版本,0或则1,通常为0。一下的字节数均按照version=0设置 |
flag | 3 | |
creation time | 4 | 建立时间,相对于UTC时间(1904-01-01零点的秒数) |
modification time | 4 | 修改时间 |
time scale | 4 | 文件媒体在1秒内的时间刻度,即把1秒划分红多少个小的时间片) |
duration | 4 | 该track的时间长度,用duration和time sacle值能够计算出track的时长; 好比audio track的time scale = 8000,duration=560128,则时长为70.016; video track的time scale=600,duration=42000,时长为70。 |
rate | 4 | 推荐播放速率,高16位和低16位分别为小数点整数部分和小数部分,即[16.16]。 如1.0会表示成0x00010000,表示正常向前播放。 |
volume | 2 | 与rate相似,[8.8] 格式,1.0(0x0100)表示最大音量 |
reserved | 10 | 保留位 |
matrix | 36 | 视频变换矩阵 |
pre-defined | 24 | |
next track id | 4 | 下一个track的id号 |
mvhd的字节实例以下图,各字段已经用颜色区分开:
数据结构的定义视频
struct mov_mvhd_t { // FullBox uint32_t version : 8; uint32_t flags : 24; uint32_t timescale; // time-scale for the entire presentation, the number of time units that pass in one second uint64_t duration; // default UINT64_MAX(by timescale) uint64_t creation_time; // seconds sine midnight, Jan. 1, 1904, UTC uint64_t modification_time; // seconds sine midnight, Jan. 1, 1904, UTC uint32_t rate; uint16_t volume; // fixed point 8.8 number, 1.0 (0x0100) is full volume //uint16_t reserved; //uint32_t reserved2[2]; int32_t matrix[9]; // u,v,w //int32_t pre_defined[6]; uint32_t next_track_ID; };
trak也是一个container box,其子box包含了该track的媒体数据引用和描述(hint track除外)。一个MP4文件中的媒体能够包含多个track,且至少有一个track,这些track之间彼此独立,有本身的时间和空间信息。trak必须包含一个tkhd和一个mdia,此外还有不少可选的box(略)。其中tkhd为track header box,mdia为media box,该box是一个包含一些track媒体数据信息box的container box。
trak的部分字节实例以下图,其中黄色为trak box的头,绿色为tkhd,蓝色为edts(一个可选box),红色为一部分mdia。对象
tkhd结构以下表。
字段 | 字节数 | 意义 |
---|---|---|
box size | 4 | box大小 |
box type | 4 | box类型 |
version | 1 | box版本,0或1,通常为0。(如下字节数均按version=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均设置了这两项;对于hint track,该值为0 |
creation time | 4 | 建立时间(相对于UTC时间1904-01-01零点的秒数) |
modification time | 4 | 修改时间 |
track id | 4 | id号,不能重复且不能为0 |
reserved | 4 | 保留位 |
duration | 4 | track的时间长度 |
reserved | 8 | 保留位 |
layer | 2 | 视频层,默认为0,值小的在上层 |
alternate group | 2 | track分组信息,默认为0表示该track未与其余track有群组关系 |
volume | 2 | [8.8] 格式,若是为音频track,1.0(0x0100)表示最大音量;不然为0 |
reserved | 2 | 保留位 |
matrix | 36 | 视频变换矩阵 |
width | 4 | 宽 |
height | 4 | 高 |
mdia也是个container box,其子box的结构和种类仍是比较复杂的。先来看一个mdia的实例结构树图。
结构以下表:
字段 | 字节数 | 意义 |
---|---|---|
box size | 4 | box大小 |
box type | 4 | box类型 |
version | 1 | box版本,0或1,通常为0。(如下字节数均按version=0) |
flags | 3 | |
creation time | 4 | 建立时间(相对于UTC时间1904-01-01零点的秒数) |
modification time | 4 | 修改时间 |
time scale | 4 | 文件媒体在1秒内的时间刻度,即把1秒划分红多少个小的时间片) |
duration | 4 | 该track的时间长度,用duration和time sacle值能够计算出track的时长; 好比audio track的time scale = 8000,duration=560128,则时长为70.016; video track的time scale=600,duration=42000,时长为70。 |
language | 2 | 媒体语言码。最高位为0,后面15位为3个字符(见ISO 639-2/T标准中定义) |
pre-defined | 2 |
字段 | 字节数 | 意义 |
---|---|---|
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’结尾的字符串 |