location_on 首页 keyboard_arrow_right 科技 keyboard_arrow_right 正文

FFmpeg处理MP4必懂:Box和Sample是什么

科技 access_alarms2026-04-18 visibility4 text_decrease title text_increase

1.MP4格式概述1.1 简介

MP4或称MPEG-4第14部分(MPEG-4 Part 14)是一种标准的数字多媒体容器格式。扩展名为.mp4。虽然被官方标准定义的唯一扩展名是.mp4,但第三方通常会使用各种扩展名来指示文件的内容:

大部分数据可以通过专用数据流嵌入到MP4文件中,因此MP4文件中包含了一个单独的用于存储流信息的轨道。目前得到广泛支持的编解码器或数据流格式有:

1.2 术语

为了后面能比较规范的了解这种文件格式,这里需要了解下面几个概念和术语,这些概念和术语是理解好MP4媒体封装格式和其操作算法的关键。

(1)Box

这个概念起源于QuickTime中的atom,也就是说MP4文件就是由一个个Box组成的,可以将其理解为一个数据块,它由Header+Data组成,Data 可以存储媒体元数据和实际的音视频码流数据。Box里面可以直接存储数据块但是也可以包含其它类型的Box,我们把这种Box又称为container box。

(2)Sample

简单理解为采样,对于视频可以理解为一帧数据,音频一帧数据就是一段固定时间的音频数据,可以由多个Sample数据组成,简而言之:存储媒体数据的单位是sample。

(3)Track

表示一些sample的集合,对于媒体数据而言就是一个视频序列或者音频序列,我们常说的音频轨和视频轨可以对照到这个概念上。当然除了Video Track和Audio Track还可以有非媒体数据,比如Hint Track,这种类型的Track就不包含媒体数据,可以包含一些将其他数据打包成媒体数据的指示信息或者字幕信息。简单来说:Track 就是电影中可以独立操作的媒体单位。

(4)Chunk

一个track的连续几个sample组成的单元被称为chunk,每个chunk在文件中有一个偏移量,整个偏移量从文件头算起,在这个chunk内,sample是连续存储的。

这样就可以理解为MP4文件里面有多个Track,一个Track又是由多个Chunk组成,每个Chunk里面包含着一组连续的Sample,正是因为定义了上述几个概念,MP4这种封装格式才容易实现灵活、高效、开放的特性,所以要仔细理解。

2.MP4整体结构2.1 MP4结构概览

MP4格式是一个box的格式,box容器套box子容器,box子容器再套box子容器。

MP4文件结构详解_MP4格式概述_ffmpeg h

一个box由两部分组成:box header、box body。

MP4格式概述_ffmpeg h_MP4文件结构详解

完整的Box结构:

ffmpeg h_MP4文件结构详解_MP4格式概述

每个Box承载的数据内容如下:

ffmpeg h_MP4文件结构详解_MP4格式概述

2.2 Box结构

mp4 封装格式采用称为 box 的结构来组织数据。结构如下:

  +-+-+-+-+-+-+-+-+-+-+
  |  header  |  body  |
  +-+-+-+-+-+-+-+-+-+-+

其它所有 box 都在语法上继承自此基本 box 结构。

2.2.1 box header

box 分为普通 box 和 fullbox。

(1)普通 box header 结构如下:

字段

类型

描述

size

4 Bytes

包含 box header 的整个 box 的大小

type

4 Bytes

4 个 ascii 值,如果是 "uuid",则表示此 box 为用户自定义,可忽略

large size

8 Bytes

size=1 时才有的字段,用于扩展,例如 mdat box 会需要此字段

(2)fullbox 在上面的基础上新增了 2 个字段:

2.2.2 box body

一个box可能会包含其它多个box,此种box称为container box。因此box body可能是一种具体box类型,也有可能是其它box。

