avc1就是h.264的别名,这个盒子里面放了很多解码需要的参数,如level、SPS、PPS等,如最大参考帧的数目等,参考上图注解。如果最大参考帧放得比较宽,可以使用的参考帧比较多的时候,压缩比能得到提升,但是解码的效率就会降低,并且在seek寻址的时候也不方便,需要往后读很多帧,或者往前保留很多帧,特别是流式播放的时候可能需要提前下载很多内容。上面SPS分析得到的最大参考帧数目是3(max_num_ref_frames).
接下来怎么对图像帧进行解码还原成rgb图像呢? 3. 视频帧解码I帧的解码不需要参考帧,解码过程比较类似于JPG,P帧和B帧需要依赖前后帧才能还原完整内容,所以帧的解码顺序通常不是按照播放顺序来的。我们不妨研究一下上面的示例视频的所有帧的类型,可以借助一个在线网站Online Video GOP Analyzer,分析结果如下图所示:
x轴表示从0到23共24帧,y轴表示每一帧的大小,绿色的是关键帧I帧,红色的是前向预测帧P帧,蓝色的表示双向预测帧B帧,可以清楚地看到,在体积上I帧 > P帧 > B帧。这24个帧的排列顺序:
I B B B P B B B P ... B P I
首尾两帧都是I帧,刚好形成一个GOP图像序列(group of pictures),在一个GOP序列里面,I帧是起始帧,接下来是B帧和P帧(可能会没有B帧)。
上图的帧顺序是按照每个帧播放时间戳PTS(presentation timestamp)依次递增,其中第12帧(中间红色柱子)推导的播放时间点PTS是0.54s。
但是存储顺序和解码顺序并不是按照播放的顺序来的,可对比第2步里的帧的大小图:
其中,sample_sizes是存储的顺序,柱形图的顺序是按照PST,两者对比可以看到每一帧的解码时间戳DTS(decode timestamp)是按照以下顺序:
I P B B B P B B B ...
在一个GOP序列里面,I帧是起始帧,最先解析,然后就是P帧,最后才是B帧,可以猜测因为P帧依赖于I帧,所以要先P帧要先于B帧,而B帧可能要依赖于I帧和P帧,所以最后才能解析。那怎么才能知道具体的依赖关系,也就是每一帧的参考帧列表呢?
首先每一帧的播放顺序POC(Picture Order Count)可以从每一帧的头部信息计算得到,借助一些如JW Reference软件,能够查到从存储顺序的第1帧到第5帧POC依次为:
0 8 2 4 6 ...
这里是按照2递增的,换算成1的话就是:
0 4 1 2 3 ...
与上面的分析一致。
接着怎么知道帧间预测帧B帧和P帧的参考帧是谁呢?在回答这个问题之前需要知道参考帧参考的是什么,在jpg/h264里面把图片划分为一个个的宏块(macroblock),一个宏块是16 * 16px,以宏块为单位进行存储,记录的颜色信息是以YCbCr格式,Y是指亮度也就是灰度,Cb是指蓝色分量,Cr是红色的分量。如下图所示: