第五章:ffmpeg和QT开发播放器之使用QT播放

写在前面:

    编写完视频的编码转码程序之后,就需要将整个程序重新封装一下,以便于后续的工作,这里对应视频课程中的4-1~4-2。前阵子忙着工作上的事情,也就没什么进度,想想还是不应该,QT稍微接触了下,感觉还是很多不会的。

1、绘制QT播放界面

双击ui文件,打开QT的设计界面。

                         第五章:ffmpeg和QT开发播放器之使用QT播放_第1张图片

然后在右侧的属性编辑器中的geometry属性中修改高度和宽度为我们代码中设置的800*600

                                                第五章:ffmpeg和QT开发播放器之使用QT播放_第2张图片

        那么创建出来的窗口就可以用来显示视频了,但是显示视频我们可以调用显卡来加速,在这里我们选择使用QT自带的Open GL Widget来显示。

        我们直接在QT设计器的左侧找到Open GL Widget,并拖放到ui界面上,然后点击拖放好的模块,在右侧属性编辑器设置好Open GL Widge的X、Y以及宽度高度这四个参数,参数和上面一致。

第五章:ffmpeg和QT开发播放器之使用QT播放_第3张图片

2、添加图标

       在项目代码主目录中,追加图标文件,图标文件直接用老师提供的好了,将Resources文件放入主目录中。

                        第五章:ffmpeg和QT开发播放器之使用QT播放_第4张图片

       然后再ui界面上添加按钮。按钮的添加在左侧工具栏的Buttons可以看到,我们选择Push Button按钮。拖放到ui界面上后,在button上右击,选择改变样式表,然后选择添加资源选项的下按钮,选择第二个选项border-image。然后再选择资源栏中点击那个笔。

                                    第五章:ffmpeg和QT开发播放器之使用QT播放_第5张图片

在出现的编辑资源中,点击红色框框,在选择添加我们刚刚放入工程目录中的Resources文件夹里面的图标。

                第五章:ffmpeg和QT开发播放器之使用QT播放_第6张图片

然后按步骤点ok,最后我们会发现那个botton会变成我们设置的图标了,通过修改编辑样式表的内容,可以做的将鼠标移动到按钮时,切换图标。
QPushButton:!hover{border-image: url(:/Xplay/open_normal.png);}//鼠标没碰到时候

       QPushButton:hover{border-image: url(:/Xplay/open_hot.png);} //鼠标碰到的时候

                                        第五章:ffmpeg和QT开发播放器之使用QT播放_第7张图片

同样再添加一个播放按钮,然后也和上面设置的一样,最后在右侧对象查看器中,选择Qwidget,然后在下方属性编辑器中,找到WindowIcon选项,选择整个程序的logo。

                                                        第五章:ffmpeg和QT开发播放器之使用QT播放_第8张图片

之后保存好qt界面,编译一下,应该就能够显示出我们绘制的qt界面。

3、创建类

       将ffmpeg解码出来的视频传递到QT中播放。使用的方法是重载这个OpenGLWidget。

       在QT设计器右侧的对象查看器,单击右键,选择提升。然后在新建提升类中输入提升类的名称,然后按添加,再按提升。

                            第五章:ffmpeg和QT开发播放器之使用QT播放_第9张图片

       然后回到VS中,创建VideoWidget类,然后还需要继承QOpenGLWidget这个类。

class VideoWidget :public QOpenGLWidget
{
public:
	VideoWidget(QWidget *p = NULL);
	virtual ~VideoWidget();
};
同时修改构造函数。
VideoWidget::VideoWidget(QWidget *p) :QOpenGLWidget(p)
{

}

4、绘制函数的构建

     void paintEvent(QPaintEvent *e); //当窗口发生绘制的时候,调用这个函数

void timerEvent(QTimerEvent *e); //定时器刷新

       我们需要通过OpenGL,toRGB之后的值来给到paintEvent里面。

       paintEvent函数中首先会用到QPainter painter,所以要先包含头文件#include

       使用painter.begin开始绘制。painter.end是结束绘制,也就能显示图像。在两者之间就需要做图像的显示出来

       painter.drawImage来绘制图像,传入显示的起始位置,和显示图像数据image。但是image的空间还未被分配,所以还需要new一个空间给image存放图像数据的。

       使用QImage函数创建image的空间。

5、视频的解码和显示

先打开视频文件,这时候就可以引用之前创建的XFFmpeg类里面的实现函数。
      在VideoWidget类中的构造函数中打开XFFmpeg::Get()->Open("my.mp4");
      之后在paintEvent函数中调用之前XFFmpeg中的打开视频函数

       1)AVPacket pkt = XFFmpeg::Get()->Read();                                            //读取视频帧

       2)AVFrame *yuv = XFFmpeg::Get()->Decode(&pkt);                         //解码

       3)XFFmpeg::Get()->ToRGB(yuv, (char*)image->bits(), width(), height());//转码

6、刷新屏幕

视频播放的时候还需要对它进行刷新,那么就需要用到timerEvent函数,由于在测试阶段,所以就简单的编写这个刷新函数。

  通过在VideoWidget类中的构造函数中设置定时器的间隔时间,然后再timeEvent函数中调用update函数进行刷新。

main.cpp
#include "xplay.h"
#include 
#include "XFFmpeg.h"

//static double r2d(AVRational r)
//{
//	return r.num == 0 || r.den == 0 ? 0. : (double)r.num / (double)r.den;
//}

#define OUT_WIDTH	800
#define OUT_HEIGHT	600

int main(int argc, char *argv[])
{
	char *rgb = new char[OUT_WIDTH*OUT_HEIGHT * 4];	//图像的数据RGBA
	
	{
		printf("open success!\n");
	}
	else
	{
		printf("open failed!%s", XFFmpeg::Get()->GetError().c_str());
		getchar();
		return -1;
	}
	
	while (1)
	{
		if (pkt.size == 0)
			break;
		printf("pts=%lld\n", pkt.pts);

		if (pkt.stream_index != XFFmpeg::Get()->videoStream)
		{
			av_packet_unref(&pkt);	//如果不是视频格式的 就释放掉
			continue;
		}

		AVFrame *yuv = XFFmpeg::Get()->Decode(&pkt);	//解码视频
		if (yuv)
		{
			printf("[D]");
			XFFmpeg::Get()->ToRGB(yuv, rgb, OUT_WIDTH, OUT_HEIGHT);
		}

		av_packet_unref(&pkt);
	}

	//AVFrame *yuv = av_frame_alloc();		//分配的视频帧
	QApplication a(argc, argv);
	Xplay w;
	w.show();
	return a.exec();
}



你可能感兴趣的:(第五章:ffmpeg和QT开发播放器之使用QT播放)