Qt + ffmpeg 视频解码

1.创建Qt项目,选择编译器为Android_for_armeabi_v7。


2.使用之前编译好的ffmpeg头文件和库文件 


a.在项目目录创建ffmpeg目录,目录里面包含include目录和lib目录,分别为ffmpeg的头文件和静态库文件所在目录 


b.把ffmpeg\lib\libavcodec.a ffmpeg\lib\libavformat.a ffmpeg\lib\libavutil.a ffmpeg\lib\libswscale.a拷贝到 Qt目录\Qt5.3.1\5.3\android_armv7\lib目录下面 


c.修改ffmpeg\include\libavutil\common.h 增加一行 #define UINT64_C(value) __CONCAT(value, ULL)


3.编辑项目文件


QT += core gui widgets


HEADERS += video.h videodec.h


SOURCES += main.cpp video.cpp videodec.cpp


INCLUDEPATH += ./ffmpeg/include #头文件路径


DEFINES += UINT64_C #增加定义


LIBS += -L./ffmpeg/lib -lavcodec -lavformat -lswscale -lavutil # -lavutil 放在最后面


4.编译、发布到android手机。

付源码:

ffmpeg.pro

QT += core gui widgets
 
HEADERS += \
    video.h \
    videodec.h
 
SOURCES += \
    main.cpp \
    video.cpp \
    videodec.cpp
 
INCLUDEPATH += ./ffmpeg/include
 
DEFINES += UINT64_C
 
LIBS += -L./ffmpeg/lib -lavcodec -lavformat -lswscale -lavutil

main.cpp

#include "video.h"
#include <QApplication>
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.showMaximized();
    return a.exec();
}

video.h

#ifndef VIDEO_H
#define VIDEO_H
 
#include <QThread>
#include <QWidget>
#include <QDebug>
#include <QImage>
#include <QPixmap>
#include <QPushButton>
#include <QLineEdit>
#include <QLabel>
#include "videodec.h"
 
class Video;
 
class MainWindow : public QWidget
{
    Q_OBJECT
 
public:
    explicit MainWindow(QWidget *parent = 0);
 
private:
    QPushButton *playButton;
    QPushButton *browseButton;
    QLineEdit *fileNameEdit;
    QLabel *fileLabel;
    Video *video;
 
private:
    void setupUI();
 
private slots:
    void onVideoPlay();
    void onBrowseMP4();
 
};
 
class Video : public QWidget
{
    Q_OBJECT
 
public:
    explicit Video(QWidget *parent = 0);
    ~Video();
 
private:
    QThread *videoDecThread;
    VideoDec *videoDec;
 
protected:
    void paintEvent(QPaintEvent *event);
 
signals:
    void init();
    void play();
    void setFileName(QString);
 
public slots:
    void showVideo(const QImage &img);
    void onVideoPlay();
    void onBrowseMP4(QString fileName);
 
};
 
#endif // VIDEO_H

video.cpp

#include "video.h"
#include <QPainter>
#include <QHBoxLayout>
#include <QFileDialog>
#include <QApplication>
 
static QImage showImage;
 
Video::Video(QWidget *parent) : QWidget(parent)
{
    videoDecThread = new QThread(this);
    videoDec = new VideoDec;
    videoDec->moveToThread(videoDecThread);
    videoDecThread->start();
 
    connect(this, SIGNAL(init()), videoDec, SLOT(init()));
    connect(this, SIGNAL(play()), videoDec, SLOT(play()));
    connect(this, SIGNAL(setFileName(QString)), videoDec, SLOT(setFileName(QString)));
    connect(videoDec, SIGNAL(SendImage(QImage)), this, SLOT(showVideo(QImage)));
}
 
Video::~Video()
{
}
 
void Video::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
 
    QRectF target(0, 0, width(), height());
    QRectF source(0.0, 0.0, width(), height());
 
    painter.drawImage(target, showImage, source);
}
 
void Video::onVideoPlay()
{
    emit init();
    emit play();
}
 
void Video::onBrowseMP4(QString fileName)
{
    emit setFileName(fileName);
}
 
void Video::showVideo(const QImage &img)
{
    showImage = img;
    update();
 
//    QPixmap pix;
//    pix = pix.fromImage(img).scaledToWidth(ui->VideoShow->width());
}
 
 
MainWindow::MainWindow(QWidget *parent) : QWidget(parent)
{
    setupUI();
}
 
