C語言使用ffmpeg和sdl實現(xiàn)多路音頻播放
前言
音頻的播放通常是單例的,在進程內(nèi)通常一個播放設(shè)備只能打開一次,且只支持一個寫入。寫播放器的時候,會遇到需要實現(xiàn)多開同時播放多個視頻,比如視頻剪輯工具的多軌道播放。這個時候就需要采用一定的方法,比如音頻混合。本文將提供一種基于ffmpeg和sdl實現(xiàn)的音頻多路混合的方法。
一、 如何實現(xiàn)
1、回調(diào)式打開設(shè)備
為實現(xiàn)多路共用一個播放設(shè)備,只能采用SDL的回調(diào)式打開音頻設(shè)備。
回調(diào)方法
static std::map<void*, std::function<void(void* userdata, Uint8* stream, int len)>> _audioCallbacks;//記錄每一路音頻的回調(diào)方法 //總的回調(diào)方法 static void _audio_callback_sum(void* userdata, uint8_t* stream, int len) { memset(stream, 0, len); std::unique_lock< std::mutex >lck(_mtx); //調(diào)用每一路的回調(diào)方法 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、注冊多路回調(diào)
注冊一路音頻回調(diào)示例如下
_audioCallbacks[pFrame] = [&](void* userdata, Uint8* stream, int len) { //此處實現(xiàn)單獨一路的播放邏輯 };
3、寫入隊列
每一路音頻都創(chuàng)建一個音頻隊列,將解碼的音頻數(shù)據(jù)寫入隊列,下面是使用AVAudioFifo作為音頻隊列的例子。
if (av_audio_fifo_space(fifo) >= samples) { av_audio_fifo_write(fifo, (void**)&data, (int)samples); break; }
4、混合音頻
在音頻單獨的回調(diào)中即上面_audioCallbacks注冊的方法中,進行數(shù)據(jù)混合,示例如下。
//讀取音頻隊列數(shù)據(jù) 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">中斷標(biāo)記</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(); }
總結(jié)
以上就是今天要的內(nèi)容了,采用ffmpeg結(jié)合sdl實現(xiàn)音頻多路播放還是比較容易的,都有相關(guān)的接口去調(diào)用,只要設(shè)計實現(xiàn)整體的上層邏輯即可。但是一開始基本沒有頭緒,通過一番嘗試后找到關(guān)鍵方法SDL_MixAudioFormat后,實現(xiàn)起來還是很簡單的,這個是實踐才能得到的知識。
到此這篇關(guān)于C語言使用ffmpeg和sdl實現(xiàn)多路音頻播放的文章就介紹到這了,更多相關(guān)C語言多路音頻播放內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vs2019 MFC實現(xiàn)office界面的畫圖小項目
本文主要介紹了vs2019 MFC實現(xiàn)office界面的畫圖小項目,對大家入門有一定的幫助,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-06-06OpenCV實戰(zhàn)之基于Hu矩實現(xiàn)輪廓匹配
這篇文章主要介紹了利用C++ OpenCV實現(xiàn)基于Hu矩的輪廓匹配,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)OpenCV有一定的幫助,感興趣的可以學(xué)習(xí)一下2022-01-01簡單對比C語言中的fputs()函數(shù)和fputc()函數(shù)
這篇文章主要介紹了簡單對比C語言中的fputs()函數(shù)和fputc()函數(shù),注意其之間的區(qū)別,需要的朋友可以參考下2015-08-08