双击ui文件,打开QT的设计界面。
然后在右侧的属性编辑器中的geometry属性中修改高度和宽度为我们代码中设置的800*600
那么创建出来的窗口就可以用来显示视频了,但是显示视频我们可以调用显卡来加速,在这里我们选择使用QT自带的Open GL Widget来显示。
我们直接在QT设计器的左侧找到Open GL Widget,并拖放到ui界面上,然后点击拖放好的模块,在右侧属性编辑器设置好Open GL Widge的X、Y以及宽度高度这四个参数,参数和上面一致。
2、添加图标
在项目代码主目录中,追加图标文件,图标文件直接用老师提供的好了,将Resources文件放入主目录中。
然后再ui界面上添加按钮。按钮的添加在左侧工具栏的Buttons可以看到,我们选择Push Button按钮。拖放到ui界面上后,在button上右击,选择改变样式表,然后选择添加资源选项的下按钮,选择第二个选项border-image。然后再选择资源栏中点击那个笔。
在出现的编辑资源中,点击红色框框,在选择添加我们刚刚放入工程目录中的Resources文件夹里面的图标。
然后按步骤点ok,最后我们会发现那个botton会变成我们设置的图标了,通过修改编辑样式表的内容,可以做的将鼠标移动到按钮时,切换图标。
QPushButton:!hover{border-image: url(:/Xplay/open_normal.png);}//鼠标没碰到时候
QPushButton:hover{border-image: url(:/Xplay/open_hot.png);} //鼠标碰到的时候
同样再添加一个播放按钮,然后也和上面设置的一样,最后在右侧对象查看器中,选择Qwidget,然后在下方属性编辑器中,找到WindowIcon选项,选择整个程序的logo。
之后保存好qt界面,编译一下,应该就能够显示出我们绘制的qt界面。
将ffmpeg解码出来的视频传递到QT中播放。使用的方法是重载这个OpenGLWidget。
在QT设计器右侧的对象查看器,单击右键,选择提升。然后在新建提升类中输入提升类的名称,然后按添加,再按提升。
然后回到VS中,创建VideoWidget类,然后还需要继承QOpenGLWidget这个类。
class VideoWidget :public QOpenGLWidget
{
public:
VideoWidget(QWidget *p = NULL);
virtual ~VideoWidget();
};
同时修改构造函数。
VideoWidget::VideoWidget(QWidget *p) :QOpenGLWidget(p)
{
}
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的空间。
先打开视频文件,这时候就可以引用之前创建的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());//转码
视频播放的时候还需要对它进行刷新,那么就需要用到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();
}