系列文章目录
MP4文件解析
文章目录
- 系列文章目录
- 前言
- 一、MP4文件的构成
- 二、MP4文件内部结构
- 三、结合实例
- 1、File Type Box(ftyp)
- 2、Movie Box(moov)
- 3、Video/AudioTrack Box
- 4、Free Space Box(free或skip)
- 5、Meida Data Box(mdat)
前言
最近在做的项目需要了解MP4的格式,于是就学习了一番,这里记录一下所学的知识。我们都知道MP4是一套用于音频、视频信息的压缩编码标准,也是我们日常生活中遇到最多的一种视频格式,最开始MP4指的是音频(MP3的升级版),即MPEG-2 AAC标准。随后MP4概念被转移到视频上,对应的是MPEG-4标准。
一、MP4文件的构成
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进行描述。
二、MP4文件内部结构
1.基本结构
其中,size指明了整个box所占用的大小,包括header部分。如果box很大(例如存放具体视频数据的mdat box),超过了uint32的最大数值,size就被设置为1,并用接下来的8位uint64来存放大小。
2.整体结构
三、结合实例
1、File Type Box(ftyp)
该box只有一个只能被包含在文件层,而不能被其他box包含,”ftyp”body一次包含一个32位的minor version(整数)和一个以32位(四个字符)为单位元素的数组compatible brands。这些都是用来指示文件级别的信息
2、Movie Box(moov)
该部分包含了文件媒体的metadata信息,“moov”是一个contanier box,具体内容由其子box诠释。同ftyp box一样该box有且只有一个,且制备包含在文件层,一般情况下moov会跟着ftyp出现。
一般情况下,“moov”中会包含一个“mvhd”和若干个“trak”其中“mvhd”作为header box,一般作为“moov”的第一个子box出现,。“trak”包含了一个track的相关信息,是一个contanier box
其中粉色部分为box header,橙色部分为mvhd
Movie header box(mvhd)结构如下:
“mvhd”的字节实例如下图,各字段已经用颜色区分开:
3、Video/AudioTrack Box
3.1 Track Header Box(tkhd)
Trak也是一个container box 其子box包含了该track的媒体数据引用和描述(hint track除外)。一个MP4文件中的媒体可以包含很多个track,且至少有一个track,这些track之间彼此独立,有自己的时间和空间信息。Trak必须包含一个tkhd和一个mdia,此外还有其他可选择的box,其中tkhd为 track header box ,mdia为media box,该box是一个包含track媒体数据信息的container box。
Trak部分字节如下图所示,其中橙色为trak box的头,绿色为tkhd蓝色为edts(一种可选box)红色部分是mdia
"tkhd"结构如下:
3.2Media Box
3.2.1 media header box (mdhd)
“mdhd”的字节实例如下图所示:
3.2.2 handler reference box(hdlr)
Hdlr解释了媒体的播放过程信息,该box也可以被包含在meta box中,hdlr结构如下:
Hdlr的字节实例图如下:
3.2.3 media information box(minf)
“minf”存储了解释track媒体数据的handler-specific信息,media handler用这些信息见媒体时间映射到媒体数据并进行处理。”minf”中的信息格式和内容与媒体类型及解释媒体数据的media handler密切相关,其他media handler不知到如何解释这些信息,同时minf时一个container box其内容由其子box说明;
一般情下,minf包含一个header box,一个dinf和一个stbl,其中header box根据track type(及media handler type)分别为vmhd、smhd、hmhd和nmhd,dinf时data information box,stbl为sample table box 下面分别介绍:
下图为minf部分字节实例,蓝色为box header,粉色为smhd,绿色为dinf,橙色为一部分stbl;
3.2.3.1 Video Media Header Box(vmhd)
"vmhd"字节结构如下表:
3.2.3.2 Data Information Box(dinf)
“dinf”解释如何定位媒体信息,是一个container box。“dinf”一般包含一个“dref”,即data reference box;“dref”下会包含若干个“url”或“urn”,这些box组成一个表,用来定位track数据。简单的说,track可以被分成若干段,每一段都可以根据“url”或“urn”指向的地址来获取数据,sample描述中会用这些片段的序号将这些片段组成一个完整的track。一般情况下,当数据被完全包含在文件中时,“url”或“urn”中的定位字符串是空的。
“dref”的字节结构如下表:
“url”或“urn”都是box,“url”的内容为字符串(location string),“urn”的内容为一对字符串(name string and location string)。当“url”或“urn”的box flag为1时,字符串均为空。
下面是一个“dinf”的字节实例图。其中黄色为“dinf”的box header,由红色部分我们知道包含的“url”或“urn”个数为1,红色后面为“url”box的内容。紫色为“url”的box header(根据box type我们知道是个“url”),绿色为box flag,值为1,说明“url”中的字符串为空,表示track数据已包含在文件中。
3.2.3.3 Sample Table Box(stbl)
“stbl”几乎是普通的MP4文件中最复杂的一个box了,首先需要回忆一下sample的概念。sample是媒体数据存储的单位,存储在media的chunk中,chunk和sample的长度均可互不相同,如下图所示。
“stbl”包含了关于track中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”包含了编码的信息,其存储的信息随媒体类型不同而不同。
3.2.3.3.1Sample Description Box(stsd)
box header和version字段后会有一个entry count字段,根据entry的个数,每个entry会有type信息,如“vide”、“sund”等,根据type不同sample description会提供不同的信息,例如对于video track,会有“VisualSampleEntry”类型信息,对于audio track会有“AudioSampleEntry”类型信息。
视频的编码类型、宽高、长度,音频的声道、采样等信息都会出现在这个box中。
3.2.3.2 Time To Sample Box(stts)
“stts”存储了sample的duration,描述了sample时序的映射方法,我们通过它可以找到任何时间的sample。“stts”可以包含一个压缩的表来映射时间和sample序号,用其他的表来提供每个sample的长度和指针。表中每个条目提供了在同一个时间偏移量里面连续的sample序号,以及samples的偏移量。递增这些偏移量,就可以建立一个完整的time to sample表。
3.2.3.3 Sync Sample Box(stss)
“stss”确定media中的关键帧。对于压缩媒体数据,关键帧是一系列压缩序列的开始帧,其解压缩时不依赖以前的帧,而后续帧的解压缩将依赖于这个关键帧。“stss”可以非常紧凑的标记媒体内的随机存取点,它包含一个sample序号表,表内的每一项严格按照sample的序号排列,说明了媒体中的哪一个sample是关键帧。如果此表不存在,说明每一个sample都是一个关键帧,是一个随机存取点。
3.2.3.4 composition times(ctts)
在通常的场景中,编解码器编码一个I帧,然后向前跳过几个帧,用编码I帧作为基准帧对一个未来P帧进行编码,然后跳回到I帧之后的下一个帧。编码的I帧和P帧之间的帧被编码为B帧。之后,编码器会再次跳过几个帧,使用第一个P帧作为基准帧编码另外一个P帧,然后再次跳回,用B帧填充显示序列中的空隙。这个过程不断继续,每12到15个P帧和B帧内插入一个新的I帧。
节目输入顺序是按实际出现顺序排列的,即I、B、B、P、B、B、P、B、B……I、B、B、P……;但为了解码时便于从I、P画面插补得到B画面,在编码录制节目时,将顺序改变了,即按照I、P、B、B……顺序,即改为按原来0、3、1、2、6、4、5、9、7、8…的画面顺序。解码时先解出0帧、3帧,再由其插补预测计算得出1帧、2帧等等。为此,须在解码器内设置动态存储器,将I、P帧先解码并存储,再计算出各个B帧。不过最后输出时,还是应当按照实际播放顺序重组读出,按正确顺序输出。
I B B P B B P…B B I I P B B P B B … I B B
1 2 3 4 5 6 7 … 1 4 2 3 7 5 6 …
(a) 显示顺序 (PTS 显示时间戳顺序) (b) 编解码顺序(DTS 时间戳的顺序,在封装Nalus时时间戳顺序)
当带有B帧的Nalus流封装后,再次解码显示,此时PTS 和 DTS 不能一一对应,因为B帧的时间戳小于P帧,此时CTS 可以记录这个偏差,用以回复解码的时间戳。
3.2.3.4 Sample To Chunk Box(stsc)
用chunk组织sample可以方便优化数据获取,一个thunk包含一个或多个sample。“stsc”中用一个表描述了sample与chunk的映射关系,查看这张表就可以找到包含指定sample的thunk,从而找到这个sample。
3.2.3.5 Sample Size Box(stsz)
“stsz” 定义了每个sample的大小,包含了媒体中全部sample的数目和一张给出每个sample大小的表。这个box相对来说体积是比较大的。
3.2.3.6 Chunk Offset Box(stco)
“stco”定义了每个thunk在媒体流中的位置。位置有两种可能,32位的和64位的,后者对非常大的电影很有用。在一个表中只会有一种可能,这个位置是在整个文件中的,而不是在任何box中的,这样做就可以直接在文件中找到媒体数据,而不用解释box。需要注意的是一旦前面的box有了任何改变,这张表都要重新建立,因为位置信息已经改变了。
4、Free Space Box(free或skip)
“free”中的内容是无关紧要的,可以被忽略。该box被删除后,不会对播放产生任何影响。
5、Meida Data Box(mdat)
该box包含于文件层,可以有多个,也可以没有(当媒体数据全部为外部文件引用时),用来存储媒体数据。数据直接跟在box type字段后面,具体数据结构的意义需要参考metadata(主要在sample table中描述)。
友情提示;我这里用到的可视化分析mp4文件 的工具是“mp4info”,由于这个软件能显示的数据有限,可以搭配其他的软件(例如:UE、HEXEdit等)一起分析。