[SilkyBible] XviD系列-3

来源:互联网 发布:软件开发 税种 编辑:程序博客网 时间:2024/04/26 05:34
 
引用 12-12-2002
引用另外顺便再提一下这个linear curve,sbc对于curve的压缩已经是约定俗成,xvid的早期开发也一直对这个问题纠缠不清,还搞出original cc和alt cc两套做法,我实在想不明白为什么一下子又回到了原始状态。。而且效果还比cc好?或许xvid本身的码率分配比较合理?koepi一直对这个问题避而不答,也没有程序员出来解释。。
我也不懂为什么他没有回答这个问题。
2-pass 的 curve compression/scaling 主要就是由他和 foxer 设计的,
他不回答,其它三位真正的 XviD 核心开发人员(gruel,michael,pete)也无法帮他说明。
(他们三位也不上 Doom9,这三位才是 XviD 幕后的大功臣)
从理论上来说,linear-scaling 应该是最完美的,不过当码率不够的时候,用 original cc/
Alt. cc 应该还是会有它的作用。不过这个调整不好调,参数设错,反而会遭致反效果。
问题是怎样的设定才是好的设定?这个最佳的设定会随影片不同而不同,没有固定的标准。
所以说很难调。(而且 Alt. cc 的参数很难懂,有多少人知道那些参数代表的意义?
连 XviD Stats Viewer 的作者 NiTroGen 一开始的时候都搞不清楚 curve aggression 是在
做什么....)

不过,我最近突然发现,用 GKnot 乱搞出来的 scaling 效果反而更好?!
GKnot 的 linear-scaling 会分析画面的 motion,更适当的分配码率。
不过它并不适用在 XviD 上,GKnot 主要是针对 Nandub 设计,有很多判断的方法不适用于 XviD。
如 GKnot 会计算 Luma noise,XviD 根本没有这种问题。
GKnot 还会根据 1st pass 每个 frame 的:
1.k-blocks: = intra-blocks 不参考前后画面,独立压缩的 block。
Intra-frame(或者称为 I-frame)全部都用这种 block 压缩。
所以如果分辨率是 640x480,总共的 MacroBlock 是 (640/16)*(480/16) = 1200 个,
如果是 I-frame,1st pass 时你会看到 XviD 回报该 frame 的 k-blocks 是 1200,
m-blocks 和 u-blocks 都为 0。

2.m-blocks: = inter-blocks 参考前后画面,压缩的 block,记录的是和前后画面的误差。
P-frame 和 B-frame(统称为 Inter-frame)中大部分的 block 都是这种 block,
只有当该 block 和前后画面的差异太大,找不到适当的参考方块,才会改以 intra-block 压缩。

3.u-blocks: = uncoded-block = skip block,不压缩,直接 skip 掉的 block。
当该 block 几乎没有变动,和前后参考画面几乎完全一样时,譬如说完全静止的画面,
我们就可以 skip 掉这个 block 不压缩,直接沿用前一个 block 来显示。

这三个数值 1st pass 的时候会计算出来,GKnot 会根据这些数值来判断 motion/scene change。

k-blocks + m-blocks + u-blocks = 总 MacroBlock 数,如 640x480 即为 1200。
XviD 1st pass 时 debug view 只会显示 k-blocks 和 m-blocks,而 1200-(kblocks + mblocks)
得到的数字便是 u-blocks。

然而这个不适用在 XviD 上,因为 XviD 目前 B-frame 回报的数目并不正确,GKnot 可能会算错
真正的 motion 值!

不过我很意外的发现,用 GKnot scale 出来的 2nd-pass stats 效果还是比 StatsReader 好!
不过不要用 GKnot 判断 scene change 的功能,要选择保留原 1st-pass stats 檔的 Key-Frames
设定(按 Stats 按钮),其它如 F.-Size Correction、Motion Correction、Luma Correction
通通不能勾选。

