前言

视频中帧的颜色信息非常重要,表示着编码时用到的标准,意味着解码时也要对应上,或者要使用正确的转换函数,否则就会带来色差问题。
关于FFmpeg中的颜色参数,有下边几个重要的结构体:

颜色参数相关的结构体

这些结构体都在pixfmt.h中定义:

AVColorPrimaries

enum AVColorPrimaries {AVCOL_PRI_RESERVED0 = 0,AVCOL_PRI_BT709 = 1,///< also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP177 Annex BAVCOL_PRI_UNSPECIFIED = 2,AVCOL_PRI_RESERVED= 3,AVCOL_PRI_BT470M= 4,///< also FCC Title 47 Code of Federal Regulations 73.682 (a)(20)AVCOL_PRI_BT470BG = 5,///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAMAVCOL_PRI_SMPTE170M = 6,///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSCAVCOL_PRI_SMPTE240M = 7,///< functionally identical to aboveAVCOL_PRI_FILM= 8,///< colour filters using Illuminant CAVCOL_PRI_BT2020= 9,///< ITU-R BT2020AVCOL_PRI_SMPTE428= 10, ///< SMPTE ST 428-1 (CIE 1931 XYZ)AVCOL_PRI_SMPTEST428_1 = AVCOL_PRI_SMPTE428,AVCOL_PRI_SMPTE431= 11, ///< SMPTE ST 431-2 (2011) / DCI P3AVCOL_PRI_SMPTE432= 12, ///< SMPTE ST 432-1 (2010) / P3 D65 / Display P3AVCOL_PRI_JEDEC_P22 = 22, ///< JEDEC P22 phosphorsAVCOL_PRI_NB///< Not part of ABI};

色度主基准:描述视频色度信息,即视频中可见颜色的范围。它定义了色度信号的原色坐标。
不同的色度主基准对应不同的色彩空间范围。
比如BT.601,BT.709,BT.2020等。

AVColorTransferCharacteristic

enum AVColorTransferCharacteristic {AVCOL_TRC_RESERVED0= 0,AVCOL_TRC_BT709= 1,///< also ITU-R BT1361AVCOL_TRC_UNSPECIFIED= 2,AVCOL_TRC_RESERVED = 3,AVCOL_TRC_GAMMA22= 4,///< also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAMAVCOL_TRC_GAMMA28= 5,///< also ITU-R BT470BGAVCOL_TRC_SMPTE170M= 6,///< also ITU-R BT601-6 525 or 625 / ITU-R BT1358 525 or 625 / ITU-R BT1700 NTSCAVCOL_TRC_SMPTE240M= 7,AVCOL_TRC_LINEAR = 8,///< "Linear transfer characteristics"AVCOL_TRC_LOG= 9,///< "Logarithmic transfer characteristic (100:1 range)"AVCOL_TRC_LOG_SQRT = 10, ///< "Logarithmic transfer characteristic (100 * Sqrt(10) : 1 range)"AVCOL_TRC_IEC61966_2_4 = 11, ///< IEC 61966-2-4AVCOL_TRC_BT1361_ECG = 12, ///< ITU-R BT1361 Extended Colour GamutAVCOL_TRC_IEC61966_2_1 = 13, ///< IEC 61966-2-1 (sRGB or sYCC)AVCOL_TRC_BT2020_10= 14, ///< ITU-R BT2020 for 10-bit systemAVCOL_TRC_BT2020_12= 15, ///< ITU-R BT2020 for 12-bit systemAVCOL_TRC_SMPTE2084= 16, ///< SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systemsAVCOL_TRC_SMPTEST2084= AVCOL_TRC_SMPTE2084,AVCOL_TRC_SMPTE428 = 17, ///< SMPTE ST 428-1AVCOL_TRC_SMPTEST428_1 = AVCOL_TRC_SMPTE428,AVCOL_TRC_ARIB_STD_B67 = 18, ///< ARIB STD-B67, known as "Hybrid log-gamma"AVCOL_TRC_NB ///< Not part of ABI};

色调传递特性:描述视频的色调传递函数,即为亮度信号分配不同的电压或光强度。
不同的色调传递特性决定了视频在显示设备上的亮度响应曲线。
比如AVCOL_TRC_SMPTE2084,AVCOL_TRC_ARIB_STD_B67(HLG)等HDR标准。

AVColorSpace

enum AVColorSpace {AVCOL_SPC_RGB = 0,///< order of coefficients is actually GBR, also IEC 61966-2-1 (sRGB)AVCOL_SPC_BT709 = 1,///< also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / SMPTE RP177 Annex BAVCOL_SPC_UNSPECIFIED = 2,AVCOL_SPC_RESERVED= 3,AVCOL_SPC_FCC = 4,///< FCC Title 47 Code of Federal Regulations 73.682 (a)(20)AVCOL_SPC_BT470BG = 5,///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601AVCOL_SPC_SMPTE170M = 6,///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSCAVCOL_SPC_SMPTE240M = 7,///< functionally identical to aboveAVCOL_SPC_YCGCO = 8,///< Used by Dirac / VC-2 and H.264 FRext, see ITU-T SG16AVCOL_SPC_YCOCG = AVCOL_SPC_YCGCO,AVCOL_SPC_BT2020_NCL= 9,///< ITU-R BT2020 non-constant luminance systemAVCOL_SPC_BT2020_CL = 10, ///< ITU-R BT2020 constant luminance systemAVCOL_SPC_SMPTE2085 = 11, ///< SMPTE 2085, Y'D'zD'xAVCOL_SPC_NB///< Not part of ABI};

色彩空间:描述视频的色彩编码方式,即颜色信息在视频中的表示方式。
不同的色彩空间定义了颜色的表示范围和编码方式。

AVColorRange

enum AVColorRange {AVCOL_RANGE_UNSPECIFIED = 0,AVCOL_RANGE_MPEG= 1, ///< the normal 219*2^(n-8) "MPEG" YUV rangesAVCOL_RANGE_JPEG= 2, ///< the normal 2^n-1 "JPEG" YUV rangesAVCOL_RANGE_NB ///< Not part of ABI};

色域范围:描述视频的色彩值范围,即视频中亮度和色度值的取值范围。
不同的色域范围定义了亮度和色度值的归一化范围。

在ffmpeg命令查看一个视频文件的时候,有yuv420pyuvj420p。这两种格式就分别对应AVCOL_RANGE_MPEGAVCOL_RANGE_JPEG

AVCOL_RANGE_MPEG的像素颜色范围是[16,235],16表示黑色,235表示白色。主要用于TV。
AVCOL_RANGE_JPEG的像素颜色范围是[0,255],0表示黑色,255表示白色。主要用于PC。

不同标准间的转码

线性RGB:相机CMOS 传感器产生并写入原始文件(Raw File)的数据是线性的。线性数据通常看起来非常暗且对比度较低。
非线性RGB:原始文件数据经过伽马校正来匹配人眼感知。
XYZ:色彩转换需要在线性空间下进行,不同的 RGB 色域空间是不能直接进行转换的,需要一个设备无关、线性的颜色模型(XYZ)作为中转。

FFmpeg 中,BT. 601->BT. 709 的转换过程:

在如上的变换中,涉及到 3 个颜色空间的转换,分别是:

