Qt+FFMPEG实现循环解码详解

2022-11-13 14:11:09 循环 解码 详解

一、结果

可以设置延时函数-----遍历每一帧的信息进行打印

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解码内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

相关文章