赞
踩
目录
前两篇文章仅仅说了视频播放,而没有加入音频,而本篇将加入音频的内容,通过ffmpeg解码音频,SDL实现音频播放
SDL(Simple DirectMedia Layer)是一套使用C语言编写的开源跨平台多媒体开发库
提供了数种控制图像、声音、输出入的函数,让开发者只要用相同或是相似的代码就可以开发出跨多个平台(Linux、Windows、Mac OS X等)的应用软件
目前SDL多用于开发游戏、模拟器、媒体播放器等多媒体应用领域
SDL库下载地址:http://www.libsdl.org/
首先在Qt Creator中新建一个C++工程项目SDLDemo
将下载好的SDL和ffmpeg拷贝到与main.cpp同级的工程目录下
在SDLDemo.pro项目配置文件中加入头文件和引入库,同时引用SDL和ffmpeg的文件
以C语言的方式添加头文件,并定义两个宏,用于后续的音频解码
加入SDL的头文件后编译运行发现这样一个错误
转定义main函数
发现在这部分SDL将main定义为SDL_main,而我们并没有定义SDL_main
解决办法是:在main函数前添加#undef main,再次运行可以输出
打开ffmpeg和SDL的bin目录,将项目依赖的dll粘贴到debug路径下
解码流程如图所示,已知AVPacket中存放的是AAC格式的数据,AVFrame中存放的是PCM格式数据
主控线程main函数读取音频流向缓冲队列中投递,SDL通过回调函数audio_callback定期从缓冲队列中取数据进行解码,再拷贝到SDL播放缓冲区进行音频播放
这实际上是一个生产者-消费者模型,主线程负责从文件中读取音频流,存入到缓冲队列,解码线程负责从缓冲队列中取得数据进行解码
由于回调函数是每隔一段时间执行一次的,所以解码速度肯定没有读取音频流的速度快
使用缓冲队列的目的是为了协调读取音频流和解码的速度,主线程和解码线程不需要互相等待,减少等待的延时
因为SDL每次取固定大小的数据包进行播放,而一次解码的数据可能比它每次取的数据量要大,所以在回调函数callback中设置一个用户缓冲区
将解码得到的存入用户缓冲区audio_buf,每次取固定大小数据包时,如果取得数量不够,就从队列中继续取数据解码
如果取得数量足够,则回调函数返回,剩下的数据放在缓冲区中等待下一次再取
主线程流程
具体带有详细注释的代码请移步github
https://github.com/boomshakalakaaa/SDLDemo
从零开始学习音视频编程技术(七) FFMPEG Qt视频播放器之SDL的使用
最简单的基于FFMPEG+SDL的视频播放器 ver2 (采用SDL2.0)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。