Qt+FFMPEG實現(xiàn)循環(huán)解碼詳解
一、結(jié)果
可以設(shè)置延時函數(shù)-----遍歷每一幀的信息進行打印
25(fps)*30(秒)=750幀
二、解碼準備工作+循環(huán)解碼相關(guān)操作
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:視頻像素數(shù)據(jù)格式轉(zhuǎn)換 #include <libswscale/swscale.h> //avdevice:各種設(shè)備的輸入輸出 #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(); //參數(shù)一:封裝格式上下文->AVFormatContext->包含了視頻信息(視頻格式、大小等等...) //參數(shù)二:打開文件(入口文件)->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.查找視頻流信息"; //參數(shù)一:封裝格式上下文->AVFormatContext //參數(shù)二:配置 //返回值: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) { //循環(huán)遍歷每一流 //視頻流、音頻流、字幕流等等... if (avformat_context->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO){ //找到了 av_stream_index = i; break; } } if (av_stream_index == -1) { qDebug()<<QString("沒有找到視頻流"); } //第二點:根據(jù)視頻流->查找到視頻解碼器上下文->視頻壓縮數(shù)據(jù) //編解碼器上下文 avcodec_context = avformat_context->streams[av_stream_index]->codec; //第三點:根據(jù)解碼器上下文->獲取解碼器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()<<"視頻詳細信息輸出"; //此函數(shù)自動打印輸入或輸出的詳細信息 av_dump_format(avformat_context, 0, cinputFilePath.toStdString().c_str(), 0); qDebug()<<"----------------解碼準備工作完成-----------------"; qDebug()<<"----------------開始循環(huán)解碼操作-----------------"; qDebug()<<"6.循環(huán)解碼"; //讀取幀數(shù)據(jù)換成到哪里->緩存到packet里面 AVPacket* av_packet = (AVPacket*)av_malloc(sizeof(AVPacket)); //解碼的狀態(tài)類型(0:表示解碼完畢,非0:表示正在解碼) int current_frame_index = 0; //>=0:說明有數(shù)據(jù),繼續(xù)讀取 <0:說明讀取完畢,結(jié)束 //從視頻文件上下文中讀取包--- 有數(shù)據(jù)就一直讀取 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.關(guān)閉所有解碼組件"; av_packet_free(&av_packet); //關(guān)閉流 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"http://數(shù)據(jù)庫類 #include"videodecode.h" //當前C++兼容C語言 extern "C" { //avcodec:編解碼(最重要的庫) #include <libavcodec/avcodec.h> //avformat:封裝格式處理 #include <libavformat/avformat.h> //swscale:視頻像素數(shù)據(jù)格式轉(zhuǎn)換 #include <libswscale/swscale.h> //avdevice:各種設(shè)備的輸入輸出 #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");//創(chuàng)建數(shù)據(jù)庫 mySqlite::createUserTable("user");//創(chuàng)建用戶表 videoDecode *p = new videoDecode; //開機動畫 myView kaiji;//對象創(chuàng)建 kaiji.show();//調(diào)用方法 return a.exec(); }
到此這篇關(guān)于Qt+FFMPEG實現(xiàn)循環(huán)解碼詳解的文章就介紹到這了,更多相關(guān)Qt FFMPEG解碼內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用pybind11封裝C++結(jié)構(gòu)體作為參數(shù)的函數(shù)實現(xiàn)步驟
這篇文章主要介紹了用pybind11封裝C++結(jié)構(gòu)體作為參數(shù)的函數(shù)實現(xiàn)步驟,本文分步驟通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2020-02-02使用VSCode和VS2017編譯調(diào)試STM32程序的實現(xiàn)
這篇文章主要介紹了使用VSCode和VS2017編譯調(diào)試STM32程序的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-05-05結(jié)合C++11的新特性來解析C++中的枚舉與聯(lián)合
這篇文章主要介紹了C++編程中的枚舉與聯(lián)合,結(jié)合了范圍(或強類型)enum class類型等C++11的新特性來講解,需要的朋友可以參考下2016-01-01c++ 內(nèi)聯(lián)函數(shù)和普通函數(shù)的區(qū)別
內(nèi)聯(lián)函數(shù)是c++為了提高程序的運行速度做的改進,那么內(nèi)聯(lián)函數(shù)和普通函數(shù)的區(qū)別是什么,本文就來詳細的介紹一下,感興趣的朋友可以了解一下2021-05-05