Qt播放多路视频的理解

    之前很久就考虑过这个问题,为什么视频在界面刷新那么快,而Qt的界面依然很流畅。在做过多路视频播放后,接触了SDL播放视频,自已也实现了opengl播放视频,也使用过Qt的MediaPlayer播放视频。对比效果终于有结果了,原来是视频这种高频率的刷新本来就有能用widget这种QPainter来画的,是使用的GPU渲染。以下是我对多路视频播放实践的一些效果对比。

    1、SDL:(以下仅针对图像刷新)

                优点:后台渲染,只需要传入窗口句柄,与Qt是不同的图形显示框架;完全可以在非GUI线程中传入句柄和图像数据,完全不影响GUI线程的刷新,因为它连Qt的事件循环都没有进入,更新显示是使用的传入句柄后台显示的,SDL自已的刷新策略。可以显示的视频格式多。GPU转换图像格式

                缺点:由于没有进入Qt的事件循环,所以在widget这种GUI程序update()的时候,如果没有禁用updatesEnable()那么Qt对这个widget也会重绘刷新一次,而这上widget的句柄SDL也在用,如此就会造成闪屏。另外,如果在视频上放一些Qt的一些widget控件,也会造成闪屏(或者直接没有),这也是因为视频的刷新是SDL,而视频上面的刷新是Qt。SDL里面的窗口叠加和Qt的窗口叠加应该不一样导致的吧,直接没显示,可能是因为你禁用了updatesEnable(),视频上面的widgets都不会刷新了。所以要在视频上面画图案就只有用SDL在视频上面画了,另外如果禁用updatesEnable(),在多分屏窗口如果窗口从大的窗口变成小的多个窗口时,就会花屏了,因为大的窗口的区域没有刷新。

    2、 QOpenGLWidget:

            优点 : 使用GUI渲染视频,widget原生控件,可以在视频上面放其它widget控件,不会闪屏之类 其它问题,可以自定义shader显示yuv、nv12等视频格式。GPU转换图像格式

            缺点 :进入了Qt的事件循环, 刷新多路视频的时候,某一时刻每一路视频的每帧图像依然是在一个openglwidget中传入数据给opengl渲染后,再接着下一个,这里的每一个openglwidget都相当于一个opengl场景。由于以上原因,我的电脑i5CPU、显卡是英伟达的(型号忘了,反正够显示了),在显示20个每秒25帧的视频画面时,有一点卡滞但不严重。由于是给一个openglwidget传递数据等它渲染好了,再到下一个,所以主循环耗掉了一些时间,但opengl渲染给力,每个耗时不长,所以卡滞不严重。

    3 、自定义qml视频显示控件

            优点 : 使用GPU渲染;如果是QQuick应用,那么还有多线程渲染。可以在视频上面放置其它qml控件,所有的qml控件在同一个图像渲染场景中,本身就是一个状态机,可以一次把多路视频都渲染了,因为qml场景中的渲染,就是渲染场景中有变化的都一次性渲染了,当外部把数据传进来时,并不是立即刷新的,而是把数据给到了渲染场景中,再下一次刷新时,会一个结点一个节点的取数据,一次性渲染,所以效果较好。显示100路25帧的视频时,界面依然很流畅

            缺点 : 进入了事件循环,开发windows应用周期长,一些复杂控件,像QTreeWidget、QDateTime、QTableView这种复杂控件没有传统的widget功能齐全。我实现的是需要外部转换图像格式,不能直接显示Yuv和Nv12这种视频格式,qt封装的类中我暂没看到可以用来解码的,可能也有像材质、纹理之类的可以处理,暂不清楚。

    4 、 QMediaPlayer

            优点 : 官方控件,支持格式多,用directshow做底层,不用处理视频、音频解码,功能齐全。界面流畅效果和使用SDL一样,非常流畅,rtsp和http视频都可以

            缺点 : 需要安装K-Lite插件(里面包含directshow),我电脑测试显示最多8路视频同时播放,再多程序就挂了。直接以QVideoWidget为父对象放Qt控件时,直接不显示。以QVideoWidget的父对象为父对象放置控件,并把位置调整到视频上,背景不能透明,应该是放置上去的控件在栈区中的分层在QVideoWidget的下面,而其中的视频可能是在类似3d场景中渲染的,3d场景中默认的背景是黑色(猜测)。不能自字义使用多张显示(解码),directshow的GUI配置里面是选择其中一种

        这是我针对视频显示的看法,如果是显示多路视频的话,首先由于多路视频解码很可能是多张显卡,所以,我的方案如下;

 1、SDL    显示路数非常多(二十路以上这种),对SDL熟悉,能在视频上面显示其它东西,比如画矩形,线,文字这种,能够接受widget刷新时的闪屏(很快,但还是能看出来,如果禁用刷新,在多路全屏和正常显示时或其它操作,与其它widget控件的布局很可能造成花屏)

 2、QOpenGLWidget 显示路数中等20路左右

 3、 qml自定义视频 显示路数非常多(20路以上),一般为windows应用,可以使用QQuickWidget把qml嵌入到widget应用中,CPU配置较好,i5以上吧(用于图像格式转换,个人不会单独使用GPU图像格式转换,像CUDA这种)。

        以上显示都需要自己写视频的解码,在视频解码中就可以自由选择显卡了,视频解码还没搞懂。

    如果是显示单路、两路、三路这种,对视频上面的控件没有透明要求还是用QMediaPlayer吧,安装个插件,什么格式都支持,解码也搞定了。


你可能感兴趣的:(opengl,Qt,qml)