视频转码主要涉及编码压缩算法(Encoding)、格式封装操作(Muxing)、数据传输(例如RTMP、RTP)、格式解封装(Demuxing)、解码解压缩算法(Decoding)几方面的操作。
在我们将视频流、音频流写入到一个封装容器中之前,需要先弄清楚这个容器是否支持我们当前的视频流、音频流数据。
音频的PCM数据、视频的YUV和RGB的图像数据直接存储或者通过带宽传输会比较消耗空间,那么为了节省存储,或者确保占用的带宽更少一些,就需要把音频、视频的数据压缩。
音频是连续的采样序列,而视频则是连续的图像序列,这些序列是有前后关系的。
有一个6帧的连续视频图像,每一帧都是宽100、高100的画幅,在每一帧的正中央都有一个字母在变化。遇到这种情况时,如果我们每一帧图像全都做传输或存储操作的话,占用的带宽或空间都会很大.
为了节省空间,我们可以来分析一下图像的规律。因为这6帧图像大范围是相同的,只有正中心的一小部分内容是变化的。刷新第一帧图像后,从第二帧开始,我们只要刷新正中心字母区域的内容即可。这个叫局部更新,只需要逐步更新A、B、C、D、E、F的区域就可以了,这样在传输内容的时候既节省带宽,又能在存储内容的时候节省画幅的数据存储空间。
在看视频的时候可不仅仅是内容的更新,还涉及内容位置的运动等变化,所以视频内容更新的算法会更复杂一些。在做视频压缩的时候,就拿前面的这个例子来说,需要有一个参考帧,这里参考的是第一帧,后面每一帧都参考前面一帧做了局部更新。
而我们的视频图像序列不能只做局部更新,因为里面的目标对象还会运动,所以我们不仅可以前向做参考,还有可以做双向参考的技术。在这个过程中就涉及了图像的类型,通常我们遇到的是这三类帧:I帧、P帧和B帧。
I帧(Intra-frame)作为关键帧,仅由帧内预测的宏块组成。而P帧(predictive-frame)代表预测帧,通过使用已经编码的帧进行运动估计,B帧(bi-directionalinterpolatedpredictionframe)则可以参考自己前后出现的帧。如果比较IBP帧包所占空间大小的话,通常是I帧>P帧>B帧,所以适当地增加B帧可以减少视频流占用的带宽或者存储空间
在示意图里,我们可以看出,解码顺序是1423756,但是显示顺序却是1234。Iframe的解码不依赖于任何其他的帧。而Pframe的几码则依赖于前面的面的Ifarme或者Pframe.Bframe的解码则依赖于其前的最近一个Iframe或者Pframe及其后的最近的一个Pframe。
当编码中存在B帧的时候,因为解码需要双向参考帧,所以需要多缓存几帧作为参考数据,从而也就带来了一定的显示延迟。所以在实时直播场景下,参考标准中推荐的做法通常是不带B帧。
在视频编码时,因为图像的画面以及图像中对象运动的复杂程度比较高,为了保证清晰度,运动的图像组中通常也会包含更多的图像运动参考信息,所以压缩难度也提升了很多,压缩后的视频码率也就变得比常规图像更高一些,这个码率的波动通常时高时低,具有可变性,我们一般称之为可变码率(VBR)
而在有些直播场景下,因为一个传输信号通道中会携带多条流,为了确保多条流在同一个信号通道中互不干扰,一般会要求编码时采用恒定码率的方式(CBR)。但是如果采用CBR的话,画质往往会有一些损耗,这也就是为什么我们现在在一些老式的电视直播场景中看到的画质偶尔会变得很差,比如交通广播电视场景。
平时经常会听到说视频是MP4格式的,也会说音乐格式是M4A等等,可以粗略地认为说的是封装格式,也就是常说的容器格式。
在容器格式的内部会存储音频、视频的数据,称之为视频流、音频流。音视频流在容器中的存储形式有两种,既可以交错式存储,也可以是不同类型的流单独存储在自己的连续区域。
存储音视频数据的时候,如果是顺序读取音视频数据的话,当然就是音视频数据交错存储比较好,这样会给内存、硬盘或者网络节省很多开销。
MP4格式标准为ISO-14496Part12、ISO-14496Part14,标准内容并不是特别多,如果要了解MP4的格式信息,首先要清楚几个概念:
1.MP4文件由许多个Box与FullBox组成;
2.每个Box由Header和Data两部分组成;
3.FullBox则是Box的扩展,在Box结构的基础上,在Header中增加8bit位version标志和24bit位的flags标志;
4.Header包含了整个Box的长度的大小(Size)和类型(Type),当Size等于0时,代表这个Box是文件中的最后一个Box;当Size等于1时说明Box长度需要更多的bits位来描述,在后面会定义一个64bits位的largesize用来描述Box的长度;当Type为uuid时,说明这个Box中的数据是用户自定义扩展类型
5.Data为Box的实际数据,可以是纯数据,也可以是更多的子Box;
6.当一个Box中Data是一系列的子Box时,这个Box又可以称为ContainerBox。
MP4封装格式文件中,经常会遇到moovbox与mdatbox。
,这个moov的生成,一般需要先写入mdat中的音视频数据,这样我们就知道数据采样存储的位置和大小,然后才能写入到moov中,所以是先写入mdat后写入moov这样一个顺序。解决办法是生成文件之后做一个后处理,也就是将moov移动到mdat前面。
在音视频技术领域,编解码、封装格式都有对应的参考标准,并且都是开放标准。
思考题
MP4是否能够应用于直播场景中呢?怎么处理才能够支持直播?
参考答案:
fragmentedmp4,也就是fmp4,是适应于现代浏览器的一种流媒体格式。和mp4格式不同的是,以往的mp4格式化也分为header信息和payload信息,一个大的mp4就会有一个很大的头信息,不适合与现在的网络环境。所以新的fmp4格式就出现了,fmp4格式有一个带了metadata的头片段,及后面一序列的fragment,每个fragment都有各自的header信息,这样就把header信息也分成了一个个小的片段,更适合现在的应用场景。所以fmp4格式也就是用于MediaSource对象的SourceBuffer的格式,通过一个initSegment和一序列的segment塞给MediaSource对象来播放。