『漫游』酷论坛>『DVDRip技术研修室』>[导读] XviD的一些必读 ..

[导读] XviD的一些必读【转贴】

xxp@2002-12-28 18:00

『 XviD中的精彩技术 』 ---- 作者:Silky
Quarter Pel = Quarter Pixel = 1/4 Pixel = QPel:
MPEG 压缩的时候,P-Frame 会参考前一个画面压缩,B-Frame 会参考前面或后面,或前后的画面压缩。
此时只要纪录和参考画面之间的差异,也就是预测的误差,还有物体移动的方向(动作向量 MV),不用重新压缩整个画面,所以可以节省很多 bits,达到很高的压缩率。
其中又以 B-Frame 的压缩效率最高,因为 B-Frame 可以同时参考前面和后面的画面,以前后画面的平均值((前+后)/2)做为参考画面,可以大幅减少预测的误差。(预测的误差越小,所需花费的纪录误差的 bits 数就越少,档案就越小,压缩效率就越高)
同时 MPEG-4 的 B-VOP 还有第四种预测模式,叫做 Direct Mode,直接拿后面的 P-Frame 的 MV除以二作为动作向量,省去记录 MV 的空间,也可以达到很高的压缩效率。
如:
I B P
我们可以预测,B 的物体移动必然是介于 I 和 P 之间,所以 B 的 MV 大概会接近 P 的 MV 的一半。
以上是大致的压缩原理,我们回过头来看什么是 QPel。
前面说到 P/B Frame 会在参考画面上寻找最接近的区块,然后记录和这个区块的误差值,以及相距的方向和位置(MV)。
MPEG 压缩的时候是以 16x16 的方块为单位,称为 MacroBlock(MB),一个 MB 一个 MB 地搜寻最匹配、误差最小的参考方块在哪里。(也就是搜寻这个物体移动到哪里)搜寻会在一定的范围内搜寻,譬如说在周围 32x32 的范围内搜寻,而不会无限制的扩大搜寻下去。
所以当画面上动态很大的时候,物体移动距离较远,超出搜寻范围,或是画面变化的差异太大,我们就找不到误差很小的参考方块,此时压缩率就会下降,需要较多的 bits 来记录。
很明显的,物体的移动和像素(Pixel)的精确度无关,物体不会按照像素的格子,一格一格的移动,每次都移动整数的格子点,刚好落在像素上。
所以我们以整数像素的单位做搜寻、比对,显然无法找到最匹配、最相似、误差最小的参考方块。
为了克服这个问题,MPEG-2 压缩的时候,会先将要参考的画面做内插补值(interpolation),补出像素和像素之间的次像素的数值,如:
A x B
x x x
C x D
像素 A 的值为 11,像素 B 的值为 13,则我们可以预测 A 和 B 之间的次像素 x 的值为 12。
依此类推,补出所有的 x 的数值,也就是 1/2 Pixel 的值,再以此 1/2 Pixel 精确度的画面做为参考画面,于其上搜寻最近似的参考方块。
这样,我们就可以找到误差更小的参考方块,压缩率就更高,同品质下档案就更小,同容量下品质就更高。
根据测试,使用 1/2 Pixel 精确度的 ME(动作估计),PSNR(Peak Signal to Noise Ratio,讯噪比,常见的一种客观测试影像品质的方法)可以上升 3~5dB。
而 MPEG-4 用的 Quarter Pixel = 1/4 Pel,就是比 1/2 Pel 更精确,再补出 1/2 像素和像素之间的 1/4 Pel,以此做为参考画面。理论上 1/4 Pel 可以再提升 PSNR 2~3dB。
AoxoB
ooooo
xoxox
ooooo
CoxoD
o: 1/4 Pel
但是,如果 1/4 Pel 没有良好的实作出来,导致用了 1/4 Pel 也没有找到更好的参考方块,那么因为 1/4 Pel 所使用的动作向量 MV 需要原本 1/2 Pel 的双倍精度来记录(如:1.5 --> 1.25),所以压出来的档案反而会变大。(同容量下品质就更差)
早期 XviD 的 QPel 就是没有良好的实作,同时有一些错误,所以对于压缩效率没有助益,使用之后档案反而更大。
但是现在 XviD 的 QPel 已经修正完毕,完全符合 MPEG-4 的标准规范,同时也达到理论上它的压缩助益。
您可以做一个测试,以同品质压缩(固定 Quantizer),开了 QPel 之后,档案大约会减小 ~3%。
这代表同档案大小下,开 QPel 的品质会比没开 QPel 的品质好。

