头像
dgwxx
管理猿
帖子: 771
注册时间: 2010-09-19 20:42
联系: 网站

YC伸张与YC压缩的实验

4月16日中午12:00更新:
mpeg2source不会进行YC伸张,而是直接输出原始数据。谢谢qyqgpower 指出。

4月16日早7:00更新:
添加了测试用影片,测试您播放时的YC伸张是否准确。只有上面的白色是235、下面的白色是255时才是正确播放。
此外请大家注意到,本文不是我一个人所写,有两部分是VempX所写的哦~大家不要忘记他。
(链接见楼下)
============================================
正文:
YC伸张与YC压缩是一个从Silky大人时代就留下来的古老问题。包括我在内的很多人都没搞明白,制作和播放的时候提心吊胆,生怕弄错了颜色。最近正好没事,进行了一系列的实验,看看YC伸张和YC压缩到底是真么回事。本文的阅读对象是已经知道YC问题的由来,但不知道如何处理的读者,如果您还不知道什么是YC伸张和压缩,推荐您先去复习一下Silky的文章。
本次实验分为四个部分,分别是准备篇、AVS篇,AU篇和播放篇,由我和VempX分别进行自己熟悉的部分。
限于作者水平,或许会有疏漏错误,请多指教。

准备篇
By Dgwxx.
为了正确判断出软件是否进行了YC伸张和压缩,就需要一把标准的尺子,因此彩条Colorbar成了最合适的尺子。因为普通的彩条难以判断黑、白、红、绿、蓝的范围,所以我们用Photoshop制作一张专门用来判断颜色、亮度范围的640*480的彩条图片,保存为24bit bmp格式。彩条上半部分的颜色范围为16~240,黑白部分为16~235(601 Range)。下半部分全部为0~255(Full range),用于进行对比。
之后,使用使用以下AVS代码将bmp图片生成一个5秒钟的短片。

代码: 全选

#AVS代码1:
ImageSource ("colorbar.bmp",end=149)
AssumeFPS("ntsc_video")
将这个短片送入TMPGEnc压缩成MPEG2格式。压缩时,打开TMPGEnc的YC压缩选项,此时图像上部为30~217,下部为16~235。
观察时:
  • 图像上部为30~217、下部为16~235,则没有进行YC伸张。
  • 图像上部正常回复为601 Range、下部为Full range则判断为进行了一次YC伸张。
  • 如果上下全都变成了0~255的Full range,则是进行了两次YC伸张。
只有中间的结果是正确的。
观察AVS时使用下面代码

代码: 全选

#AVS代码2,部分实验upconv参数有改动:
loadplugin("e:\gk\dgmpgdec\DGDecode.dll")
mpeg2source("colorbar_with_yc_compress.d2v",upconv=[b]0[/b])
AVS篇
By VempX.
AVS压DVDRIP主要来源于DGMPGDec。
通过对彩条的观察得知,通过VDM打开AVS,会发现无论YUV-> RGB选项如何选择,画面都会是Full Range,也就是0-255,这是为什么呢?因为YUV是无法直接在PC上显示的,必须转成RGB才能显示出来。VDM会自动调用系统的ColorSpace转换滤镜进行转换,这个转换过程会做一次YC伸张,所以在VDM里显示出来的色彩会是Full Range。DGMPGDec解码出来的仍然是没有进行YC伸张的原YV12数据。而vfapi插件、预览图像、保存BMP选项受菜单中YUV -> RGB的影响,PC Scale会进行YC伸张,而TV Scale不会进行YC伸张(注意,是“不伸张”,而不是“压缩”!)。
所以AVS里的是原始的YV12数据,再次强调一下,除了全程YV12之外,不要在AVS里动颜色!

