营销型网站建设 深圳信科,wordpress使用指南,购物网站哪个最好,前端开发常用网站参考链接
FFmpeg中mp4的demuxer(mov.c)代码阅读 - 简书mp4文件格式解析 - 简书mp4封装格式各box类型讲解及IBP帧计算_青丶空゛的博客-CSDN博客5分钟入门MP4文件格式 - 程序猿小卡 - 博客园关于M4A文件的随机访问 - 云社区 - 腾讯云
MP4文件格式相关内容
MP4文件由许多box组…参考链接
FFmpeg中mp4的demuxer(mov.c)代码阅读 - 简书mp4文件格式解析 - 简书mp4封装格式各box类型讲解及IBP帧计算_青丶空゛的博客-CSDN博客5分钟入门MP4文件格式 - 程序猿小卡 - 博客园关于M4A文件的随机访问 - 云社区 - 腾讯云
MP4文件格式相关内容
MP4文件由许多box组成每个box包含不同的信息 这些box以树形结构的方式组织。以下是主要box的简要说明根节点之下主要包含三个节点ftyp、moov、mdat。 ftyp文件类型。描述遵从的规范的版本。moov box媒体的metadata信息保存了音视频数据的时空信息。mdat具体的媒体数据。说明在 mp4 中默认写入字节序是 Big-Endian的。
2. mp4文件基本信息
分析mp4文件的工具
mp4box.js一个在线解析mp4的工具。bento4包含mp4dump、mp4edit、mp4encrypt等工具。MP4Box类似于bento4包含很全面的工具。mp4info.exe: windows平台图形界面展示mp4基本信息的工具。mvhd针对整个影片tkhd针对单个trackmdhd针对媒体vmhd针对视频smhd针对音频可以认为是从 宽泛 具体前者一般是从后者推导出来的。 mp4文件基本信息
audio信息 smplratesample rate(采样率)。channel通道个数。bitrate比特率。audiosamplenum音频sample的个数。video信息 width、height视频的宽/高。bitrate比特率(码率)秒为单位。等于视频总的大小/时长。frames视频帧数。fps帧率(frame per second)。total_time时间长度ms为单位。等于duration/timescale。timescale时间的粒度1000表示1000个单位为1s。duration时间粒度的个数。videosamplenum视频sample的个数。
3. 封装格式重要概念 box
mp4文件由若干个box组成。下面是box结构的一个示意图。box由header和body组成header指明box的size和type。size是包含box header的整个box的大小。box type通常是4个ASCII码的字符如“ftyp”、“moov”等这些box type都是已经预定义好的表示固定的含义。如果是“uuid”表示该box为用户自定义扩展类型如果box type是未定义的应该将其忽略。如果header中的size为1则表示box长度需要更多的bits位来描述在后面会有一个64bits位的largesize用来描述box的长度。如果size为0表示该box为文件的最后一个box文件结尾同样只存在于“mdat”类型的box中。只有“mdat”类型的box才可能会用到large sizesize后面紧跟着的32位为box type一般是4个字符如“ftyp”、“moov”等这些box type都是预定义好的分别表示固定的意义。如果是“uuid”表示box为用户的扩展类型如果未定义box type 需要将其忽略box中可以包含box这种box称为container box。box分为两种Box和Fullbox。FullBox 是 Box 的扩展Header 中增加了version 和 flags字段分别定义如下
aligned(8) class Box (unsigned int(32) boxtype,optional unsigned int(8)[16] extended_type) {unsigned int(32) size;unsigned int(32) type boxtype;if (size1) {unsigned int(64) largesize;} else if (size0) {// box extends to end of file}if (boxtype‘uuid’) {unsigned int(8)[16] usertype extended_type;}
}
FullBox有version和flags字段
aligned(8) class FullBox(unsigned int(32) boxtype, unsigned int(8) v, bit(24) f)
extends Box(boxtype) {unsigned int(8) version v;bit(24) flags f;
} MP4box
ftyp box
该box有且只有1个并且只能被包含在文件层而不能被其他box包含。该box应该被放在文件的最开始指示该MP4文件应用的相关信息。“ftyp” body依次包括1个32位的major brand4个字符1个32位的minor version整数和1个以32位4个字符为单位元素的数组compatible brands。这些都是用来指示文件应用级别的信息。major_brand比如常见的 isom、mp41、mp42、avc1、qt等。它表示“最好”基于哪种格式来解析当前的文件。举例major_brand 是 Acompatible_brands 是 A1当解码器同时支持 A、A1 规范时最好使用A规范来解码当前媒体文件如果不支持A规范但支持A1规范那么可以使用A1规范来解码minor_version提供 major_brand 的说明信息比如版本号不得用来判断媒体文件是否符合某个标准/规范compatible_brands文件兼容的brand列表。比如 mp41 的兼容 brand 为 isom。通过兼容列表里的 brand 规范可以将文件 部分或全部解码出来在实际使用中不能把 isom 做为 major_brand而是需要使用具体的brand比如mp41因此对于 isom没有定义具体的文件扩展名、mime type。下面是常见的几种brand以及对应的文件扩展名、mime type更多brand可以参考 这里 。MP4封装格式介绍及解析_tiankong19999的博客-CSDN博客_mp4封装
补充
关于AVC/AVC1
在讨论 MP4 规范时提到AVC有的时候指的是“AVC文件格式”有的时候指的是AVC压缩标准H.264这里简单做下区分。 AVC文件格式基于 ISO基础文件格式 衍生的使用的是AVC压缩标准可以认为是MP4的扩展格式对应的brand 通常是 avc1在MPEG-4 PART 15 中定义。AVC压缩标准H.264在MPEG-4 Part 10中定义。ISO基础文件格式(Base Media File Format) 在 MPEG-4 Part 12 中定义。
FREE可选的
free是可选的如果存在则通常出现在moov与mdat之间即moov-free-mdat。free中的数据通常为全0其作用相当于占位符在实时拍摄视频moov数据增多时分配给moov使用。因为设备录制视频时并不能预先知道视频数据大小如果moov在mdat之前随着拍摄mdat的数据会增加moov数据也会增多如果没有free预留的空间则要不停的向后移动mdat数据以腾出moov空间。 “free”中的内容是无关紧要的可以被忽略。该box被删除后不会对播放产生任何影响。
moov box
moov box 是一个 container box 该box包含了文件媒体的元数据信息具体内容信息由子box诠释。同File Type Box一样该box有且只有一个且只被包含在文件层。一般情况下“moov”会紧随“ftyp”出现。可以看到这个demo 中有 mvhd、trak、udta 三种 box 一般情况下 “moov”中会包含1个“mvhd”和若干个“trak”。其中“mvhd”为header box一般作为“moov”的第一个子box出现。“trak”包含了一条音、视频轨/流/track的相关信息也是一个container box。该box是解析MP4文件里面最重要的一个box它包含了音视频数据的编码格式、音视频数据样本chunks的大小、存储位置也即偏移offset、时间戳单位、DTSCTS(PTS)解码时间、显示时间等等…moov box中记录的每帧音视频数据位置信息实际上都在mdat box中通过解析moov box来获取到每帧音视频数据具体位置后使得播放器能方便的拖拉进度条。
mvhd box (Movie Header Box)
mvhd 描述了与具体音频或视频流无关的文件整体信息其中的duration/timescale的值即为单位为秒的媒体时长。创建时间、修改时间、时间度量标尺、可播放时长等信息字段字节数意义box size4box大小box type4box类型version1box版本0或1一般为0。以下字节数均按version0flags3creation time4创建时间相对于UTC时间1904-01-01零点的秒数modification time4修改时间time scale4文件媒体在1秒时间内的刻度值可以理解为1秒长度的时间单元数duration4该 track的时间长度用duration和time scale值可以计算track时长比如audio track的time scale 8000, duration 560128时长为70.016video track的time scale 600, duration 42000时长为70rate4推荐播放速率高16位和低16位分别为小数点整数部分和小数部分即[16.16] 格式该值为1.00x00010000表示正常前向播放volume2与rate类似[8.8] 格式1.00x0100表示最大音量reserved10保留位matrix36视频变换矩阵一般忽略不计pre-defined24next track id4下一个track使用的id号
补充 timescale一秒包含的时间单位整数。举个例子如果timescale等于1000那么一秒包含1000个时间单位后面track等的时间都要用这个来换算比如track的duration为10,000那么track的实际时长为10,000/100010snext_track_ID32位整数非0一般可以忽略不计。当要添加一个新的track到这个影片时可以使用的track id必须比当前已经使用的track id要大。也就是说添加新的track时需要遍历所有track确认可用的track id
trak box (Track Box)
trak也是一个container box其子box包含了该track的媒体数据引用和描述。一个MP4文件中的媒体可以包含多个track且至少有一个track这些track之间彼此独立有自己的时间和空间信息。“trak”必须包含一个“tkhd”和一个“mdia”此外还有很多可选的box略track表示一些sample集合对于媒体数据来说track表示一个视频或者音频序列一系列子box描述了每个媒体轨道的具体信息hint track并不包含媒体数据而是包含将一些其他数据track打包成流媒体的指示信息sample对于非hint track来说video sample 表示视频帧或者一组连续视频帧audio sample即为一段连续的压缩音频统称为sample对于hint tracksample定义了一个或者多个流媒体的格式sample table指明sample的时序和物理布局的表chunk 一个track的几个sample组成的单元MP4文件中 媒体内容在moov的box中一个moov包含多个track每个track就是一个随时间变化的媒体序列track里每个时间单位是一个samplesample是按照时间顺序排列。注意一帧音频可以分解为多个音频sample所以音频一般用sample作为单位而不用帧
tkhd(track header box)
tkhd 描述的该track的如果是视频会有宽、高信息、 还有文件创建时间、修改时间等。字段字节数意义box size4box大小box type4box类型version1box版本0或1一般为0。以下字节数均按version0flags3按位或操作结果值预定义如下0x000001 track_enabled否则该track不被播放0x000002 track_in_movie表示该track在播放中被引用0x000004 track_in_preview表示该track在预览时被引用。一般该值为7如果一个媒体所有track均未设置track_in_movie和track_in_preview将被理解为所有track均设置了这两项对于hint track该值为0creation time4创建时间相对于UTC时间1904-01-01零点的秒数modification time4修改时间track id4id号不能重复且不能为0reserved4保留位duration4track的时间长度当前track的完整时长需要除以timescale得到具体秒数reserved8保留位layer2视频层默认为0值小的在上层视频轨道的叠加顺序数字越小越靠近观看者比如1比2靠上0比1靠上alternate group2track分组信息默认为0表示该track未与其他track有群组关系当前track的分组IDalternate_group值相同的track在同一个分组里面。同个分组里的track同一时间只能有一个track处于播放状态。当alternate_group为0时表示当前track没有跟其他track处于同个分组。一个分组里面也可以只有一个trackvolume2[8.8] 格式如果为音频track1.00x0100表示最大音量否则为0reserved2保留位matrix36视频变换矩阵width4宽height4高均为 [16.16] 格式值与sample描述中的实际画面大小比值用于播放时的展示宽高
补充
flags按位或操作获得默认值是70x000001 | 0x000002 | 0x000004表示这个track是启用的、用于播放的 且 用于预览的。 Track_enabled值为0x000001表示这个track是启用的当值为0x000000表示这个track没有启用Track_in_movie值为0x000002表示当前track在播放时会用到Track_in_preview值为0x000004表示当前track用于预览模式
mdia (Track Media Structure)
mdia box 描述了这条音视频轨/流(trak)的媒体数据样本的主要信息对播放器来说是一个很重要的box“mdia”也是个container box其子box的结构和种类还是比较复杂的。先来看一个“mdia”的实例结构树图。总 体来说“mdia”定义了track媒体类型以及sample数据描述sample信息。一般“mdia”包含一个“mdhd”一个“hdlr”和 一个“minf”其中“mdhd”为media header box“hdlr”为handler reference box“minf”为media information box。下面依次看一下这几个box的结构。
mdhd (Media Header Box)
当前音/视频轨/流(trak)的总体信息, 该box中有duration字段和timescale字段duration/timescale的值即为当前流的时长。hdlr box用来指定该流的类型字段字节数意义box size4box大小box type4box类型version1box版本0或1一般为0。以下字节数均按version0flags3creation time4创建时间相对于UTC时间1904-01-01零点的秒数modification time4修改时间time scale4同前表duration4track的时间长度language2媒体语言码。最高位为0后面15位为3个字符见ISO 639-2/T标准中定义pre-defined2Handler Reference Boxhdlr
“hdlr”解释了媒体的播放过程信息该box也可以被包含在meta boxmeta中。“hdlr”结构如下表。
字段字节数意义box size4box大小box type4box类型version1box版本0或1一般为0。以下字节数均按version0flags3pre-defined4handler type4在media box中该值为4个字符“vide”— video track“soun”— audio track“hint”— hint trackreserved12name不定track type name以‘\0’结尾的字符串
handler_type的取值包括 vide0x76 69 64 65video tracksoun0x73 6f 75 6eaudio trackhint0x68 69 6e 74hint trackname为utf8字符串对handler进行描述比如 L-SMASH Video Handler参考 这里。“hdlr”的字节实例如下图各字段已经用颜色区分开stsd box的子box用于保存该流的编码类型avcC box指定了该流的编码类型为H264储了解码所需的SPS、PPS信息。stsc stsz stco三个box用于保存每帧视频或音频数据在文件中的保存位置。stts stss ctts三个box用于保存媒体数据和时间戳的对应关系。在同级的stbl的样本表box里面可以查到对应的样本 描述信息(stsd),时序信息(stts),样本的大小信息(stsz),样本到chunk的映射信息(stsc),chunk的位置信息(stco)等等
Media Information Boxminf “minf” 存储了解释track媒体数据的handler-specific信息media handler用这些信息将媒体时间映射到媒体数据并进行处理。“minf”中的信息格式和内容与媒体类型以及解释媒体数据的media handler密切相关其他media handler不知道如何解释这些信息。“minf”是一个container box其实际内容由子box说明。 一 般情况下“minf”包含一个header box一个“dinf”和一个“stbl”其中header box根据track type即media handler type分为“vmhd”、“smhd”、“hmhd”和“nmhd”“dinf”为data information box“stbl”为sample table box。下面分别介绍。 下图为“minf”部分字节实例其中红色为box header蓝色为“smhd”绿色为“dinf”黄色为一部分“stbl”。Media Information Header Boxvmhd、smhd、hmhd、nmhd
Video Media Header Boxvmhd
字段字节数意义box size4box大小box type4box类型version1box版本0或1一般为0。以下字节数均按version0flags3graphics mode4视频合成模式为0时拷贝原始图像否则与opcolor进行合成opcolor2×3redgreenblue
Sound Media Header Boxsmhd
字段字节数意义box size4box大小box type4box类型version1box版本0或1一般为0。以下字节数均按version0flags3balance2立体声平衡[8.8] 格式值一般为0-1.0表示全部左声道1.0表示全部右声道reserved2
Hint Media Header Boxhmhd 略Null Media Header Boxnmhd 非视音频媒体使用该box略
Data Information Boxdinf “dinf”解释如何定位媒体信息是一个container box。“dinf”一般包含一个“dref”即data reference box“dref”下会包含若干个“url”或“urn”这些box组成一个表用来定位track数据。简单的说track可以被分成若干段每 一段都可以根据“url”或“urn”指向的地址来获取数据sample描述中会用这些片段的序号将这些片段组成一个完整的track。一般情况下当 数据被完全包含在文件中时“url”或“urn”中的定位字符串是空的。 “dref”的字节结构如下表。
字段字节数意义box size4box大小box type4box类型version1box版本0或1一般为0。以下字节数均按version0flags3entry count4“url”或“urn”表的元素个数“url”或“urn”列表不定“url”或“urn”都是box“url”的内容为字符串location string“urn”的内容为一对字符串name string and location string。当“url”或“urn”的box flag为1时字符串均为空。 下 面是一个“dinf”的字节实例图。其中黄色为“dinf”的box header由红色部分我们知道包含的“url”或“urn”个数为1红色后面为“url”box的内容。紫色为“url”的box header根据box type我们知道是个“url”绿色为box flag值为1说明“url”中的字符串为空表示track数据已包含在文件中。Sample Table Boxstbl “stbl”几乎是普通的MP4文件中最复杂的一个box了首先需要回忆一下sample的概念。sample是媒体数据存储的单位存储在media的chunk中chunk和sample的长度均可互不相同如下图所示。“stbl” 包含了关于track中sample所有时间和位置的信息以及sample的编解码等信息。利用这个表可以解释sample的时序、类型、大小以及在各自存储容器中的位置。“stbl”是一个container box其子box包括sample description boxstsd、time to sample boxstts、sample size boxstsz或stz2、sample to chunk boxstsc、chunk offset boxstco或co64、composition time to sample boxctts、sync sample boxstss等。 “stsd”必不可少且至少包含一个条目该box包含了data reference box进行sample数据检索的信息。没有“stsd”就无法计算media sample的存储位置。“stsd”包含了编码的信息其存储的信息随媒体类型不同而不同。
Sample Description Boxstsd
给出视频、音频的编码、宽高、音量等信息以及每个sample中包含多少个frame 存储了编码类型和初始化解码器需要的信息。有与特定的track-type相关的信息相同的track-type也会存在不同信息的情况如使用不一样的编码标准。结构如下box header和version字段后会有一个entry count字段根据entry的个数每个entry会有type信息如“vide”、“sund”等根据type不同sample description会提供不同的信息例如对于video track会有“VisualSampleEntry”类型信息对于audio track会有“AudioSampleEntry”类型信息。视频的编码类型、宽高、长度音频的声道、采样等信息都会出现在这个box中。
Time To Sample Boxstts 结构如下“stts” 存储了sample的duration描述了sample时序的映射方法我们通过它可以找到任何时间的sample。“stts”可以包含一个压缩的 表来映射时间和sample序号用其他的表来提供每个sample的长度和指针。表中每个条目提供了在同一个时间偏移量里面连续的sample序号以 及samples的偏移量。递增这些偏移量就可以建立一个完整的time to sample表。
Sample Size Boxstsz
每个sample的size单位是字节 根据 sample_size 字段可以知道当前track包含了多少个sample或帧。结构如下“stsz” 定义了每个sample的大小包含了媒体中全部sample的数目和一张给出每个sample大小的表。这个box相对来说体积是比较大的。有两种不同的box类型stsz、stz2。
stsz
sample_size默认的sample大小单位是byte通常为0。如果sample_size不为0那么所有的sample都是同样的大小。如果sample_size为0那么sample的大小可能不一样。sample_count当前track里面的sample数目。如果 sample_size0那么sample_count 等于下面entry的条目entry_size单个sample的大小如果sample_size0的话
stz2
field_sizeentry表中每个entry_size占据的位数bit可选的值为4、8、16。4比较特殊当field_size等于4时一个字节上包含两个entry高4位为entry[i]低4位为entry[i1]sample_count等于下面entry的条目entry_sizesample的大小。
Sample To Chunk Boxstsc 结构如下用chunk组织sample可以方便优化数据获取一个thunk包含一个或多个sample。“stsc”中用一个表描述了sample与chunk的映射关系查看这张表就可以找到包含指定sample的thunk从而找到这个sample。
Sync Sample Boxstss
结构如下“stss” 确定media中的关键帧。对于压缩媒体数据关键帧是一系列压缩序列的开始帧其解压缩时不依赖以前的帧而后续帧的解压缩将依赖于这个关键帧。 “stss”可以非常紧凑的标记媒体内的随机存取点它包含一个sample序号表表内的每一项严格按照sample的序号排列说明了媒体中的哪一个 sample是关键帧。如果此表不存在说明每一个sample都是一个关键帧是一个随机存取点。
Chunk Offset Boxstco
thunk在文件中的偏移 结构如下“stco” 定义了每个thunk在媒体流中的位置。位置有两种可能32位的和64位的后者对非常大的电影很有用。在一个表中只会有一种可能这个位置是在整个文 件中的而不是在任何box中的这样做就可以直接在文件中找到媒体数据而不用解释box。需要注意的是一旦前面的box有了任何改变这张表都要重新 建立因为位置信息已经改变了。针对小文件、大文件有两种不同的box类型分别是stco、co64它们的结构是一样的只是字段长度不同。chunk_offset 指的是在文件本身中的 offset而不是某个box内部的偏移。在构建mp4文件的时候需要特别注意 moov 所处的位置它对于chunk_offset 的值是有影响的。有一些MP4文件的 moov 在文件末尾为了优化首帧速度需要将 moov 移到文件前面此时需要对 chunk_offset 进行改写。
PTS和DTS的计算
I P B 帧的概念
在音视频中为了提高压缩效率会将每帧画面压缩为不同类型的视频帧数据。I帧表示关键帧包含有一帧画面的完整信息解码时只需要本帧数据就可以解码出完整的一帧画面。P帧表示前向参考帧它保存了本帧与上一帧的差异信息它不能单独解码需要根据上一帧的画面加上本帧保存的差值来获取本帧的完整画面。B帧为双向参考帧它解码时需要依赖它之前和之后的帧来获取最终的画面因为B帧需要依赖它后面的帧来进行解码所以它的解码顺序就必然和显示顺序不能保持一致这时就需要解码时间戳DTS和显示时间戳PTS来共同决定一帧视频数据何时解码然后何时显示了。举个例子一小段视频帧序列如下 type : I — B — B — P — B — B — PPTS : 0.33 0.67 1.00 1.33 1.67 2.00 2.33DTS : 0.00 0.67 1.00 0.33 1.67 2.00 1.33PTS DTS根据mp4 stts和ctts 可以得到DTS和PTS
sttsDecoding Time to Sample Box) stts 可以计算出每个sample的dts其中sample_delta为该sample的dts相对于上一个smaple的差值stts包含了DTS到sample number的映射表主要用来推导每个帧sample的时长。那么此样本数据的dts为 : 0 1000 2000 3000 4000 ···entry_countstts 中包含的entry条目数sample_count单个entry中具有相同时长duration 或 sample_delta的连续sample的个数。sample_deltasample的时长以timescale为计量
cttsComposition Time to Sample Box
Composition Time 构成时间目前我直接理解的PTS。。ctts 有每个sample的构成时间(Composition Time)和解码时间(DTS)之间的差值(CTTS)即图中的composition_offset。如果不存在ctts则代表该流不存在B帧那么PTS就直接等于DTS。帧解码到渲染的时间差值通常用在B帧的场景对于存在B帧的视频来说ctts就需要存在了。当PTS、DTS不相等时就需要ctts了公式为 CT(n) DT(n) CTTS(n) 。 对于只有I帧、P帧的视频来说解码顺序、渲染顺序是一致的此时ctts没必要存在。 timescale
最后就是关于单位,你可以看到图中样本的单位都是以1000为单位浮动实际上真实DTS和PTS时间是需要除以mdia/mdhd中的timescale。这里是30000。有了这些我们就可以在ctts里面计算出pts了 :else if (box_type_equa(uint32_to_str(bh.type, sbuffer), ctts)) {uint32_t version 0;read_net_bytes_to_host_uint32(box[8], version);if(version ! 0) {LOG_E(ctts unsupport version :%d , version)return;}uint32_t entry_cnt 0;read_net_bytes_to_host_uint32(box[12], entry_cnt);char buf[128] {0};tree_childs_insert_with_val(tree, version, uint32_to_ascii(version, buf));tree_childs_insert_with_val(tree, entry_cnt, uint32_to_ascii(entry_cnt, buf));uint32_t i 0, j 0, num 0, pos 16;for (i 0; i entry_cnt; i) {uint32_t sample_cnt;read_net_bytes_to_host_uint32(box[pos], sample_cnt);pos 4;uint32_t sample_offset;read_net_bytes_to_host_uint32(box[pos], sample_offset);pos 4;for (j 0; j sample_cnt; j) {PushBack_Array(pts_array, At_Array(dts_array, num) sample_offset);float dt, pt 0.0;printf(dts : %9.3f ms | pts : %9.3f ms | \n, At_Array(dts_array, num - 1) / (mdhd_time_scale * 1.0), At_Array(pts_array, num - 1) / (mdhd_time_scale * 1.0));}stss (Sync Sample Box)
stss 里面存放了关键帧的序号(I帧)跳转时需要从关键帧开始解码否则会花屏。哪些sample是关键帧mp4文件中关键帧所在的sample序号。如果没有stss的话所有的sample中都是关键帧。entry_countentry的条目数可以认为是关键帧的数目sample_number关键帧对应的sample的序号从1开始计算stsz (Sample Size Boxes)
顾名思义样本大小.stsc (Sample To Chunk Box):
媒体数据的样本是被打包进chunks(块)的,chunks和样本(samples)的大小不固定该box用于说明chunks关联样本的信息。每个thunk中包含几个sampleentry_count有多少个表项每个表项包含first_chunk、samples_per_chunk、sample_description_index信息 first_chunk 该入口第一个chunks的索引(index).samples_per_chunk 样本数量/chunks.sample_description_index指向 stsd 中 sample description 的索引值参考stsd小节 sample 以 chunk 为单位分成多个组。chunk的size可以是不同的chunk里面的sample的size也可以是不同的 前面描述比较抽象这里看个例子这里表示的是
序号1~15的chunk每个chunk包含15个sample序号16的chunk包含30个sample序号17以及之后的chunk每个chunk包含28个sample以上所有chunk中的sample对应的sample description的索引都是1
first_chunksamples_per_chunksample_description_index11511630117281
stco (Chunk Offset Box)
描述每个chunks相对文件的偏移量。如图 第一个chunks即前10个样本(此例), samples.1起始地址为 423257, samples.1的地址则为 423257 140798 564055, 依此类推…有了这些即可计算出音视频的时间和空间信息了mdat box
Meida Data Box 媒体数据box 位于顶层定义是一个字节数组用来存储媒体数据。该box数量可以为0个也可以有多个当媒体数据全部为外部文件引用时数据直接跟在box type字段后面具体数据结构的意义需要参考metadata主要在sample table中描述。实际媒体数据。我们最终解码播放的数据都在这里面该box包含于文件层可以有多个也可以没有当媒体数据全部为外部文件引用时用来存储媒体数据。数据直接跟在box type字段后面具体数据结构的意义需要参考metadata主要在sample table中描述。mehdMovie Extends Header Box
mehd是可选的用来声明影片的完整时长fragment_duration。如果不存在则需要遍历所有的fragment来获得完整的时长。对于fmp4的场景fragment_duration一般没办法提前预知。
trexTrack Extends Box
用来给 fMP4 的 sample 设置各种默认值比如时长、大小等 字段含义如下 track_id对应的 track 的 ID比如video track、audio track 的IDdefault_sample_description_indexsample description 的默认 index指向stsddefault_sample_durationsample 默认时长一般为0default_sample_sizesample 默认大小一般为0default_sample_flagssample 的默认flag一般为0老版本规范里前6位都是保留位新版规范里只有前4位是保留位。is_leading 含义不是很直观下一小节会专门讲解下。reserved4 bits保留位is_leading2 bits是否 leading sample可能的取值包括 0当前 sample 不确定是否 leading sample一般设为这个值1当前 sample 是 leading sample并依赖于 referenced I frame 前面的 sample因此无法被解码2当前 sample 不是 leading sample3当前 sample 是 leading sample不依赖于 referenced I frame 前面的 sample因此可以被解码sample_depends_on2 bits是否依赖其他sample可能的取值包括 0不清楚是否依赖其他sample1依赖其他sample不是I帧2不依赖其他sampleI帧3保留值sample_is_depended_on2 bits是否被其他sample依赖可能的取值包括 0不清楚是否有其他sample依赖当前sample1其他sample可能依赖当前sample2其他sample不依赖当前sample3保留值sample_has_redundancy2 bits是否有冗余编码可能的取值包括 0不清楚是否存在冗余编码1存在冗余编码2不存在冗余编码3保留值sample_padding_value3 bits填充值sample_is_non_sync_sample1 bits不是关键帧sample_degradation_priority16 bits降级处理的优先级一般针对如流传过程中出现的问题
is_leading
为方便讲解下面的 leading frame 对应 leading samplereferenced frame 对应 referenced samle。以 H264编码 为例H264 中存在 I帧、P帧、B帧。由于 B帧 的存在视频帧的 解码顺序、渲染顺序 可能不一致。mp4文件的特点之一就是支持随机位置播放。比如在视频网站上可以拖动进度条快进。很多时候进度条定位的那个时刻对应的不一定是 I帧。为了能够顺利播放需要往前查找最近的一个 I帧如果可能的话从最近的 I帧 开始解码播放也就是说不一定能从前面最近的I帧播放。将上面描述的此刻定位到的帧称作 leading frame。leading frame 前面最近的一个 I 帧叫做 referenced frame。回顾下 is_leading 为 1 或 3 的情况同样都是 leading frame什么时候可以解码decodable什么时候不能解码not decodable我没看懂
1、is_leading 为 1 的例子 如下所示帧2leading frame 解码依赖 帧1、帧3referenced frame。在视频流里从 帧2 往前查找最近的 I帧 是 帧3。哪怕已经解码了 帧3帧2 也解不出来。 2、is_leading 为 3 的例子 如下所示此时帧2leading frame可以解码出来。 moof
moof是个container box相关 metadata 在内嵌box里比如 mfhd、 tfhd、trun 等。mfhdMovie Fragment Header Box
结构比较简单sequence_number 为 movie fragment 的序列号。根据 movie fragment 产生的顺序从1开始递增。
trafTrack Fragment Box
对 fmp4 来说数据被氛围多个 movie fragment。一个 movie fragment 可包含多个track fragment每个 track 包含0或多个 track fragment。每个 track fragment 中可以包含多个该 track 的 sample。 每个 track fragment 中包含多个 track run每个 track run 代表一组连续的 sample。tfhdTrack Fragment Header Box
tfhd 用来设置 track fragment 中 的 sample 的 metadata 的默认值。sample_description_index、default_sample_duration、default_sample_size 没什么好讲的这里只讲解下 tf_flags、base_data_offset。首先是 tf_flags不同 flag 的值如下同样是求按位求或 0x000001 base‐data‐offset‐present存在 base_data_offset 字段表示 数据位置 相对于整个文件的 基础偏移量。0x000002 sample‐description‐index‐present存在 sample_description_index 字段0x000008 default‐sample‐duration‐present存在 default_sample_duration 字段0x000010 default‐sample‐size‐present存在 default_sample_size 字段0x000020 default‐sample‐flags‐present存在 default_sample_flags 字段0x010000 duration‐is‐empty表示当前时间段不存在sampledefault_sample_duration 如果存在则为0 0x020000 default‐base‐is‐moof如果 base‐data‐offset‐present 为1则忽略这个flag。如果 base‐data‐offset‐present 为0则当前 track fragment 的 base_data_offset 是从 moof 的第一个字节开始计算sample 位置计算公式为 base_data_offset data_offset其中data_offset 每个 sample 单独定义。如果未显式提供 base_data_offset则 sample 的位置的通常是基于 moof 的相对位置。举个例子比如 tf_flags 等于 57表示 存在 base_data_offset、default_sample_duration、default_sample_flags。base_data_offset 为 1263 ftyp、moov 的size 之和为 1263。trunTrack Fragment Run Box
前面听过track run 表示一组连续的 sample其中 sample_countsample 的数目data_offset数据部分的偏移量first_sample_flags可选针对当前 track run中 第一个 sample 的设置tr_flags 如下大同小异 0x000001 data‐offset‐present存在 data_offset 字段0x000004 first‐sample‐flags‐present存在 first_sample_flags 字段这个字段的值只会覆盖第一个 sample 的flag设置当 first_sample_flags 存在时sample_flags 则不存在0x000100 sample‐duration‐present每个 sample 都有自己的 sample_duration否则使用默认值0x000200 sample‐size‐present每个 sample 都有自己的 sample_size否则使用默认值0x000400 sample‐flags‐present每个 sample 都有自己的 sample_flags否则使用默认值0x000800 sample‐composition‐time‐offsets‐present每个 sample 都有自己的 sample_composition_time_offset0x000004 first‐sample‐flags‐present覆盖第一个sample的设置这样就可以把一组sample中的第一个帧设置为关键帧其他的设置为非关键帧举例如下tr_flags 为 2565。此时存在 data_offset 、first_sample_flags、sample_size、sample_composition_time_offset。
补充
moofbox这个box是视频分片的描述信息。并不是MP4文件必须的部分但在我们常见的可在线播放的MP4格式文件中例如Silverlight Smooth Streaming中的ismv文件确是重中之重。mfra box一般在文件末尾媒体的索引文件可通过查询直接定位所需时间点的媒体数据。 附Smooth Streaming中ismv文件结构文件分为了多个Fragments每个Fragment中包含moof和mdat。这样的结构符合渐进式播放需求。mdat及其描述信息逐步传输收齐一个Fragment便可播放其中的mdat。mp4和fmp4的区别fMP4 跟普通 mp4 基本文件结构是一样的。普通mp4用于点播场景fmp4通常用于直播场景。 它们有以下差别 普通mp4的时长、内容通常是固定的。fMP4 时长、内容通常不固定可以边生成边播放普通mp4完整的metadata都在moov里需要加载完moov box后才能对mdat中的媒体数据进行解码渲染fMP4中媒体数据的metadata在moof box中moof 跟 mdat 通常结对出现。moof 中包含了sample duration、sample size等信息因此fMP4可以边生成边播放怎么判断mp4文件是普通mp4还是fMP4呢一般可以看下是否存在存在mvexMovie Extends Box。 当存在mvex时表示当前文件是fmp4非严谨。此时sample相关的metadata不在moov里需要通过解析moof box来获得。sample video sample 即为一帧或者一组连续的视频帧audio sample 即为一段连续的音频sample table 指明sample时序和物理布局的表