YUV 数据格式完全解析

Posted by Piasy on April 27, 2018
本文是 Piasy 原创,发表于 https://blog.piasy.com,请阅读原文支持原创 https://blog.piasy.com/2018/04/27/YUV/

从事多媒体开发的朋友,对 YUV 绝对不陌生,但大家真的能把 YUV 彻底讲清楚吗?这次,让我们彻底揭开 YUV 的「不神秘」面纱。

采样比

  • 人类视觉系统对亮度(luma)的敏感度高于对色度(chroma)的敏感度,因此可以对色度数据进行下采样;
  • 采样比通常表示为 J:a:b,以表示一个宽为 J 像素、高为 2 像素的采样区域内 Y Cb Cr 的采样比:
    • J 表示采样区域的宽度,通常为 4;
    • a 表示第一行色度采样数;
    • b 表示第二行色度采样与第一行色度采样的不同样点数;

例如上图:

  • 4:1:1:宽度 J 为 4,第一行只有一个样点(一种颜色),所以 a 为 1,第二行和第一行不同的样点只有一个,所以 b 为 1,所以为 4:1:1
  • 4:2:0:宽度 J 为 4,第一行有两个样点,所以 a 为 2,第二行和第一行样点完全相同,所以 b 为 0,所以为 4:2:0

这个比例值并非 Y Cb Cr(Y U V)分量的直接比例。对亮度来说,一个样点有一个 Y 值,对色度来说,一个样点有两个值:Cb 和 Cr。对 4:2:0 来说,4 个亮度,2 个色度,所以是 4 个 Y,2 个 Cb,2 个 Cr。

planar, packed 和 semi planar

planar, packed 和 semi planar 是描述分量如何存储的:

  • planar: 有时也称 triplanar,有三个 plane,每种分量连续存储,先存储所有的 Y 分量,再存储所有的 Cb 分量,最后存储所有的 Cr 分量(也可以 Cr 在前,Cb 在后);
  • packed: 只有一个 plane,n 个样点的 Y Cb Cr 分量一起存储,接着存储下 n 个样点的分量;n 的取值、其中三种分量的存储方式,也有多种组合;
  • semi planar: 有两个 plane,先存储所有的 Y 分量,后面 Cb 和 Cr 分量一起存储;

I420

I420 的采样比是 4:2:0,它是 planar 存储方式,分量存储顺序依次是 Y, Cb, Cr,例如下图表示了宽为 6 像素、高为 4 像素图像的三种分量存储方式:

最好忽略那几个箭头,采样区域通常都是 4x2,而非 2x2

NV12

安卓的 MediaCodec 对于 YUV 的输入格式,COLOR_FormatYUV420SemiPlanar 支持得最好,而这种格式就是 NV12 格式。

NV12 的采样比是 4:2:0,它是 semi planar 存储方式,先存储 Y 分量,后面 Cb 和 Cr 分量一起存储,Cb 在前,Cr 在后:

NV21

安卓的 Camera API 回调的 YUV 数据,默认就是 NV21 格式。

NV21 和 NV12 类似,采样比是 4:2:0,也是 semi planar 存储方式,先存储 Y 分量,后面 Cb 和 Cr 分量一起存储,只不过 Cr 在前,Cb 在后:

注意:有个工具网站 rawpixels.net,它的 Predefined format 应该是把 NV12 和 NV21 搞反了,它的 NV12 是 V 在前,NV21 是 U 在前,实际上应该是 NV12 U 在前,NV21 V 在前,因此使用这个网站时,这两种格式应该互换一下。

其他格式

YUV 的格式太多,这里就不一一介绍了,把握上面介绍的两个要点即可:采样比,存储方式。

参考文章