视频数据帧YUV格式转RGB格式--ffmpeg转换Qt利用Image显示

it2022-05-05  200

接之前帖子,自己编写算法视频格式转换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(新群)


最新回复(0)