ffmpeg 显示图片 接收网络数据用ffmpeg 显示

#ifndef IMAGE_PROCESSOR_H
#define IMAGE_PROCESSOR_H

#include 
#include 
#include 

extern "C" {
#include 
#include 
#include 
}

class ImageProcessor : public QObject
{
    Q_OBJECT
public:
    explicit ImageProcessor(QObject *parent = nullptr);
    ~ImageProcessor();

    void processImage(const QByteArray& imageData, QImage& image);

signals:
    void imageProcessed(const QImage &image);

private:
    AVCodec *decoder;
    AVCodecContext *decoderContext;
    SwsContext *swsContext;
};

#endif // IMAGE_PROCESSOR_H    
#include "image_processor.h"
#include 
ImageProcessor::ImageProcessor(QObject *parent) : QObject(parent)
{
    av_register_all();
    avcodec_register_all();

    decoder = avcodec_find_decoder(AV_CODEC_ID_MJPEG);
    if (!decoder) {
        qDebug() << "Could not find decoder";
        return;
    }

    decoderContext = avcodec_alloc_context3(decoder);
    if (!decoderContext) {
        qDebug() << "Could not allocate codec context";
        return;
    }

    if (avcodec_open2(decoderContext, decoder, nullptr) < 0) {
        qDebug() << "Could not open codec";
        return;
    }
}

ImageProcessor::~ImageProcessor()
{
    if (decoderContext) {
        avcodec_free_context(&decoderContext);
    }
    if (swsContext) {
        sws_freeContext(swsContext);
    }
}

void ImageProcessor::processImage(const QByteArray &imageData, QImage& image)
{
    AVPacket packet;
    av_init_packet(&packet);
    packet.data = reinterpret_cast(const_cast(imageData.data()));
    packet.size = imageData.size();

    AVFrame *frame = av_frame_alloc();
    if (!frame) {
        qDebug() << "Could not allocate frame";
        return;
    }

    if (avcodec_send_packet(decoderContext, &packet) < 0) {
        qDebug() << "Error sending packet to decoder";
        av_frame_free(&frame);
        return;
    }

    if (avcodec_receive_frame(decoderContext, frame) < 0) {
        qDebug() << "Error receiving frame from decoder";
        av_frame_free(&frame);
        return;
    }

    int newWidth = decoderContext->width;
    int newHeight = decoderContext->height;

    swsContext = sws_getContext(
        decoderContext->width, decoderContext->height, decoderContext->pix_fmt,
        newWidth, newHeight, AV_PIX_FMT_RGB24,
        SWS_BILINEAR, nullptr, nullptr, nullptr
    );
    if (!swsContext) {
        qDebug() << "Could not allocate sws context";
        av_frame_free(&frame);
        return;
    }

    AVFrame *outputFrame = av_frame_alloc();
    if (!outputFrame) {
        qDebug() << "Could not allocate output frame";
        sws_freeContext(swsContext);
        av_frame_free(&frame);
        return;
    }

    outputFrame->format = AV_PIX_FMT_RGB24;
    outputFrame->width = newWidth;
    outputFrame->height = newHeight;
    if (av_frame_get_buffer(outputFrame, 0) < 0) {
        qDebug() << "Could not allocate output frame buffer";
        sws_freeContext(swsContext);
        av_frame_free(&outputFrame);
        av_frame_free(&frame);
        return;
    }

    sws_scale(swsContext, frame->data, frame->linesize, 0, decoderContext->height,
              outputFrame->data, outputFrame->linesize);

    QImage img(newWidth, newHeight, QImage::Format_RGB888);
    for (int y = 0; y < newHeight; ++y) {
        memcpy(img.scanLine(y), outputFrame->data[0] + y * outputFrame->linesize[0], newWidth * 3);
    }

    emit imageProcessed(img);

    sws_freeContext(swsContext);
    av_frame_free(&outputFrame);
    av_frame_free(&frame);
    img.swap(image);
}    

在做网络投屏时,遇到接收数据后在加载到QImage时,时不时的就会出现加载图片失败,导致实时投屏显示花屏、闪烁,就行借用了ffmpeg 对图片数据的处理能力。处理好后绘制到QT界面上。

你可能感兴趣的:(ffmpeg,网络,qt5)