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

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

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值