void MainWindow::setupUI()
{
    fileLabel = new QLabel("File:", this);
    fileNameEdit = new QLineEdit(this);
 
    playButton = new QPushButton("Play", this);
    connect(playButton, SIGNAL(clicked()), this, SLOT(onVideoPlay()));
 
    browseButton = new QPushButton("Browse", this);
    connect(browseButton, SIGNAL(clicked()), this, SLOT(onBrowseMP4()));
 
    video = new Video(this);
 
    QHBoxLayout *toolLayout = new QHBoxLayout;
    toolLayout->addWidget(fileLabel);
    toolLayout->addWidget(fileNameEdit);
    toolLayout->addWidget(browseButton);
    toolLayout->addWidget(playButton);
 
    QVBoxLayout *mainLayout = new QVBoxLayout;
    mainLayout->addLayout(toolLayout);
    mainLayout->addWidget(video);
 
    setLayout(mainLayout);
}
 
void MainWindow::onVideoPlay()
{
    video->onVideoPlay();
}
 
void MainWindow::onBrowseMP4()
{
    QString dir = QApplication::applicationDirPath();
 
    QString fileName = QFileDialog::getOpenFileName(this, tr("Select a image file"), dir, tr("Image Files (*.*)"));
 
    if (!fileName.isEmpty())
    {
        fileNameEdit->setText(fileName);
        video->onBrowseMP4(fileName);
    }
}

videodec.h

#ifndef VIDEODEC_H
#define VIDEODEC_H
 
extern "C"{
    #include "libavcodec/avcodec.h"
    #include "libavformat/avformat.h"
    #include "libavutil/avutil.h"
    #include "libavutil/mem.h"
    #include "libavutil/fifo.h"
    #include "libswscale/swscale.h"
}
 
#include <QObject>
#include <QImage>
#include <QThread>
#include <QDebug>
 
typedef quint8 uint8_t;
 
class VideoDec : public QObject
{
    Q_OBJECT
public:
    explicit VideoDec(QObject *parent = 0);
    int videoindex;
    AVFormatContext *pFormatCtx;
    AVCodecContext *pCodecCtx;
    AVCodec *pCodec;
    AVPacket *packet;
    AVFrame *pFrame,*pFrameRGB;
    QString FileName;
 
signals:
    void SendImage(QImage img);
 
public slots:
    void init();
    void play();
    void setFileName(QString name);
 
};
 
#endif // VIDEODEC_H

videodec.cpp

#include "videodec.h"
VideoDec::VideoDec(QObject *parent) : QObject(parent)
{
}
void VideoDec::init()
{
    avcodec_register_all();
    av_register_all();
    pFormatCtx = avformat_alloc_context();
    if(avformat_open_input(&pFormatCtx, FileName.toLatin1().constData(), NULL, NULL) != 0)
    {
        qDebug() << "OpenFail";
    }
    if(avformat_find_stream_info(pFormatCtx, NULL) < 0)
    {
        qDebug() << "FindFail";
    }
    videoindex = -1;
    for(int i = 0; pFormatCtx->nb_streams; i++)
    {
        if(pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
        {
            videoindex = i;
            break;
        }
    }
    if(videoindex == -1)
    {
        qDebug() << "Din't find video stream";
    }
    pCodecCtx = pFormatCtx->streams[videoindex]->codec;
    pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
    if(pCodec == NULL)
    {
        qDebug() << "codec not find";
    }
    if(avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
    {
        qDebug() << "can't open codec";
    }
    pFrame = avcodec_alloc_frame();
    pFrameRGB = avcodec_alloc_frame();
    play();
}
void VideoDec::play()
{
    int got_picture;
 
    int size = pCodecCtx->width*pCodecCtx->height;
    packet=(AVPacket *)malloc(sizeof(AVPacket));
    av_new_packet(packet, size);
 
    uint8_t *buffer;
    buffer = new uint8_t[avpicture_get_size(PIX_FMT_RGB32, pCodecCtx->width, pCodecCtx->height)];
    avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB32, pCodecCtx->width, pCodecCtx->height);
    while(av_read_frame(pFormatCtx,packet) >= 0)
    {
        if(packet->stream_index == videoindex)
        {
            int rec = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
            if(rec > 0)
            {
                SwsContext *convertCtx = sws_getContext(pCodecCtx->width,pCodecCtx->height,
                                                        pCodecCtx->pix_fmt,
                                                        pCodecCtx->width,
                                                        pCodecCtx->height,
                                                        PIX_FMT_RGB32,
                                                        SWS_BICUBIC,
                                                        NULL, NULL, NULL);
                sws_scale(convertCtx, (const uint8_t* const*)pFrame->data, pFrame->linesize,
                          0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
                QImage Img((uchar *)pFrameRGB->data[0], pCodecCtx->width, pCodecCtx->height, QImage::Format_RGB32);
                emit SendImage(Img);
            }
        }
        av_free_packet(packet);
        QThread::msleep(4);
    }
}
void VideoDec::setFileName(QString name)
{
    FileName = name;
}
 

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值