视频基础和MP4容器解封装

最近在研究基于移动端平台上使用视频作动画载体的方案,目前移动端平台使用动画的方案有:gif图、apng、webp、lottie、svga等,各有各的优点,也有相应的劣势,而使用视频作动画的目的,寻求的是完美还原设计师的设计特效外,同时性能达到极致。html

在这个过程当中,也积累了一些视频相关的知识,借此同你们分享下。web

第一部分 视频相关基础

1、视频的编解码方式

谈到视频,咱们常常会听到视频编解码、H.264等诸如此类的内容。那么视频编解码是什么意思呢?算法

视频编解码,其实就是对视频数据进行压缩和解压缩的过程,而在讨论到编解码时,又常常同H.264联系到一块儿,那么H.264又是什么?windows

H.264是一种视频压缩标准,简称AVG,一种被普遍使用的高精度视频的录制、压缩和发布格式。该标准引入了一系列新的可以大大提升压缩性能的技术,并可以同时在高码率端和低码率端大大超越之前的诸标准,能够说是一种压缩算法,但又不只仅止步于此。markdown

H.264H.26X系列中的一种,目前最新是H.265,简称HEVC,在一样的画面质量下,后者的压缩率是前者两倍(比特率减小50%),是将来发展趋势,iOS上的Video ToolBox目前可支持H.265的编解码。网络

视频编码还有其余的标准,好比AMVAVS等等,但主流基本是H.26X系列。ide

2、关于H.264

H.264是视频的原始码流,分为两层,分别是视频编码层(VCL)和网络提取层(NAL),前者是H.264编码/压缩的核心,主要负责将视频数据编码/压缩,再切分,后者负责格式化VCL数据并提供头信息,以保证数据适合各类信道和存储介质的传输,基本单位是NALUsvg

经过上图能够看到,一个视频帧包含了一个或多个NALU,开头通常是SPSPPS,这两个主要是用于初始化解码器所须要的参数信息,也是解码的关键,接下去就是I/P/B帧等NALU数据,而NALU细分下去还有切片、宏等单位,这里因为篇幅缘由就不在展开述论。工具

3、视频帧相关概念

在视频的编解码中,常常会讨论到几个很关键的名词,如I帧、P帧、B帧等。接下来从编码和解码角度来理解它们。oop

从编码角度上来讲:

  1. I帧:帧内编码帧, I帧一般是每一个GOP(MPEG所使用的一种视频压缩技术)的第一个帧,通过适度地压缩,做为随机访问的参考点,能够当成静态图像,I帧压缩掉视频的空间冗余信息;
  2. P帧:前向预测编码帧,经过将图像序列中前面已编码帧的时间冗余信息充分去除来压缩传输数据量的编码图像;
  3. B帧:双向预测内插编码帧,既考虑源图像序列前面的已编码帧,又顾及源图像序列后面的已编码帧之间的时间冗余信息,来压缩传输数据量的编码图像。

从解码角度上来讲:

  1. I帧自身能够经过视频解压算法解压成一张单独的完整视频画面,因此I帧去掉的是视频帧在空间维度上的冗余信息;
  2. P帧须要参考其前面的一个I帧或者P帧来解码成一张完整的视频画面;
  3. B帧则须要参考其前一个I帧或者P帧及其后面的一个P帧来生成一张完整的视频画面,因此P帧与B帧去掉的是视频帧在时间维度上的冗余信息。

除次以外,还有PTSDTSGOP

PTS是用来描述视频解码阶段的帧输出顺序,DTS用来描述视频解码阶段的帧解码顺序,在无B帧的状况下,PTS等于DTS,在有B帧的状况下,输出顺序须要参考PTS

GOP,描述的是两个I帧之间造成的一组图片。

第二部分 MP4解封装

1、MP4定义

MP4是咱们常见的视频资源,但MP4的本质又是什么呢?和H.264有什么不可告人的秘密呢?

MP4也叫MPEG-4,是一种多媒体容器格式,后缀是.mp4,其容器格式借鉴了AppleQuickTime的组织方式,即以一系列BOX为基本单位。

2、Box理解