正确的图:
avs_source.png
avs_source.png (1.95 KiB) 查看 7412 次
Aviutl篇
By Dgwxx.
首先我们拿到DVD之后需要进行的是解码。对于AU来说,解码主要分为两个解码器、三条途径。两个解码器分别是M2V和DGMPGDec。M2V与AU结合有两条途径,分别是aui与vfapi。而DGMPGDec与AU结合只有vfapi一条途径。
我们先看相对简单的DGMPGDec
DGMPGDec的vfapi插件是DGVfapi.vfp,正式名称叫做DGMPGDec D2V/AVS Reader。不同版本在AU中出现的名称会加上版本号,但基本的名字是这个。如果你注册了DVD2AVI(现在可能很少有人记得这个软件了)的vfapi插件,那么就需要在输入插件的优先顺序调节中将DGMPGDec的优先度调高,避免DVD2AVI的vfapi插件误食引起麻烦。
我们将DGIndex生成的索引文件d2v拖拽到au界面之后,au会通过DGMPGDec的vfapi插件打开这个d2v文件。这一点通过「その他」中「ファイル情報」对话框的「ファイル制御」一项确认。
DGIndex及DGMPGDec控制是否进行YC伸张的秘密在于DGIndex中Video菜单下YUV -》 RGB选项。这个选项对于DGIndex的预览图像、File菜单下的Save BMP选项、vfapi解码得到的图像起作用,对于其avs解码插件mpeg2source不起作用,mpeg2source不会进行YC伸张,回直接输出原始数据。
用文本编辑器打开.d2v文件之后就会发现有一个项目叫做YUVRGB_Scale,对应YUV -》 RGB的选项,当值为1的时候,vfapi解码器会做YC拉伸,否则不会。这个选项在avs中使用mpeg2source载入d2v的时候会被忽视,不做YC拉伸。

再来看M2V
M2V可以通过vfapi方式与AU结合(m2v.vfp),同时也具备专供AU的输入插件(m2v.aui)。前者经注册后在AU中的名字是MPEG-2 VIDEO Plug-In,后者的名字是MPEG-2 VIDEO File Reader。前者向AU输出RGB颜色空间,后者则是YUY2。使用的时候一定要注意想要把解码任务交给谁,调整好插件的优先级。
M2V调节是否做YC拉伸的选项在于m2vconf.exe中YUV Range一项。这里调节的是片源的属性,而不是输出的属性。
当选择ITU-R BT.6011 Range的时候,MPEG-2 VIDEO Plug-In会进行YC拉伸。
当选择Full Range的时候,MPEG-2 VIDEO Plug-In不会进行YC拉伸。
也就是说YUV Range只对MPEG-2 VIDEO Plug-In起作用,而MPEG-2 VIDEO File Reader则始终会进行YC拉伸。
YUY2 Matrix选项与YC压缩拉伸无关,是选择MPEG-2 VIDEO File Reader颜色转换公式用的。

播放篇
By VempX.
我们用一个色彩正确的ColorBar方案用AVS脚本,并直接送给x264压制,得到了一个mp4,现在我们知道这个mp4的颜色是正确的。

播放器:Media Player Classic Home Cinema
解码器:ffdshow
分离器:Haali
显卡: GeForce 8600GT

我会试图用几种组合告诉大家如何得到正确的播放结果。

1. VRM9无渲染+ffdshow YV12输出 颜色错误

2. VRM9无渲染+ffdshow RGB32输出 颜色正确

3. Haali渲染器+ffdshow YV12输出 颜色正确

4. 覆盖合成器+ffdshow YV12输出 颜色错误(存疑)

5. 覆盖合成器+ffdshow RGB32输出 颜色正确


首先来说RGB,当YUV转换到RGB时,就已经做了一次YC伸张,所以颜色已经是正确的,VRM9渲染器是无法对RGB色彩数据做处理的,所以最后会得到正确的结果。
而Haali的渲染器,功能可谓十分强大。它可以自动判断601或709,并且可选是否做YC伸张。当使用Haali的渲染器时,他会根据视频窗口大小和视频源分辨率来自动做不同的高品质Resize,品质要远远高于播放器自带Resize。
这两个方案都有各自的弊端。Haali的渲染器现在还不能用它打开硬解。ATI的显卡貌似也是同样的问题(感谢冰冷的心提供资料),而且ATI的显卡还可能存在Resize的瑕疵。覆盖合成器无法保存图像和使用QQ截图,十分不方便。RGB输出对系统资源消耗太大。
这时我们就要用到VRM9无渲染的厉害功能了。我们使用VRM9无渲染,在播放时单击右键,可以找到渲染菜单,里面默认会有一个16-235 -> 0-255,我们勾上这个,就会得到YC伸张的画面了,也就是正确的颜色。
所以,我推荐的组合是,VRM9无渲染+ffdshow YV12输出+shader着色器YC伸张。当然如果你的机器足够强,你还可以用Haali渲染器+ffdshow YV12输出的组合,除了不能开硬解,其他都近乎完美,缺点是系统资源消耗较大。

话说帖一张有意思的图:
cal_error.png
我怀疑是不是我弄错了,AU的误差怎么这么大了,连他自家的m2v都这样。