我只有试过几个 clip,压出来的效果都比 StatsReader 的 scaling 好,不过不确定是否所有影片
都具有同样的效果,如果你不满意 XviD 目前的 2-pass 算法,可以试试看 GKnot。
重申一次,我不确定这样乱搞压出来的效果一定会比较好,您可以观察 2nd-pass 压出来的
平均 quantizer 有没有降低,如果有降低,那应该就是有帮助 :P
(不过目前 XviD 显示的 B-frame quantizer 也不正确,似乎不能做为判断依据 ^^;)
引用我只想知道rrp 的编解碼是什么?
它的原理和功效.
抱歉上面打错了,是 rrv 不是 rrp ^^;
rrp 全名是 reduced resolution VOPs,当高动态的时候,人眼看不清楚细节,
高动态的时候通常必须使用高 quantizer 来压缩,导致画面出现明显压缩瑕疵,
此时如果改成纪录比较低的分办率的画面,压缩的画面缩小,就可以降低 quantizer,
显示的时候再 up-sampling 回原本的分办率显示。
虽然这样细节会减少,但是反正高动态人眼也看不清楚,总之没有明显压缩瑕疵就好 :P

rrv 会将记录的 texture,长宽各缩短一半,也就是重新取样变为原本的 1/4,32x32 -> 16x16
只记录一半的分办率,解压缩时再 up-sampling,放大回原本的分办率。

这个是 MPEG-4 Profile 中,属于 Advanced Real Time Simple 这个 Profile 所使用的压缩工具。
http://www.m4if.org/resources/profiles/visualtools.php
其中的 Dynamic Resolution Conversion 就是。
XviD 的目标是要作出 Advanced Coding Efficency 这个 Profile 中的所有压缩工具。

不过有人也说了,XviD 目前还有没完整做完 Advanced Simple Profile 中所有的工具,
并且最佳化这些工具,使之达到最大的压缩效益和最快的压缩速度,
现在就直接跳到开发 rrv,另一个 Profile 的压缩工具,似乎太早了一些。
我非常同意
引用 12-13-2002
引用CC的弃用我认为证明那一套失败了,当初设计的时候可能考虑了D3的做法,也可能是为了“区别”D5的证明:XVID比保密的D5要更“开放”。alt cc的调节容易引起混乱,曾经很多人想依靠试验得出最佳效果,但是排列出来的组合太多,根本没办法一一试验,更何况电影的千差万别呢,现在使用linear scale,问题简单化,对使用者和编程者都是一件好事。
您说出了我心里面的想法,我也觉得 Alt. cc 的设计是失败的,
参数太过复杂,使用者根本不知道要怎么调整,而且调整的效果也不是非常理想。
像 DivX 5 的 2-pass 多轻松,使用者根本不需要去修改什么设定,反复实验最佳的结果。
通常来说,只要用默认值就可以得到不错的码率分配,这对初学者来说,容易上手得多。
引用GK的curve计算也可以用在XVID上。。这倒是第一次听说,以前被alt cc已经搞得头大,还真没想过用GK计算,有空一定试验一下。不过我猜想GK除了改变码率分配曲线,可能还因为B帧的不正确读入自行加入了一定数量的intra-frame?GK已经长期没有更新,希望下一个版本能直接支持XVID的曲线压缩计算,除了能快速生成avs文件外,这也是GK最拿手的法宝了,希望thewefs不会让我们失望
因为 XviD 的 2-pass 是 koepi 设计的,koepi 从前曾经参与过 Nandub 的改版设计,
所以他在设计 XviD 的 2-pass 的时候,就采用了和 Nandub 一样的 stats 檔格式,
所以 GKnot 也可以读取 XviD 生成的 stats 檔。
不过如前所述,两者的参数有些不相同,像 XviD 的 stats 档就没有 Luma noise
这个参数,所以 GKnot 读取显示的 Luma noise 的数值都是错的。
基本上是不能用 GKnot 来做 XviD 的 scaling 的,所以我以前也从没这样做过。
最近是一时无聊,试试看用 GKnot 乱搞出来的 stats 檔拿给 XviD 压会压出什么结果,
结果效果非常好!我自己也很惊讶,我原来以为会压出乱七八糟的东西....

XviD 我现在最不满意的就是 2-pass 的算法不像 DivX 5 那么好,
而使用 linear-scaling 时如果码率太低,静态画面的画质会不够好,
导致明明 XviD 的压缩效率已经大幅超越 DivX 5,但是做 2-pass 的时候总是觉得某些画面
还是不如 DivX 5(因为分配码率的问题,要分配得恰到好处,才能在有限的码率下隐藏压缩
的缺点,增进表面上看起来的视觉品质)。
现在用 GKnot scaling 出来的 stats,我觉得已经接近 DivX 5 VBR 的水准,
让 XviD 的 2-pass 明显超越同码率下的 DivX 5。
不过再重申一次,我只有做了两三个 clip 的压缩测试,无法确定每一部电影使用 GKnot 都会有
相同的优异效果,毕竟现在的 GKnot 理论上根本不支持判断、分析、计算 XviD 的 stats 檔。

