qt+ffmpeg 实现音视频播放(二)之音频播放
一、音频播放流程
1、打开音频文件
通过 avformat_open_input() 打开媒体文件并分配和初始化 AVFormatContext 结构体。
函数原型如下:
int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options);
参数说明:
- `ps`:指向 `AVFormatContext` 结构体指针的指针,用于存储打开的媒体文件的信息。
- `url`:要打开的媒体文件的 URL 或文件路径。
- `fmt`:指定输入格式,通常可以设置为 `NULL`,由 FFmpeg 根据文件内容自动检测。
- `options`:附加选项,可以传入一些额外的选项参数。
2、查找输入流信息
调用 avformat_find_stream_info() 函数将会读取媒体文件中的帧,解析它们的头部,
并填充 AVFormatContext 中的流信息,通过访问 AVFormatContext 的 streams 字段来获取每个流的详细信息。
函数原型如下:
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);
参数说明:
- `ic`:指向已打开媒体文件的 `AVFormatContext` 结构体的指针。
- `options`:指向包含附加选项的 `AVDictionary` 指针。
3、查找流索引
使用 av_find_best_stream() 从媒体文件中找到最佳的流索引
函数原型如下:
int av_find_best_stream(AVFormatContext *ic, enum AVMediaType type, int wanted_stream, int related_stream, AVCodec **decoder_ret, int flags);
参数说明:
- `ic`:指向已打开媒体文件的 `AVFormatContext` 结构体的指针。
- `type`:要查找的流类型,可以是 `AVMEDIA_TYPE_VIDEO`、`AVMEDIA_TYPE_AUDIO` 等。
- `wanted_stream`:期望的流索引,如果为负值,则表示没有特定的偏好。
- `related_stream`:相关流索引,用于查找与之相关的最佳流。
- `decoder_ret`:用于返回找到的解码器。
- `flags`:附加标志,可以用来指定额外的查找选项。
4、查找解码器
使用 avcodec_find_decoder() 查找符合指定解码器名称的解码器。
函数原型如下:
AVCodec *avcodec_find_decoder(enum AVCodecID id);
参数说明:
- `id`:要查找的解码器的 ID。
5、初始化解码上下文
调用 avcodec_alloc_context3() 函数会为特定的编解码器分配一个 AVCodecContext 结构体,并对其进行初始化。 AVCodecContext 结构体包含了编解码器的相关参数和状态信息,比如编解码器类型、解码参数、帧率等。
函数原型如下:
AVCodecContext *avcodec_alloc_context3(const AVCodec *codec);
参数说明:
- `codec`:指定要使用的编解码器,可以通过 `avcodec_find_decoder()` 或其他方式获取。
6、获取解码参数
调用 `avcodec_parameters_to_context()` 函数可以方便地将 `AVCodecParameters` 结构体中的参数(如编解码器类型、帧率、分辨率等)复制到 `AVCodecContext` 结构体中,从而准备进行编解码操作。
函数原型如下:
int avcodec_parameters_to_context(AVCodecContext *codec, const AVCodecParameters *par);
参数说明:
- `codec`:要填充参数的 `AVCodecContext` 结构体指针。
- `par`:包含编解码器参数的 `AVCodecParameters` 结构体指针。
7、打开解码器
调用 `avcodec_open2()` 函数可以打开并初始化指定的编解码器上下文,使其准备好进行编解码操作。
函数原型如下:
int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);
参数说明:
- `avctx`:要打开和初始化的编解码器上下文。
- `codec`:要使用的编解码器,可以通过 `avcodec_find_decoder()` 或其他方式获取。
- `options`:可选的字典参数,用于设置编解码器的选项。
打开解码器时可以使用多线程参数优化解码速度。
AVDictionary* opts = NULL;
//使用多线程解码
if (!av_dict_get(opts, "threads", NULL, 0))
av_dict_set(&opts, "threads", "auto", 0);
8、创建音频重采样上下文
调用 `swr_alloc_set_opts()` 函数可以创建一个音频重采样上下文,并设置其参数。这个函数可以方便地指定输入和输出音频的通道布局、采样格式和采样率等参数。
函数原型如下:
struct SwrContext *swr_alloc_set_opts(struct SwrContext *s,
int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,
int64_t in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate,
int log_offset, void *log_ctx);
参数说明:
- `s`:要创建或设置参数的音频重采样上下文。如果传入非空指针,则会设置现有上下文的参数;如果传入空指针,则会创建一个新的上下文。
- `out_ch_layout`:输出音频的通道布局(channel layout)。
- `out_sample_fmt`:输出音频的采样格式(sample format)。
- `out_sample_rate`:输出音频的采样率(sample rate)。
- `in_ch_layout`:输入音频的通道布局。
- `in_sample_fmt`:输入音频的采样格式。
- `in_sample_rate`:输入音频的采样率。
- `log_offset`:日志输出偏移量。
- `log_ctx`:日志上下文。
9、初始化音频重采样上下文
调用 `swr_init()` 函数可以初始化音频重采样上下文,使其准备好进行音频重采样操作。
函数原型如下:
int swr_init(struct SwrContext *s);
参数说明:
- `s`: 要初始化的音频重采样上下文。
10、分配并初始化一个临时的帧和包
调用 `av_packet_alloc()` 函数可以分配一个 AVPacket 结构体,并返回指向该结构体的指针。AVPacket 结构体用于存储音视频数据,包括数据缓冲区、大小、时间戳等信息。
调用 `av_frame_alloc()` 函数可以分配一个 AVFrame 结构体,并返回指向该结构体的指针。AVFrame 结构体用于存储音视频帧的数据,包括像素数据、采样数据、时间戳等信息。
函数原型如下:
AVPacket *av_packet_alloc(void);
AVFrame *av_frame_alloc(void);
11、读取音视频源文件
调用 `av_read_frame()` 函数可以从输入文件或流中读取一帧音视频数据,并将其存储在 AVPacket 结构体中。
函数原型如下:
int av_read_frame(AVFormatContext *s, AVPacket *pkt);
参数说明:
- `s`:输入文件或流的 AVFormatContext 上下文。
- `pkt`:存储读取到的音视频帧数据的 AVPacket 结构体。
12、发送音频数据到解码器
调用 `avcodec_send_packet()` 函数可以将 AVPacket 数据包发送给解码器进行解码。在发送完所有数据包后,需要调用 `avcodec_send_packet()` 传递一个空的 AVPacket 指针,以便告知解码器已经发送完所有数据。
函数原型如下:
int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt);
参数说明:
- `avctx`:指向 AVCodecContext 结构体的指针,表示解码器上下文。
- `avpkt`:指向要发送给解码器的 AVPacket 数据包的指针。
13、从解码器接收解码后的音频数据
调用 `avcodec_receive_frame()` 函数可以从解码器中接收解码后的音视频帧数据,并将其存储在 AVFrame 结构体中。
函数原型如下:
int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame);
参数说明:
- `avctx`:指向 AVCodecContext 结构体的指针,表示解码器上下文。
- `frame`:用于存储接收到的解码后的 AVFrame 帧数据的结构体。
14、进行音频重采样
调用 `swr_convert()` 函数可以将输入缓冲区中的音频数据进行重采样,并将结果存储到输出缓冲区中。
函数原型如下:
int swr_convert(struct SwrContext *s, uint8_t **out, int out_count, const uint8_t **in, int in_count);
参数说明:
- `s`:指向 SwrContext 结构体的指针,表示音频重采样上下文。
- `out`:指向输出音频数据缓冲区的指针数组。
- `out_count`:输出缓冲区中的样本数。
- `in`:指向输入音频数据缓冲区的指针数组。
- `in_count`:输入缓冲区中的样本数。
15、播放音频
将重采样后的数据写入声卡中进行播放。
简洁流程如下:
其他重要API:
void av_dump_format(const AVFormatContext *ic, int index,
const char *url, int is_output);
//可以将输入/输出文件的格式信息以人类可读的形式打印出来,包括流的详细信息、编解码器信息等。这对于调试和了解输入/输出文件的结构和信息非常有帮助。
参数说明:
- `ic`:指向 AVFormatContext 结构体的指针,表示要进行格式信息输出的输入/输出文件的 AVFormatContext。
- `index`:如果为非负值,表示要输出的流的索引;如果为负值,表示输出所有流信息。
- `url`:文件的 URL 或名称,在打印信息时会用到。
- `is_output`:如果为非零值,表示输出的是输出文件的格式信息;如果为 0,表示输出的是输入文件的格式信息。
int av_samples_get_buffer_size(int *linesize, int nb_channels, int nb_samples, enum AVSampleFormat sample_fmt, int align);
//计算出存储指定数量音频样本所需的缓冲区大小。这个函数通常用于动态分配音频样本数据缓冲区的场景。
参数说明:
- `linesize`:指向存储每个通道数据大小的数组的指针。
- `nb_channels`:音频通道数。
- `nb_samples`:每个通道中的音频样本数。
- `sample_fmt`:音频样本格式,使用 AVSampleFormat 枚举类型。
- `align`:对齐方式,通常为 0。
AVFormatContext *avformat_alloc_context(void);
//用于分配内存并返回一个初始化后的 AVFormatContext 结构体指针。
AVFormatContext 结构体里面有一个重要的参数 interrupt_callback.callback ,用来设置回调函数。当调用av_read_frame或avformat_find_stream_info会阻塞执行很长时间的时候,只要设置该回调函数返回 1 ,那么就会不再阻塞,立即返回。
代码例程:点击跳转
相关文章:

qt+ffmpeg 实现音视频播放(二)之音频播放
一、音频播放流程 1、打开音频文件 通过 avformat_open_input() 打开媒体文件并分配和初始化 AVFormatContext 结构体。 函数原型如下: int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options); 参数说…...
Bash Shell中双引号中的感叹号问题详解
Bash Shell中双引号中的感叹号问题详解 在Bash Shell中,感叹号(!)是一个特殊字符,主要用于历史扩展。历史扩展允许你使用!来引用历史命令。然而,当你在双引号中使用感叹号时,如果你在双引号中直接使用感叹号,它可能会…...
MFC中CString的用法及使用示例
CString 是 Microsoft Foundation Classes (MFC) 库中的一个类,用于处理 C 风格的字符串。它提供了很多有用的方法和函数,使得字符串的操作变得更加简单和安全。下面是一些 CString 的基本用法和使用示例: 1. 包含头文件 首先,你…...

注册个人小程序
访问地址 https://mp.weixin.qq.com/ 立即注册 选择小程序 注册 填写信息 登录邮箱 访问邮箱的链接激活账号 选择个人,填写信息 注册完成,即可登录进入填写信息...
VTK----VTK的事件机制
事件的发送和接收对于一个应用或系统来说是一个基本的功能,所以一些通用的库对应地也建立了自己的一套管理事件的机制,例如QT、VTK都有自己的事件管理机制。VTK库中定义了很多的事件,这些事件是如何进行管理的,下面从三个方面来详细的说明。 1 事件的管理 在讲述VTK的事件…...
常用的vim和linux命令
常用的vim命令和linux命令 vim编辑器有三种模式 命令模式、编辑模式、末行模式 模式间切换方法: 1.命令模式下,输入:后,进入末行模式 2.末行模式下,按esc慢退、按两次esc快退、或者删除所有命令,可以回…...
生产环境中间件服务集群搭建-zk-activeMQ-kafka-reids-nacos
环境: 系统:centos7.9 工作目录:/home 安装包位置:/home/op/tools 1.系统初始化 安装依赖环境 yum -y install net-tools vim screen telnet vim gcc gcc-c 修改主机名,为另外两台添加hosts文件 [rootmq01 conf…...

Smart Light Random Memory Sprays Retinex 传统图像增强 SLRMSR
文章目录 前言1、Smart Light Random Memory Sprays Retinex概况2、Smart Light Random Memory Sprays Retinex的实现2.1、SLRMSR算法的伪代码2.2、初始化记忆喷雾(CreateInitialMemorySpray)2.3、更新记忆喷雾 (UpdateMemorySpray)2.4、计算颜色校正因子…...
Oracle数据库实例概述
Oracle数据库实例是由内存结构(SGA和PGA)及后台进程这两大部分组成。 内存结构 SGA (System Global Area):这是数据库实例的共享内存区域,所有与该实例连接的进程都可以访问。SGA包含多个内存结构,例如: 数…...

Odoo17免费开源ERP开发技巧:如何在表单视图中调用JS类
文/Odoo亚太金牌服务开源智造 老杨 在Odoo最新V17新版中,其突出功能之一是能够构建个性化视图,允许用户以独特的方式与数据互动。本文深入探讨了如何使用 JavaScript 类来呈现表单视图来创建自定义视图。通过学习本教程,你将获得关于开发Odo…...

[RCTF2015]EasySQL ---不会编程的崽
今天也是sql注入的新类型---二次注入。不得不说花样真的多哦。 既然真的是sql注入了。那就不测试其他地方了。现在注册进去看一下界面 单纯的回显了名字。源代码里发现user.php。 可以修改密码?二次注入应该就在用户名这里了。因为修改密码时,用户名会被…...

Memcached-分布式内存对象缓存系统
目录 一、NoSQL 介绍 二、Memcached 1、Memcached 介绍 1.1 Memcached 概念 1.2 Memcached 特性 1.3 Memcached 和 Redis 区别 1.4 Memcached 工作机制 1.4.1 内存分配机制 1.4.2 懒惰期 Lazy Expiration 1.4.3 LRU(最近最少使用算法) 1.4.4…...
bash: sqlplus: command not found 问题解决方法
一、问题描述 在Linux中Oracle安装成功后,首次启动使用时,出现 sqlplus 命令不识别的问题,现象如下: $ sqlplus / as sysdba bash: sqlplus: command not found...二、问题分析 查看环境变量是否正确配置: $ vim .ba…...
大模型-Prompt
一、prompt是什么 在大型语言模型集成中,"prompt" 是指您向模型提供的输入文本或指令,以引导模型生成特定类型的响应。这个 prompt 可以是一个问题、一段描述、一个任务说明,甚至是一部分对话历史记录等。通过设计和优化 prompt&a…...
Python实战:SQLAlchemy ORM使用教程
一、SQLAlchemy ORM使用教程 SQLAlchemy是一个流行的Python SQL工具包和对象关系映射(ORM)框架,它为开发人员提供了一种高效、灵活的方式来与数据库进行交互。在本篇博客中,我们将深入探讨SQLAlchemy ORM的核心知识,并…...
能不能绕过c去学c++?
目前做工程开发,基本都是c/c混着用的,c/c是同源的,c/是在c的基础上发展起来的,它们之间有些联系和区别: 区别: 1.可用库不同 c基本是系统底层语言,一般系统底层开发用c(例如&…...
Python 小爬虫:爬取 bing 每日壁纸设为桌面壁纸
请求 URLJSON 版示例代码代码片段注意点headers 中的 User-Agent响应头中的 Content-Type终端通过代理API从 bing.com 找Bing 每日壁纸设置为桌面壁纸代码设定计划任务自动执行 python 脚本请求 URL 通过模仿必应(Bing)自己的 AJAX 调用方式获得请求 URL。 JSON 格式:...

利用textarea和white-space实现最简单的文章编辑器 支持缩进和换行
当你遇到一个非常基础的文章发布和展示的需求,只需要保留换行和空格缩进,你是否会犹豫要使用富文本编辑器?实际上这个用原生的标签两步就能搞定! 1.直接用textarea当编辑器 textarea本身就可以保存空格和换行符,示例如…...

总结mac下解决matplotlib中文显示问题的几种方法
一、前言: 使⽤matplotlib画图时,由于matplotlib默认没有中⽂,显⽰中文时会出现空⽩⼩⽅块。 二、方法: 2.1 matplotlib中使用SimHei字体 1)进入终端后查看matplotlib的字体路径: $ python >>&g…...

探索区块链世界:从加密货币到去中心化应用
相信提到区块链,很多人会想到比特币这样的加密货币,但实际上,区块链技术远不止于此,它正在深刻地改变我们的生活和商业。 首先,让我们来简单了解一下什么是区块链。区块链是一种分布式数据库技术,它通过将…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...

如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...

【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
区块链技术概述
区块链技术是一种去中心化、分布式账本技术,通过密码学、共识机制和智能合约等核心组件,实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点:数据存储在网络中的多个节点(计算机),而非…...