全部测试结果图打包下载:
YUV.rar
(4.44 KiB) 下载 157 次
日常推 @dgwxx: 基本没什么技术的话题,欢迎没事看看消遣。
► 显示剧情透露 平庸的rip
► 显示剧情透露 “不知道”的五大理由
头像
dgwxx
管理猿
帖子: 771
注册时间: 2010-09-19 20:42
联系: 网站

播放过程中YC伸张的实验

前天我和VempX瞄准DVDRIP过程中的YV伸张与压缩进行了一些实验。今天我做了一些实验,整理了一下播放过程中YC伸张与否的规律,分享给大家。其实我有些怀疑这篇文章的意义,因为用户随便按一下显示器上的MagicSet之类的按钮,或者调节一下亮度色温对比度给图像带来的改变远远大于播放设置错误带来的误差。老实说,我在这做了半天实验带来的实际意义似乎并不是很大。
但就算这样,该做的还是要做,该写的还是要写。少点错误总比多点错误强。
本文理论浓度较低,但是实践的部分比较复杂,估计有不少人会头晕,头晕的话可以先去看结论,等回过头来再看实践部分或许就能理解了。
文章中若存在错误、不足的地方,还要您请多指教。

废话少说,现在进入理论。
理论篇
首先我们要明确,YC伸张发生且仅发生于从YUV颜色空间向RGB颜色空间进行转换的过程。明确了这点之后我们就可以减少很多不必要的猜想和迷惑。
其次,在播放过程中影响YC伸张的环节有三,一个是解码器,一个是渲染器,还有就是显卡。
有些解码器/渲染器不带有YC伸张或RGB转换功能,那最终完成YUV到RGB转换任务的或许就是显卡。

实验准备篇
为了清楚地知道播放过程中是否进行了YC伸张,必须要准备的东西还是彩条,这里称为彩条A。因为普通的彩条难以判断黑、白、红、绿、蓝的范围,所以我们用Photoshop制作一张专门用来判断颜色、亮度范围的640*480的彩条图片,保存为24bit bmp格式。彩条上半部分的颜色范围为16~240,黑白部分为16~235(601 Range)。下半部分全部为0~255(Full range),用于进行对比。
之后,使用使用以下AVS代码将bmp图片生成一个5秒钟的短片。

代码: 全选

#AVS代码1:
ImageSource ("colorbar.bmp",end=149)
AssumeFPS("ntsc_video")
将这个短片送入TMPGEnc压缩成MPEG2格式。压缩时,打开TMPGEnc的YC压缩选项,此时图像上部为30~217,下部为16~235
播放时:
  • 图像上部为30~217、下部为16~235,则没有进行YC伸张。(也就是MPEG2里面的原始数据)
  • 图像上部正常回复为601 Range、下部为Full range则判断为进行了一次YC伸张。
  • 如果上下全都变成了0~255的Full range,则是进行了两次YC伸张。
当然,只有第二种情况才是正确的。

除此之外,为了判断显卡/渲染器是否能够自动判断是否进行YC伸张,我们制作了另一个彩条,这里称为彩条B。彩条B的内容与彩条A完全一致,但是在送入TMPGEnc压缩成MPEG2格式时,关闭TMPGEnc的YC压缩选项,此时图像上部为16~235,下部为0~255
播放时:
  • 图像上部为16~235、下部为0~255,则没有进行YC伸张。(也就是MPEG2里面的原始数据)
  • 图像上下完全相同,都是0~255,则进行了至少一次YC伸张。
只有第一种情况是正确的。
因为我在学校只有一台笔记本电脑,主板集成Intel X3100显卡,所以没办法测试其他厂商的显卡效果如何,所以在测试显卡是否做了YC伸张这个环节里,结果只代表X3100。

实验进行篇
【播放TV Scale的视频(彩条A)】(我们下载到的99%的视频都是TV Scale的)
haali's video render(设置为tv scale,进行YC伸张)
Elecard(yuy2) 正确
ffdshow libmpeg2(yuy2 tv/pc) 正确
ffdshow libmpeg2(转换为rgb,设定为TV Scale,伸张) 正确
ffdshow libmpeg2(转换为rgb,设定为PC Scale,不伸张) 错误

haali's video render(设置为pc scale,不进行YC伸张)
ffdshow libmpeg2(yuy2) 错误
ffdshow libmpeg2(转换为rgb,设定为TV Scale,伸张) 错误
ffdshow libmpeg2(转换为rgb,设定为PC Scale,不伸张) 正确

