前言

MP4 也称为 MPEG-4 第 14 部分,是继承 MPEG-4 第 12 部分的 ISO 基础媒体文件格式并略作扩展而来,定义于标准 ISO/IEC 14496-14 中,是一种标准的数字多媒体容器格式。

在现在互联网使用的视频中,MP4 是最常见的格式之一,尤其是短视频。如果我们要对短视频的播放体验做优化,了解 MP4 的格式是非常必要的。

一图理解MP4

MP4 文件的数据都是封装在一个又一个名为 Box 的单元中。一个 MP4 文件由若干个 Box/FullBox 组成,每个 Box 包含了 Header 和 Data。

box类型有很多,下面是3个比较重要的顶层box:

ftyp:File TYPE Box,描述文件遵从的MP4规范与版本;

moov:Movie Box,媒体的metadata信息,有且仅有一个。

mdat:Media Data Box,存放实际的媒体数据,一般有多个;

整个就是一个多层的树状结构图

流媒体可以分为几种类型(流媒体协议图解)(1)

MP4 流化处理

对于通过网络播放 MP4 视频的场景,都建议将视频处理为 moov 前置。因为只有拿到 moov box 的数据才能初始化解码器并开始播放。

通过 FFmpeg 工具将 moov box 前置 -movflags faststart

ffmpeg -i slow_play.mp4 -movflags faststart fast_play.mp4

MP4封装格式介绍及解析

MP4文件由许多box组成,每个box包含不同的信息, 这些box以树形结构的方式组织。以下是主要box的简要说明:

流媒体可以分为几种类型(流媒体协议图解)(2)

根节点之下,主要包含三个节点:ftyp、moov、mdat。

ftyp:文件类型。描述遵从的规范的版本。

moov box:媒体的metadata信息。

mdat:具体的媒体数据。

说明:在 mp4 中默认写入字节序是 Big-Endian的。

分析mp4文件的工具:

MP4Box.js:一个在线解析mp4的工具。

bento4:包含mp4dump、mp4edit、mp4encrypt等工具。

MP4Box:类似于bento4,包含很全面的工具。

mp4info.exe: windows平台图形界面展示mp4基本信息的工具。

音视频开发 2022最新学习资料包、教学视频有需要的可以点击FFmpegWebRTCRTMPRTSPHLSRTP播放器-音视频流媒体高级开发

流媒体可以分为几种类型(流媒体协议图解)(3)

下图为使用mp4info.exe打开mp4文件的界面:

流媒体可以分为几种类型(流媒体协议图解)(4)

1、 文件,由许多Box和FullBox组成。

2、 Box,每个Box由Header和Data组成。

3、 FullBox,是Box的扩展,Box结构的基础上在Header中增加8bits version和24bits flags。

4、 Header,包含了整个Box的长度size和类型type。当size==0时,代表这是文件中最后一个Box;当size==1时,意 味着Box长度需要更多bits来描述,在后面会定义一个64bits的largesize描述Box的长度;当type是uuid时,代表Box中的数 据是用户自定义扩展类型。

5、 Data,是Box的实际数据,可以是纯数据也可以是更多的子Boxes。

6、 当一个Box的Data中是一系列子Box时,这个Box又可成为Container Box。

结构如下图:

流媒体可以分为几种类型(流媒体协议图解)(5)

1、 ftypbox,在文件的开始位置,描述的文件的版本、兼容协议等;

2、 moovbox,这个box中不包含具体媒体数据,但包含本文件中所有媒体数据的宏观描述信息,moov box下有mvhd和trak box。

>>mvhd中记录了创建时间、修改时间、时间度量标尺、可播放时长等信息。

>>trak中的一系列子box描述了每个媒体轨道的具体信息。

3、 moofbox,这个box是视频分片的描述信息。并不是MP4文件必须的部分,但在我们常见的可在线播放的MP4格式文件中(例如Silverlight Smooth Streaming中的ismv文件)确是重中之重。

4、 mdatbox,实际媒体数据。我们最终解码播放的数据都在这里面。

5、 mfrabox,一般在文件末尾,媒体的索引文件,可通过查询直接定位所需时间点的媒体数据。

附:Smooth Streaming中ismv文件结构,文件分为了多个Fragments,每个Fragment中包含moof和mdat。这样的结构符合渐进式播放需求。(mdat及其描述信息逐步传输,收齐一个Fragment便可播放其中的mdat)。

MP4文件结构

MP4是由Atom嵌套来存放媒体信息。Atom的基本结构是:

