MP4 封装格式详解

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 文件的典型结构如下:

  +-+-+-+-+-+-+-+-+-+-+-+-+-+
  |  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组成。

  +-+-+-+-+-+-+-+-+-+-+
  |  Header  |  Data  |
  +-+-+-+-+-+-+-+-+-+-+

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

Box Header

Box 分为普通 Box 和 FullBox。

在这里插入图片描述

普通 Box Header 结构如下:

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

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

字段类型描述
version1 Byte版本号
flags3 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_brand4 bytes主版本号
minor_version4 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。

字段类型描述
version1 Byte版本,取 0 或 1,一般取 0
flags3 Bytes标识
creation_time8/16 Bytes创建时间,当 version=0 时取 4 字节
modification_time8/16 Bytes修改时间,当 version=0 时取 4 字节
timescale8 Bytes时间基
duration8/16 Bytes文件时长,当 version=0 时取 4 字节
rate8 Bytes播放速率,默认取 0x00010000,即 1.0
volume4 Bytes音量,默认取 0x0100,即 1.0
reserved4 Bytes0
reserved2 x 8 Bytes0
matrix9 x 8 Bytes视频播放矩阵,可忽略
pre_defined6 x 8 Bytes0
next_track_id8 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 的形式进行存储,即一个一个音频帧或视频帧的形式进行存储。没有同步字,没有分隔符,只能根据索引进行访问。即:

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参数有关。

字段类型描述
version8 bit取 0 或 1,一般取 0
flags24 bit
entry_count32 bitentry 个数
开始循环
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中的字段都是相同的):

FieldComment
typebox类型,包括 “预定义类型”、“自定义扩展类型”。预定义类型:比如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种的字段都是相同的):

FieldComment
typebox类型,包括 “预定义类型”、“自定义扩展类型”。预定义类型:比如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内容:

FieldComment
datahint数据

stts(Decoding Time to Sample Box)

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

字段类型描述
version8 bit取 0 或 1,一般取 0
flags24 bit
entry_count32 bit条目个数
开始循环
sample_count32 bit单个entry中,具有相同时长(duration 或 sample_delta)的连续sample的个数
sample_delta32 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 都是一个关键帧。

字段类型描述
version8 bit取 0 或 1,一般取 0
flags24 bit
entry_count32 bit条目个数
开始循环
sample_number32 bitsample 计数,从 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) 。

字段类型描述
version8 bit取 0 或 1,一般取 0
flags24 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)

字段类型描述
version8 bit取 0 或 1,一般取 0
flags24 bit
first_chunk当前表项中,对应的第一个chunk的序号
samples_per_chunk同一个entry中每个chunk包含的sample数
sample_description_indexchunk使用的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
字段类型描述
version8 bit取 0 或 1,一般取 0
flags24 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
字段类型描述
version8 bit取 0 或 1,一般取 0
flags24 bit
field_sizeentry表中,每个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 进行改写。

字段类型描述
version8 bit取 0 或 1,一般取 0
flags24 bit
chunk_offsetchunk 在文件中的位置(在文件本身中的 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_brand4 bytes主版本号
minor_version4 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
  • 35
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 是的,一般情况下,MP4文件需要先读取整个文件头部信息,才能够获取到视频和音频的相关信息,然后再根据视频和音频的相关信息去读取具体的视频和音频数据,才能进行播放。因此,如果要播放一个完整的MP4文件,通常需要先将整个文件读取到内存中,然后才能进行播放。不过,对于一些较大的MP4文件,这样的处理方式可能会导致内存的占用过高,因此需要采用一些特殊的技术,例如流式传输等方式来实现边读取边播放的效果。 ### 回答2: MP4是一种常见的音视频文件格式,它通常需要读取整个文件才能进行播放。这是因为MP4文件采用了封装(容器)格式,它将音频、视频和其他多媒体信息封装到同一个文件中。因此,为了播放MP4文件,需要依次读取文件的封装头部信息、音频和视频数据。 首先,播放器需要读取MP4文件的封装头部信息,这些信息包括文件的格式、版本、封装流的结构等。这些信息能够帮助播放器正确地解析文件,并获取包含在文件中的音视频数据的位置和格式。 接下来,播放器会读取音频和视频数据。MP4文件中的音频和视频数据被分割成一系列的帧,每一帧包含一部分音频或视频信息。为了将音频和视频还原出来,播放器需要按照一定的顺序读取这些帧并进行解码。 在读取帧数据之前,播放器还可能需要读取一些其他的相关信息,比如索引表。索引表为播放器提供了快速定位音视频数据的能力,使得播放器能够在一个较大的MP4文件中快速找到特定的帧或时间点。 因此,MP4文件的播放需要逐个地读取文件中的封装头部信息、音频和视频数据,并进行解析和解码。这样才能将音频和视频还原出来,并通过播放器呈现给用户观看和听取。 ### 回答3: MP4是一种常见的视频文件格式,它是通过将音频和视频编码压缩为一个单独的文件来实现高质量的播放效果。要播放MP4文件,需要将整个文件读取到设备的内存中,然后对其中的音频和视频数据进行解码和播放。 首先,设备会读取MP4文件的文件头,这包含了文件的元数据信息,如分辨率、码率、音频格式等。然后,设备会根据这些元数据信息来分配内存空间,用于存储解码后的音频和视频数据。 接下来,设备会对MP4文件进行解码。它会逐帧地读取文件中的音频和视频数据,并进行解压缩和解码,以恢复原始的音频和视频信号。然后,设备会使用解码后的数据来渲染音频和视频画面,从而实现播放效果。 由于MP4文件是按顺序存储的,每个帧都依赖于前面的帧,所以需要读取整个文件才能正确解码和播放。即使只需要播放一部分视频,设备也需要先读取整个文件,然后再根据需要来播放指定的部分。 总之,为了播放MP4文件,设备需要读取整个文件并解码其中的音频和视频数据。这样可以保证音频和视频的连贯性和稳定性,从而实现高质量的视频播放体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UestcXiye

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值