覆盖合成器
ffdshow libmpeg2(yv12) 正确
ffdshow libmpeg2(转换为rgb,设定为TV Scale,伸张) 正确
ffdshow libmpeg2(转换为rgb,设定为PC Scale,不伸张) 错误

VMR9无渲染
ffdshow libmpeg2(yv12) 正确
ffdshow libmpeg2(转换为rgb,设定为TV Scale,伸张) 正确
ffdshow libmpeg2(转换为rgb,设定为PC Scale,不伸张) 错误

小结:因为片源是TV Scale的,因此播放过程中需要做一次且只能做一次YC伸张。从实验结果看出,YC伸张发生并且仅发生于YUV颜色空间到RGB颜色空间的转换过程中。因此,要不在解码器这一步伸张并转换RGB,要不在渲染器中伸张转换成RGB。
当在解码器中转换为RGB时:ffdshow中,RGB变换页里的“对比度”设置会起作用。当选择“标准”的时候做YC伸张,选择“全范围”的时候不做YC伸张。渲染器收到RGB之后会跳过YC伸张步骤。
不在解码器中转换为RGB时:当解码器输出YUV颜色空间给渲染器时(haali不吃YV12,只吃YUY2和RGB的样子),部分渲染器会将其转换为RGB颜色输出给显卡。haali好像就是这样做的,haali会根据用户设置的TV range(伸张)还是PC range(不伸张)决定是否进行伸张。覆盖合成器和VMR9的资料比较少,我不知道他们是否会将颜色空间转换为RGB,但是至少从直观看来,通过覆盖合成器和VMR9之后,都经过了YC伸张,只是不知道这个伸张是显卡做的还是合成器做的。

【播放PC Scale的视频(彩条B)】
覆盖合成器
ffdshow libmpeg2(yv12) 错误

VMR9无渲染
ffdshow libmpeg2(yv12) 错误

haali's video render(tv scale)
ffdshow libmpeg2(yuy2) 错误

haali's video render(pc scale)
ffdshow libmpeg2(yuy2) 正确

小结:自动判断是否需要YC伸张是不可能实现的?

结论篇
主要的结论在前面的小结中已经给出。尽管不同的显卡对于图像具体的处理方式不同,我们仍然有一个方法可以在所有的显卡上显示出正确的图像:将正确的RGB颜色交给显卡就可以了(尽管可能需要较高的系统配置,但大多数标清级的视频的话P4以上的CPU应该都能胜任)。因此,ffdshow解码和haali渲染着对组合不错。ffdshow输出yuy2颜色,在haali渲染器中进行YC伸张。如果实在不知所措的话,不如干脆拿彩条试一试,看看怎么能放出正确的颜色即可。
日常推 @dgwxx: 基本没什么技术的话题,欢迎没事看看消遣。
► 显示剧情透露 平庸的rip
► 显示剧情透露 “不知道”的五大理由
头像
明镜止水
帖子: 7
注册时间: 2011-04-09 1:52

Re: YC伸张与YC压缩的实验

http://www.dgwxx.net/files/colorbar_for_yc_test.m2v 這個測試影片下載鏈接已經失效,貌似是 dgwxx.net 過期了

於是自己試著重新做了一份,在 github 上開了一個 repo 供分享:
https://github.com/KagamiChan/YC_colorbar

對於沒有 git 操作經驗的同學,需要下哪個文件的話點擊文件,再點擊 raw 即可。

因為原來的製作過程的說明我有點沒理解,我個人對 TMPGEnc 也不熟,所以說說我的製作過程。在 Setting 中使用了 Automatic VBR Mode 的碼率控制模式,在 Quantize 選項卡的 special setting 處沒有勾選 Output YUV data as Basic YCbCr ont CCIR601。
mp4 製作的代碼可以見 bat 文件

如果我的製作方法有問題的話請指出

(思考再三,總覺得這種挖墳的理由應該是可以理解的吧……不行的話我另開新帖……
Je peux encore courir le monde, la pluie peut me mouiller et le soleil me brûler jusqu'à en mourir
头像
dgwxx
管理猿
帖子: 771
注册时间: 2010-09-19 20:42
联系: 网站

Re: YC伸张与YC压缩的实验

感谢楼上~
日常推 @dgwxx: 基本没什么技术的话题,欢迎没事看看消遣。
► 显示剧情透露 平庸的rip
► 显示剧情透露 “不知道”的五大理由

回到 “理论讨论 / Theoratical discussion”