YUV视频格式详解(翻译自微软文档)
原文: 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。
此文接下来会聊聊这些话题:
- 确定DirectShow的YUV格式—解释如何描述DirectShow的YUV格式类型
- YUV采样—描述最普通的YUV采样方法
- 表面定义—描述推荐的YUV定义格式
- 颜色空间和色度采样频率转换—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种采样格式:
- 4:4:4 表示色度通道没有降采样
- 4:2:2 表示2:1的水平降采样和垂直方向没有降采样,简单的理解为采样线条里面有4个Y,2个U,2个V
- 4:2:0 表示2:1的水平和垂直方向的降采样
- 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=2192^(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视频格式详解(翻译自微软文档)的更多相关文章
- Android 音视频编解码——YUV视频格式详解
一.YUV 介绍 YUV是一种颜色编码方方式,通常由彩色摄像机进行取像,然后把取得的彩色图像信号经过分色.分别放大校正后得到RGB,再经过矩阵变换得到亮度信号Y和两个色差信号B-Y(即U).R-Y(即 ...
- 音视频编解码——YUV视频格式详解
一.YUV 介绍 YUV是一种颜色编码方方式,通常由彩色摄像机进行取像,然后把取得的彩色图像信号经过分色.分别放大校正后得到RGB,再经过矩阵变换得到亮度信号Y和两个色差信号B-Y(即U).R-Y(即 ...
- git研究详解(官网文档)及总结
前言:git作为新一代的版本控制软件,说实话比svn好用多了,个人见解,关于git的详细介绍及研究,我推荐三个地方 1.git官网上的文档(推荐UC浏览器,比火狐多个英文翻译的功能) 地址为:http ...
- FLV视频封装格式详解
FLV视频封装格式详解 分类: FFMpeg编解码 2012-04-04 21:13 1378人阅读 评论(2) 收藏 举报 flvheaderaudiovideocodecfile 目录(?)[-] ...
- PNG,JPEG,BMP,JIF图片格式详解及其对比
原文地址:http://blog.csdn.net/u012611878/article/details/52215985 图片格式详解 不知道大家有没有注意过网页里,手机里,平板里的图片,事实上,图 ...
- BMP格式详解
BMP格式详解 BMP文件格式详解(BMP file format) BMP文件格式,又称为Bitmap(位图)或是DIB(Device-Independent Device,设备无关位图),是Win ...
- java分享第十五天(log4j 格式详解)
log4j 格式详解 log4j.rootLogger=日志级别,appender1, appender2, -. 日志级别:ALL<DEBUG<INFO<WARN<ERRO ...
- php 序列化(serialize)格式详解
1.前言 PHP (从 PHP 3.05 开始)为保存对象提供了一组序列化和反序列化的函数:serialize.unserialize.不过在 PHP 手册中对这两个函数的说明仅限于如何使用,而对序列 ...
- Java字节码(.class文件)格式详解(一)
原文链接:http://www.blogjava.net/DLevin/archive/2011/09/05/358033.html 小介:去年在读<深入解析JVM>的时候写的,记得当时还 ...
随机推荐
- Git挽回错误的push(commit)
若你的(zhu)队友不小心把错误的代码提交到远程仓库,特别是包含了很多删除文件指令,不要尝试使用Git的API修改,或者删除Git仓库里的某次提交记录,风险十分大,正确的做法是备份你的本地源码,然后拉 ...
- 最短路径 | 1003 dfs 或 dij ,单源最短路径条数与经过的点权最大
这题很早之前就遇到过,是pat留给我的第一印象,然而昨天却有点写不出来.今天dfs用了10分钟不到写出来了.dij用了大约15分钟,捉虫花了一点时间. dfs: 注意剪枝的时候别剪错就行了. #inc ...
- 【BZOJ3837】[PA2013]Filary
[BZOJ3837][PA2013]Filary 题面 darkbzoj 题解 考虑到模数为\(2\)时答案至少为\(\frac n2\),这是我们答案的下界. 那么我们对于任意的一个数,它们答案集合 ...
- uiView获取指定子view
判断对象类型 -(BOOL) isKindOfClass: classObj判断是否是这个类或者这个类的子类的实例 -(BOOL) isMemberOfClass: classObj 判断是否是这个类 ...
- Java 并发系列之二:java 并发机制的底层实现原理
1. 处理器实现原子操作 2. volatile /** 补充: 主要作用:内存可见性,是变量在多个线程中可见,修饰变量,解决一写多读的问题. 轻量级的synchronized,不会造成阻塞.性能比s ...
- POI开发:Java中的Excel相关操作
一.Apache POI 1.简介: Apache POI支持大多数中小规模的应用程序开发,提供API给Java程序对Microsoft Office格式档案读和写的功能,呈现和文本提取是它的主要特点 ...
- Python(三)对装饰器的理解
装饰器是 Python 的一个重要部分,也是比较难理解和使用好的部分.下面对装饰器做一下简单整理 1. 前言 装饰器实际上是应用了设计模式里,装饰器模式的思想: 在不概念原有结构的情况下,添加新的功能 ...
- Zuul之路由熔断
Zuul作为Netflix组件,可以与Ribbon.Eureka.Hystrix等组件结合,实现负载均衡.熔断器的功能 Spring boot2X集成zuul与consul实现负载均衡和反向代理 当后 ...
- pycharm安装pytorch失败的问题
在无GPU的情况下,打算安装pytorch跑几个demo练练手,但是pycharm发现总是失败,无法安装成功.错误显示如下: 无奈之下,只能够使用官方推荐的命令pip3安装,命令如下: pip3 in ...
- 《Linux就该这么学》培训笔记_ch12_使用Samba或NFS实现文件共享
<Linux就该这么学>培训笔记_ch12_使用Samba或NFS实现文件共享 文章最后会post上书本的笔记照片. 文章主要内容: SAMBA文件共享服务 配置共享资源 Windows挂 ...