Qt+FFmpeg+opengl从零制作视频播放器-3.解封装

解封装:如下图所示,就是将FLV、MKV、MP4等文件解封装为视频H.264或H.265压缩数据,音频MP3或AAC的压缩数据,下图为常用的基本操作。

 ffmpeg使用解封装的基本流程如下:

在使用FFmpeg API之前,需要先注册API,然后才能使用API。当然,新版本ffmpeg库不需要再调用下面的方法。

av_register_all()

初始化网络配置

avformat_network_init

设置一些参数,如下图所示,设置了最大延迟、传输协议等参数。

	//参数设置AVDictionary *opts = NULL;//设置rtsp流已tcp协议打开av_dict_set(&opts, "rtsp_transport", "tcp", 0);av_dict_set(&opts, "max_delay", "500", 0);av_dict_set(&opts, "buffer_size", "1024000", 0);av_dict_set(&opts, "probsize", "4096", 0);av_dict_set(&opts, "fps", "25", 0);

构建AVFormatContext,声明输入的封装结构体,通过输入文件或者流地址作为封装结构的句柄。

    AVFormatContext* inputFmtCtx = nullptr;const char* inputUrl = "test.mp4";///打开输入的流,获取数据 beginint ret = avformat_open_input(&inputFmtCtx, inputUrl, NULL, NULL);

查找音视频流信息,通过下面的接口与AVFormatContext中建立输入文件对应的流信息。

    //查找;if (avformat_find_stream_info(inputFmtCtx, NULL) < 0){printf("Couldn't find stream information.\n");return false;}


