ffmpeg解析pcm文件进行播放

avatar
作者
筋斗云
阅读量:0

初始化音频子系统是使用 SDL 播放音频之前的一个必要步骤。这确保了 SDL 能够正确地配置和使用音频硬件。如果你不进行初始化,试图使用音频功能可能会导致未定义的行为或错误。

为什么需要初始化音频子系统?
1.资源分配:
SDL 需要为音频设备分配资源,比如设置缓冲区大小、采样率等。
初始化确保 SDL 可以适当地配置音频设备。
2.设备兼容性:
不同的操作系统和硬件平台有不同的音频设备驱动程序。
初始化过程确保 SDL 使用正确的驱动程序与音频硬件通信。
3.状态设置:
初始化过程中可以设置音频输出的基本参数,如通道数、采样率、格式等。
这些设置对于播放音频是必需的。
4.错误检测:
初始化时 SDL 会尝试检测并报告任何潜在的问题,如音频设备不可用或驱动程序错误。

//初始化Audio子系统     if(SDL_Init(SDL_INIT_AUDIO))     {         qDebug() << "SDL_Init error" << SDL_GetError();         return;     } 
#include "playthread.h" #include <SDL2/SDL.h> #include <QDebug> #include <QFile>  #define FILENAME "D:/ffmpeg/ffm.pcm" #define SAMPLE_RATE 44100 #define SAMPLE_FORMAT AUDIO_S16LSB #define SAMPLE_SIZE (SAMPLE_FORMAT & 0xFF)//== SDL_AUDIO_BITSIZE() = 16; #define CHANNELS 2  //缓冲区样本数量 #define SAMPLES 1024 //每个样本占用多少字节 #define BYTES_PER_SAMPLE ((SAMPLE_SIZE * CHANNELS)/8) // 4 //文件缓冲区大小 #define BUFFER_SIZE BYTES_PER_SAMPLE * SAMPLES//4096  typedef struct {     int len = 0;     int pullLen = 0;     char* data = nullptr; }AudioBuffer; 
//音频参数     SDL_AudioSpec spec;     //采样率     spec.freq = SAMPLE_RATE;     //采集格式(s16le)     spec.format = AUDIO_S16LSB;//小端读取     //声道数     spec.channels = CHANNELS;     //音频缓冲区的样本数量(这个值必须是2的幂)     spec.samples = 1024;     //回调     spec.callback = pull_audio_data;      //传递给回调函数的参数     AudioBuffer buffer;     spec.userdata = &buffer;      //打开设备     if(SDL_OpenAudio(&spec,nullptr))     {         qDebug() << "SDL 0penAudio error" << SDL_GetError();         //清楚所有子系统         SDL_Quit();         return;     }      //打开文件     QFile file(FILENAME);     if(!(file.open(QFile::ReadOnly)))     {         qDebug() << "file open error" << FILENAME;         //关闭设备         SDL_CloseAudio();         //清除所有子系统         SDL_Quit();         return;     }      //开始播放(0是取消暂停) -- 开始后会一直调用回调函数     SDL_PauseAudio(0);      //存放从文件中读取的数据     char data[BUFFER_SIZE];     while(!isInterruptionRequested())     {         //只要从文件中读取的音频数据,还没有填充完毕,就跳过         if(buffer.len > 0) continue;         buffer.len = file.read(data,BUFFER_SIZE);         if(buffer.len <= 0)         {             //剩余的样本数量             int samples = buffer.pullLen / BYTES_PER_SAMPLE;             int ms = samples * 1000 / SAMPLE_RATE;             qDebug() << ms;             break;         }          //读取到了文件数据         buffer.data = data;     }      //关闭文件     file.close();      //关闭设备     SDL_CloseAudio();      //清除所有子系统     SDL_Quit(); 

当进行传参并进行设置回调函数后,线程就会不停歇的进行调用回调函数,知道线程结束

//等待音视频设备回调(会回调多次) void pull_audio_data(void *userdata,                      //需要往stream中填充PCM数据                      Uint8 *stream,                      //希望填充的大小(samples *format *channels / 8)                      int len) {     //清空stream     SDL_memset(stream,0,len);      AudioBuffer* buffer = (AudioBuffer*)userdata;     //如果bufferLen的长度为0说明还没有准备好     if(buffer->len <= 0) return;      //取len、bufferLen的最小值(防止指针越界)     buffer->pullLen = (len > buffer->len) ? buffer->len : len;      //填充数据进行播放     SDL_MixAudio(stream,(Uint8*)buffer->data,buffer->pullLen,SDL_MIX_MAXVOLUME);      buffer->data += buffer->pullLen;     buffer->len -= buffer->pullLen; } 

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!