有了以上这些 MPEG 压缩的基础说明,我补充一下上次提到的几个名词说明:
Chroma ME 这个选项
ME = Motion Estimation 动作估计
在参考画面上搜寻最近似的方块,找出相距的距离和方向 => 动作向量 MV = Motion Vector 的过程叫做 ME。
MC = Motion Compensation 动作补偿
将目前要压缩的方块和找到的参考方块相减,纪录它们之间的误差值,以便在解压缩的时候能够补上这个误差值,这个过程叫做 MC。
MPEG 压缩的时候将像素分为 YUV 三个平面,一般只在 Y(亮度)的平面上做 ME,搜寻 Y 误差最小的 MV。
而 UV(色度,Chroma)的动作向量则是直接拿 Y 找到的动作向量除以二,作为 UV 的动作向量。
(当 MPEG 以 YUV 4:2:0 记录时,UV 的分辨率只有 Y 的一半,也就是画面大小只有 Y 的一半。
如 Y: 640x480,UV 则只有 320x240。所以动作向量直接拿 Y 除以二,可以得到近似值)
这是因为人眼对 Y 亮度比较敏感,对 C 色度比较不敏感。色度分辨率差一点,人眼也看不出来。
减少 C 所占的空间,给 Y 使用多一点空间,可以在有限的流量大小下,增进视觉看起来的品质。
然而做 ME 的时候偷懒,只精确的求 Y 的 MV,而 C 的 MV 就直接拿 Y 的 MV/2 来使用,这样虽然可以加快压缩的速度,但是品质也会下降。(C 没有精确的求出误差最小的参考方块,需要花较多的 bits 纪录,使得压缩率下降)
XviD 现在加入了 Chroma ME 的这个选项,会同时搜寻 Y/C 平面上,误差最小的 MV,速度会慢一点,但是品质会较好。
尤其是压动画类影片,效果最明显。

为什么动态越大的时候要减少连续 B-Frame 的个数?B-Frame 不是压缩率最高,越多越好吗?
MPEG-1 里面,有三种 Frame 型态:
I-Frame: 不参考其它画面,独立压缩,压缩率最差,需要最多 bits,Frame size 最大。
P-Frame: 参考前一张 I 或 P Frame 压缩,压缩率次之。
B-Frame: 参考前后的 I 或 P Frame 压缩,压缩率最高。B-Frame 不能被其它 Frame 拿来当作参考画面。
B-Frame(在 MPEG-4 里面正确的名称是 B-VOP)的预测模式有四种:
a. Forward 顺向预测,参考前一张画面,记录和前一张画面的差距。和 P-Frame 的预测方法一样。
b. Backward 逆向预测,参考下一张画面,记录和下一张画面的的差距。
c. Bi-Directionally 双向预测,参考前面和后面两张画面,记录的是和「前后两张画面的平均值」的差距。也叫做内插预测,压缩率最高。
d. Direct Mode,不搜寻、纪录动作向量,直接由下一张的 P Frame
推导出动作向量。譬如说 I B P,我们可以预测 B 画面的动作必然
是介于 I 和 P 两个画面之间,所以我们可以直接用 P 的 MV/2 作为B 的动作向量,这样可以省去记录 MV 的空间。
压缩 B-Frame 的时候会从上面几种预测模式中选压出来最小的一个模式来使用。
当把最大 B Frame 的个数设得太多的时候,如果 XviD 的动态 Frame Type 决策没有好好发挥它的功能,会造成误判,在高动态的地方还是插入过多的 B-frame。
如:
大动态画面
I B B B B P
P 距离参考的 I Frame 太远,误差太大,容量暴增。而第一个 B-frame,因为 I 和 P 的差距很大,(I+P)/2 两个 Frame 的平均值和 B Frame 的差异还是很大,倒不如只用 I Frame来预测。此时 B 只参考前一张 I 压缩,等于 P-frame。中间的 B 参考 (I+P)/2 压缩,因为差异量大,还是无法取得很好的压缩率。最后一个 B 只参考后面的 P 压缩。
最后这四张 B-frame 都无法取得很好的压缩率,大小都变成和 P 差不多大,此时如果改成
0 1 2 3 4 5
I P P P P P
反而可以得到更好的压缩率。
(因为 1P 参照 0I,差距小。2P 又可以参照 1P,差距也小。以此类推....)
现在 XviD 的动态分配决策已经比以前好很多,最大 B-frames 个数可以放心设到 4 没有问题。
至于 DivX 5 的 B-frame,最多连续个数只能为 1,只能是 I B P B P B P B... 这种型态,更别提 XviD 现在使用的先进 I/P/B Frame 分配决策,DivX 5 已经完全比不上 XviD。