读取音视频流,采用av_read_frame来读取数据包,读出来的数据存储在AVPacket中,确定其为音频、视频、字幕数据,最后解码,或者存储。

    AVPacket* pkt = NULL;pkt = av_packet_alloc();while (av_read_frame(inputFmtCtx, pkt) >= 0){//获取数据包//.....解码或者存储//重置av_packet_unref(pkt);}

上述代码所示,通过循环调用av_read_frame()读取到pkt包,然后可以进行解码或者存储数据,如果读取的数据结束,则退出循环,开始指向结束操作。

每次使用完AVPacket包后,需要重置,否则会内存泄漏。

    //重置av_packet_unref(pkt);

执行结束后关闭输入文件,释放资源。

    //关闭avformat_close_input(&inputFmtCtx);//释放avformat_free_context(inputFmtCtx);//释放资源av_packet_free(&pkt);

 新建空白解决方案,如下图所示。

解决方案,右键-添加-新建项目。 

新建Qt控制台程序,3_demuxDemo 

然后,配置ffmpeg的编译环境:看目录4。

ffmpeg环境配置 

解封装源码示例:

#include <QtCore/QCoreApplication>extern "C" {
#include "libavutil/avstring.h"
#include "libavutil/channel_layout.h"
#include "libavutil/eval.h"
#include "libavutil/mathematics.h"
#include "libavutil/pixdesc.h"
#include "libavutil/imgutils.h"
#include "libavutil/dict.h"
#include "libavutil/fifo.h"
#include "libavutil/parseutils.h"
#include "libavutil/samplefmt.h"
#include "libavutil/time.h"
#include "libavutil/bprint.h"
#include "libavutil/opt.h"
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"
#include "libavfilter/avfilter.h"
#include "libavdevice/avdevice.h"
#include "libswscale/swscale.h"
#include "libavutil/opt.h"
#include "libavutil/imgutils.h"  
#include "libavcodec/avfft.h"
#include "libswresample/swresample.h"
}#include <iostream>
using namespace std;static double r2d(AVRational r)
{return r.den == 0 ? 0 : (double)r.num / (double)r.den;
}int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);//av_register_all();avformat_network_init();AVDictionary* options = NULL;av_dict_set(&options, "buffer_size", "1024000", 0);av_dict_set(&options, "max_delay", "500000", 0);av_dict_set(&options, "stimeout", "2000000", 0);av_dict_set(&options, "rtsp_transport", "tcp", 0);AVFormatContext* inputFmtCtx = nullptr;const char* inputUrl = "F:/1920x1080.mp4";///打开输入的流,获取数据 beginint ret = avformat_open_input(&inputFmtCtx, inputUrl, NULL, NULL);if (ret != 0){printf("Couldn't open input stream.\n");return -1;}int vIndex = -1;int aIndex = -1;//查找;if (avformat_find_stream_info(inputFmtCtx, NULL) < 0){printf("Couldn't find stream information.\n");return false;}for (int i = 0; i < inputFmtCtx->nb_streams/*视音频流的个数*/; i++){//查找视频if (inputFmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO){vIndex = i;}else if (inputFmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO){aIndex = i;}}//===================video=================//视频宽int width = inputFmtCtx->streams[vIndex]->codecpar->width;//视频高int height = inputFmtCtx->streams[vIndex]->codecpar->height;//视频总时长sint64_t m_totalTime = static_cast<double>(inputFmtCtx->duration) / AV_TIME_BASE;//获取帧率;int fps = r2d(inputFmtCtx->streams[vIndex]->avg_frame_rate);if (fps == 0){fps = 25;}int iHour, iMinute, iSecond, iTotalSeconds;//HH:MM:SS//打印结构体信息puts("AVFormatContext信息:");puts("---------------------------------------------");iTotalSeconds = (int)inputFmtCtx->duration/*微秒*/ / 1000000;iHour = iTotalSeconds / 3600;//小时iMinute = iTotalSeconds % 3600 / 60;//分钟iSecond = iTotalSeconds % 60;//秒printf("持续时间:%02d:%02d:%02d\n", iHour, iMinute, iSecond);printf("平均混合码率:%d kb/s\n", inputFmtCtx->bit_rate / 1000);printf("视音频个数:%d\n", inputFmtCtx->nb_streams);puts("---------------------------------------------");puts("AVInputFormat信息:");puts("---------------------------------------------");printf("封装格式名称:%s\n", inputFmtCtx->iformat->name);printf("封装格式长名称:%s\n", inputFmtCtx->iformat->long_name);printf("封装格式扩展名:%s\n", inputFmtCtx->iformat->extensions);printf("封装格式ID:%d\n", inputFmtCtx->iformat->raw_codec_id);puts("---------------------------------------------");puts("AVStream信息:");puts("---------------------------------------------");printf("视频流标识符:%d\n", inputFmtCtx->streams[vIndex]->index);printf("音频流标识符:%d\n", inputFmtCtx->streams[aIndex]->index);printf("视频流长度:%d微秒\n", inputFmtCtx->streams[vIndex]->duration);printf("音频流长度:%d微秒\n", inputFmtCtx->streams[aIndex]->duration);puts("---------------------------------------------");printf("视频时长:%d微秒\n", inputFmtCtx->streams[vIndex]->duration);printf("音频时长:%d微秒\n", inputFmtCtx->streams[aIndex]->duration);printf("视频宽:%d\n", inputFmtCtx->streams[vIndex]->codecpar->width);printf("视频高:%d\n", inputFmtCtx->streams[vIndex]->codecpar->height);printf("音频采样率:%d\n", inputFmtCtx->streams[aIndex]->codecpar->sample_rate);printf("音频信道数目:%d\n", inputFmtCtx->streams[aIndex]->codecpar->channels);puts("AVFormatContext元数据:");puts("---------------------------------------------");AVDictionaryEntry *dict = NULL;while (dict = av_dict_get(inputFmtCtx->metadata, "", dict, AV_DICT_IGNORE_SUFFIX)){printf("[%s] = %s\n", dict->key, dict->value);}puts("---------------------------------------------");puts("AVStream视频元数据:");puts("---------------------------------------------");dict = NULL;while (dict = av_dict_get(inputFmtCtx->streams[vIndex]->metadata, "", dict, AV_DICT_IGNORE_SUFFIX)){printf("[%s] = %s\n", dict->key, dict->value);}puts("---------------------------------------------");puts("AVStream音频元数据:");puts("---------------------------------------------");dict = NULL;while (dict = av_dict_get(inputFmtCtx->streams[aIndex]->metadata, "", dict, AV_DICT_IGNORE_SUFFIX)){printf("[%s] = %s\n", dict->key, dict->value);}puts("---------------------------------------------");av_dump_format(inputFmtCtx, -1, inputUrl, 0);printf("\n\n编译信息:\n%s\n\n", avcodec_configuration());AVPacket* pkt = NULL;pkt = av_packet_alloc();while (av_read_frame(inputFmtCtx, pkt) >= 0){//获取数据包//.....解码或者存储//重置av_packet_unref(pkt);}//关闭avformat_close_input(&inputFmtCtx);//释放avformat_free_context(inputFmtCtx);//释放资源av_packet_free(&pkt);return a.exec();
}

运行截图:

完整工程:

https://download.csdn.net/download/wzz953200463/88959152icon-default.png?t=N7T8https://download.csdn.net/download/wzz953200463/88959152

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/540201.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

记某次HVV:文件上传打入内网