我也是担心 GKnot 会自己加入 Key-Frame,导致不正确的结果,所以在 Key-Frames 的设定那边
指定 GKnot 使用原本 stats 档内的 Frame Type 不要变更(按 Stats 那个按钮),
同时 ""不能"" 勾选 F.-Size、Motion、Luma 这三个 Correction 的校正,
然后才按 Calculate 计算 scale 的 Frame 大小,然后存盘。
压出来 Key-Frames 的数目是对的,没有乱增加。
不过说实在的,用得心理毛毛的 ^^;
看起很不错就是了 :)
引用B帧的quantizer一直是我想不通的问题,XVID的VFW介面下可以设定上限的只有I和P帧,B帧的quant计算公式。。我看不懂。记得syskin说过在150%的ratio下B帧会比相邻的P帧大1或2个quant值,但是因为P帧的上限永 远是整个电影的最高上限(debugview内的结果),所以我想不通,要么是xvid报错信息,要么本来就是如此。要是silky兄对此有心得,还望不吝赐教。
赐教不敢当,小弟提供一点心得,您参考看看,大家一起研究研究 :D
XviD 的 B-frame 的 quantizer 设定是用 B-frame quantizer ratio 和 B-frame quantizer offset
这两个参数来控制的。
因为 B-frame 不能拿来做为参考画面,也就是说 B-frame 不会再被其它画面参考到,所以 B-frame
可以压得比较差一点,通常 quantizer 会设得比较高。
这是因为 MPEG 压缩的时候 I-frame 和 P-frame 会被其它画面拿来做为参考画面,
其它画面会参考这两种 frame 来压缩,只纪录和参考画面之间的差异。
参考的时候参考的是压缩过的画面,举例:
I P P P ...

首先第一张 I 独立压缩,压缩完以后再解压缩,还原一张经过压缩过的画面 I'。
第二张 P 要参考前一张画面压缩,此时要参考的是未压缩过的、原本的画面 I,
还是压缩过,再解压缩回来的 I' 画面?
答案是压缩过,再解压缩回来的 I' 画面。
因为 P 纪录的是和前一个画面的差异,解压缩时用前一张画面补上这个差异便能得到正确的画面。
然而解压缩的时候的前一张画面是什么?是经过压缩过的 I',不是原本的 I。
原本的 I 在压缩档里面已经不存在了(当然,不然怎么叫有损压缩 :D )。
所以我们可以了解,P 要参考的画面必须是压缩过的 I' 画面,要记录的是未压缩的目前的画面,
和前一张压缩过的参考画面之间的差异。
所以,如果前一张 I' 压缩得很烂,它和目前的画面的差异必然很大,必然很不像现在的这张画面。
这样这张 P 就必须提高码率才能记录这么大的差异,如果码率不够用,这张 P 就无法压得很好。
接着后面的 P 又要参考这张前面压得不好的 P..... 如此恶性循环,结果所有的 frame 都无法压得好。

所以会被参考的 I-frame/P-frame 必须要压好一点(或者说要压得正确一点),
尤其是 I-frame是独立压缩,比较不好压缩,需要的码率要大,所以才会有 I-frame boost 这种选项。
(不过要做到 linear-scaling 便不能使用 I-frame boost,前一次忘了提,这里补充)

反过来说,B-frame 不会被参考到,所以可以压得比较不精确一点,所以通常我们会提高
B-frame 的 quantizer 达到高压缩率。
例如 TMPGEnc 的 VBR 和 CQ 压缩模式当中的设定选项「B picture spoilage」
(英文版,中文版我不知道是怎么翻译),就是让你设定 B Frame 相较于 I/P Frame 所要减少的品质。

回过来说 XviD 的 B-frame quantizer 设定。本来只有一个选项「B-frame quantizer ratio」,
用的算式是:
((前面参考画面的 quantizer + 后面参考画面的 quantizer)/2 * ratio)/100

