1.概述
MP4视频文件封装格式是基于QuickTime容器格式定义的,因此参考QuickTime的格式定义对理解MP4文件格式很有帮助。MP4文件格式是一个十分开放的容器,几乎可以用来描述所有的媒体结构,MP4文件中的媒体描述与媒体数据是分开的,并且媒体数据的组织也很自由,不一定要按照时间顺序排列,甚至媒体数据可以直接引用其他文件。同时,MP4也支持流媒体。MP4目前被广泛用于封装h.264视频和AAC音频,是高清视频的代表。
MP4文件中的所有数据都装在box(QuickTime中为atom)中,也就是说MP4文件由若干个box组成,每个box由BoxHeader和BoxData组成类,BoxHeader一般包括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进行描述。
2. 几个名词
track:表示一些sample的集合,对于媒体数据来说,track表示一个视频或音频序列。
hint track:特殊的track,并不包含媒体数据,包含的是一些将其他数据track打包成流媒体的指示信息。
sample:对于非hint track来说,video sample即为一帧视频,或一组连续视频帧,audio sample即为一段连续的压缩音频,它们统称sample,对于hint track,sample定义一个或多个流媒体包的格式。
chunk:一个track的几个sample组成的单元。
3.组成
一个典型的mp4文件构成如下图所示:
File Type Box(ftyp)
该box有且只有1个,并且只能被包含在文件层,而不能被其他box包含。该box应该被放在文件的最开始,指示该MP4文件应用的相关信息。
“ftyp” body依次包括1个32位的major brand(4个字符),1个32位的minor version(整数)和1个以32位(4个字符)为单位元素的数组compatible brands。这些都是用来指示文件应用级别的信息。
Movie Box(moov)
该box包含了文件媒体的metadata信息,“moov”是一个container box,具体内容信息由子box诠释。同File Type Box一样,该box有且只有一个,且只被包含在文件层。一般情况下,“moov”会紧随“ftyp”出现,当然也可以出现在mdat后面,这种情况下在网络传输时需要下载完整个文件才能播放。
一般情况下,“moov”中会包含1个“mvhd”和若干个“trak”。其中“mvhd”为header box,包含了整个媒体文件的信息,如视频时长,创建时间等信息;“trak”表示Video、Audio等,详细信息如图2所示。
Media Data(mdat)
包含真正的媒体数据。
4.几个主要问题
问题1:mp4文件如何Seek,换句话说就是给定一个时间,如何找到对应的sample位置?
1)通过stts,就是sample table boxer里的time to sample 列表,找到对应的sample的序列号,比如说是50。
2)通过stsc 即 sample table boxer里的sample to chunk 列表,定位到属于哪个chunk.
3)通过stco 即sample table boxer 里的chunk offset table 列表,找到这个chunk在整个文件中的偏移量。
4)通过stss,即sample table boxer里的sample size 列表, 顺序查找这个sample的大小,已经其前面的sample的大小,直到改chunk的第一个sample,然后累加偏移量,就可以得到该sample在这个文件中的偏移。
整个过程是一层层来确定最终的文件位置。
问题2:为什么某些大于4G的mp4文件无法正常播放?
这种情况在实际开发中会经常遇到,首先看一下Box的组成,对于大于4G的文件,mdat用uint32是无法保存的,在转码操作时要特别注意。
欢迎大家一起讨论问题。