MP4简介
MP4(MPEG-4 Part 14)是一种常见的多媒体容器格式,它是在“ISO/IEC 14496-14”标准文件中定义的,属于MPEG-4的一部分,是“ISO/IEC 14496-12(MPEG-4 Part 12 ISO base media file format)”标准中所定义的媒体格式的一种实现,后者定义了一种通用的媒体文件结构标准。
MP4是一种描述较为全面的容器格式,被认为可以在其中嵌入任何形式的数据,各种编码的视频、音频等都不在话下,不过我们常见的大部分的MP4文件存放的AVC(H.264)或MPEG-4(Part 2)编码的视频和AAC编码的音频。
MP4格式的官方文件后缀名是“.mp4”,还有其他的以mp4为基础进行的扩展或者是缩水版本的格式,包括:M4V, 3GP, F4V等。
Box
MP4文件中的所有数据都装在box(QuickTime中为atom)中,也就是说MP4文件由若干个box组成,每个box有类型和长度,可以将box理解为一个数据对象块。
box中可以包含另一个box。
一个MP4文件首先会有且只有一个“ftyp”类型的box,作为MP4格式的标志并包含关于文件的一些信息;之后会有且只有一个“moov”类型的box(Movie Box),它是一种容器 box,里面包含了各种子box,子box包含了媒体的metadata信息。
MP4文件的媒体数据包含在“mdat”类型的box(Midia Data Box)中,该类型的box也是容器box,可以有多个,也可以没有(当媒体数据全部引用其他文件时)。
标准的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是未定义的,应该将其忽略。
box根据header部分包含的信息的不同可以分为box和full box。
box和full box的区别如图所示:
1、 File Type Box(ftyp)
该box有且只有一个,并且不能包含其他box,一般放在文件的最开始位置,包含一些该MP4文件的基本信息。
ftyp box包含一个32位的major brand(4个字符),一个32位的minor version和一个以32位为单位的compatible数组。
这些都是用来指示文件应用级别的信息。
下面来分析一个示例文件:
00 00 00 18 66 74 79 70 6D 70 34 32 00 00 00 00 6D 70 34 32 00 00 00 00 ...
box的类型为ftyp box大小为24个字节,其中major_brand和minor_version都是mp42。
2、 Movie Box(moov)
该box包含了文件媒体的metadata信息,“moov”是一个容器 box,具体内容信息由子box诠释。
该box也是有且只有一个,且只被包含在文件层。
有时输出的格式拿到网络上后发现需要完整下载后才能开始播放,而不能像网上的很多视频那样一开始就能播放,造成这个问题的原因是一些描述mp4文件信息的moov box元数据放置在了视频文件的最后,而所有的播放器都需要这些信息来正确构建播放(比如视频分辨率到底是多少,视频到底有多长......),因此需要把这些信息想办法移动到mp4文件的前部,这样读取到这些信息后客户端播放器就可以搭起播放环境,后续只需要播放数据即可。
2.1、 Movie Header Box(mvhd)
由上图MP4文件结构图可以看出“moov”中会包含1个“mvhd box”和若干个“trak box”。
其中“mvhd”为header box,一般作为“moov”的第一个子box出现(对于其他容器 box来说,header box都应作为首个子box出现)。
mvhd 定义了整个 movie 的特性,例如 time scale 和 duration。具体字段的表结构如图:
2.2、 Track Box(trak)
一个mp4文件可以包含一个或多个 tracks,它们之间相互独立,各自有各自的时间和空间信息。
每个track box都有与之关联的media box。trak box 要求必须有一个 trak header box (‘tkhd’) 和一个 media box(‘mdia’)。
其中tkhd box包含了该track的特性和总体信息,如时长,宽高等。tkhd box的字段结构如下表:
字段 | 字节长度(多少个字节) | 含义 |
---|---|---|
box size | 4 | box大小 |
box type | 4 | box类型 |
version | 1 | box版本,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 | 指定创建时间(相对于UTC时间1904-01-01零点的秒数) |
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.8] 格式的音量信息,如果为音频track,1.0(0x0100)表示最大音量;否则为0 |
reserved | 2 | 保留位 |
matrix | 36 | 指定视频变换矩阵 |
width | 4 | 宽,为 [16.16] 格式值,与sample描述中的实际画面大小比值,用于播放时的展示宽高 |
height | 4 | 高 |
而mdia box是一个包含一些track媒体数据信息的容器 box。
mdia的子 box 的结构和种类还是比较复杂的。总体来说,“mdia”定义了 trak 媒体类型以及 sample 数据,描述 sample 信息。
一般“mdia”包含一个“mdhd”, 一个“hdlr”和一个“minf”,其中“mdhd”为 media header box,“hdlr” 为 handler reference box,“minf”为 media information box。
2.2.1、 mdhd box
mdhd(Media header box):包含了了该track的总体信息,mdhd 和 tkhd 内容大致都是一样的。tkhd 通常是对指定的 track 设定相关属性和内容,而 mdhd 是针对于独立的 media 来设置的。
2.2.2、 hdlr box
hdlr(handler reference box) 解释了媒体流的播放过程。例如,一个视频 handler 处理一个 video track。
2.2.3、 ninf box
minf box介绍 “minf”存储了解释 trak 媒体数据的 handler-specific 信息,media handler用这些信息将媒体时间映射到媒体数据并进行处理。
“minf”中的信息格式和内容与媒体类型以及解释媒体数据的 media handler密切相关,其他 media handler 不知道如何解释这些信息。
“minf”是一个 container box,其实际内容由子 box说明。
minf的子box 一般情况下,“minf”包含一个 header box,一个“dinf”和一个“stbl”。
header box 根据track type(即 media handler type)分为“vmhd”、“smhd”,
“dinf”为 data information box,“stbl”为 sample table box。
2.2.3.1、 vmhd box
vmhd:用在视频track中,包含当前track的视频描述信息(如视频编码等信息)。除了box header之外还包含graphicsmode和opcolor两个字段。
其中graphicsmode: 视频合成模式,占4个字节。为0时拷贝原始图像,否则与opcolor进行合成。
而opcolor:{red,green,blue},占2X3字节。
2.2.3.2、 smhd box
smhd:用在音频track中,包含当前track的音频描述信息(如编码格式等信息)。其中有一个balance字段;
balance:立体声平衡,占2个字节,[8.8] 格式值,一般为0,-1.0表示全部左声道,1.0表示全部右声道。
2.2.3.3、 stbl box
“stbl”包含了关于 trak 中 sample 所有时间和位置的信息,以及 sample 的编解码等信息。
利用这个表,可以解释sample 的时序、类型、大小以及在各自存储容器中的位置。
“stbl”是一个 container box,其子 box 包括:sample description box(stsd)、time to sample box(stts)、sample size box(stsz 或stz2)、sample to chunk box(stsc)、chunk offset box (stco 或co64)、composition time to sample box(ctts)、sync sample box(stss)等。
“stsd”必不可少,且至少包含一个条目,该box包含了data reference box进行sample数据检索的信息。没有“stsd”就无法计算media sample的存储位置。
stsd:box header和version字段后会有一个entry count字段,根据entry的个数,每个entry会有type信息,如“vide”、“sund”等,根据type不同sample description会提供不同的信息,例如对于video track,会有“VisualSampleEntry”类型信息,对于audio track会有“AudioSampleEntry”类型信息。视频的编码类型、宽高、长度,音频的声道、采样等信息都会出现在这个box中。
stts:stts box存储了sample的duration,描述了sample时序的映射方法,我们通过它可以找到任何时间的sample。stts box可以包含一个压缩的表来映射时间和sample序号,用其他的表来提供每个sample的长度和指针。表中每个条目提供了在同一个时间偏移量里面连续的sample序号,以及samples的偏移量。递增这些偏移量,就可以建立一个完整的time to sample表(时间戳到sample序号的映射表)。
stsz:“stsz” 定义了每个sample的大小,包含了媒体中全部sample的数目和一张给出每个sample大小的表。这个box相对来说体积是比较大的。
stsc: 用chunk组织sample可以方便优化数据获取,一个thunk包含一个或多个sample。“stsc”中用一个表描述了sample与chunk的映射关系,查看这张表就可以找到包含指定sample的thunk,从而找到这个sample。
stss:“stss”确定media中的关键帧。对于压缩媒体数据,关键帧是一系列压缩序列的开始帧,其解压缩时不依赖以前的帧,而后续帧的解压缩将依赖于这个关键帧。“stss”可以非常紧凑的标记媒体内的随机存取点,它包含一个sample序号表,表内的每一项严格按照sample的序号排列,说明了媒体中的哪一个sample是关键帧。如果此表不存在,说明每一个sample都是一个关键帧,是一个随机存取点。
stco:“stco”定义了每个thunk在媒体流中的位置,sample的偏移可以根据其他box推算出来。位置有两种可能,32位的和64位的,后者对非常大的电影很有用。在一个表中只会有一种可能,这个位置是在整个文件中的,而不是在任何box中的,这样做就可以直接在文件中找到媒体数据,而不用解释box。需要注意的是一旦前面的box有了任何改变,这张表都要重新建立,因为位置信息已经改变了。
2.2.3.4、 dinf box
介绍:“dinf”解释如何定位媒体信息,是一个 container box。“dinf”一般包含一个“dref”,即 data reference box;“dref”下会包含若干个“url”或“urn”,这些 box 组成一个表,用来定位 trak 数据。简单的说,trak可以被分成若干段, 每一段都可以根据“url”或“urn”指向的地址来获取数据,sample 描述中会用这些片段的序号将这些片段组成一个完整的 trak。一般情况下,当数据被完全包含在文件中时,“url”或“urn”中的定位字符串是空的。
dref中包含entry_version和entry_flags字段:
entry_version: 用来指明当前 entry 的格式。
entry_flags: 其值不是固定的,但是有一个特殊的值, 0x000001 用来表示当前 media 的数据和 moov 包含的数据一致。
3、 Mdat Box
MP4的媒体信息和数据是分开存放的。就是你想获得数据之前必须要解析出每个帧数据所在的位置。mp4存放这个帧信息的是放在stbl这个box里。而真实的数据放在mdat中。
4、 free Box
free box中的内容是无关紧要的,可以被忽略。该box被删除后,不会对播放产生任何影响,它的type域可以是free或skip。
如果你对音视频开发感兴趣可以关注公号:思想觉悟