最后,关于 XviD 保留的细节比较多的问题。
MPEG 压缩的时候,以每个 16x16 像素方块大小的 MacroBlock 为单位作 ME,然后量化的时候会切成 4 个 8x8 的 Block(微方块),做一种称为 DCT 的转换。经过 DCT 转换以后,8x8 方块里的 64 个像素点的 YUV 值,就变成代表空间频率的系数。
人眼对高频比较不敏感,相对的低频的系数就比较重要,所以我们利用量化把高频的系数削掉多一点,保留比较重要的低频系数,在有限的流量的情况下,可以增进肉眼看起来的品质。
XviD 可以使用两种不同的量化方法(Quantization Type),一种是 H.263,另一种是 MPEG。
H.263 的量化方法,顾名思义,就是使用 H.263 这个压缩规格所使用的量化方法,量化的时候,8x8 的像素方块内的所有 DCT 系数,全部除以同一个数字。(这个动作就叫做量化)例如全部都除以 32,如果有一个 DCT 系数为 15,小于 32,经过相除之后,会被量化为 0,如此便可以省下很多记录的 bits。
当然,除的数字越大,量化的误差也就越大,品质也就越差,但是压缩率会越高,压出来档案会越小。
我们会利用另一个参数来调整量化的误差,控制最后量化的品质和档案的大小,这个参数叫做 Quantizer。
量化的系数会再乘上这个 Quantizer 的倍数,例如原本要除的量化系数是 32,Quantizer 是 2,对应的放大倍数也是 2,最后真正要除的量化系数就变成 32*2 = 64。
所以 Quantizer 越大,要除的量化系数就越大,量化误差就越大,品质就越差,但是档案也越小。
H.263 的量化方法还规定,相邻的两个 MacroBlock 的 Quantizer 不能相差超过 2。
而另一种 MPEG 的量化方法,高低频系数可以除以不同的量化系数,可以视情况将高频削多一点。
这个 8x8 的量化系数,也就是 Quantize Matrix(量化矩阵)。
XviD 还可以让你自订、编辑这个矩阵的量化系数,你可以依照影片内容、使用码率,自订最适当的量化矩阵。
(量化方法要选 MPEG-Custom,同时更改 Edit Quantizer Matrix... 里面的预设量化矩阵,目前这个功能无法和 B-Frame 同时共享)
MPEG 的量化方法对相邻的 MB 使用的 Quantizer 差距并没有限制。
根据经验,使用均匀量化矩阵(uniform quantization)的 H.263 量化法,压出来的画面会较模糊。MPEG 量化方法的画面会比较锐利。(不过锐利线条的周围、物体的边缘,会产生一些噪声)MS MPEG-4,也就是 DivX 3.11,使用的是 MPEG 的量化方式,所以一直以来,大家的评价都是 MS MPEG-4的画面比较锐利,保留比较多的细节。DivX 4, DivX 5 都是使用 H.263 的量化方法,尤其是 DivX 4,画面非常模糊。虽然表面上看起来压缩瑕疵较少,但是细节都被削光光了。
(DivX 5 其实可以藉由修改 registry 的方法,改成以 MPEG 的量化方式压缩,但是显然有 bug,压出来的东西惨不忍睹)
XviD 则可以让使用者自行选择要固定使用哪种量化方法,或者是视情况切换量化的方法。
(量化方法选择 Modulated,Quantizer 小于或等于 3 时会使用 MPEG 量化,大于 3 时使用 H.263 量化。New Modulated HQ 则反过来)

GMC,也就是 S(GMC)-VOP,只有在整个画面上,有大部分的区块都往同一个方向移动时,才能派上用场。譬如说镜头做 pan(由左往右 或 由右往左 平移)的时候,全体由上往下,或由下往上移动,以及 zoom in/zoom out(物体放大缩小)的时候,才会使用 S(GMC)-VOP。(其实还有其他功能,例如变形、旋转的时候,不过目前 DivX 和 XviD 都没有完整的作出这些功能)
使用 GMC 的时候,那个 Frame 会使用 MPEG-4 才有的 Frame Type,叫做 S-VOP。(因为 MPEG-4 是以物件 Object 为单位压缩,所以叫做 Video Object Plane,VOP,视讯物件平面。有 I-VOP/P-VOP/B-VOP 和特别的 S-VOP 这几种 VOP)为了要和 Stripe 做区分,我们又把它叫做 S(GMC)-VOP。所以要比较 GMC 的使用情形,必须找两个相同的画面,而且是 S(GMC)-VOP(也就是有使用 GMC 的 VOP),才能看出 GMC 的使用结果。
目前 XviD 的 GMC 只有非常简单的功能,现在使用 Global MC 不会比原来的 Local MC 有效率,对压缩没有助益,用了之后档案反而会更大(压缩效率更差,同容量下品质更差)。
而且还有一些正确性的问题要修正(要符合 ISO 制订的 MPEG-4 的标准规格,否则便是做错,压出来的东西将来无法为其他标准的 MPEG-4 decoder 解码),所以不建议使用。

XviD 的编程人员每个人都是学富五车,而且是世界上顶尖的编程高手,目前Codec中的问题他们不是不知道,而是还在思考解决的方法。
譬如说目前 B-frame 一定要勾选 DX50 B-VOP compatibility,这个 Closed GOV(等于 MPEG-1/2 的 Closed GOP)的问题开发人员不是不知道,而是很困难解决。(我们来想的话会觉得很简单。没错,理论上很简单,实作就知道有多困难 )
而且开发人员每个人都还有自己的学业、工作要忙,仅能利用一点的闲余时间来从事这项编程工作,所以无法说改就改,立刻就解决这些问题。
不过尽管如此,XviD 仍然是目前世界上,品质最好的 MPEG-4 编码软件... 之一 (话不能说得太满,要留一点进步的空间 )
XviD 这么优秀,您还要继续用 DivX 5 吗 ^^
引用

xxp@2002-12-28 18:10

