10Bit 色彩 数字视频编码

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

10Bit 色彩数字视频编码
根据我最近研究高清播放的经验,得出了以下结论,如果有说的不对的欢迎指出。

有关整个视频处理过程的颜色问题,水很深。

首先是目前视频本身的色系一般用的是YUV,而不是显示器输出使用的RGB。

因为色度抽样(Chroma subsampling)用的是Y:Cb:Cr=4:2:0(YUV色系中,Y为亮度通道,Cb和Cr 为色差通道信号),亮度抽取样(Luma subsample)和色度抽样不平衡,所以可以节省一半的空间,而只有4:4:4才是完整的色度取样。

引用一段百科:“4:2:0并不意味着只有Y,Cb而没有Cr分量。

它指得是对每行扫描线来说,只有一种色度分量以2:1的抽样率存储。

相邻的扫描行存储不同的色度分量,也就是说,如果一行是4:2:0的话,下一行就是4:0:2,再下一行是4:2:0...以此类推。

对每个色度分量来说,水平方向和竖直方向的抽样率都是2:1,所以可以说色度的抽样率是4:1。

PAL制式和SECAM制式的色彩系统特别适合于用这种方式来存储。

绝大多数视频编解码器都采用这种格式作为标准的输入格式。

对非压缩的8比特量化的视频来说,每个由2x2个2行2列相邻的像素组成的宏像素需要占用6字节内存。


而视频目前所使用的色深(Bit Depth)是8bit,也就是Y、Cb、Cr每个通道使用8bit存储信息,又由于4:2:0抽样,一个像素点占用8bit×3/2=12bit数据量。

8bit的色深意味着Y、Cb、Cr每个通道可以取值0-255(2^8个),这个是全范围(Full Range);而目前视频里使用的都是有限范围(Limited Range或601 Range),Y取16-235、Cb和Cr取16-240。

这个就是指输入级别(Input Level)。

H.264压缩的视频经过视频解码器(Video Decoder)解码以后生成了8bit的YUV(4:2:0)的图像,然后输出时会需要一个输出色系,主要有平面YUV:YV12、NV12等,压缩YUV:YUY2、UYVY等,RGB:RGB32、RGB24等。

通常视频解码器会输出YV12。

视频解码器已经将YV12的图像交给了视频渲染器(Video Renderer),视频渲染器负责将视频从YV12转换为RGB然后输出最后的画面(给显卡,显卡再将画面输出至显示器),首先最后输出的RGB通常是8bit色深,而且对于RGB肯定是4:4:4的全采样模式,RGB32就是红绿蓝各8bit,剩下一个不使用的通道占8bit,另外一种叫ARGB32,最后这个通道就是Alpha通道(透明通道)。

从YV12到RGB的过程就存在2个问题,第一个是转换矩阵,目前主要使用的YCbCr规范有2种:ITU-R BT.601和ITU-R BT.709。

这2种转换矩阵会产生不同的结果,如果一个RGB视频源使用ITU-R BT.601转换为YUV然后进行编码,那么最后解码以后也要用ITU-R BT.601将其转换成RGB,对于ITU-R BT.709也是一样的道理,如果最后解码时用了错误的转换矩阵,就会出来错误的颜色。

ITU-R BT.601主要是在标清时代所采用,包括DVD、NTSC、PAL和SDTV之类的;而高清视频,包括BD和HDTV以及各种高清的重编码,多数都是使用ITU-R BT.709。

但也可能存在少数例外,解码这些例外时就很容易因为使用了错误的转换矩阵而得出错误的颜色。

比如AIR的BD就存在一定争议,这个BD用了MPEG-2编码,是从DVD的标清视频直接upconv上来的,分辨率是1920x1080,帧模式十分混乱,各种24t、30i、30p混杂在一起。

如果从它是DVD upconv来看,应该是用BT.601,但是BD/高清视频应该是普遍使用BT.709的,所以它到底是什么,还真的说不清楚。

第二个问题是输出级别(Output Level),决定转换后的RGB的每个通道的范围。

一般有2种,Full Range的电脑显示器(RGB:16-255),Limited Range的电视机(RGB:16-235),但是现在有不少电视机也是支持0-255的全范围输入的,所以需要有正确的判断。

而且电视机的画面的设置调整也很重要,需要配合Super HiVi CAST一类的调整视频来调出正确的黑位和白位。

将Limited Range转换至Full Range的RGB,这个过程可以称作YC伸张,反过来的话就是YC压缩。

在高清播放中这个很关键,一般如果输入是Limited Range,而你输出的设备支持Full Range,那要做1次YC伸张;如果输出设备是Limited Range或者输入是Full Range,那么就不需要做YC伸张。

而可以做YC伸张的东西有视频解码器、视频渲染器、播放器的Shader后处理、显卡,所以控制好他们最后做的YC伸张的次数成了一个关键。

幸好现在Win7下EVR一般会对YV12输入做一次YC伸张,对RGB32输入不做改变,而显卡通常不去做改变,所以还是比较容易控制的,以前XP系统时用VMR7/9作渲染器,就很容易碰到黑位不正的问题,往往就是YC伸张没做对。

引用一段六维的zfylich写的教程:
TV/PCRange:TVrange -> PC Range称之为YC伸张;
提到这个主要涉及一个YC压缩和伸张的过程,该过程出现来自于BT.601和BT.709(601标准的高清版)标示颜色的可取数值与实际可取数值的偏差导致。

