标准定义

ISO/IEC 14496-12

MP4整体结构

MP4的Box结构

[Box Header] -> [Box Data]

Box Header定义

字段占用(Byte)说明
size4表示整个 box 的大小。size=0说明是最后一个box;size=1时,后面的largesize表示真正的box长度
type44 个 ASCII 值,如果是 “uuid”,则表示此 box 为用户自定义拓展类型
largesize8size=1 时才有的字段,用于扩展,例如 mdat box 会需要此字段
version1版本号
flags3标识
  • version和flags当是full box时存在
  • 以下是一些常见的full box类型

    • mvhd (Movie Header Box)
    • tkhd (Track Header Box)
    • mdhd (Media Header Box)
    • hdlr (Handler Reference Box)
    • vmhd (Video Media Header Box)
    • smhd (Sound Media Header Box)
    • dref (Data Reference Box)
    • stsd (Sample Description Box)
    • stts (Decoding Time to Sample Box)
    • stsc (Sample To Chunk Box)
    • stsz (Sample Size Box)
    • stco / co64 (Chunk Offset Box

MP4需要的基本Box

  • [ftyp]
  • [moov]

    • [mvhd]

      • [tkhd]
      • [media]

        • [mdhd]
        • [hdlr]
        • [minf]

          • [stbl]

            • [stsd]
            • [stts]
            • [stsc]
            • [stsz]
            • [stz2]
            • [stss]
            • [stco]
            • [co64]
  • [mdat]

ftyp(File Type Box)

ftyp是MP4文件的第一个Box,通过判断该Box来确定文件的类型。

字段名称占用空间(Byte)说明
box-size4整个 ftyp box 的总长度,包含这个长度字段本身在内。
box-type4box 的类型标识,固定为 ASCII 字符 "ftyp"。
major_brand4文件的主要品牌标识。它指明了文件最好遵循哪种规范进行解析,例如 isommp41avc1 等。
minor_version4major_brand 相关的版本号。这是一个无符号整数,通常用于指示次要版本,但不应被用来判断文件是否符合某个规范。
compatible_brands可变长度一个兼容性品牌列表,每个品牌占 4 字节。它列出了文件所兼容的其他格式或规范,播放器可以通过检查此列表来判断是否能正确解析该文件。

moov(Movie Box)

moov 是MP4文件中必须有的一个 Box,但只能存在一个,一般出现在 ftyp 之后或 MP4 文件末尾。

字段名称占用空间(Byte)说明
box-size4整个 moov box 的总长度(包含头部)。如果值为 1,则表示实际长度在随后的 8 字节 large-size 中。
box-type4box 的类型标识,固定为 ASCII 字符 "moov"。
mvhd可变Movie Header Box。包含整个时间轴的全局信息,如创建时间、修改时间、时间刻度、总时长、播放速率、音量以及矩阵变换信息。
trak可变Track Box。描述单个轨道(如视频轨、音频轨、字幕轨)的信息。一个 MP4 文件通常包含一个或多个 trak。其内部包含 tkhd (轨道头)、mdia (媒体信息) 等。
udta可变User Data Box。包含用户数据,如元数据标签、版权信息、封面图等(可选)。
pssh可变Protection System Specific Header Box。如果文件有 DRM 加密,这里会包含相关的密钥系统信息(可选)。

mvhd(moov header)

该box是全文件唯一的一个 Box,其对整个媒体文件所包含的媒体数据进行全面的描述。其中包含了媒体的创建和修改时间,默认音量、色域、时长等信息。

字段名称占用空间(Byte)说明
box-size4整个 mvhd box 的总长度。
box-type4box 的类型标识,固定为 ASCII 字符 "mvhd"。
version1box 的版本号,通常为 0 或 1。版本 1 支持 64 位的时间戳和时长。
flags3标志位,通常为 0。
creation_time4 或 8文件的创建时间。当 version 为 0 时占 4 字节,为 1 时占 8 字节。时间基准是 UTC 1904-01-01。
modification_time4 或 8文件的最后修改时间。长度规则同上。
timescale4时间刻度,表示 1 秒被划分成多少个时间单元。它是计算时长的基准。
duration4 或 8文件的总时长,以 timescale 为单位。当 version 为 0 时占 4 字节,为 1 时占 8 字节。
rate4推荐的播放速率,使用 16.16 定点数格式。0x00010000 表示 1.0 倍速正常播放。
volume2推荐的播放音量,使用 8.8 定点数格式。0x0100 表示最大音量。
reserved10保留字段,通常为 0。
matrix36一个 3x3 的变换矩阵,用于定义视频画面的旋转、缩放等图形变换。
pre_defined24预定义字段,通常为 0。
next_track_ID4下一个轨道(track)将使用的 ID 号,通常为现有最大 track ID 加 1。

trak

trak box 是一个 container box,其子 box 包含了该 track 的媒体信息。
一个 mp4 文件可以包含多个 track,track之间是独立的,trak box 用于描述每一路媒体流。一般情况下,一个MP4文件有两个trak,分别对应音频流和视频流。

字段名称占用空间(Byte)说明
box-size4整个 trak box 的总长度(包含头部和所有子 box)。
box-type4box 的类型标识,固定为 ASCII 字符 "trak"。
tkhd可变Track Header Box。轨道头,包含该轨道的基本信息,如轨道ID、创建时间、时长、音量(音频)、宽高(视频)、图层等。
edts可变Edit Box。编辑列表,用于定义轨道的播放顺序,例如实现剪辑、快进、慢放或跳过某些片段(可选)。
mdia可变Media Box。媒体信息容器,包含了该轨道媒体数据的详细声明,如媒体类型、时间信息、数据引用和采样表等。
udta可变User Data Box。用户数据,包含与该轨道相关的元数据,如轨道名称、版权信息等(可选)。

tkhd

tkhd 是 trak 容器的核心子 Box,它描述了单个轨道(如视频轨或音频轨)的宏观属性,例如轨道的启用状态、时长、空间位置(宽高)、音量以及图层关系。
tkhd 是一个 FullBox,其内部字段的长度会根据 version 的值(0 或 1)而有所不同,主要体现在时间戳和时长字段上。

字段名称占用空间(Byte)说明
box-size4整个 tkhd box 的总长度。
box-type4box 的类型标识,固定为 ASCII 字符 "tkhd"。
version1box 的版本号,通常为 0 或 1。版本 1 支持 64 位的时间戳和时长。
flags3标志位,用于控制轨道的启用和显示状态。常见值为 7 (0x000007),表示轨道启用、用于播放且用于预览。
creation_time4 或 8轨道的创建时间。当 version 为 0 时占 4 字节,为 1 时占 8 字节。时间基准是 UTC 1904-01-01。
modification_time4 或 8轨道的最后修改时间。长度规则同上。
track_ID4轨道的唯一标识符,不能为 0 且不能重复。
reserved4保留字段,通常为 0。
duration4 或 8轨道的总时长,以 moovmvhd 的时间刻度为单位。当 version 为 0 时占 4 字节,为 1 时占 8 字节。
reserved8保留字段,通常为 0。
layer2视频轨道的图层顺序。值越小越在上层(越靠近观看者),默认为 0。
alternate_group2轨道分组 ID。相同 ID 的轨道属于同一组,播放时通常只选择其中一个(例如不同语言的音轨),默认为 0 表示不分组。
volume2轨道音量,使用 8.8 定点数格式。对于音频轨道,0x0100 表示 1.0(最大音量);对于视频轨道,通常为 0。
reserved2保留字段,通常为 0。
matrix36一个 3x3 的变换矩阵,用于定义视频画面的旋转、缩放等图形变换。
width4视频画面的宽度,使用 16.16 定点数格式。
height4视频画面的高度,使用 16.16 定点数格式。

edts

edts 是 trak 容器的一个可选子 Box,它的主要作用是定义轨道的播放编辑列表,通过调整时间戳来实现剪辑、偏移或重复播放等效果。

字段名称占用空间(Byte)说明
box-size4整个 edts box 的总长度(包含头部和所有子 box)。
box-type4box 的类型标识,固定为 ASCII 字符 "edts"。
elst可变Edit List Box。编辑列表,是 edts 的核心,包含了具体的编辑指令,用于将轨道的媒体时间映射到整个影片的播放时间线上。

media

mdia 是 trak(轨道)容器的核心子 Box,它详细描述了该轨道所包含的媒体数据的特性,例如媒体类型(音频/视频)、时间信息、语言以及数据在文件中的具体位置。

字段名称占用空间(Byte)说明
box-size4整个 mdia box 的总长度(包含头部和所有子 box)。
box-type4box 的类型标识,固定为 ASCII 字符 "mdia"。
mdhd可变Media Header Box。媒体头,包含该媒体的创建时间、修改时间、时间刻度(timescale)、时长以及语言信息。
hdlr可变Handler Reference Box。处理器引用,声明了该轨道的媒体类型(如 vide 表示视频,soun 表示音频)以及用于处理该媒体的组件。
minf可变Media Information Box。媒体信息容器,包含了描述媒体数据具体属性的信息,如视频头(vmhd)、音频头(smhd)以及最重要的数据索引表(stbl)。

mdat(media data box)

mdat 用于存储音视频数据,可从该Box解封装出真实的媒体数据。该Box一般都会存在,但非必须。
mdat的位置比较灵活,可以位于moov之前,也可以位于moov之后,但必须和stbl中的信息保持一致。

字段名称占用空间(Byte)说明
box-size4整个 mdat box 的总长度(包含头部和数据)。如果值为 1,则表示实际长度在随后的 8 字节 large-size 中。
box-type4box 的类型标识,固定为 ASCII 字符 "mdat"。
data可变媒体数据实体。这里存放的是经过编码的音视频样本(Sample)数据。播放器必须依赖 moov 中的索引信息才能正确解析和播放这部分数据。

stbl(Sample Table Box)

stbl 表在 MP4 文件中的位置:moov -> trak -> mdia -> minf -> stbl。
stbl 是 minf (Media Information Box) 的核心子 Box,也是整个 MP4 文件中最复杂、信息量最大的部分。你可以把它理解为媒体数据的“索引目录”或“地图”。它并不包含实际的音视频数据,而是告诉播放器如何从 mdat 中找到每一个样本(Sample),以及何时播放、如何解码。

字段名称占用空间(Byte)说明
box-size4整个 stbl box 的总长度(包含头部和所有子 box)。
box-type4box 的类型标识,固定为 ASCII 字符 "stbl"。
stsd可变Sample Description Box。样本描述,存储了解码所需的编码格式信息(如 H.264/AVC, AAC)以及初始化参数(如 SPS/PPS)。
stts可变Time-To-Sample Box。时间映射表,定义了每个样本的播放时长(Duration),用于计算 DTS(解码时间戳)。
stss可变Sync Sample Box。同步样本表,列出了所有关键帧(I 帧)的序号,用于支持随机访问和快进。
stsc可变Sample-To-Chunk Box。样本到块映射表,描述了样本是如何分布在数据块(Chunk)中的。
stsz / stz2可变Sample Size Box。样本大小表,记录了每个样本的字节大小。
stco / co64可变Chunk Offset Box。块偏移表,记录了每个数据块(Chunk)在文件中的起始位置(偏移量)。
ctts可变Composition Time To Sample Box。显示时间偏移表,用于计算 PTS(显示时间戳),处理 B 帧时的显示顺序与解码顺序不一致的问题(可选)。

stsd

stsd 是 stbl (Sample Table Box) 的第一个子 Box,它至关重要,因为它存储了解码媒体数据所需的初始化信息和编码格式定义。没有 stsd,播放器就不知道该用哪种解码器来播放音视频。

字段名称占用空间(Byte)说明
box-size4整个 stsd box 的总长度。
box-type4box 的类型标识,固定为 ASCII 字符 "stsd"。
version1box 的版本号,通常为 0。
flags3标志位,通常为 0。
entry_count4样本描述条目的数量。通常为 1,表示该轨道只使用一种编码格式。
Sample Entry可变样本条目。具体的编码信息容器。对于 H.264 视频,这里通常是 avc1 box;对于 AAC 音频,则是 mp4a box。它包含了编解码器特定的配置数据(如 SPS/PPS)。

stts

stts 是 stbl (Sample Table Box) 的一个核心子 Box,它的作用是定义每个样本(Sample)的播放时长,从而建立起样本序号到解码时间戳(DTS)的映射关系。简单来说,它告诉播放器每一帧应该播放多久。

字段名称占用空间(Byte)说明
box-size4整个 stts box 的总长度。
box-type4box 的类型标识,固定为 ASCII 字符 "stts"。
version1box 的版本号,通常为 0。
flags3标志位,通常为 0。
entry_count4时间映射表中的条目数量。
entries8 * entry_count一个数组,包含 entry_count 个条目。每个条目由 sample_countsample_delta 组成,用于描述一段连续样本的时长信息。

entries 数组中每个条目的结构:

字段名称占用空间(Byte)说明
sample_count4连续具有相同时长的样本数量。
sample_delta4每个样本的时长,单位是 mdhd box 中定义的 timescale(时间刻度)。

stss

stss 是 stbl (Sample Table Box) 的一个子 Box,它的核心作用是标记媒体流中的关键帧(也称为同步样本或 I 帧)。关键帧是可以独立解码的帧,不依赖于其他帧的信息,因此它们是视频快进、快退和随机播放的“锚点”。

字段名称占用空间(Byte)说明
box-size4整个 stss box 的总长度。
box-type4box 的类型标识,固定为 ASCII 字符 "stss"。
version1box 的版本号,通常为 0。
flags3标志位,通常为 0。
entry_count4关键帧的数量。
sample_numbers4 * entry_count一个数组,包含 entry_count 个条目。每个条目是一个 4 字节的整数,代表一个关键帧的样本序号(从 1 开始计数)。

ctts

ctts 是 stbl (Sample Table Box) 的一个可选子 Box,它的核心作用是处理视频帧的解码顺序与显示顺序不一致的问题,这在包含 B 帧(双向预测帧)的视频中非常常见。

字段名称占用空间(Byte)说明
box-size4整个 ctts box 的总长度。
box-type4box 的类型标识,固定为 ASCII 字符 "ctts"。
version1box 的版本号。通常为 0,但如果存在负的偏移量(即 PTS < DTS),则必须为 1。
flags3标志位,通常为 0。
entry_count4时间偏移表中的条目数量。
entries8 * entry_count一个数组,包含 entry_count 个条目。每个条目由 sample_countsample_offset 组成。

entries 数组中每个条目的结构:

字段名称占用空间(Byte)说明
sample_count4连续具有相同显示时间偏移量的样本数量。
sample_offset4显示时间偏移量(CTS),单位是 mdhd box 中定义的 timescale(时间刻度)。

stsc

stsc 是 stbl (Sample Table Box) 的核心子 Box 之一。它的作用是建立 样本(Sample) 与 数据块(Chunk) 之间的映射关系。
简单来说,stsc 告诉播放器:在某个数据块中,究竟包含了多少个样本(帧)。

字段名称占用空间(Byte)说明
box-size4整个 stsc box 的总长度。
box-type4box 的类型标识,固定为 ASCII 字符 "stsc"。
version1box 的版本号,通常为 0。
flags3标志位,通常为 0。
entry_count4映射表中条目的数量(注意:这是规则的数量,不是 Chunk 的总数)。
entries12 * entry_count一个数组,包含具体的映射规则。

entries 数组中每个条目的结构:

字段名称占用空间(Byte)说明
first_chunk4这一组规则的起始 Chunk 索引(从 1 开始计数)。
samples_per_chunk4first_chunk 开始,每个 Chunk 包含的样本数量。
sample_description_index4样本描述的索引,指向 stsd 表中的条目(通常用于区分不同的编码格式,但在单编码流中通常为 1)。

stsz

stsz 是 stbl (Sample Table Box) 的核心子 Box 之一。它的核心作用非常直观:记录每一个样本(Sample/帧)的大小(字节数)。
在 MP4 文件中,样本(Sample)的大小通常是不一样的(例如视频中的 I 帧通常比 P 帧大得多)。stsz 提供了一张表,告诉播放器每一帧占用了多少字节,这对于从数据块(Chunk)中准确切割出每一个样本至关重要。

字段名称占用空间(Byte)说明
box-size4整个 stsz box 的总长度。
box-type4box 的类型标识,固定为 ASCII 字符 "stsz"。
version1box 的版本号,通常为 0。
flags3标志位,通常为 0。
sample_size4默认样本大小。如果此值不为 0,表示所有样本大小相同,后面就不需要跟大小表;如果此值为 0,表示样本大小不一,必须读取后面的 entry_size 表。
sample_count4样本的总数量。这个值必须与 sttsstsc 中计算出的总样本数一致。
entry_size4 * sample_count样本大小表。仅当 sample_size 为 0 时存在。这是一个数组,包含 sample_count 个条目,每个条目记录对应样本的具体字节大小。

stco

stco 是 stbl (Sample Table Box) 的核心子 Box 之一。它的核心作用非常明确:记录每一个数据块(Chunk)在 MP4 文件中的物理起始位置(偏移量)。
你可以把它理解为文件中的“物理地址表”。如果说 stsz 告诉我们样本有多大,stsc 告诉我们样本怎么分组,那么 stco 就告诉我们要去哪里(文件的哪个字节位置)读取这些数据。

字段名称占用空间(Byte)说明
box-size4整个 stco box 的总长度。
box-type4box 的类型标识,固定为 ASCII 字符 "stco"。
version1box 的版本号,通常为 0。
flags3标志位,通常为 0。
entry_count4偏移表中的条目数量(也就是 Chunk 的总数量)。
chunk_offsets4 * entry_count偏移量数组。每个条目是一个 4 字节的无符号整数,表示对应 Chunk 距离文件开头的字节数。

参考链接

MP4 封装格式详解