『 Silky的XviD 2-pass研究心得--曲线压缩 』 ---- 作者:Silky
结论就是,不要用那些「曲线压缩」比较好 :P
压缩的时候,bitrate 会视压缩的困难程度上下变化(VBR),encoder 的 rate control会控制让压出来的平均 bitrate 接近我们所设定的最终大小。
「曲线压缩」的意思就是将 bitrate 较大的 frame 拉下来,降低一点流量(High bitrate scenes %),bitrate 较小的 frame 补上去,提高一点流量(Low bitrat scenes %)。也就是将原本上下震荡的流量曲线压平一点,最大和最小的差距不要那么大。压得越平,流量曲线就越接近一条固定的直线,也就是变成 CBR。
Alt. Curve 也是做一样的事情,只是参数更复杂。
不过这样实在很没有意义不是吗?本来 bitrate 高的 frame,就是因为这个 frame 需要
较多的 bits 纪录,你现在把它拉下来,画质岂不更惨?而 bitrate 低的 frame,就是不需要花那么多 bits 记录的 frame,你又给它多补一些 bits,岂不浪费?
所以我从 Nandub 开始就一直搞不懂,Koepi 的曲线压缩设计到底是在做什么。
如果有人问我 Nandub 的曲线压缩要怎么设,我一定回答通通不要用 :P
因为我从来没压过流量设得极低的作品,所以无法理解这些曲线压缩究竟有什么用。
根据 Koepi 的说法,当流量极低的时候,很多 frame 的 bitrate 都不够。
此时如果把少数几个 bitrate 很高的 frame 拉低一点,把省下来的 bits 分给其它frame,立刻会对这些游走在底线边缘的 frame 的画质有很大的帮助。
曲线压缩的目的便是牺牲少数几个 frame,让大部分的 frame 增进画质。
而,这少数几个 bitrate 超高的 frame,又通常都是高动态的画面。
人眼对高动态的画面比较无法精确的判断、分辨出画质的好坏。
所以牺牲这几个 frame,增进大部分时间看起来的品质,可以说是相当划算。
好像还蛮有道理的 :P
不过如果曲线压缩的参数设定得不好的话,对画质会有很大的伤害,而且在不是超低流量的情况下,曲线压缩也没有意义。
所以最好的作法还是,让 encoder 自行视情况调节,使用自由的 VBR,这样压出来的结果会越接近 CQ「固定品质」。
(当然,如果流量实在设得超低,CQ 压出来的结果就是「固定烂品质」:P这时适当的运用曲线压缩,以少换多,就有它的价值了)
经过许多人的测试经验,最后的结论就是「linear scaling」的结果最好。
linear scaling 就是不用任何的曲线压缩,1st-pass 以 quant 2 压一遍,2nd-pass 就直接把 1st-pass 压出来的流量曲线整个往下平移,降低 bitrate,达到你所设定的目标大小为止。
由于曲线只是整个往下平移,使得最终的 bitrate 变小,而不改变其原本的震荡幅度,所以称为「线性的调整大小」。
这样,原本复杂,需要高 bitrate 的画面还是分到较多的 bits;简单,不用太多 bitrate 的画面也不会浪费了 bits。
线性调整压出来的结果较接近「完美的 VBR」,也就是固定的平均品质,不会有几个 frame 突然发生明显劣化的情况。
使用 linear scaling 的方法很简单,2nd-pass 的时候,把 Two Pass 设定底下的High bitrate scenes % 和 Low bitrate scenes % 两个设定都设为 0,不使用曲线压缩。
payback delay 一般设为 10 秒,也就是 24fps 的话设 240,30fps 设 300。
同时关闭 Alt. Curve,通通不要用。
这样跑 2nd-pass 的时候就会自动根据 XviD Codec 内建的 scaling 算法,做线性调整。
另一个方法,就是用 Kopei 写的 StatsReader。
(Koepi 后来也建议,使用 linear scaling 较好)
用 StatsReader 读入 1st-pass 的 stats 文件,设定目标档案大小,然后储存一个新的 stats 檔。
XviD 压缩时选 2 Pass - 2nd pass Ext.,Two Pass 设定底下的 2nd pass stats选你刚刚储存的那个 stats 檔。同样曲线压缩、Alt. Curve 等等都要关掉。
这样便会用 Kopei 设计的 linear scale 来做线性调整了。(Koepi 设计的 linear scale 和 Codec 内建的计算法有些不同)
还有,用 NiTroGen 写的 XviD Stats Viewer 也可以做 linear scaling,用法和 Kopei 的相同

不建议使用Alt.Cuv,直接使用linear scale就好了...xxp留
引用

xxp@2002-12-28 18:16

