Qt与FFMPEG联合开发--循环解码相关操作

目录

一:结果

二:解码准备工作+循环解码相关操作

videodecode.h .cpp

main.cpp


一:结果

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

 

 

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();
}

猜你喜欢

转载自blog.csdn.net/m0_56051805/article/details/125050168