第一点我保留自己的观点,持怀疑态度。akiduki 写了:1. 你看清楚,我说的是8->16没有问题。
2. 8->10的转换确实有问题,但和dither_plane没有关系。请你再读一遍dither_plane里面你应用的那句注释。
3. 我不知道avs变相输出16-bit给x264会是什么样的路径,看上去会走dither_plane吧。avs输出16-bit的那个trick我没仔细研究过。再者,16-bit的limited range YUV是什么样的nominal peak可没标准定义。所以这里本身就是个问号。
4. madshi用的是full range RGB,不是YUV,别看错了。
5. madshi提出的banding问题,本身的问题提出就是错的。而且在他推崇的直接左移两位的方法(也是MSDN的方法)中也存在,你自己算下就知道了。
这不奇怪,原本8-bit的unit(1) value差,转换成>8bit后差值应该大于1,而大于1并不等于出现了gradient的增加(banding)。8bit原有的dynamic,提高bitdepth后应该保持(不可能增加,这样就违背信息论了。dithering另当别论。)才对。
就像你考试得了10分中的9分,我得了8.5分;换成百分制后你是90我是85,那你能说换了百分制后我和你之间的分差增大了么?
第二点我认同,我说的是“16bit输入x264时的16bit->10bit的dither”和“8bit输入时发生在x264内部的8bit->16bit->10bit转换,无涉及dither路径”,这点上我们达成一致看法
第三点最终输出的是10bit,BT.709标准里定义了10bit的nominal peak,至少这是可以肯定的
第四点和第五点认同,再次达成一致看法。
于是现在需要关注的是如何修改libswscale和x264的depth filter,做正确的8bit->10bit转换以及16bit->10bit的dither?
Update:
十分制转换到百分制的例子,衡量两个情况下差距时应该将差值标准化后才能比较,比如将十分制下差距0.5除以10和百分制下5除以100比较,得出结果是差距是相同的。
对于madshi举的例子:
8bit full-range RGB data:
60, 61, 62, 63, 64, 65, 66, 67
10bit full-range RGB data, upscaled with x264:
240, 244, 248, 252, 257, 261, 265, 269
原先8bit下相邻数字间相差均为1
用x264目前的算法转换到10bit后,(257-252=)5,而(269-265)=(265-261)=(261-257)=(252-248)=(248-244)=(244-240)=4?!
如果按照Y = X*(2^8+1)或者Y = X*2^8将8bit数值X转换到16bit数值Y
对于8bit数值序列60, 61, 62, 63, 64, 65, 66, 67
按照Y = X*(2^8+1)转换后为
15420,15677,15934,16191,16448,16705,16962,17219
相邻数值相差为(2^8+1)
按照Y = X*2^8转换后为
15360,15616,15872,16128,16384,16640,16896,17152
相邻数值相差2^8
唯一的区别是
按照Y = X*(2^8+1)转换后,16bit数值Y范围是0 ~ (2^16-1)
按照Y = X*2^8转换后,16bit数值Y范围成了0 ~ (2^16-2^8)
那么将差值标准化,(2^8+1)/(2^16-1)等于2^8/(2^16-2^8)等于1/(2^8-1),差距相等
然后对于两种方法得到的16bit数值序列同时使用右移6位转换到10bit
左移8位加原数值,然后再右移6位:
240,244,248,252,257,261,265,269
左移8位,然后再右移6位(等同于左移2位):
240,244,248,252,256,260,264,268
前者产生了banding,后者无banding,是我理解错了吗,还是大大您错了?
如果我没算错的话,使用x264目前的dither算法将
15420,15677,15934,16191,16448,16705,16962,17219
转换到10bit,结果是
241,245,249,253,257,261,265,269
无banding
对于limited range按BT.709标准
8bit 16-235 16-240
10bit 64-940 64-960
(940-64)/(235-16)=(960-64)/(240-16)=2^2
所以我认为按照BT.709标准limited range YUV 8bit转换到limited range YUV 10bit应该直接左移2位
如果我没算错的话,对于目前x264里面的dither算法,如果将235*(2^8+1)转换到10bit,结果是943
如果将235*2^8转换到10bit,结果是940或939,会有误差
如果将errors[x] = err = src[x*pitch] - (dst[x*pitch] << lshift) - (dst[x*pitch] >> rshift);
改成errors[x] = err = src[x*pitch] - (dst[x*pitch] << lshift);
再将235*2^8转换到10bit,结果是940
有错误,请仔细阅读后指出