原文: https://docs.microsoft.com/en-us/previous-versions/aa904813(v=vs.80)

YUV视频格式详解(翻译自微软文档)
https://blog.csdn.net/qq_36006553/article/details/52389592


Video Rendering with 8-Bit YUV Formats

Gary Sullivan 和 Stephen Estrop
微软数字媒体部门
四月 2002年
更新于 八月 2003 年

摘要:此文描述了在windows操作系统上推荐的视频格式----8位的YUV,此文同时也展示了YUV和RGB格式的互相转换计算方法,提供了上采样YUV的方法。这篇文章的适用人群是从事于YUV视频显示和编码的开发人员。

介绍:在整个视频行业里面,YUV定义有很多种类。此文讲解的是微软推荐的适用于windows操作系统的YUV格式。同时,解码器供应商和显示器供应商都是被鼓励支持文中所提到的YUV格式。本文并没有解决YUV彩色的其他用途,如静止摄像。

本文中描述的格式是使用8位像素去编码Y通道(也称为亮度通道)和每个样本使用8位编码U或者V色度通道。然而,大多数的YUV格式并没有24位像素,因为它们含有较少的U或V通道数据,相比Y通道而言。

为了此文章后目的表述,术语U相当于Cb,术语V相当于Cr。

此文接下来会聊聊这些话题:

  1. 确定DirectShow的YUV格式—解释如何描述DirectShow的YUV格式类型
  2. YUV采样—描述最普通的YUV采样方法
  3. 表面定义—描述推荐的YUV定义格式
  4. 颜色空间和色度采样频率转换—RGB和YUV的互相转换

确定DirectShow的YUV格式

本文指定的YUV格式都是4字节,一个4字节代码是一个32位的无符号整型数据,它包含了4个人ASCII字符。
有许多的C/C++的四字节宏定义使得它的能够更加简单的描述。下面是简单的代码

DWORD fccYUY2 = MAKEFOURCC('Y','U','Y','2');
DWORD fccYUY2 = FCC('YUY2');
//解释一下,FCC就是自定义的一个宏。使得上面的两行代码是一个意思。
//下面还有一句更加简单的,也是一个意思
DWORD ffcYUY2 = '2YUY'
//这行代码中,我们发现YUY2发生了位置反转。这是由于windows操作系统采用了小端模式架构
  • 在ASCII中,‘Y’=0x59 ‘U’=0x55 ‘2’=0x32,于是可以得到:

‘2YUY’ = 0x32595559

在DirectShow中,格式定义的主要类型是全局唯一标识符和二级全局唯一标识符。由于主要是类型是计算机视频媒体格式,其二级全局唯一标识符可以由4字节代码映射构建。

xxxxxxxx-0000-0010-8000-00AA00389B71
其中的xxxxxxxx代表4字节代码,因此YUY2可以表示为:
32595559-0000-0010-8000-00AA00389B71

这个部分本来还有代码展示的,非YUV视频开发人员就忽略吧。文章最后会附上英文原文地址,有兴趣可以自行阅读。

YUV采样

YUV的优点在于:色度和亮度隔离,并且色度采样频率低于Y通道的,也不会导致图像质量的剧烈下降。
为了简化表达方式,符号A:B:C表示Y:U:V,可以理解为:U和V相对于Y的比例。

总共有4种采样格式:

  1. 4:4:4 表示色度通道没有降采样
  2. 4:2:2 表示2:1的水平降采样和垂直方向没有降采样,简单的理解为采样线条里面有4个Y,2个U,2个V
  3. 4:2:0 表示2:1的水平和垂直方向的降采样
  4. 4:1:1 表示4:1的水平降采样和没有垂直降采样,简单理解为采样线条里面有4个Y,1个U,1个V

下面用图形完成4种格式的理解:
亮度用叉来表示,色度则用圈表示。

第一、4:4:4格式

图1. 4:4:4

第二、4:2:2

图2. 4:2:2