『 XviD新版新技术 』 ---- 作者:Silky
又更新了 ^^;
(最近很频繁...)
Koepi's XviD-02122002-1.exe
http://www.roeder.goe.net/~koepi/
Changelog:
- Fresh CVS checkout
- bframe updates (mpeg + cust. quant matrices work)
- refdivx's lumi masking bugfixed (hopefully)
- sysKin's updated dynamic halfpel/quarterpel code is used.
- StatsReader updated to 2.0.
- 现在 B-frame 可以和使用者自订的 MPEG Quantization Matrix
一起使用(之前不行)。
- RefDivX 是一个人,他提供了一些 HVS 的适应性量化程序代码加入到 adapt_quant.c 里面。之前据说有画面上会产生白点的 bug,希望现在已经修正了。打开 lumi masking 才会使用HVS(Human Visual System)人类视觉系统,根据人类视觉的特性,建立模型,量化的时候根据这些特性,将人眼较不敏感的区域压得差一点,将人眼较容易注意到的区域压得好一点,可以提升肉眼看起来的品质。
- sysKin 也是一个人,是 XviD 目前使用的 ME 算法、动态 I/P/B Frame 决策的设计者。他现在加入了动态 HPel/QPel 使用决策的设计,会先侦测画面边缘,来判断画面是锐利的还是平滑的,锐利的画面才使用 Qpel,并且在高动态的时候使用 HPel。
(侦测边缘的程序代码是直接从 RefDivX 提供的 HVS 程序代码里面 copy 来的 :P使用的侦测法是 sobel 微分法,不过目前程序代码没有 asm 化,速度会比较慢)
QPel(1/4 Pixel)和 HPel(1/2 Pixel)的 Motion Estimation现实生活中物体的移动和像素(Pixel)无关,物体不会按照像素的格子,一格一格的移动,每次都移动整数的格子点,刚好落在像素上。所以我们以整数像素的单位做搜寻、比对,显然无法找到误差最小的参考方块。为了克服这个问题,MPEG-2 压缩的时候,会先将要参考的画面做内插补值(interpolation),补出像素和像素之间的次像素的数值,如:
A x B
x x x
C x D
x: 1/2 Pixel
以此 1/2 Pixel 精确度的画面做为参考画面,于其上搜寻最近似的参考方块。
MPEG-4 用的 QPel = 1/4 Pel,就是再补出 1/2 像素和像素之间的 1/4 Pixel:
AoxoB
ooooo
xoxox
ooooo
CoxoD
o: 1/4 Pixel
sysKin 说根据他的测试,现在使用的动态 HPel/QPel,可以达到压出来的档案大小和只使用 HPel一样大,但是保留 QPel 的锐利、细节较多的效果。许多使用者和我的测试都显示,使用 QPel,以固定 quant 压缩,压出来的档案会变大。这表示在同样档案大小下,使用 QPel 的品质会较差。(2-pass 固定档案大小,QPel 压出来会较小,这是因为 quant 提高,并不是因为 QPel 提升了压缩率)
所以 sysKin 现在很高兴,新的动态 HPel/QPel 决策能使压出来的档案和只使用 HPel 一样大,同时保留了 QPel 的优点。
不过 XviD 开发团队的 Michael 持不同的看法,他认为 Qpel 不是只有在锐利的画面才有用,而平滑的画面就没有用。不过高动态使用 HPel 也许是比较好的作法,因为根据他的观察,QPel 在高动态的时候越难成功的找到误差最小的参考方块。(这点也和我的测试结果相同,我觉得这是目前 XviD 使用的 ME 算法的问题)另外他很困惑为什么使用者会回报使用 QPel 档案反而会变大。根据他的测试,QPel 压出来几乎都比 HPel 小。他手上有一个 clip,QPel 压出来比 HPel小了 30%(^^; 是哪一个 clip 这么猛)。我自己的测试,我没用学界常用的那几个标准的 clip 来测试,只有压了几部动画的 OP出来的结果,QPel 几乎都大了约 3%。
至于 QPel 压出来的画面较锐利,细节较多?
好像是有那么一点,不过 noise 也较多 :P
TMPGEnc 的设定中说,静止画面使用 HPel ME 画面会模糊,那么照理说低通得更厉害的 QPel 应该更糊才对?
- StatsReader 2.0,可以让使用者插入 keyframe。
这表示 2nd-pass 的时候不会重做 I/P/B 分配决策了?
希望能够再加入强制指定某个 Frame 为 P-Frame or B-Frame 的功能。
现在的 XviD 对淡入淡出的场景压缩很差,因为这种场景前后亮度的变化很大,
XviD 会误判为 Scene Change,全部压缩成 I-Frame,浪费许多 bits。
如果有手动指定 Frame Type 的功能,在 encoder 改进之前可以先手动补救一下。
因为我无法使用 Koepi 编译的版本(他用的最佳化方式会使得我的破烂 CPU 的指令集无法支持),而他的这个版本的许多更新是直接跟作者拿的热腾腾的 source code,CVS 上都还没更新,所以我也无法自行编译测试,就静待各位的测试心得

放长眼睛看吧,呵呵...xxp留
XviD-24122002-1.exe (482kb)
Changelog:
- Christmas edition ;)
- RefDivX' HVS based lumi masking code (a bit slow though).
- Including Nic's latest standalone decoder (23122002).

XviD-03012003-1.exe (404kb)
Changelog:
- Fresh CVS checkout.
- some problems with missing EMMS fixed.
- dshow now compiled with directx9 sdk.
引用

魔术杨@2003-02-19 20:59

XXP 也收集Silky大大的帖子啊 我也来贴点
这是关于VHQ的那篇
……其实不用指名小弟,论坛上其它前辈也可以回答,指名小弟的话只有小弟进来看,万一小弟事情一忙没有上来的话怎么办 :P

引用 stevenxu 发表的贴子:
1)Maillist上讲的VHQ是什么东东?

简单的说,高品质模式,开了同码率下品质比较好,固定品质下档案比较小。

复杂的说... 真的要复杂的说吗? :P
(有人要看吗? ^^;)

我们知道压缩的时候会将画面切成好多个 16x16 大小的小方块作动作预测,每个方块称为 Macroblock。每个 Macroblock 压缩的时候要做好几个选择,首先我们要决定这个 Macroblock 是要独立压缩,压成一个 intra-block,或者是要参考其它画面压缩,压成一个 inter-block。
接下来如果是压成 inter-block,要参考其它画面作预测压缩,那么要使用哪种动作预测模式呢?例如 MPEG-4 有 INTER4V(4MV)模式,一个 Macroblock 可以有 4 个 Motion Vector(动作向量),内部 4 个 8x8 的小方块各自使用一个 MV,各自记录最接近的参考对象。使用 4MV 让内部的小方块各自参考误差最小的对象,可以缩小所需记录的误差值,但是同时需要记录的向量个数也会增加为 4 个,一来一往、此消彼长,到底能不能提高压缩效率并不一定,要看情况。那么是要使用一般的 16x16 方块共享一个 MV 的预测模式(INTER),还是要使用 8x8 方块的 4MV 预测模式(INTER4V),这个 encoder 必须要作决定。

