FFmpeg开发笔记(十八)FFmpeg兼容各种音频格式的播放

2024-04-10 09:44

本文主要是介绍FFmpeg开发笔记(十八)FFmpeg兼容各种音频格式的播放,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

FFmpeg结合SDL可以播放音频文件,也能播放视频文件中的音频流,《FFmpeg开发实战:从零基础到短视频上线》一书第10章的示例程序playaudio.c支持播放mp3和aac两种格式的音频,却不支持播放其他格式的音频。
因为mp3和aac两个格式拥有标准的规范定义,比如mp3规定每帧音频固定包含1152个样本,而aac规定每帧音频固定包含1024个样本。在它们的解码器实例AVCodecContext中,即可从frame_size字段获取每帧音频的样本数量。
然而其他音频格式(如ogg、amr、wma等)的每帧样本数并不固定,从frame_size字段取到的样本数量为0,这不仅导致SDL初始化失败,还导致重采样过程异常。为了能够播放其他格式的音频,需要对playaudio.c做下列三处修改。
1、从解码器实例获取音频样本数时,如果发现frame_size为0,就要把样本数变量设为512(注意该数值必须为2的n次幂,如256、512、1024等),修改后的赋值代码如下所示:

int out_nb_samples = audio_decode_ctx->frame_size; // 输出的采样数量
if (out_nb_samples <= 0) {out_nb_samples = 512;
}

2、在遍历音频帧的时候,要重新计算实际的采样位数,以便确定多少音频数据送给扬声器。具体的计算过程是这样的:先调用swr_convert函数对音频重采样,该函数的返回值为输出的数据大小;这个输入大小乘以声道数量乘以音频样本的位深(位深表示每个音频样本占据几个字节),最终的乘积便是要送给扬声器的音频数据大小。详细的计算代码如下所示:

// 重采样。也就是把输入的音频数据根据指定的采样规格转换为新的音频数据输出
int swr_size = swr_convert(swr_ctx, // 音频采样器的实例&out_buff, MAX_AUDIO_FRAME_SIZE, // 输出的数据内容和数据大小(const uint8_t **) frame->data, frame->nb_samples); // 输入的数据内容和数据大小
audio_pos = (unsigned char *) out_buff; // 把音频数据同步到缓冲区位置
// 这里要计算实际的采样位数
audio_len = swr_size * out_channels * av_get_bytes_per_sample(out_sample_fmt);

3、SDL的音频回调函数当中,注意每次要凑足len个字节。鉴于重采样后的音频数据可能较大(主要是amr格式有这种情况),因此要按照len指定的长度切割数据,确保每次回调函数都刚好把长度为len的音频数据送往扬声器。修改后的回调代码如下所示:

// 回调函数,在获取音频数据后调用
void fill_audio(void *para, uint8_t *stream, int len) {SDL_memset(stream, 0, len); // 将缓冲区清零if (audio_len == 0) {return;}while (len > 0) { // 每次都要凑足len个字节才能退出循环int fill_len = (len > audio_len ? audio_len : len);// 将音频数据混合到缓冲区SDL_MixAudio(stream, audio_pos, fill_len, SDL_MIX_MAXVOLUME);audio_pos += fill_len;audio_len -= fill_len;len -= fill_len;stream += fill_len;if (audio_len == 0) { // 这里要延迟一会儿,避免一直占据IO资源SDL_Delay(1);}}
}

上述修改后的代码已经附在了《FFmpeg开发实战:从零基础到短视频上线》一书第10章的源码chapter10/playaudio2.c,这个c代码是playaudio.c的改进版,除了支持原来mp3和aac格式的音频播放,还支持ogg、amr、wma等格式的音频播放,以及asf、webm等视频文件的音频播放。
接着执行下面的编译命令。

gcc playaudio2.c -o playaudio2 -I/usr/local/ffmpeg/include -L/usr/local/ffmpeg/lib -I/usr/local/sdl2/include -L/usr/local/sdl2/lib -lsdl2 -lavformat -lavdevice -lavfilter -lavcodec -lavutil -lswscale -lswresample -lpostproc -lm

编译完成后执行以下命令启动测试程序,期望播放音频文件ring.ogg。

./playaudio2 ../ring.ogg

程序运行完毕,发现控制台输出以下的日志信息。

Success open input_file ../ring.ogg.
out_sample_rate=11025, out_nb_samples=512
out_buffer_size=1024
256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256 256
Success play audio file.
Quit SDL.

同时电脑扬声器传来了两个“叮咚”的铃声,表示上述代码正确实现了播放ogg音频的功能。


 

这篇关于FFmpeg开发笔记(十八)FFmpeg兼容各种音频格式的播放的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/890711

相关文章

Spring Boot集成/输出/日志级别控制/持久化开发实践

《SpringBoot集成/输出/日志级别控制/持久化开发实践》SpringBoot默认集成Logback,支持灵活日志级别配置(INFO/DEBUG等),输出包含时间戳、级别、类名等信息,并可通过... 目录一、日志概述1.1、Spring Boot日志简介1.2、日志框架与默认配置1.3、日志的核心作用

PyQt5 GUI 开发的基础知识

《PyQt5GUI开发的基础知识》Qt是一个跨平台的C++图形用户界面开发框架,支持GUI和非GUI程序开发,本文介绍了使用PyQt5进行界面开发的基础知识,包括创建简单窗口、常用控件、窗口属性设... 目录简介第一个PyQt程序最常用的三个功能模块控件QPushButton(按钮)控件QLable(纯文本

基于Python开发一个图像水印批量添加工具

《基于Python开发一个图像水印批量添加工具》在当今数字化内容爆炸式增长的时代,图像版权保护已成为创作者和企业的核心需求,本方案将详细介绍一个基于PythonPIL库的工业级图像水印解决方案,有需要... 目录一、系统架构设计1.1 整体处理流程1.2 类结构设计(扩展版本)二、核心算法深入解析2.1 自

SpringBoot开发中十大常见陷阱深度解析与避坑指南

《SpringBoot开发中十大常见陷阱深度解析与避坑指南》在SpringBoot的开发过程中,即使是经验丰富的开发者也难免会遇到各种棘手的问题,本文将针对SpringBoot开发中十大常见的“坑... 目录引言一、配置总出错?是不是同时用了.properties和.yml?二、换个位置配置就失效?搞清楚加

Python如何将OpenCV摄像头视频流通过浏览器播放

《Python如何将OpenCV摄像头视频流通过浏览器播放》:本文主要介绍Python如何将OpenCV摄像头视频流通过浏览器播放的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完... 目录方法1:使用Flask + MJPEG流实现代码使用方法优点缺点方法2:使用WebSocket传输视

Python中对FFmpeg封装开发库FFmpy详解

《Python中对FFmpeg封装开发库FFmpy详解》:本文主要介绍Python中对FFmpeg封装开发库FFmpy,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录一、FFmpy简介与安装1.1 FFmpy概述1.2 安装方法二、FFmpy核心类与方法2.1 FF

基于Python开发Windows屏幕控制工具

《基于Python开发Windows屏幕控制工具》在数字化办公时代,屏幕管理已成为提升工作效率和保护眼睛健康的重要环节,本文将分享一个基于Python和PySide6开发的Windows屏幕控制工具,... 目录概述功能亮点界面展示实现步骤详解1. 环境准备2. 亮度控制模块3. 息屏功能实现4. 息屏时间

基于Linux的ffmpeg python的关键帧抽取

《基于Linux的ffmpegpython的关键帧抽取》本文主要介绍了基于Linux的ffmpegpython的关键帧抽取,实现以按帧或时间间隔抽取关键帧,文中通过示例代码介绍的非常详细,对大家的学... 目录1.FFmpeg的环境配置1) 创建一个虚拟环境envjavascript2) ffmpeg-py

Python实例题之pygame开发打飞机游戏实例代码

《Python实例题之pygame开发打飞机游戏实例代码》对于python的学习者,能够写出一个飞机大战的程序代码,是不是感觉到非常的开心,:本文主要介绍Python实例题之pygame开发打飞机... 目录题目pygame-aircraft-game使用 Pygame 开发的打飞机游戏脚本代码解释初始化部

使用Python开发一个现代化屏幕取色器

《使用Python开发一个现代化屏幕取色器》在UI设计、网页开发等场景中,颜色拾取是高频需求,:本文主要介绍如何使用Python开发一个现代化屏幕取色器,有需要的小伙伴可以参考一下... 目录一、项目概述二、核心功能解析2.1 实时颜色追踪2.2 智能颜色显示三、效果展示四、实现步骤详解4.1 环境配置4.