[4bytes atom length] [4bytes atom name] [8bytes largesize, if size ==1] [contents of the atom, if any]

流媒体可以分为几种类型(流媒体协议图解)(6)

结构如图

SIZE表示整个Atom所占用的大小,包括header部分。如果Atom很大,超过了uint32的最大数值(例如存放具体视频数据的mdat),size就被设置为1,并用接下来的LARGESIZE来存放数据大小。

TYPE表示这个Atom的类型,主要有ftyp、moov、mdat等。

LARGESIZE,如果SIZE==1,则使用8bytes uint64来存储该Atom大小。

DATA是实际的数据。

MP4文件含有很多Atom,主要的Atom和嵌套结构如图。

流媒体可以分为几种类型(流媒体协议图解)(7)

一个典型的MP4文件实例

MP4文件需要有ftyp、moov、mdat,它们都是顶级Atom,不能被其他Atom嵌套。

ftyp标示了MP4文件,必须出现在第一个。

moov保存了视频的基本信息,

mdat保存视频和音频数据。这两个Atom顺序不固定。

一个moov在mdat之后的MP4文件的Atom结构:

流媒体可以分为几种类型(流媒体协议图解)(8)

由于moov中保存了视频数据的索引,对于在线播放的场景,需要moov在mdat之前,才能流式读取视频数据。

部分摄像设备生成的MP4文件中,moov在mdat之前,两者之间可能还存在一个Atom free,即moov-free-mdat。

free中为全0,只是用于占位。

一个moov在mdat之前的MP4文件的Atom结构:

流媒体可以分为几种类型(流媒体协议图解)(9)

FTYP

ftyp是整个文件的第一个Atom,通过判断该Atom来确定文件的类型。该Atom有且只有1个,并且只能被包含在文件层,而不能被其他Atom包含。该Atom应该被放在文件的最开始,指示文件的相关信息。

文件的最开始的四个字节就是“ftyp”Atom的大小,然后是该Atom的类型。 “ftyp”的body依次包括1个32位的major brand(4个字符),1个32位的minor version(整数)和1个以32位(4个字符)为单位元素的数组compatible brands。这些都是用来指示文件应用级别的信息。以一个MP4文件的“ftyp”Atom为例,如下所示:

0000000: 0000 0018 6674 7970 6d70 3432 0000 0000 ....ftypmp42....