最后 encoder 还要决定找到的参考对象误差是不是很小,如果小到一定程度,我们就可以视为没有误差,不用编码、记录这个 Macroblock 的误差(not coded)。此时如果 MV = (0,0),也就是参考的对象和目前的方块在画面上的同一位置,那么这个 Macroblock 就可以 skip 掉,完全不记录任何数据,显示的时候直接使用前一个画面相同位置的方块来显示。

Macroblock 要用上面哪种模式压缩,压出来所需的 bit 会最少,encoder 必须要作判断。判断的时候会根据理论上的算式作判断,例如如果 四个SAD8x8的总和 < SAD16x16,我们就把这个方块用 INTER4V 模式压缩。SAD 是 sum of absolute differences 的缩写,误差绝对值的总和,是一种计算、判断、寻找最少误差量的方法。
根据这些简单的计算判断,encoder 可以很快速的决定要用哪种模式压缩。但是这样压出来真的会最小,所需的 bit 真的会最少吗?答案是不一定。可能这个 Macroblock 用 INTER 压缩会比较有效率,压出来所需的 bit 会比较少,但是却被计算式判断为要使用 INTER4V 压缩,白白浪费了许多 bit。
所以 XviD 和 FFMPEG 的开发小组之前就发现,使用 4MV 模式的时候,压缩效率反而不好,就是因为 encoder 的判断太简陋,造成了 4MV 的使用没有效率,使得压出来的档案反而变大。

FFMPEG 首先设计了一个 VHQ 模式,也就是高品质模式,也叫做 brute force。在这个模式底下,encoder 会把 Macroblock 各种可能的压缩模式都压一遍,INTRA/INTER/INTER4V... 都压一次,然后从里面选压出来最小,所需花费的 bit 数最少的一种模式来使用。这样就可以确定,我们选择的压缩模式是最有效率的压缩模式。实验结果证明,使用 4MV 的时候一定要搭配 VHQ 模式,压出来的品质才会最好,档案也会是最小的。不过当然,使用 VHQ 模式压缩的时间也需要比较久。

XviD 现在也设计了这个 VHQ 模式,第一件做的事情(VHQ 设定选项选 "1 - Mode Decision")就是上面说的 brute force,每种模式都压一次,选最好的。

XviD 的 VHQ 模式做的第二件事情,是 FFMPEG 里面没有的,但是这个功能还是要从 FFMPEG 谈起。
FFMPEG 可以让你自行选择动作估计(ME)的时候使用的「比对最小误差」的计算方法。当我们寻找误差最小的参考对象时,要怎么比较哪个参考位置的误差是最小的呢?一般我们是使用上面提到的 SAD,将两个方块的像素值相减,取绝对值,然后把 16x16 所有的点相减的结果加起来,作为总和的误差。这个计算的方法比较简单,速度很快,效果也很不错。但是 FFMPEG 还提供了其它各种的比较方法让你作测试,有
0. SAD: sum of absolute differences,计算法如上所述
1. SSE: sum of squared errors,和 SAD 差不多,但是不是取绝对值,而是平方,计算复杂度高一点
2. SATD: sum of absolute hadamard transformed differences,将像素值先作 hadamard 转换,然后再比较两个方块 hadamard 转换后系数的绝对值差值。这是 H.264 建议使用的做法,计算复杂度又比 SSE 高
3. DCT: sum of absolute dct transformed differences,先作 DCT 转换,然后比较 DCT 系数的绝对值差值,理论上是最精确的比较法,但是计算复杂度最高
4. PSNR: sum of the squared quantization errors,计算量化误差的平方总和
5. BIT: number of bits needed for the block,计算此方块实际所需的 bit 数
6. RD: rate distoration optimal,利用 Lagrangian 算式找出 rate-distortion 的最佳平衡点

实验证明,次像素的动作检索如果使用比较精确的比对方法,例如 SATD/DCT,品质会提高(这个同时是 H.264 建议的方法)。同时固定码率下,BIT/RD 的比对法也会提升品质。另外 SSE 似乎对动画类型的影片有最好的效果。

XviD 的开发人员看到 FFMPEG 不错的实验结果,也开始着手开发类似的高品质模式。sisKin 一开始是打算使用 DCT 比对法(因为他说虽然 DCT 比 SATD 复杂,但是他发现实际上压缩的时候最耗时的动作不是在 CPU 的计算上,而是在等待内存的存取上,所以使用 SATD/DCT 的速度应该不会差太多),结果后来是使用 BIT 比对法,比较实际上所需的 bit 数最小的。
以前曾说过 ME 的时候做次像素的动作检索,例如 Quarter Pixel,可以提高压缩率,但是那时没仔细说 Quarter Pixel 是怎么做的。如果我们一开始的时候就把整个画面内插,补出 1/4 的像素,然后在这个画面上作检索,这样一定会很慢很慢,因为要搜寻、比对的位置变得很多,范围很大,而且也很没有效率。所以实际上做的时候,我们是先做整数像素的搜寻,找出整数像素上误差最小的位置,然后再内插补出这个位置周围的 1/2 像素,订出八个新的搜寻位置,如下图

