Qt+FFMPEG實現循環解碼詳解

一、結果

可以設置延時函數—–遍歷每一幀的信息進行打印

25(fps)*30(秒)=750幀

二、解碼準備工作+循環解碼相關操作

videodecode.h .cpp

#ifndef VIDEODECODE_H
#define VIDEODECODE_H
 
#include <QObject>
 
//當前C++兼容C語言
extern "C"
{
//avcodec:編解碼(最重要的庫)
#include <libavcodec/avcodec.h>
//avformat:封裝格式處理
#include <libavformat/avformat.h>
//swscale:視頻像素數據格式轉換
#include <libswscale/swscale.h>
//avdevice:各種設備的輸入輸出
#include <libavdevice/avdevice.h>
//avutil:工具庫(大部分庫都需要這個庫的支持)
#include <libavutil/avutil.h>
}
 
class videoDecode : public QObject
{
    Q_OBJECT
public:
    explicit videoDecode(QObject *parent = 0);
 
     //視頻文件上下文格式
     AVFormatContext* avformat_context;
     //編解碼器上下文格式
     AVCodecContext* avcodec_context;
     //解碼器上下文格式
     AVCodec* avcodec;
 
 
 
signals:
 
public slots:
};
 
#endif // VIDEODECODE_H
#include "videodecode.h"
#include<QDebug>
#include<QCoreApplication>
#include<QThread>
 
//解碼初始化操作
//1.註冊所有組件
//2.打開視頻輸入文件
//3.查找視頻流信息
//4.查找解碼器
//5.打開解碼器
 
videoDecode::videoDecode(QObject *parent) : QObject(parent)
{
    qDebug()<<"1.註冊所有組件";
    av_register_all();
 
    qDebug()<<"2.打開視頻輸入文件";
    QString filename = QCoreApplication::applicationDirPath();
    qDebug()<<"獲取程序運行目錄 "<<filename;
    QString cinputFilePath = "test.avi";  //本地視頻文件放入程序運行目錄
    avformat_context = avformat_alloc_context();
    //參數一:封裝格式上下文->AVFormatContext->包含瞭視頻信息(視頻格式、大小等等...)
    //參數二:打開文件(入口文件)->url
    int avformat_open_result = avformat_open_input(&avformat_context,cinputFilePath.toStdString().c_str(),NULL,NULL);
    if (avformat_open_result != 0)
    {
        //獲取異常信息
        char* error_info = new char[32];
        av_strerror(avformat_open_result, error_info, 1024);
        qDebug()<<QString("異常信息 %1").arg(error_info);
 
    };
 
    qDebug()<<"3.查找視頻流信息";
    //參數一:封裝格式上下文->AVFormatContext
    //參數二:配置
    //返回值:0>=返回OK,否則失敗
    int avformat_find_stream_info_result = avformat_find_stream_info(avformat_context, NULL);
    if (avformat_find_stream_info_result < 0){
        //獲取失敗
        char* error_info = new char[32];
        av_strerror(avformat_find_stream_info_result, error_info, 1024);
        qDebug()<<QString("異常信息 %1").arg(error_info);
    }
 
    qDebug()<<"4.查找解碼器";
    //第一點:獲取當前解碼器是屬於什麼類型解碼器->找到瞭視頻流
    //音頻解碼器、視頻解碼器、字幕解碼器等等...
    //獲取視頻解碼器流引用
    int av_stream_index = -1;
    for (int i = 0; i < avformat_context->nb_streams; ++i) {
        //循環遍歷每一流
        //視頻流、音頻流、字幕流等等...
        if (avformat_context->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO){
            //找到瞭
            av_stream_index = i;
            break;
        }
    }
    if (av_stream_index == -1)
    {
        qDebug()<<QString("沒有找到視頻流");
    }
    //第二點:根據視頻流->查找到視頻解碼器上下文->視頻壓縮數據
    //編解碼器上下文
    avcodec_context = avformat_context->streams[av_stream_index]->codec;
 
    //第三點:根據解碼器上下文->獲取解碼器ID
    avcodec = avcodec_find_decoder(avcodec_context->codec_id);
    if (avcodec == NULL)
    {
        qDebug()<<QString("沒有找到視頻解碼器");
    }
 
    qDebug()<<"5.打開解碼器";
    int avcodec_open2_result = avcodec_open2(avcodec_context,avcodec,NULL);
    if (avcodec_open2_result != 0)
    {
        char* error_info = new char[32];
        av_strerror(avformat_find_stream_info_result, error_info, 1024);
        qDebug()<<QString("異常信息 %1").arg(error_info);
    }
 
    qDebug()<<"視頻詳細信息輸出";
    //此函數自動打印輸入或輸出的詳細信息
    av_dump_format(avformat_context, 0, cinputFilePath.toStdString().c_str(), 0);
    qDebug()<<"----------------解碼準備工作完成-----------------";
    qDebug()<<"----------------開始循環解碼操作-----------------";
 
    qDebug()<<"6.循環解碼";
 
    //讀取幀數據換成到哪裡->緩存到packet裡面
    AVPacket* av_packet = (AVPacket*)av_malloc(sizeof(AVPacket));
    //解碼的狀態類型(0:表示解碼完畢,非0:表示正在解碼)
    int current_frame_index = 0;
 
    //>=0:說明有數據,繼續讀取   <0:說明讀取完畢,結束
    //從視頻文件上下文中讀取包--- 有數據就一直讀取
    while (av_read_frame(avformat_context,av_packet) >= 0)
    {
        //解碼什麼類型流(視頻流、音頻流、字幕流等等...)
        if (av_packet->stream_index == av_stream_index)
        {
                //遍歷每一幀的信息進行打印
                current_frame_index++;
                //延時操作  1秒顯示25幀--1000/25=40
                QThread::msleep(40);
                qDebug()<<QString("當前遍歷第 %1 幀").arg(current_frame_index);
        }
    }
 
    qDebug()<<"7.關閉所有解碼組件";
    av_packet_free(&av_packet);
    //關閉流
    avcodec_close(avcodec_context);
    avformat_free_context(avformat_context);
}

