调用FFmpeg库或者使用ffplay播放hevc编码的ts文件时,seek会花屏。会有如下的报错:
[hevc @ 000001e4e2292ac0] Could not find ref with POC 9
[hevc @ 000001e4e2292ac0] Could not find ref with POC 8
[hevc @ 000001e4e2292ac0] Could not find ref with POC 7
[hevc @ 000001e4e2292ac0] Could not find ref with POC 11
[hevc @ 000001e4e2292ac0] Could not find ref with POC 3
[hevc @ 000001e4e2292ac0] Could not find ref with POC 2
[hevc @ 000001e4e2292ac0] Could not find ref with POC 1
[hevc @ 000001e4e2292ac0] Could not find ref with POC 6
[hevc @ 000001e4e2292ac0] Could not find ref with POC 10
[hevc @ 000001e4e2292ac0] Could not find ref with POC 9
[hevc @ 000001e4e2292ac0] Could not find ref with POC 8
[hevc @ 000001e4e2292ac0] Could not find ref with POC 7
[hevc @ 000001e4e2292ac0] Could not find ref with POC 3
[hevc @ 000001e4e2292ac0] Could not find ref with POC 2
[hevc @ 000001e4e2292ac0] Could not find ref with POC 1
[hevc @ 000001e4e2292ac0] Could not find ref with POC 0
测试了一下release版本ffmpeg-4.2.1以及master分支的代码,这个问题还存在。
这个问题好像一直存在,不过没有人给FFmpeg提交过patch。可能是解决起来比较简单吧。
这个问题的主要原因是返回的hevc的keyframe的pos不正确。
解决办法:
需要在libavformat/mpegts.c中,针对video stream是hevc的情况,在return dts和pos的条件中增加keyframe的判断。是否keyframe可以从parser->key_frame得到。
返回正确的keyframe的pos和dts之后,seek时设置seek_flags为AVSEEK_FLAG_BACKWARD,就不会再花屏了。
这样对播放过程中的seek操作,还有一些根据keyframe信息进行切片的操作等等就都正常了。