MP4 封装格式详解

MP4 封装格式详解

  • [MP4 封装格式详解](#MP4 封装格式详解)
    • 简介
    • 概念与术语
    • [MP4 整体结构](#MP4 整体结构)
    • [Box 结构](#Box 结构)
      • [Box Header](#Box Header)
      • [Box Data](#Box Data)
    • [MP4 典型 Box](#MP4 典型 Box)
      • [ftyp(File Type Box)](#ftyp(File Type Box))
      • [moov(Movie Box)](#moov(Movie Box))
        • [mvhd(moov header)](#mvhd(moov header))
        • trak
          • [tkhd(track header box)](#tkhd(track header box))
          • [edts(edit Box)](#edts(edit Box))
          • [mdia(media box)](#mdia(media box))
        • [udta(user data)](#udta(user data))
      • [mdat(media data box)](#mdat(media data box))
      • [free(free space box)](#free(free space box))
    • [stbl(Sample Table Box)](#stbl(Sample Table Box))
      • [MP4 中的 chunk 和 sample](#MP4 中的 chunk 和 sample)
      • [stsd、stts、stss、ctts、stsc、stsz、stco 概述](#stsd、stts、stss、ctts、stsc、stsz、stco 概述)
      • [stsd(Sample Description Box)](#stsd(Sample Description Box))
      • [stts(Decoding Time to Sample Box)](#stts(Decoding Time to Sample Box))
      • [stss(Sync Sample Box)](#stss(Sync Sample Box))
      • [ctts(Composition Time to Sample Box)](#ctts(Composition Time to Sample Box))
      • [stsc(Sample To Chunk Box)](#stsc(Sample To Chunk Box))
      • [stsz(Sample Size Boxes)](#stsz(Sample Size Boxes))
      • [stco/co64(Chunk Offset Box)](#stco/co64(Chunk Offset Box))
    • [MP4 音视频数据解析过程](#MP4 音视频数据解析过程)
    • [MP4 的使用场景及优缺点](#MP4 的使用场景及优缺点)
    • Q&A
    • 参考

MP4 封装格式详解

简介

MP4(MPEG-4 Part 14)是一种标准的数字多媒体容器格式,其扩展名为.mp4,以存储数字音频及数字视频为主,也可存储字幕和静止图像。

虽然被官方标准定义的唯一扩展名是.mp4,但第三方通常会使用各种扩展名来指示文件的内容:

  • 同时拥有音频视频的MPEG-4文件通常使用标准扩展名.mp4;
  • 仅有音频的MPEG-4文件会使用.m4a扩展名。

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

视频格式:H.264/AVC、H.265/HEVC、VP8/9等。

音频格式:AAC、MP3、Opus等。

因其可容纳支持比特流的视频流(如高级视频编码),MP4可以在网络传输时使用流式传输。

在线解析 MP4 工具:

MP4box.js:https://gpac.github.io/mp4box.js/test/filereader.html

mp4parser:https://www.onlinemp4parser.com/

概念与术语

概念与术语是理解好MP4媒体封装格式和其操作算法的关键,为了方便了解MP4文件格式,需先了解以下几个概念与术语:

  1. Box:MP4文件是由一个个Box组成的,可以将其理解为一个数据块,它由Header+Data组成,Data 可以存储媒体元数据和实际的音视频码流数据。Box可直接存储数据块,也可包含其它Box,我们把包含其它Box的Box称为container box。
  2. Sample:可理解为采样,对于视频可理解为一帧数据,音频一帧数据就是一段固定时间的音频数据,可以由多个Sample数据组成,存储媒体数据的单位是sample。
  3. Chunk:连续几个sample组成的单元被称为chunk,每个chunk在文件中有一个偏移量,整个偏移量从文件头算起,在这个chunk内,sample是连续存储的。
  4. Track:表示一些chunk的集合,对于媒体数据而言就是一个视频序列或者音频序列,常说的音频/视频轨可对照该概念上。除了Video Track和Audio Track外,还可以有非媒体数据,比如Hint Track,这种类型的Track就不包含媒体数据,可以包含一些将其他数据打包成媒体数据的指示信息或者字幕信息。简单来说,Track是音视频中可以独立操作的媒体单位。

可理解为MP4文件中有多个Track,一个Track由多个Chunk组成,每个Chunk包含一组连续的Sample。例如视频流的一个Sample代表实际的nal数据,Chunk是数据存储的基本单位,它是一系列Sample数据的集合。

MP4 整体结构

MP4是一种描述较为全面的容器格式,被认为可以在其中嵌入任何形式的数据,以及各种编码的音视频。

MP4 文件由许多个 Box 和 FullBox 组成。每个Box 包含不同的信息, 这些 Box 以树形结构的方式组织。

每个 Box 由 Header 和 Data 两部分组成。Data 是 Box 的实际数据,可以是纯数据,也可以是更多的子 Box(这个 Box 称为 Container Box)。

FullBox 是 Box 的拓展,其在 Box 结构的基础上,在 Header 中添加 1 字节的 version 标志和 3 字节的 flags 标志。

Box Header 至少占 8 字节。第一个字段是 size,占 4 字节, 表示整个 Box 的大小。第二个字段是 type,占 4字节,表示 Box 的类型。当 size = 0 时,代表这是 MP4 文件的最后一个 Box,当 size = 1 时,说明 Box 长度需要更多位才能描述,在 type 后会定义一个 8 字节的 largesize 用来描述 Box 的长度。当 type = uuid 时,说明这个 Box 中的数据时用户自定义拓展类型。

下图是常见的 Box 的结构图,可用来大致了解MP4文件的构造:

一个 MP4 文件的典型结构如下:

cpp 复制代码
  +-+-+-+-+-+-+-+-+-+-+-+-+-+
  |  ftyp  |  moov |  mdat  |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+

其中:

  • ftyp(file type box):在文件的开始位置,记录一些兼容性信息,比如文件的版本、兼容协议等;
  • moov(movie box):音视频数据的metadata信息。这个box中不包含具体媒体数据,但包含本文件中所有媒体数据的宏观描述信息,moov box下有mvhd box和trak box。
    • mvhd 中记录了创建时间、修改时间、时间度量标尺、可播放时长等信息。
    • trak 中的一系列子box描述了每个媒体轨道的具体信息。
  • mdat(media data box):媒体负载,media 数据容器。我们最终解码播放的实际媒体数据都在这里面。

因为 MP4 标准中没有对 moov 和 mdat 的存放位置没有强制先后要求,所以它们的顺序不定。在互联网视频的点播中,如果希望 MP4 文件被快速打开,则需要将 moov 存放在 mdat 的前面;如果moov 放在 mdat 的后面,则需要将 MP4 文件全部下载完才可以播放。

常见 Box 的简要说明:

Box 结构

通过上面的介绍,我们了解了MP4格式就是由一个个的box组合成的box树,所有的数据都包含在box里,下面来了解一下box的基本结构。

一个box是由Header+Data组成。

cpp 复制代码
  +-+-+-+-+-+-+-+-+-+-+
  |  Header  |  Data  |
  +-+-+-+-+-+-+-+-+-+-+

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

Box Header

Box 分为普通 Box 和 FullBox。

普通 Box Header 结构如下:

字段 类型 描述
size 4 Bytes 表示整个 box 的大小。size=0说明是最后一个box;size=1时,后面的largesize表示真正的box长度
type 4 Bytes 4 个 ASCII 值,如果是 "uuid",则表示此 box 为用户自定义拓展类型
largesize 8 Bytes size=1 时才有的字段,用于扩展,例如 mdat box 会需要此字段

FullBox 在上面的基础上新增了 2 个字段:

字段 类型 描述
version 1 Byte 版本号
flags 3 Bytes 标识

Box Data

一个 Box 可能会包含其它多个 Box,此种 Box 称为 Container Box。

因此,Box Data 可能是数据,也可能是其他 Box。

MP4 典型 Box

虽然Box的类型非常多,大概有70多种,但是并不是都是必须的,一般的MP4文件都是含有必须的Box和个别非必须Box。下面介绍几种典型的 Box。

ftyp(File Type Box)

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

ftyp Box Header首先是 size(4字节),表示整个 Box 的大小;然后是 type(4字节),表示 Box 类型,其内容当然是 "ftyp"。

ftyp Box Data 有三个字段:

字段 类型 描述
major_brand 4 bytes 主版本号
minor_version 4 bytes 次版本号
compatible_brands[] 4×n bytes 指定兼容的版本,注意此字段是一个 list,可以包含多个版本号,每个版本号占 4 字节

实例:

moov(Movie Box)

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

实例:

moov 是一个 Container Box,其包含的所有 Box 用于描述媒体信息(metadata),其子 Box 一般有三种:

  1. mvhd(moov header):用于简单描述一些所有媒体共享的信息。
  2. trak:即track,轨道。用于描述音频流或视频流信息,可以有多个轨道,上面的样例中trak出现了 2 次,分别表示一路音频和一路视频流。
  3. udta(user data):用户自定义,可忽略。

实例:

mvhd(moov header)

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

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

字段 类型 描述
version 1 Byte 版本,取 0 或 1,一般取 0
flags 3 Bytes 标识
creation_time 8/16 Bytes 创建时间,当 version=0 时取 4 字节
modification_time 8/16 Bytes 修改时间,当 version=0 时取 4 字节
timescale 8 Bytes 时间基
duration 8/16 Bytes 文件时长,当 version=0 时取 4 字节
rate 8 Bytes 播放速率,默认取 0x00010000,即 1.0
volume 4 Bytes 音量,默认取 0x0100,即 1.0
reserved 4 Bytes 0
reserved 2 x 8 Bytes 0
matrix 9 x 8 Bytes 视频播放矩阵,可忽略
pre_defined 6 x 8 Bytes 0
next_track_id 8 Bytes 下一个紧邻的 track box id

实例:

trak

trak box 是一个 container box,其子 box 包含了该 track 的媒体信息。

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

每个Trak Box都需要有一个tkhd box和mdia box,其它的box都是可选择的。

  • tkhd(track header box):用于简单描述该路媒体流的信息,如时长,宽度等。
  • mdia(media box):用于详细描述该路媒体流的信息
  • edts(edit Box):子Box为elst(Edit List Box),它的作用是使某个track的时间戳产生偏移。
tkhd(track header box)

tkhd(track header box)是一个 FullBox,对应字段的含义参考下图:

edts(edit Box)

不是所有的 MP4文件有这个 Box

子Box为elst(Edit List Box),它的作用是使某个track的时间戳产生偏移。

实例:

mdia(media box)

mdia(media box)也是Container Box,里面包含子Box,一般必须有mdhd box、hdlr box、minf box。基本就是当前Track媒体头信息和媒体句柄以及媒体信息。它自身非常简单,就是一个标识而已,但最复杂的还是里面包含的子box。

其中:

  • mdhd(Media Header Box):用于简单描述该路媒体流的信息。其中我们最关心的两个字段是timescale和duration,分别表示了该Track的时间戳和时长信息,这个时间戳信息也是PTS和DTS的单位。
  • hdlr(Handler Reference Box):该box解释了媒体的播放过程信息,用来设置不同Track的处理方式,标识了该Track的类型,音频Track的handler为soun,视频Track的handler为vide。
  • minf(Media Information box):该box建立了时间到真实音视频sample的映射关系,是音视频数据操作的关键。该box是container box,含有三大必须的子Box:
    • Media Info Header Box:根据track type(即media handler type)分为"vmhd"(视频)、"smhd"(音频)、"hmhd"和"nmhd"
    • dinf(data information box):描述了如何定位媒体信息,是一个container box。"dinf"一般包含一个"dref"(data reference box)。"dref"下会包含若干个"url"或"urn",这些box组成一个表,用来定位track数据。简单的说,track可以被分成若干段,每一段都可以根据"url"或"urn"指向的地址来获取数据,sample描述中会用这些片段的序号将这些片段组成一个完整的track。一般情况下,当数据被完全包含在文件中时,"url"或"urn"中的定位字符串是空的。
    • stbl(Sample Table Box):stbl box是一个container box,是整个track中最重要的一个box,其子box描述了该路媒体流的解码相关信息、音视频位置信息、时间戳信息等。

实例:

udta(user data)

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

mdat(media data box)

mdat 用于存储音视频数据,可从该Box解封装出真实的媒体数据。该Box一般都会存在,但非必须。

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

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

mdat 可以引用外部的数据,参见 moov -> udta -> meta,这里不讨论,只讨论数据存储在本文件中的形式。

mdat 也是一个 box,拥有 box header 和 box body。

对于 box body 部分,采用一个一个 samples 的形式进行存储,即一个一个音频帧或视频帧的形式进行存储。没有同步字,没有分隔符,只能根据索引进行访问。即:

cpp 复制代码
Box header + Box Data
==>
Box size + Box type + NALU + ... + NALU
NALU = NALU length + NALU Header + NALU Data

码流组织方式采用 avcc 格式,即 AUD + slice size + slice 的形式。

free(free space box)

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

free中的数据通常为全0,其作用相当于占位符,其内容是无关紧要的,可以被忽略。该box被删除后,不会对播放产生任何影响。

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

stbl(Sample Table Box)

stbl 表在 MP4 文件中的位置:moov -> trak -> mdia -> minf -> stbl。不要因为它是一个五级容器就小看它,它是整个 track 中最重要的一个 box,其子 box 描述了该路媒体流的解码相关信息、音视频位置信息、时间戳信息等。想要播放一个 MP4 文件,必须根据stbl正确找到每个sample并送给解码器。stbl用来描述每个sample的信息。

MP4 中的 chunk 和 sample

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

  • sample:ISO/IEC 14496-12 中定义 samples 之间不能共享同一个时间戳,因此,在音视频 track 中,一个 sample 代表一个视频或音频帧。
  • chunk:多个 sample 的集合,实际上音视频 track 中,chunk 与 sample 一一对应。

stsd、stts、stss、ctts、stsc、stsz、stco 概述

stbl(Sample Table Box)的子 Box 的简要介绍:

  • stsd(sample description box):存储了编码类型和初始化解码器需要的信息,并与具体编解码器类型有关。给出视频、音频的编码、宽高、音量等信息,以及每个sample中包含多少个frame。
  • stts(time to sample box):存储了该 track 每个 sample 到 dts 的时间映射关系。
  • stss(sync sample box):针对视频 track,关键帧所属 sample 的序号。
  • ctts(composition time to sample box)存储了该: track 中,每个 sample 的 cts 与 dts 的时间差。
  • stsc/stz2(sample to chunk box):存储了该 track 中每个 sample 与 chunk 的映射关系。
  • stsz(sample size box):存储了该 track 中每个 sample 的字节大小。
  • stco/co64(chunk offset box):存储了该 track 中每个 chunk 在文件中的偏移。

实例:

下面开始逐个讲解各子 Box 的细节。

stsd(Sample Description Box)

stsd 是个 container box,其存储了编码类型和初始化解码器需要的信息。

stsd的内容和track的类型有关,也就是和hdlr的handler_type参数有关。

字段 类型 描述
version 8 bit 取 0 或 1,一般取 0
flags 24 bit
entry_count 32 bit entry 个数
开始循环
AudioSampleEntry() 不定大小 子 box,当 handler_type='soun' 时才有
VisualSampleEntry() 不定大小 子 box,当 handler_type='vide' 时才有
HintSampleEntry() 不定大小 子 box,当 handler_type='hint' 时才有
MetadataSampleEntry() 不定大小 子 box,当 handler_type='meta' 时才有
结束循环

video track的stsd body内容(不同的编码方式,stsd的子box的名称会有不同,但是box中的字段都是相同的):

Field Comment
type box类型,包括 "预定义类型"、"自定义扩展类型"。预定义类型:比如ftyp、moov、mdat等预定义好的类型;自定义扩展类型:如果type==uuid,则表示是自定义扩展类型。size(或largesize)随后的16字节,为自定义类型的值(extended_type)
size 包含box header在内的整个box的大小,单位是字节。当size为0或1时,需要特殊处理
data_reference_index 当MP4文件的数据部分,可以被分割成多个片段,每一段对应一个索引,并分别通过URL地址来获取,此时,data_reference_index 指向对应的片段(比较少用到)
width、height 视频的宽高,单位是像素
horizresolution、vertresolution 水平、垂直方向的分辨率(像素/英寸),默认是0x00480000(72dpi)
frame_count 一个sample中包含多少个frame,对video track来说,默认是1
compressorname 仅供参考的名字,通常用于展示,占32个字节,比如 AVC Coding。第一个字节,表示这个名字实际要占用N个字节的长度。第2到第N+1个字节,存储这个名字。第N+2到32个字节为填充字节。compressorname 可以设置为0
depth 位图的深度信息,比如 0x0018(24),表示不带alpha通道的图片

实例:

audio track的stsd body内容(不同的编码方式,stsd的子box的名称会有不同,但是box种的字段都是相同的):

Field Comment
type box类型,包括 "预定义类型"、"自定义扩展类型"。预定义类型:比如ftyp、moov、mdat等预定义好的类型;自定义扩展类型:如果type==uuid,则表示是自定义扩展类型。size(或largesize)随后的16字节,为自定义类型的值(extended_type)
size 包含box header在内的整个box的大小,单位是字节。当size为0或1时,需要特殊处理
data_reference_index 当MP4文件的数据部分,可以被分割成多个片段,每一段对应一个索引,并分别通过URL地址来获取,此时,data_reference_index 指向对应的片段(比较少用到)
channel_count 声道数,取值为1或2
samplesize 采样位宽,一般为8bit或16bit
samplerate 采样率

实例:

hint track的stsd body内容:

Field Comment
data hint数据

stts(Decoding Time to Sample Box)

stts包含了DTS到sample number的映射表,主要用来推导每个帧的时长,描述了sample时序的映射方法,通过它可以找到任何时间的sample。

字段 类型 描述
version 8 bit 取 0 或 1,一般取 0
flags 24 bit
entry_count 32 bit 条目个数
开始循环
sample_count 32 bit 单个entry中,具有相同时长(duration 或 sample_delta)的连续sample的个数
sample_delta 32 bit 单个 sample 的播放时长,单位为 timescale,也可以说是相邻两个sample之间dts的差值
结束循环

实例:第1个sample的时长是33333,第2个sample的时长是33334,第3-4个sample的时长是33333,以此类推(假设mdhd中timescale为1000,则实际时长需要除以1000)。

stss(Sync Sample Box)

针对视频 track,它包含关键帧所在的 sample 序号。

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

字段 类型 描述
version 8 bit 取 0 或 1,一般取 0
flags 24 bit
entry_count 32 bit 条目个数
开始循环
sample_number 32 bit sample 计数,从 1 开始
结束循环

实例:第1帧、第151帧、第301帧...,是关键帧,以此类推。

ctts(Composition Time to Sample Box)

存储了该 track 中,每个 sample 的 pts 与 dts 时间差,cts = pts - dts。

对于只有I帧、P帧的视频来说,解码顺序、渲染顺序是一致的,此时,ctts没必要存在。

对于存在B帧的视频来说,ctts就需要存在了。当PTS、DTS不相等时,就需要ctts了,公式为 PTS(n) = DTS(n) + TTS(n) 。

字段 类型 描述
version 8 bit 取 0 或 1,一般取 0
flags 24 bit
sample_counts 单个entry中,具有相同差值(pts-dts)的连续sample的个数
sample_offsets 从解码(dts)到渲染(pts)之间的差值

实例:第1个sample的pts-dts=2002,第2个sample的pts-dts=5005,第3个sample的pts-dts=2002,以此类推,真实时长还要除以mdhd中的timescale。

stsc(Sample To Chunk Box)

字段 类型 描述
version 8 bit 取 0 或 1,一般取 0
flags 24 bit
first_chunk 当前表项中,对应的第一个chunk的序号
samples_per_chunk 同一个entry中每个chunk包含的sample数
sample_description_index chunk使用的stsd的序号,即不同chunk可以使用不同编解码信息

实例:

第1个entry的第一个chunk的序号是1,第2个entry的第一个chunk的序号是8225(即第1个entry包含索引值为1-8224的chunk),第3个entry的第一个chunk的索引值时8226,以此类推,最后一个entry就是从first_chunk开始一直到结束为止。

第一个entry每一个chunk包含一个sample,即第1-8224个chunk,每个chunk包含1个sample。第二个entry每一个chunk包含342个sample,即第8225的chunk个chunk包含342个sample。第三个entry每一个chunk包含382个sample,即第8226个chunk包含382个sample,以此类推。

以上所有chunk中的sample,对应的sample description的序号都是1,也就是用第一个stsd。

stsz(Sample Size Boxes)

存储了该 track 中每个 sample 的字节大小。

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

有两种不同的box类型:stsz、stz2。

stsz
字段 类型 描述
version 8 bit 取 0 或 1,一般取 0
flags 24 bit
sample_size 默认的sample大小(单位是byte),通常为0。如果sample_size不为0,那么,所有的sample都是同样的大小。如果sample_size为0,那么,sample的大小可能不一样
sample_count 当前track里面的sample数目。如果 sample_size==0,那么,sample_count 等于下面entry_size中的数据个数
entry_size(sample_sizes) 单个sample的大小(如果sample_size==0的话)

实例:

stz2
字段 类型 描述
version 8 bit 取 0 或 1,一般取 0
flags 24 bit
field_size entry表中,每个entry_size占据的位数(bit),可选的值为4、8、16。4比较特殊,当field_size等于4时,一个字节上包含两个entry,高4位为entry[i],低4位为entry[i+1]
sample_count 等于下面entry_size中的数据个数
entry_size 单个sample的大小

stco/co64(Chunk Offset Box)

chunk在文件中的偏移量(不是mdat中的偏移量)。

针对小文件、大文件,有两种不同的box类型,分别是stco、co64,它们的结构是一样的,只是字段长度不同。

需要注意的是一旦前面的box有了任何改变,这张表都要重新建立。

chunk_offset 指的是在文件本身中的 offset,而不是某个box内部的偏移。

在构建 MP4 文件的时候,需要特别注意 moov 所处的位置,它对于chunk_offset 的值是有影响的。有一些MP4文件的 moov 在文件末尾,为了优化首帧速度,需要将 moov 移到文件前面,此时,需要对 chunk_offset 进行改写。

字段 类型 描述
version 8 bit 取 0 或 1,一般取 0
flags 24 bit
chunk_offset chunk 在文件中的位置(在文件本身中的 offset,而不是某个box内部的偏移)

实例:第1个chunk的offset是48,第2个chunk的偏移是72831,以此类推。

MP4 音视频数据解析过程

这里说的解析基本是指解封装、播放的过程,都是先读取box中的内容,然后根据box中内容可以找到每一个sample也就是每一帧数据,然后进行解封装、播放。

详细过程如下:

  1. 通过stss确定关键帧的数据和每个关键帧的序号。
  2. 通过stts获取音视频流的总帧数、每一帧的dts和整体时长。
  3. 通过ctts获取每一帧中pts与dts的差值。
  4. 通过stsz获取每个sample的大小及整个流的总大小。
  5. 通过stco获取音视频流中chunk的数据和在文件中的位置(不是在mdat中的位置)。
  6. 通过stsc计算出流中chunk的数据和在文件中的位置,并通过chunk在文件中的位置及chunk中每个sample的大小,确定每个sample在文件中的位置和大小。
  7. 整理每个流的码流信息和时间戳信息,构成整体播放的时间轴,之后进行解码的渲染播放。

MP4 的使用场景及优缺点

使用场景:主要是点播场景。

优点:

  1. MP4的标准非常灵活,可扩展性比较好,有很多常见的格式是基于MP4做了一些扩展,然后被应用到比较广的范围,比如 CMAF、DASH、HLS。
  2. 因为MP4格式的开放性和灵活性,使得使用范围非常广泛,我们日常看电视剧,录视频时,最常见的就是MP4格式了。

缺点:

  1. 普通mp4情况下,会导致播放延时较高。
  2. 如果moov在文件尾,播放器需要遍历整个文件后才会找到moov并播放。

Q&A

metadata中的major_brand、minor_version、compatible_brands的作用都是什么?

ftyp Box Data 有三个字段:

字段 类型 描述
major_brand 4 bytes 主版本号
minor_version 4 bytes 次版本号
compatible_brands[] 4×n bytes 指定兼容的版本,注意此字段是一个 list,可以包含多个版本号,每个版本号占 4 字节

实例:

什么是isom?

isom(ISO Base Media file)是在 MPEG-4 Part 12 中定义的一种基础文件格式,MP4、3gp、QT 等常见的封装格式,都是基于这种基础文件格式衍生的。

  • MP4 文件可能遵循的规范有mp41、mp42,而mp41、mp42又是基于isom衍生出来的。

    • 3gp(3PP):一种文件格式,主要用于3G手机上。

QT(QuickTime):.qt文件代表苹果QuickTime媒体文件。

hint track是什么?

hint track:这个特殊的track并不包含媒体数据,而是包含了一些将其它数据track打包成流媒体的指示信息。

下面是mp4官方文档对hint track的描述:

为什么mp4要采用这种chunk-sample这种方式进行逻辑上的存储呢?

总的来说是用时间换空间,因为chunk描述的是一组sample,这些sample相同的性质可以通过chunk去统一描述,比如stsc的sample_description_index就是直接对chunk描述,如果没有chunk则需要对每一个sample都描述一遍。但是在解析sample的时候就需要获取chunk的部分信息来帮助解析,没有那么直接,需要临时建一张表。

如何区分一个track描述的是视频流还是音频流?

方法一:

  • 视频:track->tkhd中width、height不为零,volume为零
  • 音频:track->tkhd中width、height为零,volume不为零

方法二:

  • 视频:track->mdia->hdlr中handler是vide
  • 音频:track->mdia->hdlr中handler是soun

方法三:

  • 视频:track->mdia->minf中有vmhd box(Video Media Information Header)
  • 音频:track->mdia->minf中有smhd box(Sound Media Information Header)

参考

  1. https://blog.csdn.net/m0_60259116/article/details/132714706
  2. https://www.jianshu.com/p/0edc3df5cae6
  3. https://zhuanlan.zhihu.com/p/639897218
  4. https://zhuanlan.zhihu.com/p/637337464
  5. https://cloud.tencent.com/developer/article/1958147
  6. https://blog.csdn.net/weixin_39399492/article/details/127837222
相关推荐
mo47763 小时前
Webrtc音频模块(四) 音频采集
音视频·webrtc
icy、泡芙3 小时前
T527-----音频调试
linux·驱动开发·音视频
易我数据恢复大师3 小时前
怎么提取音频保存到本地?电脑音频提取方法
音视频·软件·音频提取
野蛮的大西瓜3 小时前
开源呼叫中心中,如何将ASR与IVR菜单结合,实现动态的IVR交互
人工智能·机器人·自动化·音视频·信息与通信
嘟嘟实验室6 小时前
微信小程序xr-frame透明视频实现
微信小程序·ffmpeg·音视频·xr
红米饭配南瓜汤7 小时前
WebRTC服务质量(09)- Pacer机制(01) 流程概述
网络·音视频·webrtc
是十一月末10 小时前
Python进阶之opencv图片和视频基本读取关闭
python·opencv·音视频·cv2
gomogomono12 小时前
HDR视频技术之十一:HEVCH.265 的 HDR 编码方案
音视频·h.265·hdr·yuv
Eric.Lee202114 小时前
moviepy将图片序列制作成视频并加载字幕 - python 实现
开发语言·python·音视频·moviepy·字幕视频合成·图像制作为视频
却道天凉_好个秋14 小时前
音视频学习(二十四):hls协议
音视频·hls