[SilkyBible] XviD系列-2

来源:互联网 发布:淘宝上的微淘是什么 编辑:程序博客网 时间:2024/04/20 04:34


 

引用 12-03-2002又更新了 ^^;

(最近很频繁...)

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

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 上都还没更新,所以我也无法自行编译测试,就静待各位的测试心得

--------

XviD 2-pass 的研究心得

结论就是,不要用那些「曲线压缩」比较好 :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 的相同。
引用 12-12-2002以前曾经说过,使用 Qpel 的时候遇到高动态的场景,压出来的档案反而会变大。
我有提到这是 XviD ME 演算法的问题,后来有做一个补充说明没在这边提过:
引用> 不过高动态使用 HPel 也许是比较好的作法,因为根据他的观察,QPel 在高动态
> 的时候越难成功的找到误差最小的参考方块。
> (这点也和我的测试结果相同,我觉得这是目前 XviD 使用的 ME 演算法的问题)
因为目前使用 QPel 的时候,没有相对应的扩大动作搜寻的距离,
所以使用 QPel 的时候,等于动作搜寻的距离比原来少一半。
(搜寻的 Pixel 数目长度没有增加,而使用 QPel 在同范围内长宽 Pixel 数多一倍,
所以等于搜寻的范围缩小,距离减少一半)
因此使用 QPel 遇到前后物体移动距离较远的高动态画面,就越难找到误差最小的方块。
下一版应该会改进...
- sysKin fixed the search range for qpel resolution.
上述问题现在改进了

- Suxendrol's experimental chroma optimizer
这个 chroma 最佳化的处理是做在 decoder 的部分。
虽然原始提议的 mf 说搞不好用在 encoder 上也可以增加压缩率,
不过我觉得帮助应该不大。

使用动态切换 qpel/hpel,每个 VOP 需要增加一些额外的信息,记录这个 VOP 切换为
哪一种过取样模式。
就像 Quant Type 使用 Modulated 一样,要动态切换 H.263/MPEG 的量化方法,
每切换一次也需要增加一些额外的信息,这样 decode 时译码器才知道要怎么正确解碼。
如果这些动态的切换没有能够提高压缩率,或是增进画面的品质,这样这些切换反而会
白白的浪费一些 bit,用在记录这些额外的信息上面。
之前 sysKin 之所以设计动态 qpel/hpel,是因为使用 qpel 压出来的档案反而变大,
为了让 qpel 的使用更有效率,能够真正的提升压缩率,所设计了动态切换的机制,
只有静态、锐利的画面才使用 qpel。
然而现在 qpel 的搜寻范围的 bug 已经修正,即使在高动态的画面,qpel 也应该能提高
压缩率,所以 koepi 提供一个切换的开关,让你试试是单独用 qpel 压出来好,
还是动态切换 qpel/hpel 压出来好?


最新进度:XviD 现在已经实作出 rrp 的编解碼,加油 XviD!!朝最强的 MPEG-4 Encoder
继续迈进吧~~

时间不多,稍微提一下,关于 2-pass 使用的 quant type,1st pass 用的 quant type
要和 2nd pass 用的 quant type 一样,压出来的效果才会好。
2nd pass 的时候会按照 1st pass 压出来的流量曲线做调整,scale 每个 frame 的大小,
如果 1st pass 用的量化方法和 2nd pass 用的不一样,scale 的预测就会非常不准确,
连带影响 encoder 分配 bit 的效果,这样就无法做到 linear-scaling 了。
所以 koepi 以前说,当你使用 Modulated 的量化方法时,quantizer < 4 会用 MPEG 量化,
>= 4 会用 H.263 量化,quant type 会自动切换。这时如果你设定的码率比较低,
可以预期 2nd pass 时大部分的 frame 的 quantizer 会大于或等于 4,也就是大部分的
frame 会用 H.263 量化,此时你的 1st pass 就要选择 H.263,这样 2nd pass 的 scale
才会准确。
反过来,如果 2nd pass 大部分的 frame quantizer 会小于 4,则你 1st pass 就最好选择
MPEG 量化。
如果没有使用动态的切换 quant type,则 1st pass 时用哪种 quant type,2nd pass 就用哪种。

同样的道理,1st pass 时有用 QPel/Lumi masking,2nd pass 就要跟着用 QPel/Lumi masking;
1st pass 时没有用 QPel/Lumi masking,2nd pass 时就不要用 QPel/Lumi masking。
1st pass 的设定要和 2nd pass 一致。

关于 DVD2AVI 的 Force Film,以下针对的是 NTSC 的 DVD 说明:

DVD2AVI 的 Force Film 只有在 Film 的比例高达 95% 以上时才能使用。
先用预览 Preview 跑一遍,或是大概跑一段,看看 Film 的比例占多少,
如果 Film 的比率太低,强制 Force Film 输出,输出的结果会是垃圾。

DVD2AVI 的 Force Film 选项并不是像 TMPGEnc 的 IVTC 那样,
真的去分析画面交错的数据来判断还原回原来的 24fps。
DVD2AVI 的 Force Film 只是根据 DVD 内储存的旗标(Flag)信息,
组合出原本储存在 DVD 内的 24fps 的 Frame
Film 的 DVD,也就是 24fps 的 DVD,是在 DVD 压缩的时候,就先做好IVTC。
也就是 DVD 压缩的内容,本来就已经是 24fps 了。
先做好 IVTC 再压缩,因为每秒钟需要压缩的 Frame 由 30fps 减少为 24fps,
少压 6 个 Frame,所以会比较好压,同码率下画质会更好。
然而输出的时候,DVD Player 会根据 DVD 内的 RTF/TFF 旗标的信息,
将内部储存的 24fps Frame 组合成 30fps 输出,以符合 NTSC TV 的规格。
DVD2AVI 的 Force Film 就是根据这两个旗标的信息,反过来不做 24->30 的转换,
直接输出原本内部储存的 24fps。
所以如果原本的 DVD 的 Film 比例不高(也就是 24fps 的比例不高,
为 24/30 fps 混杂的 DVD),强制 Film 输出的结果会得到错误的 Frame 组合。
因此唯有当 Film 的例超过 95%,才可以选择强制 Film 输出。
一区的 DVD 有很多都是 Film(24fps)的 DVD,所以强制 Film 输出没有什么问题。

因为 DVD2AVI 并不是真的在做 IVTC,真的去分析画面,组合还原回正确的 Frame
所以也不能批评 DVD2AVI 的 ""IVTC"" 很烂。
使用者应该自行判断,什么时候该用 Force Film,什么时候不该用 Force Film。