C语言使用ffmpeg和sdl实现多路音频播放
前言
音频的播放通常是单例的,在进程内通常一个播放设备只能打开一次,且只支持一个写入。写播放器的时候,会遇到需要实现多开同时播放多个视频,比如视频剪辑工具的多轨道播放。这个时候就需要采用一定的方法,比如音频混合。本文将提供一种基于ffmpeg和sdl实现的音频多路混合的方法。
一、 如何实现
1、回调式打开设备
为实现多路共用一个播放设备,只能采用SDL的回调式打开音频设备。
回调方法
static std::map<void*, std::function<void(void* userdata, Uint8* stream, int len)>> _audioCallbacks;//记录每一路音频的回调方法 //总的回调方法 static void _audio_callback_sum(void* userdata, uint8_t* stream, int len) { memset(stream, 0, len); std::unique_lock< std::mutex >lck(_mtx); //调用每一路的回调方法 for (auto i : _audioCallbacks) { i.second(userdata, stream, len); } }
打开音频
static SDL_AudioSpec _wanted_spec, _spec; _wanted_spec.channels = 2; _wanted_spec.freq = 44100; _wanted_spec.format = AUDIO_F32SYS; _wanted_spec.silence = 0; _wanted_spec.samples = 1024; _wanted_spec.callback = _audio_callback_sum; SDL_OpenAudio(&_wanted_spec, &_spec) == 0;
2、注册多路回调
注册一路音频回调示例如下
_audioCallbacks[pFrame] = [&](void* userdata, Uint8* stream, int len) { //此处实现单独一路的播放逻辑 };
3、写入队列
每一路音频都创建一个音频队列,将解码的音频数据写入队列,下面是使用AVAudioFifo作为音频队列的例子。
if (av_audio_fifo_space(fifo) >= samples) { av_audio_fifo_write(fifo, (void**)&data, (int)samples); break; }
4、混合音频
在音频单独的回调中即上面_audioCallbacks注册的方法中,进行数据混合,示例如下。
//读取音频队列数据 int read = av_audio_fifo_read(fifo, (void**)&data, _spec.samples); //开始混合 SDL_MixAudioFormat(stream, data, _spec.format, newLen, SDL_MIX_MAXVOLUME);
二、完整代码
1、头文件
simple_audio_play.h
#pragma once /// <summary> /// 播放音频 /// 此方法同步阻塞,播放完成后返回 /// 支持多路播放,可放在线程中播放,线程安全。 /// </summary> /// <param name="input">输入url</param> /// <param name="exitFlag">中断标记</param> /// <returns></returns> int simple_audio_play(const char* input, int* exitFlag)
三、使用示例
1、播放音频
int exitflag= false; simple_audio_play("D:\\test_music.wav", &exitflag);
2、多路播放音频
#include"simple_audio_play.h" void main() { int exitflag = false; auto t1 = new std::thread([&]() { while (!exitflag) { simple_audio_play("D:\\test_music.wav", &exitflag); } }); auto t2 = new std::thread([&]() { while (!exitflag) { simple_audio_play("D:\\test.mp4", &exitflag); } }); system("pause"); exitflag = true; t1->join(); t2->join(); }
总结
以上就是今天要的内容了,采用ffmpeg结合sdl实现音频多路播放还是比较容易的,都有相关的接口去调用,只要设计实现整体的上层逻辑即可。但是一开始基本没有头绪,通过一番尝试后找到关键方法SDL_MixAudioFormat后,实现起来还是很简单的,这个是实践才能得到的知识。
到此这篇关于C语言使用ffmpeg和sdl实现多路音频播放的文章就介绍到这了,更多相关C语言多路音频播放内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
最新评论