例如前面参考画面的 quant 是 4,后面是 6,ratio 设 200,则 B-frame 的 quant 就是
((4+6)/2*200)/100 = 10

也就是「前后画面的 quant 平均,然后乘上 2」。

不过这种设计你可以看出来很不理想,如果前后的平均 quant 为 10,
中间的 B-frame 的 quant 一下子就会跳到 20。
我们知道 10 和 20 压出来的品质差很多,这种设计 quant 一下跳太快,比较没有弹性,
容易造成某些画面突然发生劣化,出现明显的瑕疵。

所以后来有人建议,才又加上了 offset 这个参数,整个 B-frame 的 quant 算式变成:
b_quant =
(AVG(prev vop quant, future vop quant) * bquant_ratio +
bquant_offset) / 100

也就是
((前面参考画面的 quantizer + 后面参考画面的 quantizer)/2 * ratio + "offset")/100

例如 ratio 设 150,offset 设 50,前后平均 5,则 B-frame 的 quant 就是
(5*150 + 50)/100 = 5*1.5 + 0.5 = 7.5 + 0.5 = 8

这样比较有弹性,前后画面是高 quant 的时候 B-frame 也不会一下劣化太快。

那么为什么 debug view 里面回报的 B-frame 的 quant 数目和算出来的不一样?
因为目前 B-frame 回报的那个数值是错的 :p
(那个只是压缩时 Codec 丢出来的讯息,本来只有设计显示 I/P Frame 讯息的部分,
没有考虑到 B-frame。反正对压缩没有影响,目前也没有人去修改这个输出的讯息。
开发人员都很忙,有更重要的 bug 要去修正 :D )

除了这个 quant 的数目,1st pass B-frame 显示出来的 k-blocks, m-blocks, u-blocks
这些数字也都是错的 -_-;;
引用rrv看来也不是什么好迹象;) 减少细节我不是很在乎,毕竟是在高动态下,看不到无所谓。但是估计decode的时候又要给CPU加活了:rolleyes:
这倒是 :)
等开发完成,应该会做个选项让使用者决定要不要开启吧。
引用 12-23-2002个人意见,我觉得 1st-pass 的设定要和 2nd-pass 的设定一致比较好,
从理论上来说,这样编码器的码率控制器(bitrate control)才能准确的工作。
码率控制器根据 1st-pass 压出来的每个 frame 的 size 做 scaling 调整大小,
也就是 2nd-pass 压缩的时候调整 quantizer 控制每个 frame 的 size 接近 scaled 后的大小,
如果因为 2nd-pass 的设定不一样,造成压出来的 frame size 和预测的差很多,
码率控制器就无法准确的预测使用的 bit 超出(overflow)的情形,
做出适当的补偿(payback),这样便可能会发生无法预期的结果。
当然这是从理论上来说,实际压出来不一定会有不好的结果,因为实际的情况可能是很复杂的,
小弟只是提供一点理论面的说法,大家参考看看,如果有时间的话可以反复多压几次,
做做实验

另外建议如果是要保存用的影片,最好不要在最终的生成结果使用 qpel。
目前 XviD 的 qpel 使用 XviD 自己的 xvid.dll 这个 vfw codec 播放是正常的,
不过这是理所当然的
如果用 ffdshow,也就是 libavcodec 这个译码器播放,水平/垂直/水平加垂直 三种 interpolation
都不正确,DivX 5 的译码器播放 水平/垂直 看起来好像没有问题,但是 水平加垂直 还是不正确。
这种错误一开始并不明显,但是如果一直参考同一个位置,连续 100 个 frame 以后就会变得很明显。
(因为各家译码器对 qpel interpolation 内插补值的作法不一样,造成补偿加上去的差值不一样,
这个错误会一直累积,连续 100 frames 之后就会变成非常明显的错误瑕疵)

因为 DivX 5 的 qpel 的作法本来就不正确,不符合标准 ISO MPEG-4 的规范,
所以 DivX 5 不能正确解碼 XviD 的 qpel 无所谓。
但是使用 MS MPEG-4 FADM 这个 MS 作的 100% 标准的 MPEG-4 软件来译码也不正确,
这个问题就很严重了,这代表目前 XviD 的 qpel 可能有兼容性(正确性)的问题。
凄惨的是,目前几个 MPEG-4 译码软件 XviD/ffdshow/DivX 5/Envivio TV 对 qpel 的 interpolation
作法都不一样,到底是谁做错?难道大家都做错?还要再研究。
(也许根本没人看懂 ISO 的标准说明文件到底在写什么 )

