FFMPEG Qt视频播放器之显示图像
Qt 显示 视频 图像 FFMPEG 播放器
2023-09-27 14:20:25 时间
由于现在我们需要显示图像了,因此现在开始需要使用Qt GUI工程了。
创建工程的时候记得选择Qt GUI应用。
引用FFMPEG请参考前面的文章,这里不再介绍。
做过图像界面开发的都知道,任何耗时的操作都不能放在主线程进行,一旦主线程阻塞了,那么体现出来的就是界面卡了。 而我们读取视频和解码视频是一个非常耗时的操作,因此需要另外开辟一个线程来专门做这件事。
Qt里面线程的用法 则是写一个类继承QThread, 然后重载其run函数,把耗时的操作全部放入run函数。
class VideoPlayer : public QThread
{
Q_OBJECT
public:
explicit VideoPlayer();
~VideoPlayer();
protected:
void run();
};
这里run函数里面就是写我们读取视频和解码视频的代码了;
读取和解码还是和前面说的一样的方法:
改动的一点是:
由于我们需要用Qt的控件来显示,因此是把解码之后的YUV数据转换成了RGB32格式的数据:
///这里我们改成了 将解码后的YUV数据转换成RGB32
img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,
pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height,
PIX_FMT_RGB32, SWS_BICUBIC, NULL, NULL, NULL);
numBytes = avpicture_get_size(PIX_FMT_RGB32, pCodecCtx->width,pCodecCtx->height);
out_buffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t));
avpicture_fill((AVPicture *) pFrameRGB, out_buffer, PIX_FMT_RGB32,
pCodecCtx->width, pCodecCtx->height);
....
...
..
sws_scale(img_convert_ctx,
(uint8_t const * const *) pFrame->data,
pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data,
pFrameRGB->linesize);
同时将转换后的RGB32数据存入QImage对象:
//把这个RGB数据 用QImage加载
QImage tmpImg((uchar *)out_buffer,pCodecCtx->width,pCodecCtx->height,QImage::Format_RGB32);
由于我们不能够在子线程中操作界面,(操作界面只能在主线程中进行,几乎所有的图形界面开发都是这样设定),因此我们只能给主线程发送信号,信号带上这个QIMage,让主线程帮忙把这个图像显示出来。
声明信号:
signals:
void sig_GetOneFrame(QImage); //没获取到一帧图像 就发送此信号
发送信号:
//把这个RGB数据 用QImage加载
QImage tmpImg((uchar *)out_buffer,pCodecCtx->width,pCodecCtx->height,QImage::Format_RGB32);
QImage image = tmpImg.copy(); //把图像复制一份 传递给界面显示
emit sig_GetOneFrame(image); //发送信号
主线程绑定并接收信号:
mPlayer = new VideoPlayer;
connect(mPlayer,SIGNAL(sig_GetOneFrame(QImage)),this,SLOT(slotGetOneFrame(QImage)));
信号处理函数如下:
void MainWindow::slotGetOneFrame(QImage img){
mImage = img;
update(); //调用update将执行 paintEvent函数
}
主线程显示图像 则是通过QPainter直接绘制:
void MainWindow::paintEvent(QPaintEvent *event){
QPainter painter(this);
painter.setBrush(Qt::black);
painter.drawRect(0, 0, this->width(), this->height()); //先画成黑色
if (mImage.size().width() <= 0) return;
///将图像按比例缩放成和窗口一样大小
QImage img = mImage.scaled(this->size(),Qt::KeepAspectRatio);
int x = this->width() - img.width();
int y = this->height() - img.height();
x /= 2;
y /= 2;
painter.drawImage(QPoint(x,y),img); //画出图像
}
运行之后的程序如下:
======BUG修复 Begin =======
2017-11-28更新:
此程序在Qt5下使用的时候会有一个bug,既播放器后打开后是黑屏的,原因是文件没有正常打开,当时用的是Qt4测试的,所有木有发现。
解决方法其实很简单:
将void VideoPlayer::run()里面的
char *file_path = mFileName.toUtf8().data();
修改成如下即可:
char file_path[512] = {0};
strcpy(file_path, mFileName.toUtf8().data())
======BUG修复 End =======
相关文章
- QT中Qthread线程彻底销毁的实例与注意事项(防止线程资源内存泄露)
- Qt中创建、写入、删除(INI、XML文件)
- Qt中QList用法详解
- Qt音视频开发27-ffmpeg视频旋转显示
- Qt音视频开发20-vlc内核动态保存录像文件(不需要重新编译源码)
- Qt数据库应用13-通用数据库分页
- Qt数据库应用5-海量数据多线程导出
- Qt编写地图综合应用文章导航
- Qt编写地图综合应用41-在线轮廓图
- Qt编写可视化大屏电子看板系统18-柱状分组图
- Qt音视频开发48-通用通道管理
- Qt音视频开发22-通用GPU显示
- Qt编写安防视频监控系统27-GPU显示
- Qt通用方法及类库6
- Qt编写气体安全管理系统24-地图管理
- Qt 模拟鼠标点击(QApplication::sendEvent(ui->pushbutton, &event0);)
- d指针在Qt上的应用及实现(有图,很清楚)
- QT中|Qt::Tool类型窗口自动退出消息循环问题解决(setQuitOnLastWindowClosed必须设置为false,最后一个窗口不显示的时候,程序会退出消息循环)
- Qt之QUrl
- Qt之QLineEdit
- Qt之加载QSS文件
- Qt之显示网络图片
- Qt SizePolicy 属性
- 在QT中添加zeromq DLL库
- QT QCharts QScatterSeries 空心点阵图,鼠标移动到上面显示数值,鼠标移开数值消失