在601标准中,YC的每个通道可取值并没有256个,对色度通道,可取值是16-240,对亮度通道,可取值只有16-235,这么设计是考虑到了模拟信号传输过程中的过冲效应(Gibbs效应);值得注意的是,在电脑播放的过程中,使用的是每个通道0-255都是可取的full range,那么从601色彩标准到full range的过程就是一个将16-235(或16-240)伸张到0-255的过程,这个过程一般称为YC伸张,那么其逆过程YC压缩也就可以理解了。

而现在10bit的视频开始普及(由于支持10bit H.264解码的解码器变多了),输入级别大大扩展,所以从根源上减轻了banding(色彩平滑过渡区域由于可用颜色数量不够产生的色带)的产生,并加强了画面暗场的还原能力,具有更高的动态范围和色彩数量。

Now let's check what the BT.709 specification says:
Black level, 8bit: 16, 10bit: 64
Achromatic, 8bit: 128, 10bit: 512
Nominal peak, 8bit: 235, 10bit: 940
也就是BT.709规定,10bit下的Y通道范围是64-940,512为中值(中灰)。

Cb、Cr通道范围是64-960,512为中值。

而我也见到有些视频使用了Full Range(0-255)的YUV编码。

也提出了用全采样的4:4:4的YUV进行编码,甚至说既然都用4:4:4了,那就直接用RGB来编码视频,省去了在RGB和YUV 之间互相转换带来的各种画面损失和各种问题。

不过还是任重而道远,这些不光考验编码器和压制的人,也考验播放器及各种解码器、渲染器,还包括显卡、显示线和显示设备的支持程度。

总结一下,有关高清播放方面,要能正确地还原出视频信息,需要能支持并正确判断其使用的色深(8bit、10bit,以后还会更高),能支持并正确判断Limited Range和Full Range的YUV输入,能支持并正确判断4:2:0和4:4:4的YUV输入,能正确判断使用何种转换矩阵(BT.601还是BT.709),判断转换后的RGB是使用Limited Range还是Full Range(这点要靠人自己根据显示设备去决定,播放器没有能力判断),然后根据判断的结果做正确的YC伸张,如果是10bit视频,转换后的RGB能够保持10bit并且一路输出给显示设备。

这里还有很多难点依然无法比较方便地去实现(一些规格比现在普遍的情况要先进很多),只有不断努力去完善了。

有关10bit视频的讨论,详见:/newbbs/viewtopic.php?f=8&t=319还有国外的CCCP论坛:/forums/
另外关于BT.601和BT.709转换也存在一些另类的问题,就是诸如DirectVobSub这种字幕滤镜,它使用的是BT.601,但是高清视频最后在渲染器端是用BT.709转换的,所以色彩就出现了问题。

解决方法之一是在ffdshow这种视频解码器里就强制转换为RGB32输出,然后字幕再被加入视
频画面里,已经是RGB,在渲染器里就不需要再经过转换,最后可以输出正确的颜色。

详情见:/newbbs/viewtopic.php?f=8&t=319&start=60
现在有关8bit到10bit的转换问题讨论很多,现在x264所使用的libswscale做的是将8bit 左移8位再加上这8bit得到对应的16bit采样的数据,然后再右移6位得到10bit的数据。

例如原始一个8bit数据为10110110(182),转成16bit得到10110110 10110110(46774),再转成10bit得到10110110 10(730)
但是madVR的作者madshi认为应该直接将8bit左移2位得到对应的10bit数据。

例如原始一个8bit数据为10110110(182),转成10bit得到10110110 00(728),得到了与libswscale 不一样的结果。

madshi指出libswscale现在使用的方法会造成量化误差,由于16bit到10bit的过程直接舍弃了最后6bit而又没做dither(抖动),导致转换后的梯度是不平滑的,如下所示:
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
252, 257这2个之间就相差了5
所以madshi认为应该宁可舍弃一小部分动态范围,直接将8bit数据左移2位得到10bit,能保证无损失的平滑转换。

经过一番讨论后,x264的主要编写人员Dark Shikari也察觉到了问题,说可能所有x264所使用的libswscale需要重新编写了。

doom9上原始的讨论在这里:/showthread.php?p=1517620
补充一下:根据06_taro菊苣的解释,现在认为对于Limited Range,BT.709里有明确的规定,就是通过左移2位的方式进行8bit到10bit的转换(相当于十进制的数据乘以4);而对于Full Range,并无这样的规定,所以并不明确,但是madshi所认为的对这也采用左移2位的方式是错误的,应该采用8bit-->16bit然后再dither(抖动)成10bit的方式转换。

所以技术和应用是相互推动与发展的,10bit的突然普及也让我们发现了许多问题,并且尝试去解决,而各种开源的编/解码器也都在不断完善对10bit的支持,相比于那些封闭的商业软件,开源社区的力量是强大的。

而直到上个月,国内许多大字幕组才开始舍弃使用rmvb,这让我们看到了巨大的差距,一方面已经开始推动10bit H.264的普及,一方面连rmvb都还没放弃使用。

rmvb这种封闭的格式(已经至少6年没有发展过了)相比x264这种开源编码器(每几天就更新一次)所得到的视频不论从哪方面看都是远远比不上的。

相关文档
最新文档