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.rhkb.cn/news/276235.html

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

相关文章

精简版 Obsidian 图床配置 PicGo+ gitee

精简版 Obsidian 图床配置 PicGo gitee 图床的作用 图床&#xff08;Image Hosting Service&#xff09;是一种在线服务&#xff0c;用于存储和托管用户上传的图片文件。用户可以将图片上传到图床服务器&#xff0c;并获得一个可访问的图片链接&#xff0c;然后可以在网页、博…

为什么要用scrapy爬虫库?而不是纯python进行爬虫?

为什么要用scrapy爬虫库&#xff1f;而不是纯python进行爬虫&#xff1f; Scrapy的优点Scrapy节省的工作使用纯Python编写爬虫的不足 Scrapy是一个使用Python编写的开源和协作的web爬虫框架&#xff0c;它被设计用于爬取网页数据并从中提取结构化数据。Scrapy的强大之处在于其广…

mysql 主从延迟分析

一、如何分析主从延迟 分析主从延迟一般会采集以下三类信息。 从库服务器的负载情况 为什么要首先查看服务器的负载情况呢&#xff1f;因为软件层面的所有操作都需要系统资源来支撑。 常见的系统资源有四类&#xff1a;CPU、内存、IO、网络。对于主从延迟&#xff0c;一般会…

加密货币在网络违法犯罪活动中的利用情况调查

一、调查背景 区块链基于分布式共识和经济激励等手段&#xff0c;在开放式、无许可的网络空间中&#xff0c;为价值的确立、存储、转移提供了新的解决方案。然而随着加密生态在过去若干年的快速发展&#xff0c;加密货币也越来越多地被用于各类风险活动&#xff0c;为网络赌博…

ES6(一):let和const、模板字符串、函数默认值、剩余参数、扩展运算符、箭头函数

一、let和const声明变量 1.let没有变量提升&#xff0c;把let放下面打印不出来&#xff0c;放上面可以 <script>console.log(a);let a1;</script> 2.let是一个块级作用域,花括号里面声明的变量外面找不到 <script>console.log(b);if(true){let b1;}//und…

el-table的border属性失效问题解决方案

目录 问题&#xff1a; 使用的代码&#xff1a; 官方文档的说明&#xff1a; 可能的问题所在&#xff1a; 关于使用了作用域插槽&#xff1a; a.自定义内容的样式覆盖&#xff1a; b.表格结构的改变&#xff1a; 解决方案&#xff1a; 通过css样式解决&#xff1a; 下面…

聚酰亚胺PI材料难于粘接,用什么胶水粘接?那么让我们先一步步的从认识它开始(一)

聚酰亚胺PI的基本概念 聚酰亚胺&#xff08;Polyimide&#xff0c;简称PI&#xff09;是一种重要的高性能聚合物材料。是指主链上含有酰亚胺环的一类聚合物&#xff0c;是综合性能最佳的有机高分子材料之一。它具有最高的阻燃等级&#xff08;UL-94&#xff09;&#xff0c;以及…

Editor.md-编辑器

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…

学生时期学习资源同步-1 第一学期结业考试题8

原创作者&#xff1a;田超凡&#xff08;程序员田宝宝&#xff09; 版权所有&#xff0c;引用请注明原作者&#xff0c;严禁复制转载

云服务器2核4G配置,阿里云和腾讯云哪个便宜?性能更好?

租用2核4G服务器费用多少&#xff1f;2核4G云服务器多少钱一年&#xff1f;1个月费用多少&#xff1f;阿里云2核4G服务器30元3个月、轻量应用服务器2核4G4M带宽165元一年、企业用户2核4G5M带宽199元一年&#xff1b;腾讯云轻量2核4G服务器5M带宽165元一年、252元15个月、540元三…

搭建谷歌Gemini

前言 Gemini是Google AI于2023年发布的大型语言模型&#xff0c;拥有强大的文本生成、理解和转换能力。它基于Transformer模型架构&#xff0c;并使用了大量文本和代码数据进行训练。Gemini可以执行多种任务&#xff0c;包括&#xff1a; 生成文本&#xff1a;可以生成各种类…

Qt/QML编程之路:基于QWidget编程及各种2D/3D/PIC绘制的示例(45)

关于使用GWidget,这里有一个示例,看了之后很多图形绘制,控件使用,及最基本的QWidget编程都比较清楚了。ui的绘制: 运行后的界面如 工程中有非常丰富的关于各种图形的绘制,比如上图中circle,还有image。有下面一段readme的说明: # EasyQPainter Various operation pra…

css超出部分显示省略号

目录 前言 一、CSS单行实现 二、CSS多行实现&#xff08;CSS3出的&#xff0c;兼容性需要注意&#xff09; 三、微信小程序超过2行出现省略号实现 四、JavaScript脚本实现 前言 CSS文本溢出就显示省略号&#xff0c;就是在样式中指定了盒子的宽度与高度,有可能出现某些内…

“antd“: Unknown word.cSpell

你遇到的问题是 VS Code 的 Code Spell Checker 插件在检查拼写时&#xff0c;将 "antd" 标记为未知单词。"antd" 是 Ant Design 的缩写&#xff0c;是一个流行的 React UI 库&#xff0c;不是一个英语单词&#xff0c;所以 Spell Checker 会将其标记为错误…

Linux的一些常用指令

一、文件中 r w x - 的含义 r&#xff08;read&#xff09;是只读权限&#xff0c; w&#xff08;write&#xff09;是写的权限&#xff0c; x&#xff08;execute&#xff09;是可执行权限&#xff0c; -是没有任何权限。 二、一些指令 # 解压压缩包 tar [-zxvf] 压缩包名…

Selenium 学习(0.20)——软件测试之单元测试

我又&#xff08;浪完&#xff09;回来了…… 很久没有学习了&#xff0c;今天忙完终于想起来学习了。没有学习的这段时间&#xff0c;主要是请了两个事假&#xff08;5工作日和10工作日&#xff09;放了个年假&#xff08;13天&#xff09;&#xff0c;然后就到现在了。 看了下…

hadoop报错:HADOOP_HOME and hadoop.home.dir are unset. 解决方法

参考&#xff1a;https://blog.csdn.net/weixin_45735242/article/details/120579387 解决方法 1.下载apache-hadoop-3.1.0-winutils-master 官网下载地址&#xff1a; https://github.com/s911415/apache-hadoop-3.1.0-winutils win配置系统环境&#xff1a; 然后重启idea…

Java优先级队列(堆)

&#x1f435;本篇文章将对优先级队列&#xff08;堆&#xff09;的相关知识进行讲解 一、优先级队列 队列是一种“先入先出”的数据结构&#xff0c;但有时操作的数据带有优先级&#xff0c;需要优先处理&#xff0c;这时普通的队列就不能满足需求。比如&#xff1a;在排队取…

(vue)Module Error (from ./node_modules/eslint-loader/index.js)

(vue)Module Error (from ./node_modules/eslint-loader/index.js) 参考&#xff1a;解决参考

mac安全干净卸载Anaconda3

使用which python显示当前使用的是/Users/username/anaconda3/bin/python 现在想卸载Anaconda&#xff0c;恢复使用mac系统自带的Python 删除隐藏文件目录 rm -rf ~/.anaconda修改~/.bash_profile文件&#xff0c;将anaconda相关删除 也有可能不是~/.bash_profile而是~/.zs…