代码:--------------------------------------------------------------------------------
y x y x y
x x x x x
y x y x y
x x x x x
y x y x y

y: 整数像素
x: 1/2 像素
中间的 y: 找出来误差最小的整数像素位置,也就是误差最小方块的左上角顶点位置
红色: 新的次像素比对位置
--------------------------------------------------------------------------------

这样我们就只要比对这八个新位置和原来的整数像素位置哪个误差最小,就可以找出 1/2 像素精度误差最小的位置。这么一来就不用内插计算那么多的点,也不用比对那么多的次数,是不是比较有效率呢?
做完 1/2 Pixel 之后,我们可以继续再做 1/4 Pixel 精度的新位置比对,依此类推。

XviD 的 VHQ 功能做的第二件事,就是当确定好了 Macroblock 的压缩模式之后,我们可能会找到有很多位置的误差都相同。因为 SAD 找出来的误差经过量化以后,较小的误差值会被量化为 0。如果 quantizer 很高的话,那么就有可能误差都被量化为 0,这个方块就不需要 coded、记录误差值了,只需要记录 MV 即可。而当使用次像检索的时候,通常邻近周围位置的误差会很接近,经过量化之后,就可能有很多位置的误差结果都变成 0,那么我们就要从这些误差都是 0 的位置里面,找一个 MV 最小的位置,也就是最靠近目前方块的位置来使用,这样不是就可以更进一步的减少记录 MV 所需的 bit 数了吗?
所以 XviD 的 VHQ 模式的 2~4 选项,就是在多做这个额外的最小 MV 搜寻,搜寻范围由 "2 - Limited Search" 到 "4 - Wide Search" 增大,范围越大找到越小 MV 的机会越高,但是所花的时间越长。

但是但是,这个额外的搜寻可以保证找出来的参考位置所需花费的总 bit 数最少,压出来的档案会最小,但是 PSNR,也就是画质却会降低喔!!
为什么呢?因为当 Macroblock 不记录误差值,not coded 的时候,会直接显示 MV 所指向的参考画面中的那一个方块,而不需要再作动作补偿,补上差值(MC)。那么和原本方块误差最小的方块应该是哪一个呢?是我们原先用 SAD 找出来的那一个。不过后来我们又发现附近有其它位置因为 "经过量化" 以后,所需记录的误差 bit 数也变为 0,所以我们又改找其它 "量化后误差为 0",而 MV 较小的位置,使压出来的 bit 数更小。但是这样却会偏离了我们原先所找出来的最佳位置,其它 MV 较小的位置,其原本的误差是比较大的,所以显示的时候直接拿这个误差比较大的方块来显示,而不是我们原先用 SAD 所找到的误差最小的方块,这样画质就会下降啰。

不知道这样解释好不好懂 ^^;

其实不用理解这么深入,总之:
VHQ 模式 1 一定可以缩小档案、同时提高品质
VHQ 模式 2~4 固定品质(quantizer)压缩,可以让档案更小,但是品质(PSNR)却会下降大概 0.1dB
使用 quanity/2pass 模式压缩时,VHQ 2~4 通常能取得较好的档案大小和 PSNR 比。


2)丢失keyframe的问题是不是一直没解决?昨天我压一个10分钟的片断,竟然只有9个keyframe。哪个版本没有这个问题?

丢失 keyframe?应该解决了呀。如果压出来 keyframe 很少,代表 XviD 判断 Scene Change 场景变换的地方很少,所以不需要插入 keyframe。如果间隔太长造成搜寻段落播放时不方便,可以藉由设定 Maximum I-frame interval 来控制 I-frame 的间隔。MPEG-4 Standard 文件里面有提到,为了避免 iDCT mismatch 的问题,建议每 132 个 inter-block 之后就要强制更新为 intra-block 压缩。目前 XviD 和其它 MPEG-4 encoder 都没有实作这个限制,我们可以自行用 Maximum I-frame interval 这个选项设为 132 来做到这个要求。(I-frame 内的 Macroblock 一定全部以 intra-block 压缩,这样设定的话不管前面如何选择,一定最少每 132 次压缩中就会有一个 intra-block)
不过这个只是建议,不一定要照做,132 的 I-frame 间距对低码率的情况来说,太密集了一点,品质会下降。


3)压VCD的时候,运动物体周围的镶边很严重,怎么办?我试了一些filter都不管用。用Divx3.11压缩的时候,同样的码率,虽然图象质量不够完善,但镶边要少得多,什么道理?

因为 MPEG-4 压缩压缩效率比较高。
因为 VCD 是 CBR,DivX 3.11 是 VBR。

我是怕我写得很乱,大家看不下去,那就白写了 ^^;
虽然我已经简化很多... ^^;;
...例如上面说的 XviD 的 VHQ 2~4 会额外做最小 MV 的搜寻,这个最小 MV 其实并不是数字上最小的 MV。不是数字上最小的 MV?那么什么才是我们要找的最小 MV 呢?因为其实 MV 也会进一步的使用预测来压缩,我们会用周围方块的 MV 来预测目前的 MV 是多少,只要记录其误差值就可以了。所以其实我们要找的最小 MV,是和「预测的 MV」误差最小的 MV,而不是实际上数字最小的 MV(和目前方块最靠近的 MV)。
实际的情况是这样,不过我想如果我上面解释 VHQ 2~4 的时候是这样写,讲得这么复杂,看的人大概会晕掉...




