本文系微信公众号和知乎专栏《MediaStack》原创文章,欢迎大家关注,随时进行交流。

背景介绍
做视频行业做的比较久了,比较容易碰到各种奇葩问题,这不一个小伙伴大周末就来问问题了:
然后大概了解了一下情况:他们用微信录制了一段视频,放到TV电视上播放,但是显示效果竟然:部分区域有偏粉红色,部分偏绿色。那这样的视频肯定无法接受,需要做一下兼容。
问题分析
拿到该问题,肯定先播放一下片源看看看效果了,如下截图:
通过Potplayer尝试一波,之后调整了一下色彩空间的参数,将视频-->像素着色-->YCgCo色彩空间自动矫正参数关闭就正常了。
之后依次测试了Windows自带的媒体播放器;电影和电视;VLC播放器,以及照片,显示都是正常的。
按照小伙伴的描述通过MediaInfo查看了相关信息,MatrixCoefficients参数显示为YCgCo,这么看来就是这个参数异常了:本身片源是用BT.709进行编码设置的,ColorPrimaries和TransferCharacteristics确实是显示为BT.709;但是参数MatrixCoefficients设置为YCgCo,导致解码时参数异常。
既然知道原因,那就需要兼容了,要想知道如何解决,肯定知道问题如何产生的,所以依据过往经验提示快速查看之前的14496-12手册
然后对比解析工具,该值就是nclx中获取到的:
然后有些片源中没有该字段,MediaInfo中也可以查找该信息:
所以只好继续排查,在查找过程中发现,MP4文件中不只是这一个地方可以获取到该值,于是查找H264中文手册,在SPS的VUI结构体中也会携带matrix_coefficients字段,而且该值会直接影响解码色彩空间的显示:
MatrixCoefficients系数相关矩阵系数定义如下图所示:
不过中文版本比较旧了,是2005年的版本。于是乎又重新review一下最新的官方spec(2021年08月),MatrixCoefficients系数相关矩阵系数定义如下图所示,可以看到定义更加全面,更加丰富了,使用场景也说明的比较详尽:
MatrixCoefficients相关定义如下:matrix_coefficients用于绿原色得亮度色度信号的系数,或者原始坐标系中的X, Y, Z坐标信息。
同时SPEC中规定:如果matrix_coefficients=8时,如果两个条件都满足时才能使用,否则留作将来保留字段。而且默认值是matrix_coefficients=2。
兼容性建议
经过一连串分析之后,目前给小伙伴的建议如下:
(1)按照SPEC中介绍,SPS中的数据才是真正的显示数据(除非本身编码时候写错,否则该值不应该错)。
(2)如果NCLX box中的数transfer_characteristics或者colour_primaries相同,但是matrix_coefficients不一致时,可以按照matrix_coefficients设置为非定义的方式绕过;该方案也是目前Android平台中MP4解析时候的这样可以规避一些场景;也可以解决小伙伴当前的问题。
然而经过半天讨论了一圈,该问题已经反馈给平台厂家,厂家回复说他们不care这个东西;同时做了横向对比实验,只有小米11用微信录制时候才会出现,目前也反馈给微信和小米了,暂时没有具体反馈,目前先按照不影响客户体验做结案,持续跟进该问题。

第二部分:代码走读
上周正好在整理代码时候,看到过类似解析代码,可以参考如下链接:
在MPEG4Extractor中解析获取ColorInfo时,会依据文件中是否包含nclx或者nclc box进行相关数据解析:
parseColorInfo主要读取数据完成nclx或者nclcbox的判断,如果存在则按照spec中介绍进行解析,依次可以得到colour_primaries,transfer_characteristics,和matrix_coefficients相关信息;否则跳过。
convertIsoColorAspectsToPlatformAspects函数主要工作是转换iso色彩空间到编解码支持的色彩空间,同时转化为平台支持的色彩空间;
convertIsoColorAspectsToCodecAspects分别完成colour_primaries,transfer_characteristics,和matrix_coefficients三个参数适用性验证,
目前Android12可以支持的IsoPrimaries参数分别为:GenericFilm, BT.470, BT.601_525, BT.601_625, BT.709, BT.2020等模式;
目前Android12可以支持的sIsoTransfers参数分别为Linear, SMPTE170M, SMPTE240M, Gamma22, Gamma28, XvYCC, BT1361, ST2084, SRGB, ST428, HLG等模式;
目前Android12可以支持的sIsoMatrixCoeffs参数分别为,BT.470_6M, BT.601_6, BT.709_5, SMPTE240M,BT.2020, BT.2020(Constant)等模式;
convertCodecColorAspectsToPlatformAspects完成编码色彩空间到平台支持的色彩空间的转换;目前参数有效性验证主要包括Range,ColorStandard, ColorTransfer等三个范围。
分别进行有效性验证:
目前Android12可以支持的Range参数分别为Limited和Full,其他的为未定义类型;
目前Android12可以支持的Range参数分别为BT.470m, BT.601_525, BT.601_625, BT.709, BT.2020, BT.2020(Constant),Film等类型;
目前Android12可以支持的Range参数分别为Linear, Gamma22, Gamma28, HLG, SMPTE_170M, SRGB, ST2084等类型。 
至此Android12完成了相关参数验证,之后获取有效值之后直接设置到meta中发送给应用进行配置。

我是一枚爱跑步的程序猿,很多内容属于自学内容,文中难免会出现一些错误或者不准确的地方,恳请大家批评指正。
继续阅读
阅读原文