接之前帖子,自己编写算法视频格式转换CPU占用率高,且转换效率低,故在此使用ffmpeg库进行转化;将一帧数据转换rgb后使用qt中QImage显示一帧数据;
#ifndef VOIDSHOWIMAGE_H
#define VOIDSHOWIMAGE_H
#include <QWidget>
#include <QLabel>
#include <QImage>
extern "C"
{
#include "libavutil/frame.h"
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavdevice/avdevice.h"
}
class VoidShowImage:public QWidget
{
public:
VoidShowImage(QWidget *parent =nullptr);
~VoidShowImage();
void showImage(QByteArray arrayData);
private:
// 初始化
void initPlay();
// 转换数据
void switchYuvToRgb(void* p_yuvData, int len);
private slots:
void paintEvent(QPaintEvent *);
private:
QLabel *pq_videoShowLabel;
char *pq_YuvData;
uint8_t *yuvBuffer;
AVFrame *pFrame ;
AVFrame *pFrameRGB;
uint8_t * rgbBuffer;
SwsContext *img_convert_ctx;
int m_iWidth;
int m_iHeight;
};
#endif // VOIDSHOWIMAGE_H
#include "VoidShowImage.h"
#include <QGridLayout>
#include <QDebug>
#include <QPainter>
VoidShowImage::VoidShowImage(QWidget *parent):
QWidget (parent)
{
m_iWidth = 640;
m_iHeight = 480;
initPlay();
pq_YuvData = new char[m_iWidth * m_iHeight * 3 / 2];
memset(pq_YuvData,0,m_iWidth * m_iHeight * 3 /2);
QGridLayout *pq_gridLayout = new QGridLayout;
pq_videoShowLabel = new QLabel(this);
pq_gridLayout->addWidget(pq_videoShowLabel);
this->setLayout(pq_gridLayout);
}
VoidShowImage::~VoidShowImage()
{
sws_freeContext(img_convert_ctx);
}
void VoidShowImage::showImage(QByteArray arrayData)
{
if (arrayData.isEmpty())
return;
memcpy(pq_YuvData,arrayData.data(),arrayData.size());
switchYuvToRgb(pq_YuvData,arrayData.length());
update();
}
void VoidShowImage::paintEvent(QPaintEvent *)
{
//把这个RGB数据 用QImage加载
QPainter painter(this);
QImage tmpImg((uchar *)rgbBuffer,m_iWidth,m_iHeight,QImage::Format_RGB32);
QImage img = tmpImg.scaled(this->size(),Qt::IgnoreAspectRatio);
int x = this->width() - img.width();
int y = this->height() - img.height();
painter.drawImage(QPoint(x,y),img); //画出图像
}
// 初始化
void VoidShowImage::initPlay()
{
//width和heigt为传入的分辨率的大小
int yuvSize = m_iWidth * m_iHeight * 3 /2;
yuvBuffer = (uint8_t *)malloc(yuvSize);
//为每帧图像分配内存
pFrame = av_frame_alloc();
pFrameRGB = av_frame_alloc();
int numBytes = avpicture_get_size(PIX_FMT_RGB32, m_iWidth,m_iHeight);
rgbBuffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t));
avpicture_fill((AVPicture *) pFrameRGB, rgbBuffer, PIX_FMT_RGB32,m_iWidth, m_iHeight);
//设置图像转换上下文
img_convert_ctx = sws_getContext(m_iWidth, m_iHeight, AV_PIX_FMT_YUV420P, m_iWidth, m_iHeight, PIX_FMT_RGB32, SWS_BICUBIC, nullptr, nullptr, nullptr);
}
// 转换数据
void VoidShowImage::switchYuvToRgb(void* p_yuvData, int len)
{
avpicture_fill((AVPicture *) pFrame, (uint8_t *)p_yuvData, AV_PIX_FMT_YUV420P, m_iWidth, m_iHeight);//这里的长度和高度跟之前保持一致
//转换图像格式,将解压出来的YUV420P的图像转换为RGB的图像
sws_scale(img_convert_ctx,
(uint8_t const * const *) pFrame->data,
pFrame->linesize, 0, m_iHeight, pFrameRGB->data,
pFrameRGB->linesize);
}
相对于之前做法,该方法具有一定提升
如有疑问加群:676977101(新群)