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

到此这篇关于Qt+FFMPEG实现循环解码详解的文章就介绍到这了,更多相关Qt FFMPEG解码内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Qt+OpenCV利用帧差法实现车辆识别

    目录 一.目标 二.使用Qt界面 三.代码实现 一.目标 Qt界面实现 点击 线程启动按钮播放视频 左边界面显示原视频 右边界面显示车辆识别视频 结果展示如下: 初始界面 点击线程启动后,即可车辆识别 二.使用Qt界面 设计好界面后最好先保存 对按钮设置槽函数 三.代码实现 难点在于:线程同步问题 需要使用到connect函数中的第五个参数[第五个参数 具体说明如下] 1 AutoConnection 为默认参数,由发送信号决定,如果发送信号和接受信号是同一个线程,则调用DirectConnec

  • Qt实现解压带有密码的加密文件

    目录 1.指定zip压缩包状态 2.创建解压文件 3.获取实际的压缩数量 4.遍历方式创建解压缩文件 4.1设置解压文件的参数 4.2以读的方式打开加密文件 4.3获取当前文件的所有内容 4.4创建解压缩后的同名文件 5.关闭zip压缩包 上一章节中介绍了如何使用Qt编译quazip库以及对文件加解密的简单应用,那么,今天我们继续深挖关于解密操作的功能吧! 简单的解密一个压缩包,可以使用#include "JlCompress.h"中的函数进行静态操作.如果你只是需要简单的应用那么,这

  • OpenCV+Qt实现图像处理操作工具的示例代码

    目录 一.目标 二.使用Qt界面 三.图像处理操作完整代码 一.目标 Qt界面实现 雪花屏 高斯模糊 中值滤波 毛玻璃 灰度化 XY方向模糊 双边模糊 腐蚀 [图像处理操作] 要求左边原图,右边效果图 结果展示如下:[图像处理实现有点多,就不一个一个地展示了,各别展示如下] 雪花屏 毛玻璃 灰度化处理 二.使用Qt界面 使用到Qt中的UI设计界面 设计好界面之后最好先保存 对每一个按钮设计槽函数 三.图像处理操作完整代码 难点在于:Qt是QImage而OpenCV是Mat,需要Mat转QImag

  • 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

  • ffmpeg播放器实现详解之框架搭建过程

    ffplay是ffmpeg源码中一个自带的开源播放器实例,同时支持本地视频文件的播放以及在线流媒体播放,功能非常强大. FFplay: FFplay is a very simple and portable media player using the FFmpeg libraries and the SDL library. It is mostly used as a testbed for the various FFmpeg APIs. ffplay中的代码充分调用了ffmpeg中的函

  • ffmpeg播放器实现详解之视频显示(推荐)

    FFmpeg是一套可以用来记录.转换数字音频.视频,并能将其转化为流的开源计算机程序.它包括了目前领先的音/视频编码库libavcodec. FFmpeg是在 Linux 下开发出来的,但它可以在包括 Windows 在内的大多数操作系统中编译.这个项目是由 Fabrice Bellard 发起的,现在由 Michael Niedermayer 主持.可以轻易地实现多种视频格式之间的相互转换,例如可以将摄录下的视频avi等转成现在视频网站所采用的flv格式. ffplay是ffmpeg源码中一个

  • Python imageio读取视频并进行编解码详解

    读视频和写视频一直由于编解码的问题给程序员造成很多麻烦.对此进行了一些探索.用Python读取视频有两种主要方法,分别是基于imageio库和OpenCV,其中OpenCV加上ffmpeg的安装编译很麻烦,推荐大家使用第一种方法,不过大家也可依据自己的需求进行使用. 方法一:使用imageio库 1. 一般imageio库Anconda自带的有,不用我们单独安装,没有安装的可用pip安装或自己下载. imageio使用方法可参考:http://imageio.readthedocs.io/en/

  • 基于Qt播放器的实现详解(支持Rgb,YUV格式)

    目录 色度空间转换 YUV转RGB的公式 对本地RGB32视频图像的播放 1.绘图显示函数 打开目录函数 2.按开始播放的槽函数 3.启动线程 进行播放 4.格式转换函数 5.实现进度条与暂停的各类函数 6.各类槽函数的连接 色度空间转换 YUV颜色模型其实常用于视频传输和图像压缩.由于人类的眼睛,对亮度的敏感度远超过对色彩的敏感度,所以视频传输过程中,为了减小带宽,通常将色彩分量 UV的比例减小,以达到降低带宽的目的.这就出现了YUV4:4:4.YUV4:2:2.YUV4:1:1等格式. RG

  • JS定时器使用,定时定点,固定时刻,循环执行详解

    本文概述:本文主要介绍通过JS实现定时定点执行,在某一个固定时刻执行某个函数的方法.比如说在下一个整点执行,在每一个整点执行,每隔10分钟定时执行的方法. JavaScript中有两个定时器方法:setTimeout()和setInterval(). 这两个方法都可以用来实现在一个固定时间段之后去执行JavaScript.实际上,setTimeout和setInterval的语法相同.它们都有两个参数,一个是将要执行的代码字符串,或者函数名,还有一个是以毫秒为单位的时间间隔,当过了那个时间段之后

  • shell中的for循环用法详解

    for 命令: for i in 的各种用法 : for i in "file1" "file2" "file3" for i in /boot/* for i in /etc/*.conf for i in $(seq -w 10) -->等宽的01-10 for i in {1-10} for i in $( ls ) for I in $(< file) for i in "$@" -->取所有位置参数

  • Windows bat脚本之for循环用法详解

    Windows bat脚本的for语句基本形态如下: 在cmd窗口中:for %I in (command1) do command2 在批处理文件中:for %%I in (command1) do command2 之所以要区分cmd窗口和批处理文件两种环境,是因为在这两种环境下,命令语句表现出来的行为虽然基本一样,但是在细节上还是稍有不同,最明显的一个差异就是:在cmd窗口中,for之后的形式变量I必须使用单百分号引用,即%I:而在批处理文件中,引用形式变量I必须使用双百分号,即%%I.为

  • java迭代器和for循环优劣详解

    在进行迭代的时候,程序运行的效率也是我们挑选迭代方法的重要原因.目前有三种迭代方法:for循环.迭代器和Foreach.前两者相信大家都非常熟悉,为了更加直观分析效率的不同,我们还加入Foreach一起比较.下面我们就三种方法的概念进行理解,然后ArrayList中探索三种方法的效率. 1.概念理解 for循环:是支持迭代的一种通用结构,是最有效,最灵活的循环结构 迭代器:是通过集合的iterator()方法得到的,所以我们说它是依赖于集合而存在的 Foreach:通过阅读源码我们还发现一个It

  • R语言“循环”知识点详解

    可能有一种情况,当你需要执行一段代码几次. 通常,顺序执行语句. 首先执行函数中的第一个语句,然后执行第二个语句,依此类推. 编程语言提供允许更复杂的执行路径的各种控制结构. 循环语句允许我们多次执行一个语句或一组语句,以下是大多数编程语言中循环语句的一般形式 - R编程语言提供以下种类的循环来处理循环需求. 单击以下链接以检查其详细信息. Sr.No. 循环类型和描述 1 repeat循环 多次执行一系列语句,并简化管理循环变量的代码. 2 while循环 在给定条件为真时,重复语句或语句组.

随机推荐