0000010: 6d70 3432 6d70 3431 0528 834f 6d64 6174 mp42mp41.(.Omdat

其中,

(1)0x00 00 00 18是“ftyp”Atom的大小,为24个字节,这在一般情况下为一个固定值。

(2)0x66 74 79 70是“ftyp”四个字符的ASCII值,也就是该Atom的类型。

(3)0x6D 70 34 32是major brand,这里为“mp42”,对于不同的文件,该值可能是不一样的。

(4)0x00 00 00 00是minor version。

(5)0x6D 70 34 32和0x6D 70 34 31是compatible brands,”mp42”和“mp41”

FTYP到底是什么呢?

ftyp就是一个由四个字符组成的码字,用来标识编码类型、兼容性或者媒体文件的用途。它存在于MP4文件和MOV文件中,当然,也存在于3GP文件中。

虽然MP4文件、MOV文件和3GP文件采用了相同的封装标准,但由于是由不同的厂商合成,因此还是存在差别的。即使是同一种媒体文件,比如MP4文件,由不同developers开发的MP4也是存在差别的。ftyp简单的说就是为了标识它的developer是谁,兼容哪些标准等。

比如上面的例子,“mp42”表示它的major brand是MP4 v2 [ISO 14496-14],而“mp42”和“mp41”则表示它的compatible brands是MP4 v2 [ISO 14496-14]和MP4 v1 [ISO 14496-1:ch13]。

FREE(可选的)

free是可选的,如果存在,则通常出现在moov与mdat之间,即moov-free-mdat。

free中的数据通常为全0,其作用相当于占位符,在实时拍摄视频,moov数据增多时分配给moov使用。

因为设备录制视频时并不能预先知道视频数据大小,如果moov在mdat之前,随着拍摄mdat的数据会增加,moov数据也会增多,如果没有free预留的空间,则要不停的向后移动mdat数据以腾出moov空间。

MOOV

moov中主要保存了媒体的时间信息、trak信息和媒体索引等。

3.1 媒体时间信息

moov-mvhd中有一个time scale,以1/n秒的形式给出一个总的时间粒度,moov-trak-tkhd中以此时间粒度给出各个track的duration;

3.2 trak信息

moov中通常包含两个trak,一个视频索引,一个音频索引。

3.2.1 trak类型

trak的类型在moov-trak-mdia-hdlr中给出,包括’vide’, ‘soun’和’hint’三种。

3.2.2 trak的时间

moov-trak-mdia-mdhd中以1/n秒的形式给出各个媒体的时间粒度以及以此时间粒度为单位的duration。

moov-trak-mdia-minf-stbl-stts中有媒体帧之间的时间间隔,单位是moov-trak-tkhd中的时间粒度。

3.2.3 索引信息

moov-trak-mdia-minf-stbl比较重要,其中保存了解码器需要的信息和索引信息,以下Atom都是stbl Atom的孩子。

stsd中保存了解码器需要的媒体描述信息。

流媒体可以分为几种类型(流媒体协议图解)(10)

标识了媒体流中的关键帧,提供了随机访问点。每个entry标识了一个关键帧。

流媒体可以分为几种类型(流媒体协议图解)(11)

关键帧号是按照增长顺序排列的。如果该Atom不存在,表示所有帧都是关键帧

Sync Sample Table的布局

stts, Time-To-Sample Atomsstts给出每个数据帧之间的时间间隔,单位是moov-trak-tkhd中的时间粒度。Atom的每个entry给出了具有相同时间间隔的连续帧的个数,这些帧的时间间隔值,结构如图。

流媒体可以分为几种类型(流媒体协议图解)(12)

Time-To-Sample的table entry布局

如果连续的帧有相同的时长,他们会被放在同一个entry中。如果所有的帧具有相同的时长,那么Atom中就只有一个entry。

stts实例

下图通过3个entries来描述9个帧。需要说明的是,这里的entry和chunk不是对应的。例如,4、5、6帧可以在同一个chunk中,但是,由于它们的时长不同,4帧的时长为3,而5、6帧的时长为1,因此,保存在不同的entry中。

流媒体可以分为几种类型(流媒体协议图解)(13)

stco/co64, Chunk Offset Atom

stco/co64给出每个数据Chunk在文件中的偏移。Chunk Offset Atom的每个entry给出了每个chunk在文件中的偏移。

如果Chunk Offset Atom的类型为stco,则保存的偏移量是32位;如果是co64,则保存的偏移量是64位的。布局如图。

流媒体可以分为几种类型(流媒体协议图解)(14)

chunk offset table的布局

需要注意的是,该Atom中只给出了每个chunk的偏移量,并没有给出每个sample的偏移量。因此,如果要获得每个sample的偏移量,还需要用到Sample Size Table和Sample-To-Chunk Table。

stsc, Sample-To-Chunk Atom

stsc给出各个数据Chunk中包含的数据帧。一个chunk可能会包含一个或者几个帧。每个chunk会有不同的size,每个chunk中的帧也会有不同的size。

entry中保存了第一个chunk号、每个chunk包含的帧数、帧描述ID。

流媒体可以分为几种类型(流媒体协议图解)(15)

Sample-To-Chunk Atom的table entry布局

每个entry包含一组chunk,其中每个chunk的帧数相同。而且,这些chunk中的每个帧都必须使用相同的帧描述。

如果chunk中的帧数或者帧描述改变,必须创建一个新的entry。

如果所有的chunk包含的帧数和帧描述相同,那么只有一个entry。

stsc实例

图中表示至少有5个chunk,第1、2个chunk分别包含3个帧,帧描述ID是23;第3、4个chunk分别包含1个帧,帧描述ID是23;第5个及以后的chunk,包含1个帧,帧描述ID是24。

对于最后一个entry需要特殊的处理,因为无法判断什么时候结束。

流媒体可以分为几种类型(流媒体协议图解)(16)

stsz, Sample Size Atom

流媒体可以分为几种类型(流媒体协议图解)(17)

sample size table的布局

3.3 用户定义数据

udta中保存了用户定义数据,例如iTune使用的meta数据就保存在udta中。

3.4 用户扩展数据

Atom的扩展通过uuid实现。用户可以使用类型为’uuid’的Atom,以16个特定的字节作为标识,定义自己的数据格式。

MDAT

所有媒体数据统一存放在mdat中,没有同步字,没有分隔符,只能根据索引进行访问。

mdat的位置比较灵活,可以位于moov之前,也可以位于moov之后,但必须和stbl中的信息保持一致。

另外,在写mp4文件的时候,对于mdat这个Atom,一般是先将Atom size填写0,待数据写完之后,再回过来填入具体大小。

,