第三、4:2:0
这里有两种常见的变化形式,其中一种形式用于 MPEG-2 视频,另一种形式用于 MPEG-1 以及 ITU-T recommendations H.261 和 H.263。图 3 显示了 MPEG-1 方案中使用的采样网格,图 4 显示了 MPEG-2 方案中使用的采样网格。


图3. 4:2:0


图4. 4:2:0

表面定义

本节讲述推荐用于视频呈现的 8 位 YUV 格式。这些格式可以分为几个类别:

4:4:4 格式,每像素 32 位

4:2:2 格式,每像素 16 位

4:2:0 格式,每像素 16 位

4:2:0 格式,每像素 12 位

首先,您应该理解下列概念,这样才能理解接下来的内容:
1、表面原点。对于本文讲述的 YUV 格式,原点 (0,0) 总是位于表面的左上角。
2、跨距。表面的跨距,有时也称为间距,指的是表面的宽度,以字节数表示。对于一个表面原点位于左上角的表面来说,跨距总是正数。
3、对齐。表面的对齐是根据图形显示驱动程序的不同而定的。表面始终应该 DWORD 对齐,就是说,表面中的各个行肯定都是从 32 位 (DWORD) 边界开始的。对齐可以大于 32 位,但具体取决于硬件的需求。
4、打包格式与平面格式。YUV 格式可以分为打包 格式和平面 格式。在打包格式中,Y、U 和 V 组件存储在一个数组中。像素被组织到了一些巨像素组中,巨像素组的布局取决于格式。在平面格式中,Y、U 和 V 组件作为三个单独的平面进行存储。

4:4:4 格式,每像素 32 位
这是一个打包格式,其中每个像素都被编码为四个连续字节,其组织顺序如下所示。

4:2:2 格式,每像素 16 位,支持两个 4:2:2 格式如下:
YUY2
UYVY
这两个都是打包格式,其中每个像素都是编码为四个连续字节的两个像素。这样会使得色度水平下采样乘以系数 2。

YUY2 内存布局


UYVY 内存布局

4:2:0 格式,每像素 16 位,支持两个 4:2:0 格式如下:
IMC1
IMC3
这两个都是平面格式,色度频道在水平方向和垂直方向上都要以系数 2 来进行再次采样。

对于IMC1而言,V和U都必须和Y的水平对齐,于是就出现了未使用的Space区域。

IMC1 内存布局


IMC3 内存布局

4:2:0 格式,每像素 12 位,支持四个 4:2:0 格式如下:
IMC2
IMC4
YV12
NV12
在所有这些格式中,色度频道在水平方向和垂直方向上都要以系数 2 来进行再次采样。

对于IMC2而言,此格式与 IMC1 相同,只是 V (Cr) 和 U (Cb) 行在半跨距边界处进行了交错。每一行都是以V开头,然后在每一行的交界处U再开始存储。

IMC2 内存布局

对于IMC4而言,与IMC2是一样的。只是U和V的位置换了而已。

IMC4 内存布局

在YV12中,U和V的平面跨度只有Y的一半。

YV12 内存布局

对于NV12格式而言,组合的 U-V 数组被视为一个由 little-endian(小断) WORD 值组成的数组时,LSB 包含 U 值,MSB 包含 V 值。

NV12 内存布局

RGB和YUV的互相转换

我们首先描述了RGB和YUV4:4:4格式之间的转换。为了把4:2:2或者4:2:0转换为RGB格式,我们一般是把它们转换为4:4:4以后,然后把4:4:4格式转换为RGB。这个4:4:4的YUV格式,为每个Y、U和V都采用8为数据。在其他的应用里面,也可以使用超过8位的来表示YUV格式。

从RGB转换到两个主要的YUV格式都是为数字视频而定义的。这两个都是基于ITU-R所推荐的BT.709。第一个转换可以称之为老的YUV,基于BT.709的50Hz,它和ITU-R推荐的BT.601是一样的,他有一个旧称----CCIR601。这种格式更加适用于标清及以下分辨率的电视视频。它有两个特征常量:

Kr = 0.299
Kb = 0.114

第二个转换可以称之为新的YUV,基于BT.709的60Hz,这种格式更加适用于标清分辨率以上的电视视频。它也有两个特征常量:

Kr = 0.2126
Kb = 0.0722

接下来就是RGB转换为YUV的定义:

//常数L
L = Kr * R + Kb * B + (1 – Kr – Kb) * G
//Y分量
Y = floor(2^(M-8) * (219*(L–Z)/S + 16) + 0.5)
//U分量
U = clip3(0, 2^M-1, floor(2^(M-8) * (112*(B-L) / ((1-Kb)*S) + 128) + 0.5))
//V分量
V = clip3(0, 2^M-1, floor(2^(M-8) * (112*(R-L) / ((1-Kr)*S) + 128) + 0.5))

上面变量以及函数定义解释:
M : YUV样本的位数
Z : 黑色的值,对于计算机RGB,Z=0;对于电视视频RGB,Z=162^(N-8),这里的N代表电视视频RGB每个分量的位数。
S : 缩放比例,对于计算机RGB,S=255;对于电视视频RGB,S=219
2^(N-8),这里的N同上。

函数floor(x)表示返回大于或者等于x的最大整数。
函数clip3(x,y,z)定义如下:

clip3(x, y, z) = ((z < x) ? x : ((z > y) ? y : z))

这个Y分量代表亮度,U和V分别代表色差里面的blue和red。下面只YUV三个分量的范围:

16*2^(M-8) ≤ Y ≤ 235*2^(M-8)//左边代表黑色,右边代表白色

16*2^(M-8) ≤ U ≤ 240*2^(M-8)

16*2^(M-8) ≤ V ≤ 240*2^(M-8)

这三个范围只是理论上的范围。实际上的值往往会超过这个范围。

如果输入数据是计算机RGB格式,那么这个clip3函数是无效的。
如果输入数据是电视视频RGB格式,clip3函数是为了保证U和V的值在0~ 2^M-1之间。

接下来会有2个转换公式:

RGB888转换到YUV4:4:4
如果是计算机RGB输入,YUV4:4:4输出,那么上面的公式可以近似简化为:

Y = ((66 * R + 129 * G +  25 * B + 128) >> 8)+16
U = ((-38 * R - 74 * G + 112 * B + 128) >> 8)+128
V = ((112 * R - 94 * G - 18 * B + 128) >> 8)+128

YUV4:4:4转换到RGB888

//第一步:
Y = round( 0.256788 * R + 0.504129 * G + 0.097906 * B) + 16
U = round(-0.148223 * R - 0.290993 * G + 0.439216 * B) + 128
V = round( 0.439216 * R - 0.367788 * G - 0.071427 * B) + 128 //第二步
C = Y - 16
D = U - 128
E = V - 128 //第三步
R = clip(round(1.164383*C+1.596027*E ))
G = clip(round(1.164383*C-(0.391762*D)-(0.812968 * E)))
B = clip(round(1.164383*C+2.017232*D)) //第四步,上面的公式可以近似为下面公式
R = clip(( 298 * C + 409 * E + 128) >> 8)
G = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8)
B = clip(( 298 * C + 516 * D + 128) >> 8)

