vp9 prob 详细分析
VP9 probe 的概念
vp9 prob 实际是vp9 probability的缩写,指的是各个编码参数出现在码流的概率。为什么需要在码流里面传递这样的参数。这个是为了节省熵编码的比特数。
例子:算术编码 编码帧间预测的模式
vp9的帧间预测模式有4种NEW, NEAREST, NEAR, ZERO 。 如果说这4种模式出现的概率相等,那么编码的时候就可以每个模式都分配同样的两个比特。
如果说ZERO 出现的概率是50%, NEAREST 是 25%, NEAR/NEW 12.5% 。那么最佳的码流比特分配方式如下,也就是给高概率少的比特,给低概率高的比特。使得最后的编出来的码流最小。
如果说估计到的语法元素出现概率跟实际上语法元素出现的概率很接近,那么就可以达到编码比特的最小。
vp9 加prob语法的目的 就是为了在码流种传递不同语法元素在码流中的概率。
编码端有两种方式来告诉解码端不同语法元素出现的概率。
1、直接在码流的头里面传递 概率, 这样会增加比特输出,但是很精确。
2、在解码的时候追踪不同语法元素被解码的次数 然后在帧结束的时候计算概率。 这个概率就用在下一帧的算术解码里面。这个是基于前后两帧出现的语法元素相近的概率很高。这种方法就不用增加比特的输出
vp9 prob用的是这两种方法的结合。
libvpx的实现
在解码前首先申请4个frame_contexts, 然后每个frame_contexts都初始化为相同的prob,这些prob 包括mode预测模式,coef残差系数,mv相关的prob。然后解析码流的frame_context_idx语法元素。frame_context_idx指定了用4个buffer里面哪个frame_contexts来进行probe 的更新。
继续会从码流中读取出来要更新的prob,frame_context_idx指定的prob和码流读进来的probe一起组成最后解码使用的probe。如果说refresh_frame_context语法为0,表明 这一帧的读出来使用的prob 是不用更新到frame_contexts,直接就丢弃了。
如果说refresh_frame_context语法为1,表明 这一帧的读出来使用的prob 是需要更新到frame_contexts,更新的位置还是当前帧frame_context_idx指定的位置。 后面帧如果说用到这个frame_contexts 那么要用的是更新之后的frame_contexts。
此外 frame_contexts 重置为默认值的情况
1、当前是I帧或者error_resilient_mode 或者reset_frame_context为3 的时候,所有4个frame_contexts都要重置为默认的prob(这个prob是写死在代码里面的)
2、reset_frame_context为2的时候 需要将帧头里解析的frame_context_idx 指定的frame_contexts 重置为默认。
bilingzhi: 为什么不叫“音频补丁”: 语境不同:在这个语境下,“Patch” 不再意味着“补丁”或“修复”,而是“连接”或“路径”。这在音频领域是一个常见的专业术语,用来表示信号如何在不同设备之间流动。 专业领域的使用习惯:在音频工程中,Patch 更常用来描述设备间的连接路径,而不是用于修复或更新某些东西。
刘之帅: Patch 是补丁的意思吧,path 是路径
lovexiaokai: 请教一下 如果想改变buffer size,需要重新申请block pool吗