虽然Box的类型非常多,大概有70多种,但是并不是都是必须的,一般的MP4文件都是含有必须的Box和个别非必须Box,我用MP4info这种工具分析了一首MP4的文件,具体的Box显示如下:

MP4格式概述_MP4文件结构详解_ffmpeg h

通过上述工具分析出来的结果,我们大概可以总结出MP4以下几个特点:

MP4文件就是由一个个Box组成,其中Box还可以相互嵌套,排列紧凑没有多的冗余数据;Box类型并没有很多,主要是由必须的ftyp、moov、mdat组成,还有free,udta非必须box组成即去掉这两种box对于播放音视频也没有啥影响。Moov一般存储媒体元数据,比较复杂嵌套层次比较深,后面会详细解释各个box的字段含义和组成。2.3 ftyp(File Type Box)

ftyp 一般出现在文件的开头,用来指示该 mp4 文件使用的标准规范:

一个示例如下:

MP4格式概述_MP4文件结构详解_ffmpeg h

2.4 moov(Movie Box)moov是一个container box,一个文件只有一个,其包含的所有box用于描述媒体信息(metadata)。moov的位置可以紧随着 ftyp 出现,也可以出现在文件末尾。由于是一个 container box,所以除了 box header,其 box body 就是其它的 box。

领音视频开发学习资料→C/C++音视频开发学习路线+资料 - 知乎

子Box:

一个示例如下:

(1)结构

ffmpeg h_MP4文件结构详解_MP4格式概述

(2)数据

ffmpeg h_MP4格式概述_MP4文件结构详解

(3)成分

ffmpeg h_MP4格式概述_MP4文件结构详解

子Box:mvhd

用于简单描述一些所有媒体共享的信息。

MP4文件结构详解_ffmpeg h_MP4格式概述

子Box:trak

track,轨道,用于描述音频流或视频流信息,可以有多个轨道,如上出现了 2 次,分别表示一路音频和一路视频流。

MP4文件结构详解_ffmpeg h_MP4格式概述

2.5 mvhd(Movie Header Box)

mvhd 作为媒体信息的 header 出现(注意此header不是box header,而是moov媒体信息的header),用于描述一些所有媒体共享的基本信息。

mvhd 语法继承自fullbox,注意下述示例出现的version和flags字段属于fullbox header。

Box Body:

ffmpeg h_MP4格式概述_MP4文件结构详解

2.6 trak(track)

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

一个示例如下:

ffmpeg h_MP4文件结构详解_MP4格式概述

其中:

2.7 tkhd(track header box)tkhd 作为媒体信息的header出现(注意此 header 不是 box header,而是 track 媒体信息的 header),用于描述一些该track的基本信息。tkhd语法继承自fullbox,注意下述示例出现的version和flags 字段属于fullbox header。

Box Body:

MP4文件结构详解_MP4格式概述_ffmpeg h

2.8 edts(edit Box)

它下边有一个elst(Edit List Box),它的作用是使某个track的时间戳产生偏移。看一下一些字段:

为使PTS从0开始,media_time字段一般设置为第一个CTTS的值,计算PTS和DTS的时候,他们分别都减去media_time字段的值就可以将PTS调整为从0开始的值。

如果media_time是从一个比较大的值,则表示要求PTS值大于该值时画面才进行显示,这时应该将第一个大于或等于该值的PTS设置为0,其他的PTS和DTS也相应做调整。

2.9 mdia(media box)

定义了track媒体类型以及sample数据,描述sample信息。它是一个container box,它必须包含mdhd,hdlr 和 minf。

一个示例如下:

ffmpeg h_MP4文件结构详解_MP4格式概述

其中:

2.10 mdhd(Media Header Box)mdhd 作为媒体信息的header出现(注意此header不是box header,而是media媒体信息的header),用于描述一些该media的基本信息。mdhd和tkhd ,内容大致都是一样的。不过tkhd通常是对指定的track设定相关属性和内容。而mdhd 是针对于独立的media来设置的。mdhd语法继承自fullbox,注意下述示例出现的 version 和 flags 字段属于fullbox header。

Box Body:

ffmpeg h_MP4格式概述_MP4文件结构详解

注:timescale同mvhd中的timescale,但是需要注意虽然意义相同,但是值有可能不同,下边stts,ctts等时间戳的计算都是以mdhd中的timescale。

2.11 hdlr(Handler Reference Box)主要解释了媒体的播放过程信息。声明当前track的类型,以及对应的处理器(handler)。hdlr 语法继承自 fullbox,注意下述示例出现的 version 和 flags 字段属于 fullbox header。

Box Body:

ffmpeg h_MP4文件结构详解_MP4格式概述

2.12 minf(Media Information box)

解释 track 媒体数据的 handler-specific 信息,media handler用这些信息将媒体时间映射到媒体数据并进行处理。minf 同样是个 container box,其内部需要关注的内容是 stbl,这也是 moov 中最复杂的部分。一般情况下,“minf”包含一个header box,一个“dinf”和一个“stbl”,其中,header box根据track type(即media handler type)分为“vmhd”、“smhd”、“hmhd”和“nmhd”,“dinf”为data information box,“stbl”为sample table box。

ffmpeg h_MP4文件结构详解_MP4格式概述

2.13 *mhd (Media Info Header Box)

可分为“vmhd”、“smhd”、“hmhd”和“nmhd”,比如视频类型则为vmhd,音频类型为smhd。

(1)vmhd

2.14 dinf(Data Information Box)描述了如何定位媒体信息,是一个container box。“dinf”一般包含一个“dref”(data reference box)。“dref”下会包含若干个“url”或“urn”,这些box组成一个表,用来定位track数据。简单的说,track可以被分成若干段,每一段都可以根据“url”或“urn”指向的地址来获取数据,sample描述中会用这些片段的序号将这些片段组成一个完整的track。一般情况下,当数据被完全包含在文件中时,“url”或“urn”中的定位字符串是空的。2.15 stbl(Sample Table Box)

在介绍stbl box之前,需要先介绍一下mp4中定义的sample与chunk:

ffmpeg h_MP4格式概述_MP4文件结构详解

stbl box是一个container box,是整个track中最重要的一个box,其子box描述了该路媒体流的解码相关信息、音视频位置信息、时间戳信息等。

MP4文件的媒体数据部分在mdat box里,而stbl则包含了这些媒体数据的索引以及时间信息。

一个示例如下:

MP4格式概述_MP4文件结构详解_ffmpeg h

其中:

2.16 stsd(sample description box)

主要存储了编码类型和初始化解码器需要的信息。这里以视频为例,包含子box:avc1,表示是H264的视频。

MP4文件结构详解_ffmpeg h_MP4格式概述

2.16.1 h264 stsd

对于h264视频,典型结构如下:

MP4格式概述_MP4文件结构详解_ffmpeg h

其上(只列出 avc1 与 avcC,其余 box 可忽略):

MP4格式概述_ffmpeg h_MP4文件结构详解

avcC(AVC Video Stream Definition Box),存储 sps && pps,即在 ISO/IEC 14496-15 中定义的

AVCDecoderConfigurationRecord 结构

ffmpeg h_MP4文件结构详解_MP4格式概述

注:在 srs 中,解析

avcc/AVCDecoderConfigurationRecord 结构解析参见

srs/trunk/src/kernel/srs_kerner_codec.cpp::SrsFormat::avc_demux_sps_pps() 函数。

2.16.2 aac stsd

对于 aac 音频,典型结构如下:

MP4格式概述_MP4文件结构详解_ffmpeg h

可以看到,aac stsd 结构比较复杂,box 众多。实际上,在 ISO/IEC 14496-3 中,定义了 AudioSpecificConfig 类型,aac stsd 结构主要信息就来自 AudioSpecificConfig。

