Qt+FFMPEG实现循环解码详解

 更新时间:2022年8月5日 15:05  点击:254 作者:我今年十六岁

一、结果

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

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

原文出处:https://blog.csdn.net/m0_56051805/article/details/125050168

[!--infotagslink--]

相关文章

  • Python 利用base64库 解码本地txt文本字符串

    这篇文章主要介绍了Python 利用base64库 解码本地txt文本字符串的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-04-09
  • Qt 使用Poppler实现pdf阅读器的示例代码

    下面小编就为大家分享一篇Qt 使用Poppler实现pdf阅读器的示例代码,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-04-25
  • 将matplotlib绘图嵌入pyqt的方法示例

    这篇文章主要介绍了将matplotlib绘图嵌入pyqt的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-27
  • Qt定时器和随机数详解

    在前一篇中我们介绍了键盘和鼠标事件,其实还有一个非常常用的事件,就是定时器事件,如果要对程序实现时间上的控制,那么就要使用到定时器。而随机数也是很常用的一个功能,在我们要想产生一个随机的结果时就要使用到随机数。本文我们就来简单介绍一下定时器和随机数。...2020-04-25
  • 一篇文章教你3分钟如何发布Qt程序

    这篇文章主要给大家介绍了关于教你3分钟如何发布Qt程序的相关资料,文中通过实例代码结束的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧...2020-08-24
  • php利用ffmpeg提取视频中音频与视频

    本篇文章为大家介绍了PHP利用ffmpeg提取视频中音频与视频画面的相关资料,很有参考价值,一起来看一看吧。 前言FFmpeg的名称来自MPEG视频编码标准,前面的“FF”代表...2017-07-06
  • Qt实现闹钟小程序

    这篇文章主要为大家详细介绍了Qt实现闹钟小程序,利用Qt的designer设计需要的闹钟界面,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-04-25
  • Qt使用windeployqt工具实现程序打包发布方法

    本文主要介绍了Qt使用windeployqt工具实现程序打包发布方法,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-11-01
  • 浅谈Qt信号与槽的各种连接方式

    信号和槽是Qt特有的信息传输机制,本文主要介绍了浅谈Qt信号与槽的各种连接方式,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-02
  • PyQt QMainWindow的使用示例

    这篇文章主要介绍了PyQt QMainWindow的使用示例,帮助大家更好的理解和学习使用pyqt,感兴趣的朋友可以了解下...2021-03-20
  • Qt实现UDP多线程数据处理及发送的简单实例

    本文主要介绍了Qt实现UDP多线程数据处理及发送的简单实例,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-10-21
  • Qt自定义控件实现线条型加载条

    这篇文章主要为大家详细介绍了Qt自定义控件实现线条型加载条,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-04-25
  • Qt自定义控件实现圆圈加载进度条

    这篇文章主要为大家详细介绍了Qt自定义控件实现圆圈加载进度条,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-04-25
  • Qt实现Flappy Bird游戏

    这篇文章主要为大家详细介绍了Qt实现Flappy Bird游戏,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-04-25
  • Qt使用QPainter绘制3D立方体

    这篇文章主要为大家详细介绍了Qt使用QPainter绘制3D立方体,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-08-21
  • Qt实现进程界面之间的鼠标焦点切换

    这篇文章主要为大家详细介绍了Qt实现进程界面之间的鼠标焦点切换,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-09-25
  • QT开发应用程序的欢迎界面实例

    下面小编就为大家带来一篇QT开发应用程序的欢迎界面实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-04-25
  • Qt实现网络聊天室的示例代码

    本文主要介绍了Qt实现网络聊天室,实现一个在线聊天室, 使用tcp对客户端和服务器端进行通讯。具有一定的参考价值,具有一定的参考价值,...2021-06-23
  • QT串口通信的实现方法

    如果用qt写程序作为上位机,然后通过和usb和下位机通信的时候,就需要用到qt中的串口通信了。本文介绍了QT串口通信的实现方法,感兴趣的小伙伴们可以参考一下...2021-05-20
  • c++ base64编解码使用示例

    这篇文章主要介绍了c++的base64编解码使用示例,需要的朋友可以参考下...2020-04-25