十、MP4封装
示例都是以NVIDIA Deepstream中的sample_720p.mp4为例。
1 概念与术语
-
Box:MP4文件是由一个个Box组成的,可以将其理解为一个数据块,它由Header+Data组成,Data 可以存储媒体元数据和实际的音视频码流数据。Box可直接存储数据块,也可包含其它Box,我们把包含其它Box的Box称为container box。
-
Sample:可理解为采样,对于视频可理解为一帧数据,音频一帧数据就是一段固定时间的音频数据,可以由多个Sample数据组成,存储媒体数据的单位是sample。
-
Chunk:连续几个sample组成的单元被称为chunk,每个chunk在文件中有一个偏移量,整个偏移量从文件头算起,在这个chunk内,sample是连续存储的。
-
Track:表示一些chunk的集合,对于媒体数据而言就是一个视频序列或者音频序列,常说的音频/视频轨可对照该概念上。除了Video Track和Audio Track外,还可以有非媒体数据,比如Hint Track,这种类型的Track就不包含媒体数据,可以包含一些将其他数据打包成媒体数据的指示信息或者字幕信息。简单来说,Track是音视频中可以独立操作的媒体单位。
2 box
2.1 ftyp(File Type Box)
-
ftyp(File Type Box)是一个非常重要的box,它定义了文件类型以及该文件所支持的兼容规范。
-
该box有且只有1个,并且只能被包含在文件层,而不能被其他box包含。该box应该被放在文件的最开始,指示该MP4文件应用的相关信息。
2.2 mdat
实际的音视频数据存储,就是在该容器里面。
2.3 moov(Movie Box)
-
moov是一个container box,一个文件只有一个,其包含的所有box用于描述媒体信息(metadata)。描述mdat里面的视频帧或者音频数据是如何播放的。
-
由于是一个 container box,所以除了 box header,其 box body 就是其它的 box
2.3.1 mvhd(Movie Header Box)
-
mvhd 作为媒体信息的 header 出现(注意此header不是box header,而是moov媒体信息的header),用于描述一些所有媒体共享的基本信息。
-
mvhd 语法继承自fullbox,注意下述示例出现的version和flags字段属于fullbox header
2.3.2 trak
-
trak box 是一个 container box,其子 box 包含了该 track 的媒体信息。
-
一个 mp4 文件可以包含多个 track,track之间是独立的,trak box 用于描述每一路媒体流。
-
一般情况下有两个trak,分别对应音频流和视频流。
trak里面含有三个box,分别是:
-
tkhd(track header box):用于简单描述该路媒体流的信息,如创建时间,修改时间,时长,视频长宽等。
-
edts(edit Box):子Box为elst(Edit List Box),主要用于描述时间轴上的编辑操作(指定视频或音频轨道的偏移、剪辑,或者跳过某些部分,来调整媒体的时间轴)。
-
mdia(media box):用于详细描述该路媒体流的信息(里面会有每帧的解码时间、显示时间相关计算数据、每帧的size)
Trak里面有stream type(使用的是AVC/H.264或者)
2.3.2.1 tkhd(track header box)
-
tkhd 作为媒体信息的header出现(注意此 header 不是 box header,而是 track 媒体信息的 header),用于描述一些该track的基本信息。
-
tkhd语法继承自fullbox,注意下述示例出现的version和flags 字段属于fullbox header。
2.3.2.2 edts(edit Box)—>elst
edts Box 包含有关编辑列表的信息,主要用于描述时间轴上的编辑操作。它通常包含一个或多个Edit List Box(elst),用于定义如何对轨道的播放进行编辑。
例如,通过 edts,可以指定视频或音频轨道的偏移、剪辑,或者跳过某些部分,来调整媒体的时间轴。
它下边有一个elst(Edit List Box),它的作用是使track的时间戳产生偏移。看一下一些字段:
3 定位样本box
下面的box是 dinf (Data Information Box)里面的box。
在介绍stbl box之前,需要先介绍一下mp4中定义的sample与chunk:
-
sample:ISO/IEC 14496-12 中定义 samples 之间不能共享同一个时间戳,因此,在音视频 track 中,一个 sample 代表一个视频或音频帧。
-
chunk:多个 sample 的集合,实际上音视频 track 中,chunk 与 sample 一一对应。
3.1 stbl(Sample Table Box)
stbl box是一个container box,是整个track中最重要的一个box,其子box描述了该路媒体流的解码相关信息、音视频位置信息、时间戳信息等。
3.2 avc1
-
avc1,是 avc/h264/mpeg-4 part 10视频编解码格式的代称,是一个 container box,但是 box body 也携带自身的信息。
-
avcC(AVC Video Stream Definition Box),存储 sps && pps,即在 ISO/IEC 14496-15 中定义的 AVCDecoderConfigurationRecord 结构。(其实就是extradata部分)
3.3 stts(time to sample box)
-
存储了该 track 每个 sample 到 dts 的时间映射关系。(可以计算出解码时间戳)
-
包含了一个压缩版本的表,通过这个表可以从解码时间映射到sample序号。表中的每一项是连续相同的编码时间增量(Decode Delta)的个数和编码时间增量。通过把时间增量累加就可以建立一个完整的time to sample表。
可以计算得到dts:
sample样本计数是从1开始计数,不是从0开始3.4 stss(sync sample box)
它包含media中的关键帧的sample表。关键帧是为了支持随机访问。如果此表不存在,说明每一个sample都是一个关键帧。
3.5 ctts
-
存储了该 track 中,每个 sample 的 pts 与 dts 时间差(cts = pts - dts):
-
如果一个视频只有I帧和P帧,则ctts这个表就不需要了,因为解码顺序和显示顺序是一致的,但是如果视频中存在B帧,则需要ctts。
3.6 stsz
包含sample的数量和每个sample的字节大小,这个box相对来说体积比较大的。表明视频帧或者音频帧大小,FFmpeg 里面的AVPacket 的size 数据大小,就是从这个box中来的。