MP4文件由若干个box组成,box的示意图如上图所示:

  1. boxheaderbody组成,header指明了boxsizetype
  2. size包含了boxheaderbody整个大小;若是size为1,表示box的长度须要用更多的bits位来描述,能够经过一个64bits位的largesize来描述box的长度,若是size为0,表示该box为文件的最后一个box
  3. type,一般使用4个ASCII码的字符如"ftyp"、"moov"等表示,这些box type是已经预约义好的,表示固定的含义,若是是"uuid",表示该box为用户自定义拓展的类型,若是box type是未定义的,应将其忽略;
  4. box中能够包含box,这种box叫作container box
  5. box分为两种,BoxFullboxFullBoxBox的拓展,header中增长了8位的version和24位的flags字段。

3、常见的MP4文件工具

  1. mp4box.js:一个在线解析mp4的工具。
  2. bento4:包含mp4dump、mp4edit、mp4encrypt等工具。
  3. MP4Box:相似于bento4,包含很全面的工具。
  4. mp4info.exe: windows平台图形界面展现mp4基本信息的工具。

咱们使用mp4box.js,能够看到MP4文件由许多box组成,每一个box包含不一样的信息,以树形的方式组织,主要的box以下:

经过上表,咱们能够看到有4个树节点:

  1. ftyp:文件类型;
  2. moov box:媒体的metadata的描述和信息;
  3. mdat:具体的媒体数据;
  4. free:可有可无的内容。

4、基本Box介绍

File Type Box

ftyp简单的说就是为了标识它的developer是谁,兼容哪些标准等,如“mp42”表示它的major brand是MP4 v2,而“mp42”和“mp41”则表示它的compatible brands是MP4 v2和MP4 v1。

  • major_brand:推荐兼容性的版本;
  • minor_version:最低兼容性的版本;
  • compatible_brands[]:全部的兼容性的版本。

Movie Box(moov)

包含了文件媒体的metadata信息,是一个container box,通常在ftyp后面。moov包含1个mvhd和若干个trak,其中mvhd是header box,做为第一个子box出现,trak包含一个trakc的相关信息,是一个container box。

Movie Header Box(mvhd)

mvhd(Movie Header Box),主要存放着视频文件的meta data,其中的time scale和 duration对文件的播放有着重要做用

  • version:box的版本,0或者1,通常为0;
  • creation time:建立时间(相对于UTC时间1904-01-01零点的秒数);
  • modification time:修改时间;
  • timescale:文件媒体在1秒时间内的刻度,可理解为1s长度的时间单元数;
  • duration:该track的时间长度;
  • rate:推荐播放速率,高16位和低16位分别为小数点整数部分和小数部分,[16.16]格式,该值为1.0(0x00010000)表示正常向前播放;
  • volume:推荐播放音量,[8.8]格式,1.0(0x0100)表示最大音量。
  • martix:视频变换矩阵
  • newxt track id:下一个track使用的id

Track Header Box(tkhd)

  • version:box版本,0或者1,通常为0;
  • flags:24-bit整数,按位或操做结果值;
  • track id:track id号,不能重复且不能为0;
  • duration:track的时间长度;
  • volume:[8.8]格式,若是为音频track,1.0(0x0100)表示最大音量,不然为0;
  • width:宽度,[16.16]格式;
  • height:高度,[16.16]格式,没必要与sample的像素尺寸一致,用于播放时显示的宽高。

Media Box(mdia)

Media Boxyeshi 也是一个container box,其定义了track媒体类型以及smaple数据,描述sample的信息。 mdia包含:

  • 一个Media Header Atom,即mdhd;
  • 一个Handler Reference,即hdlr;
  • 一个media information,即minf,解码的关键。

Media Header Box(mdhd)

mdhd和tkhd内容上大体一致,不过tkhd一般是指定的track设定的相关属性和内容,而mdhd是针对独立的media来设置的,字段包含

  • version:box的版本,0或者1,通常为0;
  • timescale:比mvhd中的timescale精度更高;
  • duration:track的时间长度;
  • language:媒体语言码,最高位为0。

handler Reference Box(hdlr)

hdlr解释了媒体的播放过程信息,可获取track类型信息,主要是有字段handler_type(uint32_t)区分,具体含义以下:

  • handler type:该值为4个字符,会有如下取值:
    • vide:视频;
    • soun:音频;
    • hint:这个特殊的track并不包含媒体数据,而是包含了一些将其余数据track打包成流媒体的指示信息。

Media Information Box(minf)

