histamine
帖子: 85
注册时间: 2010-09-23 20:07

Re: x264 10bit编码推广讨论

好吧,我再做一点补充

对于Dither_convert_8_to_16().Dither_convey_yuv4xxp16_on_yvxx()输出的16bit,LSB全是0,这是一个特殊的情况,也就是说不管是直接右移6位还是使用error diffusion dither方法转换到10bit均不会产生精度损失,也不会产生banding,两者结果应该是一致的(或者说两者应该是等价的?)

现在看一下x264里面的dither算法
65 #define DITHER_PLANE( pitch ) \
66 static void dither_plane_##pitch( pixel *dst, int dst_stride, uint16_t *src, int src_stride, \
67 int width, int height, int16_t *errors ) \
68 { \
69 const int lshift = 16-BIT_DEPTH; \
70 const int rshift = 2*BIT_DEPTH-16; \
71 const int pixel_max = (1 << BIT_DEPTH)-1; \
72 const int half = 1 << (16-BIT_DEPTH); \
73 memset( errors, 0, (width+1) * sizeof(int16_t) ); \
74 for( int y = 0; y < height; y++, src += src_stride, dst += dst_stride ) \
75 { \
76 int err = 0; \
77 for( int x = 0; x < width; x++ ) \
78 { \
79 err = err*2 + errors[x] + errors[x+1]; \
80 dst[x*pitch] = x264_clip3( (((src[x*pitch]+half)<<2)+err)*pixel_max >> 18, 0, pixel_max ); \
81 errors[x] = err = src[x*pitch] - (dst[x*pitch] << lshift) - (dst[x*pitch] >> rshift); \
82 } \
83 } \
84 }
注意我标红的那行,对于我们输入的LSB全是0的16bit数据,此时计算出来的量化误差却不等于0?!
我们分析下err = src[x*pitch] - (dst[x*pitch] << lshift) - (dst[x*pitch] >> rshift)这个运算
对于输入的某个像素点,假定其值为235*2^8,右移6位转换到10bit应该是235*2^2,由于没有精度损失,也不会产生banding,所以应该没有量化误差,也就是说基于error diffusion dither方法,计算该点的量化误差应该是0
我们把235*2^8和235*2^2代入上面那个式子
err = 235*2^8 - ( 235*2^2*2^6 ) - ( 235*2^2/2^4) = -58
看出问题了吗?原本应该是0的量化误差,按照这个error diffusion dither算法算出来却是-58

这个式子的问题在于它将16bit数值量化后的10bit数值,通过(dst[x*pitch] << lshift) + (dst[x*pitch] >> rshift)再次转换到16bit,再计算和最初16bit数值差值。但是我们输入的16bit数据是通过8bit数据左移8位得到的,如果我们肯定了“8bit数据左移2位得到10bit数据”的做法是正确的,那么10bit数据到16bit数据的转换应该是左移6位。

所以我认为err = src[x*pitch] - (dst[x*pitch] << lshift) - (dst[x*pitch] >> rshift);应该改成err = src[x*pitch] - (dst[x*pitch] << lshift);
这样err = 235*2^8 - ( 235*2^2*2^6 ) = 0,符合量化误差等于0
“这样修改过后的error diffusion dither算法将LSB全是0的16bit数据转换到10bit”和”将LSB全是0的16bit数据直接右移6位转换到10bit”是等价的

当然我上面也说过了,即使不修改这个dither算法,最终结果的误差也是很小的,肉眼可能无法察觉,对于某些数据可能最终结果根本没有误差

至于16bit输入x264时到底有没有调用这个dither函数,各位可以用printf大法验证
bakabakashi
帖子: 32
注册时间: 2011-06-01 14:09

Re: x264 10bit编码推广讨论

从编码的结果来看,16bit输入时应该是有用这个dither函数的
8bit->10bit和8bit->16bit->10bit对比的话,两者有差异
但是跟histamine所说的一样"误差也是很小的,肉眼可能无法察觉"
当然为了准确的结果还是应该用printf大法验证
histamine
帖子: 85
注册时间: 2010-09-23 20:07

Re: x264 10bit编码推广讨论

现在我开始认为
dst[x*pitch] = x264_clip3( (((src[x*pitch]+half)<<2)+err)*pixel_max >> 18, 0, pixel_max );
这行也有问题,为什么要“ *pixel_max >> 18 ”,改成“ >> 8 ”行吗?似乎这样改是错的啊
{:cat_14}

