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>的时候写的,记得当时还 ...
随机推荐
- SDOI2010选做
Round1 D1T1外星千足虫 \(BSOJ2793\)--高斯消元解异或方程组 简述 有\(n\)个数\(\{a_i\}\) 给出\(m\)个信息,每个信息给出\(\displaystyle{(\ ...
- [RN] React Native代码转换成微信小程序代码的转换引擎工具
React Native代码转换成微信小程序代码的转换引擎工具 https://github.com/areslabs/alita
- 写一个function,清除字符串前后的空格(兼容所有的浏览器)
function trim1(str){ return str.replace(/(^\s*)|(\s*$)/g,""); }
- TCP连接和连接释放(TCP的三次挥手和四次握手)
TCP的运输连接管理 TCP是面向连接的协议.运输连接是用来传送TCP报文的.TCP运输连接的建立和释放是每一次面向连接的通信中必不可少的过程.因此,运输连接就有三个阶段,即:连接建立.数据传送和连接 ...
- 从零和使用mxnet实现线性回归
1.线性回归从零实现 from mxnet import ndarray as nd import matplotlib.pyplot as plt import numpy as np import ...
- C语言中宏的相关知识
2019/04/27 16:02 1.宏的定义:宏定义就是预处理命令的一种,它允许用一个标识符来表示一个字符串.格式如下: #define name(宏名) stuff(字符串) 本质就是使用宏名去替 ...
- Python网络爬虫神器PyQuery的使用方法
#!/usr/bin/env python # -*- coding: utf-8 -*- import requests from pyquery import PyQuery as pq url ...
- ReentrantLock源码简析
概念 ReentrantLock,可重入锁.在多线程中,可以通过加锁保证线程安全. 加锁和解锁 加锁: public void lock() { sync.lock(); } 解锁 public vo ...
- Linux查看端口使用情况
1.netstat -tunlp,查看已使用的端口 2.netstat -tunlp | grep 8080,查询指定端口使用情况 3.netstat命令无法使用需要安装net-tools yum i ...
- ef core 全局过滤
有些固定的条件,基本每个查询的时候需要带的条件,我们可以使用全局过滤来帮我们,这样后面的查询就不用每次都带条件了. 微软自带的:https://docs.microsoft.com/zh-cn/ef/ ...