  1. YUV 和 非线性RGB 之间的转换
  2. 线性 RGB 和非线性 RGB 之间的转换
  3. 线性 RGB 和 XYZ 之间的转换

在FFmpeg 中,所有的这些转换参数都保存在 AVFrame 结构中:
AVFrame->colorspace 中保存了 YUV/RGB 的转换矩阵
AVFrame->color_trc 中保存了线性 RGB和非线性 RGB 之间的转换函数(transformation characteristics)。
AVFrame->color_primaries 中保存了 RGB/XYZ 的转换矩阵

上边内容来自:视频中为什么需要这么多的颜色空间?

HDR

这里说到颜色参数,就不得不提一下HDR。
来自维基百科的描述:

高动态范围成像(High Dynamic Range Imaging,简称HDRI或HDR),在计算机图形学与电影摄影术中,是用来实现比普通数位图像技术更大曝光动态范围(即更大的明暗差别)的一组技术。高动态范围成像的目的就是要正确地表示真实世界中从太阳光直射到最暗的阴影这样大的范围亮度。

gamma曲线

BT.2100标准提供两条伽玛曲线作为不同类型生产工作的标准:

  • PQ(Perceptual Quantizer 感知量化)
    PQ曲线的值是绝对的。这意味着PQ曲线不会去匹配一块屏幕的工作特性,而是正相反:屏幕必须去匹配PQ曲线。当一块屏幕的实际最大亮度与最小亮度都无法达到理想值——0 nits与10000 nits时(在目前的技术水平下可以说是必然情况),它会丢失掉显示设备允许的动态范围之外的内容。
  • HLG(Hybrid Log-Gamma 混合对数伽马)
    与传统伽马曲线相比,HLG通过对信号值的上半部分使用对数曲线(下半部分仍使用伽马曲线)来增加视频的动态范围
    HLG 的输出不带元数据,其编码值是相对值,按照百分比进行。 最大亮度值=显示设备的技术指标,因此 HLG 可以根据不同的显示设备显示出不同程度的HDR 效果,具备自适应性能。

一般的HLG适用于广电(根据用户设备的峰值亮度动态的调整最高显示亮度),PQ适用于数码电脑等(绝对的亮度,如果设备达不到,则进行削峰)

元数据

静态元数据:提供有关整个视频的信息。(包含了HDR内容的颜色信息以及亮度信息,ST 2086同时也会传输HDR内容的MaxCLL和MaxFALL)
动态元数据:描述了应该对显示在与母带显示具有不同色量的显示器上显示的内容应用什么色量变换。它针对每个场景和每帧显示进行了优化。

不同HDR标准

常见的有Dolby Vision,HDR 10+和HLG。
不同标准对于元数据的支持示意图:

SMPTE ST 2084:指的就是PQ转换函数
SMPTE ST 2086MDCV(Mastering Display Color Volume):静态元数据标准,它描述了主控显示器的色彩量(即原色、白点以及最大和最小亮度)
SMPTE ST 2094DMCVT(Dynamic Metadata for Color Volume Transform ) :是SMPTE于 2016 年发布的动态元数据标准,分为六个部分。

  • -10:用于Dolby Vision
  • -40:用于HDR10+