用户使用第三方播放器播放经过VENC编码的码流,发现编码后的码流亮暗与原始YUV不一致。
由于播放器的渲染效果不可控,播放器在解码、显示码流内容时,播放器的目标像素值域范围与VENC编码时设置的video_full_range_flag标志位不一致,导致发生像素值域映射,进而出现码流亮暗与原始YUV不一致。
关于full_range的原理介绍请参见参考信息。
不建议用播放器验收亮暗效果,因为播放器的渲染效果不可控,建议将VENC码流解码为YUV文件后再与原始YUV对比,同时需确保编码和解码时使用一致的video_full_range_flag标志位。
在
在
若默认值不满足要求,用户可以调用hi_mpi_venc_set_h264_vui或hi_mpi_venc_set_h265_vui接口修改video_full_range_flag参数值。
通过码流分析工具查看SPS字段的video_full_range_flag,flag=1表示原始YUV是full_range的,flag=0表示是limited_range的。
不同解码器的video_full_range_flag使用方式不同,此处仅以FFmpeg为例,可以通过-vf参数指定目标输出video_full_range_flag,默认为输出limited_range。
此处以ffmpeg 为例,示例指令如下,供参考:
ffmpeg -i ${instream} -pix_fmt nv12 -vf scale=out_range=full/limited -y ${outyuv}
此处举例说明亮暗对比情况。现在的YUV一般都是full_range的,暂时排除源YUV本身为limited_range的情况,考虑Venc和FFmpeg参数组合4种情况,vui表示VENC编码时设置的video_full_range_flag,ffmpeg表示FFmpeg解码时设置的video_full_range_flag:
电视机一般支持240个色阶,从16~255,也就是limited_range,对应YUV值域:Y[16, 235],UV [16, 240]。
现代电脑显示支持255个色阶,从0~255,也就是full_range,对应YUV值域:YUV[0, 255]。
以下标记等价,是在不同软件或者模块中各自的表达方式:
H.265码流中VUI字段的video_full_range_flag = 0表示源YUV是limited_range,video_full_range_flag = 1表示源YUV是full_range。注意这个标记位不影响VENC编码过程,编码生成的码流数据只由输入YUV的实际像素值决定,编码阶段不会发生像素值映射。
例如,ffmpeg解码时会判断源YUV格式和输出YUV格式是否匹配,仅在两者不匹配时触发像素值重映射。当原始YUV是full_range的,此时VENC编码设置了video_full_range_flag = 1,若ffmpeg解码输出YUV格式是limited_range的,它发现YUV格式从full_range降为limited_range,于是在解码后对像素值进行了映射,从 [0, 255] 缩小到 [16, 235],此时就会发现解出来的YUV和原始YUV存在亮暗差异。