main.cpp

#include "widget.h"
#include <QApplication>
#include"indexwin.h"
#include<QGraphicsItem>    //圖元
#include<QGraphicsScene>   //場景
#include<QGraphicsView>    //視圖
#include<QTransform>       //變換
#include<QDebug>
#include"myview.h"
#include <QWidget>
#include"usersdata.h"
#include"registerwin.h"
#include"sqlite3.h"
#include"mysqlite.h"//數據庫類
#include"videodecode.h"
 
 
//當前C++兼容C語言
extern "C"
{
//avcodec:編解碼(最重要的庫)
#include <libavcodec/avcodec.h>
//avformat:封裝格式處理
#include <libavformat/avformat.h>
//swscale:視頻像素數據格式轉換
#include <libswscale/swscale.h>
//avdevice:各種設備的輸入輸出
#include <libavdevice/avdevice.h>
//avutil:工具庫(大部分庫都需要這個庫的支持)
#include <libavutil/avutil.h>
}
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
 
    qDebug()<<"sqlite3版本"<<sqlite3_libversion();
 
    qDebug("------------------------------------------------------------------------");
    qDebug("%s", avcodec_configuration());
    qDebug("version: %d", avcodec_version());
    qDebug("------------------------------------------------------------------------");
 
    mySqlite::getInstance("app.db");//創建數據庫
    mySqlite::createUserTable("user");//創建用戶表
 
    videoDecode *p = new videoDecode;
 
    //開機動畫
    myView kaiji;//對象創建
    kaiji.show();//調用方法
 
    return a.exec();
}

到此這篇關於Qt+FFMPEG實現循環解碼詳解的文章就介紹到這瞭,更多相關Qt FFMPEG解碼內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: