本部分总结了一下界面绘制和OpenGL绘制视频,由于使用的是Qt的openGL,功能上没有那么复杂,实现起来也比较简单,毕竟人家已经给封好的,完整的代码中使用OpenGL绘制视频,对数据的顶点shader、片元shader着色,对yuv材质的绑定,分配材质内存空间、创建材质显卡空间、纹理以及显卡绘制每帧视频时如何对齐等等一些内容,这部分内容是OpenGL中的,较为复杂,待继续学习后有一定收获再来总结,现在我们继续看这里。

一、基于QT的播放器界面绘制


在做opengl绘制视频前,我们先需要设计一个界面,打开vs2013中该项目中的ui,进入Qt设计界面,设置好界面的属性后,在我们绘制视频时,可以选择3D引擎UX,或者OpenGL,但在这里我们用Qt自带的OpenGL。选择Qt的控件Open
GL
Widget,在界面中绘制一片区域,设置大小以及属性,之后加入两个按钮控件为打开文件和播放视频,加入相对应的图标,如何加入,网上有很多方法,这里就不啰嗦了,主要得知道这里两个按钮的变量名为openButton和playButton,后面需要用到的。



二、通过QT显示转码后的RGB数据


现在我们需要将FFMpeg解码后的视频播放出来,如何播放?在上面中我们创建了窗口openGLWidget,这里我们重载这个类(是对象openGLWidget的类QOpenGLWidget,重载的是这个类),然后使用我们自己的方法来控制这个窗口。这里我将QOpenGLWidget类提升为VideoWidget类。



然后我们在VS2013中用类向导创建该类进行实现(要继承自QOpenGLWidget)。首先在VideoWidget.h中申明定时器和窗口的重新绘制的函数。
#pragma once #include <QtWidgets/qwidget.h> #include <QOpenGLWidget> class
VideoWidget:public QOpenGLWidget { public: VideoWidget(QWidget *parent = NULL);
void paintEvent(QPaintEvent *event);//窗口的重新绘制 void timerEvent(QTimerEvent
*event);//定时器 virtual ~VideoWidget(); };

对于paintEvent的定义,我们知道绘制时需要FFMpeg解码出来的视频帧,而对于解封装、解码我们都在XFFMpeg类中完成,这里我们需要使用它。而在VideoWidget的构造函数里需要打开视频,同时设置定制器来显示播放,目前这是测试阶段,我们就先考虑单线程,播放时有些卡顿,当然后面我们会使用多线程解决这一问题,现在我们看下paintEvent的定义。
void VideoWidget::paintEvent(QPaintEvent *e) {//绘制 static QImage *image =
NULL; if (image == NULL) { uchar *buf = new uchar[width()*height() *
4];//存放解码后的视频空间 image = new QImage(buf, width(), height(),
QImage::Format_ARGB32); } AVPacket pkt = XFFmpeg::Get()->Read();//读取视频帧 if
(pkt.stream_index != XFFmpeg::Get()->videoStream) {//不为视频帧,释放pkt的空间
av_packet_unref(&pkt); return; } if (pkt.size == 0) return; AVFrame *yuv =
XFFmpeg::Get()->Decode(&pkt);//解码读取到的视频帧 av_packet_unref(&pkt);//解码成后也需要释放空间 if
(yuv == NULL) return; //将解码后的视频帧转化为RGB XFFmpeg::Get()->ToRGB(yuv, (char
*)image->bits(),width(),height()); QPainter painter;//hua painter.begin(this);
painter.drawImage(QPoint(0, 0), *image);//绘制FFMpeg解码后的视频 painter.end();// }
XFFMpeg的读取、解码、转换为RGB在之前我们也都说明过。这里要说下的可能就是

if (image == NULL)
           {
              uchar *buf = new uchar[width()*height() * 4];//存放解码后的视频空间
              image = new QImage(buf, width(), height(),
QImage::Format_ARGB32);
           }

这里的buf用来后面对于解码后的视频帧绘制时用到的,开辟的空间后*4是RGB有三个色彩同时这里还有一个通道数,共占用了四个字节,后面的image
的格式 QImage::Format_ARGB32也选择了32位的设置,都对应了在XFFMPeg中解码以及转化RGB格式时所设置的一些参数。

后面就是它的构造函数以及定时器函数,里面也都比较简单。
VideoWidget::VideoWidget(QWidget *parent) :QOpenGLWidget(parent) {
XFFmpeg::Get()->Open("1080.mp4");//打开视频 startTimer(10);//设置定时器 } void
VideoWidget::timerEvent(QTimerEvent *event) { this->update();//定时器更新 }
对于这部分内容大概就这么多,绘制基本如此,下一篇中我们进行视频播放进度控制,处理之前的卡顿现象。

下一篇链接:https://blog.csdn.net/hfuu1504011020/article/details/82705890
<https://blog.csdn.net/hfuu1504011020/article/details/82705890>

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:ixiaoyang8@qq.com
QQ群:637538335
关注微信