一、前言
之前就写过这个方案,当时做的是ffmpeg内核版本,由于ffmpeg内核解析都是代码实现,所以无缝切换非常完美,看不到丝毫的中间切换过程,看起来就像是在一个通道画面中。其实这种切换只能说是取巧办法,最佳的办法应该是公用一个openglwidget窗体,解码线程那边开两个,第二个解码线程打开后,解码到了数据开始,再将第一个解码线程停掉,或者先停掉第一个解码线程的信号槽关联即可。这样就真正的底层实现的无感切换。但是这种方式不适用于其他视频内核,比如vlc内核这种,如果使用的句柄模式,就不好弄了。
在轮询视频的时候,通常都是需要将之前的视频全部关闭,然后打开下一组视频,在这个切换的过程中,如果是按照常规的做法,比如先关闭再打开新的视频,肯定会出现空白黑屏之类的过度空白区间,如何避免这个问题实现无感知的无缝切换,是个需要稍微懂点脑筋的问题,有一个比较好的做法就是,准备双倍的通道或者后台解码线程,在收到需要切换指令的时候,先后台打开解码线程,直到打开完成能够正常出图像,此时再去关闭之前的解码线程,这样就相当于无缝对接上了,不会说是中间等待打开解码到能正常出图像的过程空白。但是这样又存在一个问题,那就是轮询间隔时间不是非常准确,会有个1-2s的偏差,基本上这个偏差也能接受就是,所以如果是60s的轮询间隔,你可以在58s的时候就开始打开另外一组的解码线程,2s后全部正常出图像后就关联到视频控件上显示,把之前的解码线程关闭并销毁。这样处理下来,既保证了切换过程无感知,又保证了不会过度开销占用CPU,也就切换的期间刚好有双倍的解码线程,只要内存足够,这点性能牺牲还是值得的。
公众号:Qt实战,各种开源作品、经验整理、项目实战技巧,专注Qt/C++软件开发,视频监控、物联网、工业控