qt+ffmpeg 实现音视频播放(二)之音频播放

news2024/9/22 7:33:30

一、音频播放流程

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 ,那么就会不再阻塞,立即返回。

代码例程:点击跳转

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据分析-Pandas的Andrews曲线可视化解读

数据分析-Pandas的Andrews曲线可视化解读 数据分析和处理中,难免会遇到各种数据,那么数据呈现怎样的规律呢?不管金融数据,风控数据,营销数据等等,莫不如此。如何通过图示展示数据的规律? 数据…

C#,图论与图算法,无向图(Graph)回环(Cycle)的不相交集(disjoint)或并集查找(union find)判别算法与源代码

1 回环(Cycle)的不相交集(disjoint)或并集 不相交集数据结构是一种数据结构,它跟踪划分为多个不相交(非重叠)子集的一组元素。联合查找算法是对此类数据结构执行两个有用操作的算法: 查找:确定特定元素所在的子集。这可用于确定两个元素是否在同一子集中。 并集:将…

Django中使用celery实现异步任务、延时任务、周期定时任务

配置celery 1. 安装以下环境 pip install celery pip install redis pip install eventlet # celery 4.0版本以后不支持在windows运行,还需额外安装eventlet库本文环境为:python3.9.4Django4.2.11celery5.3.6redis5.0.3 2. 配置setting.py文件 在sett…

汽车制造产生的污废水如何处理排放

汽车制造业是一个重要的工业领域,然而,伴随着汽车制造过程中的各种化学反应和材料加工,大量污废水也随之产生。为了保护环境和社会的可持续发展,汽车制造产生的污废水需要得到妥善处理和排放。 首先,针对汽车制造中涉及…

前端vue实现甘特图

1 什么是甘特图 甘特图(Gantt chart)又称为横道图、条状图(Bar chart)。以提出者亨利L甘特先生的名字命名,是项目管理、生产排程、节点管理中非常常见的一个功能。 甘特图内在思想简单,即以图示的方式通过活动列表和时间刻度形象地表示出任何特定项目的…

01.Linked-List-Basic

1. 链表简介 1.1 链表定义 链表(Linked List):一种线性表数据结构。它使用一组任意的存储单元(可以是连续的,也可以是不连续的),来存储一组具有相同类型的数据。 简单来说,「链表」…

web渗透测试漏洞复现:Elasticsearch未授权漏洞复现

web渗透测试漏洞复现 Elasticsearch未授权漏洞复现Elasticsearch简介Elasticsearch复现Elasticsearch漏洞修复和加固措施 Elasticsearch未授权漏洞复现 Elasticsearch简介 Elasticsearch 是一款 Java 编写的企业级搜索服务,它以分布式多用户能力和全文搜索引擎为特…

功能齐全的免费 IDE Visual Studio 2022 社区版

面向学生、开放源代码和单个开发人员的功能齐全的免费 IDE 下载地址 Visual Studio 2022 社区版 - 下载最新的免费版本 Visual Studio 2022 Community Edition – Download Latest Free Version 准备安装 选择需要安装的程序 安装进行中 使用C学习程序设计相关知识并培养编程…

AI基础知识(3)--神经网络,支持向量机,贝叶斯分类器

1.什么是误差逆传播算法(error BackPropagation,简称BP)? 是一种神经网络学习算法。BP是一个迭代学习算法,在迭代的每一轮使用广义的感知机学习规则对参数进行更新估计。基于梯度下降(gradient descent&am…

安卓RecyclerView简单用法

废话不多说上代码 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:app"http://schemas.android.com/apk/res-auto"xmlns:tools"http://schem…

LeetCode---388周赛

题目列表 3074. 重新分装苹果 3075. 幸福值最大化的选择方案 3076. 数组中的最短非公共子字符串 3077. K 个不相交子数组的最大能量值 一、重新分装苹果 注意题目中说同一个包裹中的苹果可以分装&#xff0c;那么我们只要关心苹果的总量即可&#xff0c;在根据贪心&#x…

华为汽车业务迎关键节点,长安深蓝加入HI模式,车BU预计今年扭亏

‍编辑 |HiEV 一年之前&#xff0c;同样是在电动汽车百人会的论坛上&#xff0c;余承东在外界对于华为和AITO的质疑声中&#xff0c;第一次公开阐释了华为选择走智选车模式的逻辑。 一年之后&#xff0c;伴随问界M7改款、问界M9上市&#xff0c;华为智选车模式的面貌已经发生了…

让图片适应标签的CSS object-fit属性

在实际的项目运行过程中&#xff0c;可能出现运营人员上传的文件与预期的图片尺寸不同的情况&#xff0c;为了解决这一问题可以使用 object-fit 属性&#xff0c;对嵌入的图像&#xff08;以及其他替代元素&#xff0c;如视频&#xff09;做相应的变化&#xff0c;更加精确地控…

数据结构 二叉树 力扣例题AC——代码以及思路记录

LCR 175. 计算二叉树的深 某公司架构以二叉树形式记录&#xff0c;请返回该公司的层级数。 AC int calculateDepth(struct TreeNode* root) {if (root NULL){return 0;}else{return 1 fmax(calculateDepth(root->left), calculateDepth(root->right));} } 代码思路 …

WPF连接MySqldemo

界面总要管理数据嘛,于是便学习了一下WPF与MySql的基本连接. 运行结果: 环境配置 需要下载安装Mysql,网上教程很多,不详说,创建的工程需要下载或者引入相关的包(MySql.Data) 连接的部分直接看具体的代码即可 xaml代码(只放置了一个按钮和文本框) <Grid><Button x:Name…

Android下的匀速贝塞尔

画世界pro里的画笔功能很炫酷 其画笔配置可以调节流量&#xff0c;密度&#xff0c;色相&#xff0c;饱和度&#xff0c;亮度等。 他的大部分画笔应该是通过一个笔头图片在触摸轨迹上匀速绘制的原理。 这里提供一个匀速贝塞尔的kotlin实现&#xff1a; class EvenBezier {p…

hadoop分布式环境搭建

准备三台centos虚拟机 。&#xff08;master&#xff0c;slave1&#xff0c;slave2&#xff09; (hadoop、jdk文件链接&#xff1a;https://pan.baidu.com/s/1wal1CSF1oO2h4dkSbceODg 提取码&#xff1a;4zra) 前四步可参考hadoop伪分布式环境搭建详解-CSDN博客 1.修改主机名…

pycharm里test connection连接成功,但是无法同步服务器文件,deployment变灰

如果服务器test connection连接成功&#xff0c;但是无法同步文件。 可以尝试以下方式&#xff1a; 点击tools-deployment-browse remonte host&#xff0c;选择要连接的服务器的文件夹 如果能正常显示服务器文件夹&#xff0c;再点击tools-deployment&#xff0c;注意要把要…

B002-springcloud alibaba 微服务环境搭建

目录 创建父工程创建基础模块创建用户微服务创建商品微服务创建订单微服务微服务调用 创建父工程 新建项目springcloud-alibaba&#xff0c;本工程不需要写代码&#xff0c;删除src 导包 <parent><groupId>org.springframework.boot</groupId><artifact…

redis设计与实现(二)——持久化

1. 前言&#xff1a; redis是一个基于内存是键值对数据库&#xff0c;但是并非把数据存入内存就高枕无忧了。为了应对可能出现的进程中止&#xff0c;断电等意外情况&#xff0c;redis提供了持久化功能把数据持久化到硬盘。 2. RDB持久化 2.1. rdb文件的创建 rdb通过创建二…