具体不做分析,可以参看 srs 中:

2.17 stts(time to sample box)存储了该 track 每个 sample 到 dts 的时间映射关系。包含了一个压缩版本的表,通过这个表可以从解码时间映射到sample序号。表中的每一项是连续相同的编码时间增量(Decode Delta)的个数和编码时间增量。通过把时间增量累加就可以建立一个完整的time to sample表。

ffmpeg h_MP4格式概述_MP4文件结构详解

这里为了节约条目的个数,采用了压缩存储的方式,即 sample_count 个连续的 sample 如果 sample_delta 时长一样,那么用一个条目就能表示了。

一个音频 track 的示例如下:

ffmpeg h_MP4文件结构详解_MP4格式概述

一个视频 track 的示例如下:

MP4文件结构详解_ffmpeg h_MP4格式概述

2.18 ctts(composition time to sample box)存储了该 track 中,每个 sample 的 pts 与 dts 时间差(cts = pts - dts):如果一个视频只有I帧和P帧,则ctts这个表就不需要了,因为解码顺序和显示顺序是一致的,但是如果视频中存在B帧,则需要ctts。

MP4文件结构详解_MP4格式概述_ffmpeg h

注意:

2.19 stss(sync sample box)

它包含media中的关键帧的sample表。关键帧是为了支持随机访问。如果此表不存在,说明每一个sample都是一个关键帧。

ffmpeg h_MP4格式概述_MP4文件结构详解

一个视频示例如下:

MP4文件结构详解_ffmpeg h_MP4格式概述

2.20 stsc/stz2(sample to chunk box)

存储了该 track 中每个 sample 与 chunk 的映射关系。

ffmpeg h_MP4格式概述_MP4文件结构详解

一个音频示例如下:

MP4文件结构详解_MP4格式概述_ffmpeg h

2.21 stsz(sample size box)

包含sample的数量和每个sample的字节大小,这个box相对来说体积比较大的。表明视频帧或者音频帧大小,FFmpeg 里面的AVPacket 的size 数据大小,就是从这个box中来的。

MP4文件结构详解_MP4格式概述_ffmpeg h

2.22 stco/co64(chunk offset box)Chunk Offset表存储了每个chunk在文件中的位置,这样就可以直接在文件中找到媒体数据,而不用解析box。需要注意的是一旦前面的box有了任何改变,这张表都要重新建立。

MP4格式概述_ffmpeg h_MP4文件结构详解

stco 有两种形式,如果你的视频过大的话,就有可能造成 chunkoffset 超过 32bit 的限制。所以,这里针对大 Video 额外创建了一个 co64 的 Box。它的功效等价于 stco,也是用来表示 sample 在 mdat box 中的位置。只是,里面 chunk_offset 是 64bit 的。

需要注意,这里 stco 只是指定的每个 Chunk 在文件中的偏移位置,并没有给出每个 Sample 在文件中的偏移。想要获得每个 Sample 的偏移位置,需要结合 Sample Size box 和 Sample-To-Chunk 计算后取得。

2.23 udta(user data box)

用户自定义数据。

2.24 free(free space box)“free”中的内容是无关紧要的,可以被忽略。该box被删除后,不会对播放产生任何影响。Ftyp可以是free或skip。2.25 mdat(media data box)mdat就是具体的编码后的数据。mdat 也是一个 box,拥有 box header 和 box body。mdat 可以引用外部的数据,参见 moov --> udta --> meta,这里不讨论,只讨论数据存储在本文件中的形式。对于 box body 部分,采用一个一个 samples 的形式进行存储,即一个一个音频帧或视频帧的形式进行存储。码流组织方式采用 avcc 格式,即 AUD + slice size + slice 的形式。

生态文明建设的内容:看重大生态环境修复工程如何落地
« 上一篇 2026-04-18
光伏板安装测距专利 一个工人就能操作
下一篇 » 2026-04-18