XviD 的开发人员之一 Isibaar(Michael Militzer)目前还在研究,寻找到底是哪里有问题。
XviD 的目标是要作出完全标准的 MPEG-4 视讯编译码器,「不标准的 MPEG-4 编译码器
有 DivX 5 一个就够了」他笑着说。
所以如果你考虑到将来播放、兼容性的问题,最好不要在保存用的影片上使用 qpel。
不过 1st-pass 的时候使用 qpel 倒是没有关系,因为并不是 qpel 有错误,
只是各家的作法不一样,造成在不同译码器上播放有不同的结果,这对 1st-pass 使用 qpel
不会造成任何影响。
(虽然我还是建议 1st-pass 的设定要和 2nd-pass 一致 )

再次提醒,Koepi/Nic/uManiac 提供的最新的 binary 是开发中的版本(development, unstable),
任何新加入的功能都可能有着错误、兼容性问题的危险,这些新功能不见得能够提高压缩率,
带来高画质,相反的它可能会制造充满错误的压缩结果,所以如果您是想用它来压缩要保存的影片,
在勾选这些功能之前请确定你知道你在做什么。
XviD 的主要开发人员之一 gruel 很担忧的说,GMC 现在充满了 bug,甚至无法正确的译码,
但是已经有人使用 GMC 来压缩要保存的影片,他可以想见将来这些使用者发现过去压缩的影片
无法正确译码的时候,将会是多么的愤怒,论坛上将会充斥着这些使用者抱怨的声音。
到时候开发小组的回答恐怕只能是:
「既然你知道这是 unstable、开发中的版本,既然你根本不晓得那些选项是做什么用的,
那你为什么还用它?」

目前已知比较安全应该没有问题的新功能:
1. Chroma Motion
实际上就是动作估计(ME)的时候多做色彩平面上的动作向量搜寻,让 ME 的结果更精确,
找到更小的误差,可以视为是 Motion Search - 7,完全没有规格上的争议,不会有错误,
所以相当安全。

2. B-frame
应该已经很稳定了,测试过各家译码器解碼大致上都正确,视情况动态插入 B-frame 的设计更是
XviD 的首创。B-frame 功能是目前能提供最大压缩率的利器,但是要注意的是 "一定" 要勾选
"DX50 B-VOP compatibility" 这个选项,禁止 B-VOP(B-frame)的下一张参考画面是 I-VOP,
否则这个 B-VOP 会出现一堆错误的方块。这个错误虽然只有一个 frame,画面一闪而过,
但是注意看的话还是会发现,所以请 "一定" 要勾选 "DX50 B-VOP compatibility"。

比较有争议的新功能:
1. Qpel
理由如上所述。
如果你不在意兼容性的问题,不在乎压出来的东西是否合于标准的 MPEG-4 规范,
不打算未来在家电产品上播放目前压的 MPEG-4 影片,并且只打算在计算机上使用 xvid.dll 播放,
那么可以使用这个功能。

2. GMC
开发中,功能简陋,完全没有实质上的压缩助益,并且还有错误需要修正,绝对不要使用。
DivX 5 的 GMC 也一样,功能简陋,不会比 XviD 好多少,XviD 的 GMC 很快的就会超越 DivX 5。

3. Modulated Quantization Type
动态切换 H.263/MPEG 的量化方式。这个 ISO 没有明文规定不可以,而且目前的译码器都支持
Modulated Quant,播放上完全没有问题,但是... 还是有隐忧,因为不保证将来的家电产品
一定都可以解 Modulated Quant,毕竟文件上没有要求要有这种规格。

如果你觉得将来太遥远,到时候可能都已经不用 MPEG-4 part 2(目前的 MPEG-4 视讯压缩法),
而改用压缩率更高,更强大,更先进的 MPEG-4 part 10(或者叫 MPEG-4 AVC,Advanced Visual
Coding,先进视讯编码法,也就是 ITU 的 H.264,旧名叫 H.26L)来编码,所以将来支不支持
旧的压缩法,对你来说都无关紧要,那么可以使用这个功能。