YUV视频格式详解(翻译自微软文档)的更多相关文章

  1. Android 音视频编解码——YUV视频格式详解

    一.YUV 介绍 YUV是一种颜色编码方方式,通常由彩色摄像机进行取像,然后把取得的彩色图像信号经过分色.分别放大校正后得到RGB,再经过矩阵变换得到亮度信号Y和两个色差信号B-Y(即U).R-Y(即 ...

  2. 音视频编解码——YUV视频格式详解

    一.YUV 介绍 YUV是一种颜色编码方方式,通常由彩色摄像机进行取像,然后把取得的彩色图像信号经过分色.分别放大校正后得到RGB,再经过矩阵变换得到亮度信号Y和两个色差信号B-Y(即U).R-Y(即 ...

  3. git研究详解(官网文档)及总结

    前言:git作为新一代的版本控制软件,说实话比svn好用多了,个人见解,关于git的详细介绍及研究,我推荐三个地方 1.git官网上的文档(推荐UC浏览器,比火狐多个英文翻译的功能) 地址为:http ...

  4. FLV视频封装格式详解

    FLV视频封装格式详解 分类: FFMpeg编解码 2012-04-04 21:13 1378人阅读 评论(2) 收藏 举报 flvheaderaudiovideocodecfile 目录(?)[-] ...

  5. PNG,JPEG,BMP,JIF图片格式详解及其对比

    原文地址:http://blog.csdn.net/u012611878/article/details/52215985 图片格式详解 不知道大家有没有注意过网页里,手机里,平板里的图片,事实上,图 ...

  6. BMP格式详解

    BMP格式详解 BMP文件格式详解(BMP file format) BMP文件格式,又称为Bitmap(位图)或是DIB(Device-Independent Device,设备无关位图),是Win ...

  7. java分享第十五天(log4j 格式详解)

    log4j 格式详解  log4j.rootLogger=日志级别,appender1, appender2, -. 日志级别:ALL<DEBUG<INFO<WARN<ERRO ...

  8. php 序列化(serialize)格式详解

    1.前言 PHP (从 PHP 3.05 开始)为保存对象提供了一组序列化和反序列化的函数:serialize.unserialize.不过在 PHP 手册中对这两个函数的说明仅限于如何使用,而对序列 ...

  9. Java字节码(.class文件)格式详解(一)

    原文链接:http://www.blogjava.net/DLevin/archive/2011/09/05/358033.html 小介:去年在读<深入解析JVM>的时候写的,记得当时还 ...

随机推荐

  1. 【oracle】截取字符串

    select id,name,substr(dept,1,2) from test; 提取字段dept前两位 substr(string,start,length)

  2. 第05组 Beta冲刺(4/4)

    第05组 Beta冲刺(4/4) 队名:天码行空 组长博客连接 作业博客连接 团队燃尽图(共享): GitHub当日代码/文档签入记录展示(共享): 组员情况: 组员1:卢欢(组长) 过去两天完成了哪 ...

  3. nginx 动静分离之 tomcat

    配置文件示例 server { listen ; server_name www.xxx.com; location ~* "\.(jpg|png|jepg|js|css|xml|bmp|s ...

  4. ROS+gre over ipv6,在ipv6的基础上建立GRE隧道

    感谢群众大神 @镜花水月全程技术支持.感谢! 环境: 1.阿里云华北5,申请ipv6测试,申请ECS带ipv6公网ip 2.为了便于测试便捷,在vultr创建2.5美元的vps,带ipv6 对了,测试 ...

  5. jiagu-工具使用

    比较好的一套处理工具吧,感谢作者,原文地址:https://github.com/ownthink/Jiagu 练习一下使用 """ Funciton: jiagu测试 ...

  6. @Import导入自定义选择器

    @Import导入自定义选择器 之前一篇博文:Spring中的@Import注解已经详细介绍了@Import注解,不赘述. 需求描述 通过@import注解自定义组件选择器,将满足我们自定义的规则的b ...

  7. thinkPHP5如何使用rabbitmq

    thinkPHP5如何使用rabbitmq? 安装好 tp5 的 rabbitmq 扩展后,在项目根目录文件添加文件 rabbitmq.php 引导启动 rabbitmq. <?php defi ...

  8. Python3+syslog使用及相关说明

    一.说明 1.1 背景说明 syslog这个东西,最早接触是在Z公司做基线安全加固的时候有启用远程日志服务器一项,然后当时还写整理了一篇“rsyslog+loganalyzer远程日志系统搭建教程(C ...

  9. 【转帖】威盛x86 AI处理器架构、性能公布:媲美Intel 32核心

    威盛x86 AI处理器架构.性能公布:媲美Intel 32核心 https://www.cnbeta.com/articles/tech/920559.htm 除了Intel.AMD,宝岛台湾的威盛也 ...

  10. 【C语言】获得数组长度

    c语言中,定义数组后可以用sizeof命令获取数组的长度(可容纳元素个数): 如: { int data[5]; int length; length=sizeof(data)/sizeof(data ...