问题描述
今天在用JM对YUV420p编码时,发现编出的码流用ffplay播放花屏,报如下错误:
JM的版本时19.1,没有使能B帧,PicOrderCntType设置为2,其它都是encoder.cfg中的默认配置。我用一些码流分析工具播放H264码流正常,用一些播放器播放也都存在花屏,不过大多数播放器都是调用的ffmpeg接口,所以需要定位为何ffmpeg播放会报错。
定位解决问题
在ffmpeg中查找报错地方,在ff_h264_build_ref_list函数中,猜测多半和参考帧列表重排有关。
查看JM配置文件,默认ReferenceReorder为1,参考帧列表排序是使能的。
ReferenceReorder = 1 # Reorder References according to Poc distance for HierarchicalCoding (0=off, 1=enable, 2=use when LowDelay is set)
其实当前没有必要排序,把ReferenceReorder设为0,再次编码,用ffplay播放无报错,所以这时可以断定和参考帧重排序有关。
用ffmpeg对有问题的码流解码,解出来后发现第17帧(帧数从1开始计数)为绿屏,看到17这个数字就很敏感了,因为设置的Log2MaxFNumMinus4=0,所以码流中内部帧号16帧一个循环,再看第17帧的码流结构,ref_pic_list_reordering句法中,abs_diff_pic_num_minus1有大于等于max_pic_num的情况,max_pic_num为16。因为协议中规定了abs_diff_pic_num_minus1必须小于max_pic_num,而有的解码器做了些容错机制,所以用码流分析工具播放未见问题,ffmpeg中是严格遵循协议的,所以会报此错误。
修复此问题也比较容易,在reorder_against_default_ref_pic_lists函数中,对abs_diff_pic_num_minus1都取max_pic_num的模即可。