免责声明 本文仅用于参考和学习交流&#xff0c;对于使用本文所提供的信息所造成的任何直接或间接的后果和损失&#xff0c;使用者需自行承担责任。本文的作者对此不承担任何责任。请在使用本文内容时谨慎评估风险并做出独立判断。谢谢&#xff01; 前言 某次地市hvv发现一个…

2024三轮车行业发展现状

环洋市场咨询&#xff08;Global Info Research&#xff09;的三轮车市场调研报告提供三轮车市场的基本概况&#xff0c;包括定义&#xff0c;分类&#xff0c;应用和产业链结构&#xff0c;同时还讨论发展政策和计划以及制造流程和成本结构&#xff0c;分析三轮车市场的发展现…

Ubuntu系统的安装及基础操作

目录 一、VMware虚拟机安装Ubuntu20.04过程 1、安装前的准备工作 2、VMware虚拟机创建Ubuntu操作系统 步骤一&#xff1a;以管理员的身份运行VMware虚拟机 步骤二&#xff1a;新建虚拟机 步骤三&#xff1a;选择类型配置 步骤四&#xff1a;选择安装客户机操作系统 步骤…

PlayBook 详解

4&#xff09;Playbook 4.1&#xff09;Playbook 介绍 PlayBook 与 ad-hoc 相比&#xff0c;是一种完全不同的运用 Ansible 的方式&#xff0c;类似与 Saltstack 的 state 状态文件。ad-hoc 无法持久使用&#xff0c;PlayBook 可以持久使用。 PlayBook 剧本是 由一个或多个 “…

Jmeter入参问题小记

表单入参的时候&#xff0c;这个地方需要勾选&#xff0c;如果不☑️选的话&#xff0c;会提示errorMsg":"Required String parameter code is not present",

【学习笔记】红队视角下的windows应急响应

1. 上线的方法 exe上线→开360晶核的情况比较困难 2&#xff09;白加黑 接下来的讲解就是基于白加黑上线&#xff0c;看如何应对应急 2. 演示 360环境启动 shell whoami →死 -beacon 如何去查杀 看外联&#xff1a; netstat -ano 提取IP 威胁情报api调用→查是否是恶意…

Redis-复制功能

0 序言 复制功能是Redis提供的多机功能中最基础的一个&#xff0c;这个功能是通过主从复制&#xff08;master-slave replication&#xff09;模式实现的&#xff0c;它允许用户为存储着目标数据库的服务器创建出多个拥有相同数据库副本的服务器&#xff0c;其中存储目标数据库…

使用maven打生产环境可执行包

一、程序为什么要打包 程序打包的主要目的是将项目的源代码、依赖库和其他资源打包成一个可执行的文件或者部署包&#xff0c;方便程序的发布和部署。以下是一些打包程序的重要理由&#xff1a; 方便部署和分发&#xff1a;打包后的程序可以作为一个独立的实体&#xff0c;方便…

计算机视觉——目标检测(R-CNN、Fast R-CNN、Faster R-CNN )

前言、相关知识 1.闭集和开集 开集&#xff1a;识别训练集不存在的样本类别。闭集&#xff1a;识别训练集已知的样本类别。 2.多模态信息融合 文本和图像&#xff0c;文本的语义信息映射成词向量&#xff0c;形成词典&#xff0c;嵌入到n维空间。 图片内容信息提取特征&…

Javaweb-MyBatis

一、概念 MyBatis是一款优秀的持久层框架&#xff0c;用于简化JDBC开发 MyBatis本是Apache的一个开源项目iBatis&#xff0c;2010年这个项目由apache software found迁移到了google code&#xff0c;并且改名为MyBatis。2013年11月迁移到Github 持久层 负责将数据到保存到数…

泛目录站群程序,seo站群系统(川圣SEO)#蜘蛛池

baidu搜索&#xff1a;如何联系八爪鱼SEO? baidu搜索&#xff1a;如何联系八爪鱼SEO? baidu搜索&#xff1a;如何联系八爪鱼SEO? 功能介绍&#xff1a; &#xff08;全新模板 PC、移动端自适应 无限泛二级域名首页&#xff0c;标题增加进制干扰码&#xff0c;关键词进制干…

深入理解 CSS——CSS进阶与实践(5w字高频面试题整理)

本文总结了CSS高频面试题&#xff0c;并搭配了演示动画进行CSS样式演示。介绍了关于如何理解盒模型&#xff0c;如何实现块级元素水平居中&#xff0c;如何实现两侧固定中间自适应的三栏布局、如何实现两栏布局&#xff0c;如何进行响应式设计&#xff0c;对BFC的理解&#xff…