视频帧
对于视频,我们都知道是由一系列的画面在一个较短的时间内(通常是 1/24 或 1/30 秒)不停地下一个画面替换上一个画面形成连贯的画面变化。这些画面称之为视频帧。
对于视频帧,在现代视频技术里面,通常都是用 RGB 颜色空间或者 YUV 颜色空间的像素矩阵来表示。在 ffmpeg 里面,我们可以看到源码 libavutil/pixfmt.h 中定义了一系列像素格式,绝大部分都是 RGB 和 YUV 颜色空间类型的。
enum AVPixelFormat {
// ... 省略部分不怎么重要的类型
///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
AV_PIX_FMT_YUV420P,
///< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
AV_PIX_FMT_YUYV422,
///< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
AV_PIX_FMT_YUV422P,
///< packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
AV_PIX_FMT_UYVY422,
///< planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
AV_PIX_FMT_YUV444P,
///< planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
AV_PIX_FMT_YUV440P,
///< packed RGB 8:8:8, 24bpp, RGBRGB...
AV_PIX_FMT_RGB24,
///< packed RGB 8:8:8, 24bpp, BGRBGR...
AV_PIX_FMT_BGR24,
///< packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
AV_PIX_FMT_ARGB,
///< packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
AV_PIX_FMT_RGBA,
///< packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
AV_PIX_FMT_ABGR,
///< packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
AV_PIX_FMT_BGRA,
///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), big-endian
AV_PIX_FMT_RGB565BE,
///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), little-endian
AV_PIX_FMT_RGB565LE,
///< packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), big-endian , X=unused/undefined
AV_PIX_FMT_RGB555BE,
///< packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), little-endian, X=unused/undefined
AV_PIX_FMT_RGB555LE,
///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), big-endian
AV_PIX_FMT_BGR565BE,
///< packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), little-endian
AV_PIX_FMT_BGR565LE,
///< packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), big-endian , X=unused/undefined
AV_PIX_FMT_BGR555BE,
///< packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), little-endian, X=unused/undefined
AV_PIX_FMT_BGR555LE,
}
每个类型的注释开头要么是 packed
要么是 planar
,YUV 类型后跟着三个数字 4:2:0、4:2:2、4:4:4 等等,这些都表示什么?带着这些疑问,开始搜索资料研究学习 RGB 和 YUV 颜色空间相关和像素格式的概念。
RGB 和 YUV
RGB 和 YUV 都是颜色空间的一种。RGB 是目前运用最广的颜色系统之一,在现代显示器上基本都是采用 RGB 颜色标准。RGB 的原理是把颜色分为红、绿、蓝三个通道,每个通道按照不同比例混合来描述一个颜色。YUV 是用一个 亮度 分量和两个 色度 分量来描述一个颜色,Y 表示亮度,U和V 表示色度。YUV 的最大特点是将亮度信息和色彩信息分离,没有了色彩信息依旧可以显示一张完整的黑白图片。
RGB
对于前端开发者来说,在 CSS 中经常会用到 RGB 或 RGBA 的颜色数值,RGB 格式非常好理解,R、G、B 分别表示红绿蓝三个通道的值。RGB 格式根据存储的位数可以分为 16 位格式 、 24 位格式 和 32 位格式。在 FFmpeg 的源码中也可以看到 16bpp、24bpp 和 32bpp 的注释说明。(因为内存的字节顺序有大端序和小端序区别,RGB 可能被表达为 BGR 顺序,本质上是一样的)
16 位格式主要是 RGB555 和 RGB565 两种表达方式。RGB555 是每个通道分量占 5 位,空出一位不用。RGB565 则顾名思义,R 和 B 通道占 5 位,G 通道占 6 位。
# RGB555
XRRR RRGG GGGB BBBB
# RGB565
RRRR RGGG GGGB BBBB
24位格式和32位格式我们最常用到,RGB24 表示每个颜色通道分量占 8 位,共 24 位。RGB32 表示除了每个颜色通道分量占8位外,还有8位用于表示透明通道,又称RGBA或ARGB等。
# RGB24
RRRR RRRR GGGG GGGG BBBB BBBB
# RGB32
RRRR RRRR GGGG GGGG BBBB BBBB AAAA AAAA
YUV
YUV 是一种彩色编码系统,主要用在视频、图形处理流水线中 (pipeline)。相对于 RGB 颜色空间,设计 YUV 的目的就是为了编码、传输的方便,减少带宽占用和信息出错。
YUV 编码系统是 Y’UV、YUV、YCbCr、YPbPr 等色彩空间的统称。由于历史关系,Y’UV、YUV 主要用在彩色电视中,用于模拟信号表示。YCbCr 则用于数字视频、图像的压缩和传输,如 MPEG、JPEG。由于数字信号的普及,目前 YUV 大多数时候指的是 YCbCr。
与 RGB 的转换
对于显示器来说,显示图像都是用 RGB 格式,所以需要先把 YUV 格式转换成 RGB。
从 YUV 转换到 RGB 有公式:
R = Y + 1.13983 * V
G = Y - 0.39465 * U - 0.58060 * V
B = Y + 2.03211 * U
从 RGB 转换到 YUV 的公式:
Y = 0.299 * R + 0.587 * G + 0.114 * B
U = -0.14713 * R - 0.28886 * G + 0.436 * B
V = 0.615 * R - 0.51499 * G - 0.10001 * B
采样
对于单个像素来说,像素数据都是由 Y/U/V 三个通道的数据来组成。但对于一整张图片来说,数据存储不一定是每个像素数据按顺序排列,在电视信号传播过程中,由于存储和发送的限制,信号处理中会减少部分信息来降低负荷。基于前提人眼对色度的敏感度不及亮度的敏感度,因此可以压缩色度同时可以极小化对图像表达的影响。YUV444、YUV422、YUV420 这些 YUV 后面跟数字的表示 YUV 的采样方式。YUV 格式主流的采样方式主要有 YUV 4:4:4 、YUV 4:2:2 、YUV 4:2:0。(这里的采样可以简单理解为从原始 RGB 图像转换成 YUV 图像的过程)
视频系统的抽样系统中通常用一个三分比值表示:J:A:B(例如4:2:2),形容一个以J个像素宽及两个像素高的概念上区域。
- J:水平抽样引用(概念上区域的宽度)。通常为4。
- A:在 J 个像素第一行中的色度抽样数目。
- B:在 J个像素第二行中的额外色度抽样数目。
YUV 4:4:4 采样
YUV 444 采样又称全采样,意思是每个Y分量使用一个UV分量,得到的图像和原始RGB图像的大小是一样的。
YUV 4:2:2 采样
YUV 4:2:2 的意思是 Y 分量和 UV 分量按 2:1 的比例采样,每两个 Y 分量共享一个 UV 分量。这么就有一半的像素点的数据大小是原来的 1/3,则整个图像的大小就会是原图像大小的 2/3。
YUV 4:2:0 采样
YUV 4:2:0 是目前比较常用的视频帧采用的格式。字面理解就是对第一行像素,Y 分量和 UV 分量按 2:1 的比例进行采样,第二行像素不采样 UV 分量。采样示意图如下:
存储格式
在上述代码注释中,开头不是 planar 就是 packed。planar 和 packed 表示的是图片数据的存储格式。
Packed
Packed 格式简单理解就是每个通道分量连续交替存储。RGB 格式基本都是 Packed 格式,因为数据排列都是 RGBRGBRGBRGB... 。YUV 中常见的 packed 方式存储的格式有 YUYV 格式 和 UYVY 格式,这两种都是基于 YUV 4:2:2 采样的格式。
-
YUYV
排列顺序举例
Y0U0Y1V0 Y2U2Y3V2
,Y0 和 Y1 共享 U0V0 分量,Y2 和 Y3 共享 U2V2 分量。 -
UYVU
排列顺序举例
U0Y0V0Y1 U2Y2V2Y3
,跟 YUYV 差异在于 UV 分量放在前面。
Planar
Planar 平面格式,指先连续存储所有像素点的 Y 分量,再存储 U 分量,最后才是 V 分量。典型的例子有 I420(视频中最常用),基于 YUV 4:2:0 采样格式。以 4 * 4 像素为例,排列方式如下:
每四个 Y 分量共享一个 UV 分量,共享关系如图所示。
后记
FFmpeg 提供了 yuv 转换成 rgb 的方法,但查阅源码发现是基于 CPU 运算的。yuv 和 rgb 的转换公式可以表达成矩阵相乘的形式
根据一切可以写成矩阵相乘的运算都可以利用 GPU 来加速原则,后续继续研究使用 GPU 加速 YUV 转换成 RGB 的方法,提高在业务侧落地时的性能。
参考文献
-
Wikipedia - Film frame
-
Wikipedia - pixel format
-
Wikipedia -色度抽样
-
Wikipedia - YUV
-
知乎 - 视频和视频帧:视频和帧基础知识整理
-
音视频开发进阶 - 一文读懂 YUV 的采样与格式
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!