引用 stevenxu 发表的贴子:
还有问题:我说的keyframe丢失是指第一遍和第二遍keyframe数量不一样,一般10万帧的一部影片,第一遍400多个keyframe,第二遍就只剩200不到,而且不管2 pass Int.还是2 pass Ext.都一样。doom9论坛上有人提到过,但是没见人回答。
Maximum I-frame interval好像不起作用,即使在第一遍的时候,设置为100的时候,10万帧的片断也不能得到1000个I帧。

嗯,不清楚您的设置是什么,您有用 B-frame + Modulated Quant 吗?
B-frame + Modulated Quant 会有问题,可能会出现错误的 Frame Type Decision,造成 I-frame 消失。
另外,Maximum I-frame interval 的问题新版已经修正了,不过要注意的是这个数字不包含 B-frame 在内。也就是如果只有 P-frame,间隔设 100,每 100 Frame 就会插入一个 I-frame。但是如果加入 B-frame,因为 B-frame 不会被其它画面参考,B-frame 的误差不会累积、传递给下一个 Frame,所以 B-frame 不包括在这个 Maximum I-frame interval 的计算里面,所以出来的结果就不会每 100 Frame 就插入一个 I-Frame。

这个是正确的,ISO 的每 132 个 inter-block 就要更新为 intra-block 的限制里面也不包含 B-frame 的 block。
这个也就是使用 B-frame 的好处,B-frame 不会被参考,误差不会传递给下一张画面,不影响下一张画面的画质,所以它可以压得比较差一点,quantizer 可以提高,把省下来的码率分给它要参考的 I/P Frame。这样 I/P Frame 的画质很好,B-frame 参考它们压缩,虽然本身的 quantizer 很高,和原本画面的误差很大,但是这个误差比较不容易形成明显的压缩瑕疵。因为参考画面没有瑕疵,不会传递瑕疵给这张 B-frame,B-frame 参考前后两张画面压缩,本来就有时间轴上内插的效果,画面会比较平滑,再加上预测准确,误差小,所以即使 quantizer 高,也比较不容易出现明显压缩瑕疵。但是其实 B-frame 的误差还是很大,画面会劣化,只是这个劣化不会产生明显压缩瑕疵,一般看不出来。(注意看的话还是可以看出,会感觉画面有一种周期性的骚动感)

所以一般的 encoder 预设会降低 B-frame 的品质,XviD 预设是 150/100,DivX 5.02 就更高了,我记得当 I/P Frame 固定 quantizer 是 2 的时候,B-frame 就已经是 4 了,I/P Frame quantizer 越高,B-frame 会越高,所以 DivX 5.02 的 B-frame 都非常小。DivX 5.02 的这个默认值可以修改 registry 的 "Bidir quant multiplier" 来变更。

扯远了,所以如果有使用 B-frame,Maximum I-frame interval 的数字就不会按照全部的 Frame 数目来计算,而会把 B-frame 排除在外。如果觉得间距太长不方便搜寻播放,可以再缩短 Maximum I-frame interval 的设定来调整。不过一般来说,没有误差累积的问题的话,I-frame 不是越少越好,尤其在低码率的时候


第三个问题怪我没说清楚,我是把55分钟左右的VCD压缩成230MB(其中视频190MB)的AVI,用XVID的时候镶边很严重,DIVX3.11就轻得多。

喔,我弄错意思了。
压 VCD 我没有经验,不过我的看法大致和大家相同,大概是 XviD 保留细节太多,画面太锐利,造成容易出现明显瑕疵。
您的设定是?我想也许用 H.263 Quant 会比较好一点。

XviD 用 MPEG Quant 的话 noise 感很重,一般的 MPEG-1/MPEG-2 encoder 会用 Adaptive Quant,每个 Macroblock 的 quantizer(MQUANT,MPEG-4 叫 DQUANT)会视情况变化,不是整个画面都一样。XviD 只有在用 Lumi masking 的时候才有这种功能,否则画面上全部的 Macroblock 的 quantizer 都一样。而且 MPEG-4 先天有个限制,Macroblock 和 Macroblock 之间最大的 DQUANT 差距不可以相差超过 3,所以它的弹性很小,限制比较多,无法像 MPEG-1/MPEG-2 那样运用自如。不知道是不是因为这个原因,还是说 MPEG-4 的 MPEG Quant 还有其它 bug(MPEG-4 的缺点太多了,有些设计简直让人吐血),我觉得 XviD 的 MPEG Quant noise 很严重,尤其是锐利线条周围,很容易出现 ringing effect。所以我后来都只用 H.263 Quant。而 DivX 5 也是使用 H.263 Quant,也只能用 H.263 Quant,不知道他们是不是也遭遇到这种 MPEG Quant 的问题。
MPEG-4 真是烂毙了... >_<

更新最新的版本看看,最近 XviD 又改进了很多,例如 sysKin 的 VHQ 模式(不能和 GMC 一起用,目前 B-frame 不会使用 VHQ,只对 P-frame 有效),pete 的高品质 AC 预测模式(intra-block 独立压缩很消耗 bit,MPEG-4 会用 DC/AC 预测进一步缩减 intra-block 的大小,pete 的这个高品质预测模式可以进一步提高 intra-block 的压缩率,虽然只有一点点,.01% ^^;;),应该会进步很多。安装前记得先把旧版本删除掉。
引用

| TOP