或者说我们其实根本不该用目前x264里面的dither算法,应该自己再写一个?
(如果做了上面两处修改之后,和修改之前的dither算法就不一样了)
上次由 histamine 在 2011-08-08 10:52,总共编辑 2 次。
头像
06_taro
核心会员
核心会员
帖子: 998
注册时间: 2010-09-22 18:32
来自: United Kingdom
联系: 网站

Re: x264 10bit编码推广讨论

应该直接给avs写一个O10的function……
つまんねー事聞くなよ!

I, personally, for me, believe (obviously sometimes) that my OS choice is right. That's me. I'm not telling you that you should believe it. Learn the facts, and the origins behind the facts, and make up your own damn mind. That's why you have one. (source)

Follow me: @06_taro

304——
为纪念伟大的宇宙史上最强压制304先生,联合国教科文组织决定,将每年的第304天,即平年的10月31日或者闰年的10月30日,定为世界304日。
histamine
帖子: 85
注册时间: 2010-09-23 20:07

Re: x264 10bit编码推广讨论

06_taro 写了:应该直接给avs写一个O10的function……
求思路

好吧,我想到一个思路
先计算出10bit数据,然后左移6位到16bit,输出给x264,在x264内部右移6位,得到我们之前计算出来的10bit数据

这样就避免了由于我们对“dither”理解不同引发的一系列问题 {:cat_16}
头像
SAPikachu
帖子: 192
注册时间: 2011-02-28 19:55
联系: 网站

Re: x264 10bit编码推广讨论

06_taro 写了:应该直接给avs写一个O10的function……
直接O10看起来不可能,x264内部总是会先把源先转到16,然后路径又一样了。所以还是得直接改源代码。
T: @SAPikachu
histamine
帖子: 85
注册时间: 2010-09-23 20:07

Re: x264 10bit编码推广讨论

histamine 写了:现在我开始认为
dst[x*pitch] = x264_clip3( (((src[x*pitch]+half)<<2)+err)*pixel_max >> 18, 0, pixel_max );
这行也有问题,为什么要“ *pixel_max >> 18 ”,改成“ >> 8 ”行吗?
验证了一下,这个改法是有问题的(仅指“ *pixel_max >> 18 ”改成“ >> 8 ”),所以可以无视我说的这段话(关于“ *pixel_max >> 18 ”改成“ >> 8 ”的那段话)
上次由 histamine 在 2011-08-08 11:27,总共编辑 1 次。
akiduki
核心会员
核心会员
帖子: 32
注册时间: 2010-09-19 22:32

Re: x264 10bit编码推广讨论

06_taro 写了: 是的,其实看709的时候我也纠结了半天到底是不是和601一样是指直接<<2,不过我觉得应该不会是在两位LSB上补什么其他数据吧= =
如果理解成另一种,就是把原8-bit数据的低2位加回来,也恰好会发生235->943的问题,只不过这个原因是因为第二位也是11-_-

搞不清楚709在这么重要的地方用这样一句恶心的带着歧义的文字,而且这句话造成的歧义还能让自己扇自己嘴巴,果然德法佬弄出来的所谓标准就是千疮百孔。
头像
dgwxx
管理猿
帖子: 771
注册时间: 2010-09-19 20:42
联系: 网站

Re: x264 10bit编码推广讨论

像AU似的,做成那种无关range的计算不行么……
http://www.nmm-hd.org/bbs/thread-1035-1-1.html
日常推 @dgwxx: 基本没什么技术的话题,欢迎没事看看消遣。
► 显示剧情透露 平庸的rip
► 显示剧情透露 “不知道”的五大理由
头像
06_taro
核心会员
核心会员
帖子: 998
注册时间: 2010-09-22 18:32
来自: United Kingdom
联系: 网站

Re: x264 10bit编码推广讨论

SAPikachu 写了: 直接O10看起来不可能,x264内部总是会先把源先转到16,然后路径又一样了。所以还是得直接改源代码。
输入10bit输出也是10bit还要做转换的话就不可理喻了……
つまんねー事聞くなよ!

I, personally, for me, believe (obviously sometimes) that my OS choice is right. That's me. I'm not telling you that you should believe it. Learn the facts, and the origins behind the facts, and make up your own damn mind. That's why you have one. (source)

Follow me: @06_taro

304——
为纪念伟大的宇宙史上最强压制304先生,联合国教科文组织决定,将每年的第304天,即平年的10月31日或者闰年的10月30日,定为世界304日。

回到 “视频编码器 / Video encoder discussion”