重要的容器box,存储了解释track媒体数据的handler-specific信息,media handler用这些信息将媒体时间映射到媒体数据并行处理,minf是一个container box,其实际内容由子box说明。 通常状况下,minf包含了一个header box,一个dinf和一个stbl,其中header box的数据类型有vmhd(视频轨)、smhd(音轨)、hmhd(hint track)、nmhd(null track),dinf为data information box,stbl为sample table box。

5、重要Box

Sample Table Box(stbl)

stbl包含了关于track中sample全部时间和位置的信息,以及sample的编解码等信息。利用这个表,能够解释sample的时序、类型、大小以及在各自存储容器中的位置。stbl是MP4文件中最复杂的一个box了,也是解开MP4文件格式的主干,是一个container box;

stbl包含:

  • stsd:sample description box,样本的描述信息;
  • stts:time to sample box,sample解码时间的压缩表;
  • ctts:composition time to sample box,sample的CTS与DTS的时间差压缩表;
  • stss:sync sample box,针对视频,关键帧的序号;
  • stsz/stz2:sample size box,每一个smaple的字节大小;
  • stsc:sample to chunk box,sample-chunk映射表;
  • stco/co64:chunk offset box,chunk在文件中的偏移。

在mp4文件中,sample是一个媒体流的基本单元,例如视频流的一个sample表明实际的nal数据。chunk是数据存储的基本单位,它是一系列sample数据的集合,一个chunk中能够包含一个或多的sample。

Sample Description Box(stsd)

存储了编码类型和初始化解码器须要的信息。 stsd有多种类型的子box,具体取决于该track是视频或是音频或是其余,对于视频,如果经过使用了H.264编码的,子box为avc1,avc1的主要字段:

  • type:avc1;
  • width、height:视频像素宽高;
  • horizresolution、vertresolution:每英寸的像素值,[16,16]格式的数据;
  • frame_count:每一个sample的视频帧数,默认是1;
  • avcC:存放sps和pps内容。

Decoding Time to Sample Box(stts)

包含一个Sample编码时序表,经过这个表能够从解码时间映射到sample序号,表中的每一项是连续相同的编码时间增量(Decode Delta)的个数和编码时间增量,经过把时间增量累加就能够创建一个完整的time to sample表。

Composition time to sample box(ctts)

这个box提供了decoding time到composition time的offset的表,用于计算pts。

  • 这个表在Decoding time和composition time不同的状况下是必须的。
  • 若是box的version等于0,decoding time必须小于等于composition time,于是差值用一个无符号的数字表示。
  • sample_count:连续相同的offset的个数;
  • sample_offset:CT和DT之间的offset。

  • DT(decoding time):编码时间;
  • CT(composition offset):创做时间;
  • Decode Delta:编码时间增量,经过前面提到的stts表可获取;
  • Composition offset:显示时间同解码时间的差值,等于CT-DT,经过ctts获取。

由此可知,经过sttsctts能够方向推出解码顺序和视频播放顺序,当无B帧视频时,ctts不存在,解码顺序和播放顺序一致。

Sync Sample box(stss)

它包含media中的关键帧的sample表,若是此表不存在,则每一帧都是关键帧。

主要字段sample_number:媒体流中同步的sample序号。

Sample Size Box(stsz/stz2)

包含sample的数量和每一个sample的字节大小,box体积有点大,主要字段有:

  • sample_size:指定默认的sample的字节大小,若是smaple大小不同,则这个字段为0;
  • sample_count:track中的sample的数量;
  • sample_sizes:每一个sample的字节大小。

Sample To Chunk Box(stsc)

meida中的sample被分组成chunk,chunk能够有不一样的大小,chunk内的sample能够有不一样的大小,经过stsc中的sample-chunk映射表能够找到指定的smaple的chunk,从而找到这个sample。结构相同的chunk能够汇集在一块儿造成一个entry,这个entry就是一个stsc映射表的表项。

主要字段说明:

  • first_chunk:一组chunk的第一个chunk的序号;

chunk的编号从1开始。

  • samples_per_chunk:每一个chunk有多少个sample;
  • sample_desc_idx:stsd中的sample desc信息的索引。

Chunk Offset Box(stco/co64)

Chunk Offset表存储了每一个thunk在文件中的位置,这样就能够找到媒体数据,而不用解析box了。

总结

感谢您阅读到这里,本次分享的内容只是视频方面的基础,过程有些枯燥,如如有什么描述不对或不得当,欢迎指出。

相关文章
相关标签/搜索