以上提供给大家做为参考。


这次写太短了,后面加一些不相关的讨论跟大家闲聊

最近 Doom9 有一篇在讨论如何压出最高品质的帖子,讨论到使用 quantizer 1 的问题,
为什么以前不建议使用 quantizer 1 呢?
quantizer 1 使用「非线性量化表」对应的量化倍数是 1x,
也就是 DCT 系数直接除量化矩阵。这样的失真应该最小,品质应该最好,
为什么反而不建议使用呢?

因为 XviD 使用的 iDCT(inverse DCT,反向 DCT 运算),会做舍弃小数,如果 quant = 1,
则矩阵中很可能会出现非常小的 DCT 系数(没有被除为零),
这些 DCT 系数在压缩时会经过 iDCT 转换回来当成参考画面。
(压缩器当中必须包含译码器才能将压缩过的画面解回来当作参考画面)

此时这些很小的系数会造成非零的 iDCT 输入,解出来却因为舍弃小数的关系而变成为零的输出。
这样子很浪费 bit,因为这些 iDCT 后为 0 的 block 本来应该 skip 掉,试想补偿时加上差值
为 0 的补偿要做什么?这样子不是等于没补偿?那花费 bit 去记录这些数据不是很浪费?
而且在 MPEG-4 规范中,这是不可以的。
如果播放的译码器使用的是和压缩器不同的 iDCT(iDCT 的算法有很多种,有的速度快,
有的算得很精确,没有规定译码器一定要用哪一种 iDCT 算法,所以不同译码器画质也可能不同),
播放端译码器的 iDCT 输出可能不为零,这样就惨了,原本压缩时,参考画面是输出为零的结果,
现在解压缩时,参考画面却不是为零,这个错误会一直累积,慢慢的画面上就会出现肉眼看得到的瑕疵。

这个叫做压缩器/译码器 iDCT mismatch 的问题。
解决这个 zero-iDCT 问题的方法,
1. 不要用 quantizer 1 (MS MPEG-4 和 DivX 5 都不用 quantizer 1)
2. 利用 TOO SMALL LIMIT 这个参数,当 block 中的 DCT 总和小于一定门坎就 skip 掉,
一般情况下是设为 1,遇到 quant =1 时调整为 2,防止 sum = 1,iDCT 后却变成 0 的情况。

XviD 已经用 2 的方法解决这个问题,不过以前说过 TOO SMALL LIMIT 太高,会损失细节。
所以到底用 quantizer 1 好不好?我试压了几个 clip,quantizer 1 的画质还是明显比较好,
不过压出来的档案非常非常大 ^^;


我们知道 resize 最强的计算方法是 lanzcos3,这个计算法转换后的画面既锐利、而且又没有
aliasing/ringing 的问题。压缩 lanzcos3 resize 的画面,锐利的线条、物体的边缘不容易
出现扩散的,斑斑点点的压缩噪讯。也就是虽然 lanzcos3 画面锐利,但是又不会增加太多的
压缩困难度。这是因为 lanzcos3 的计算法本身就等于一个完美的 Low Pass Filter,
不像其它的 resize 法为了要设计一个适当的 LPF 而伤透脑筋。
这个 resize 法本来是由一个很厉害的人实作在 AviUtl 这个软件上,做成 AviUtl 的 plug-in。
后来西方有人注意到这个好用、画面又漂亮的 resize 法,于是提议 Avisynth 加入这个 filter。
因为越来越多人使用,成为大家公认的最棒的 resize 法,所以 VD 的作者也在 1.4.13 版加入了
这个 resize。
我以前都是用 AviUtl 的 lanzcos3,不过因为 AviUtl 的速度实在太慢,所以想说改用 VD 内建的
来试试看,结果...
不知道 VD 的作者是怎么作的,VD 的 lanzcos3 aliasing 得非常严重,resize 后的画面锯齿得
很厉害,压出来的线条周围噪讯飞散,惨不忍睹,就像 bicubic 的算法如果设定成锐利化得太厉害,
压缩后的线条周围会都是噪讯一样。
所以,建议大家不要用 VD 的 lanzcos3
我没用过 Avisynth 的版本,不过我相信 Avisynth 作的应该是对的