iOS利用FFmpeg解码音频数据并播放

iOS利用FFmpeg解码音频数据并播放,第1张

利用FFmepg解析并解码音频数据,然后将解码后的音频数据送给Audio Queue以实现播放

利用FFmpeg解析音频数据流, 利用FFmpeg解码音频数据为PCM格式 利用Audio Queue Player实现音频数据播放

本例以一个苹果原生相机录制的MOV文件为例, 将该文件使用FFmpeg解析并解码,将解码后的数据放入传输队列中,然后开启audio queue player, 播放器在回调函数中轮循取出队列中的数据实现播放

FFmpeg parse流程

FFmpeg解码流程

为了每次能够重新播放,这里需要标记当前是否为解码的第一帧数据,以重新启动播放器 另一点是使用NSTimer等待音频数据放入队列再开始播放,因为audio queue是驱动播放模式,所以必须等音频数据放入传输队列再开始播放

从Parse模块中可以获取当前文件对应FFmepg的上下文对象 AVFormatContext 因此音频流解码器信息可以直接获取

AVFrame 作为解码后原始的音视频数据的容器AVFrame通常被分配一次然后多次重复(例如,单个AVFrame以保持从解码器接收的帧)。在这种情况下,av_frame_unref()将释放框架所持有的任何引用,并在再次重用之前将其重置为其原始的清理状态。

调用avcodec_send_packet将压缩数据发送给解码器最后利用循环接收avcodec_receive_frame解码后的音视频数据

现实生活中,我们听到的声音都是时间连续的,我们称为这种信号叫 模拟信号 。模拟信号需要进行数字化以后才能在计算机中使用。

目前我们在计算机上进行音频播放都需要依赖于 音频文件 音频文件 的生成过程是将 声音信息采样 、 量化 和 编码 产生的数字信号的过程 ,人耳所能听到的声音,最低的频率是从20Hz起一直到最高频率20KHZ,因此音频文件格式的最大带宽是20KHZ。根据 奈奎斯特 的理论,只有 采样频率 高于 声音信号最高频率 的两倍时,才能把数字信号表示的声音还原成为原来的声音,所以音频文件的采样率一般在40~50KHZ,比如最常见的CD音质采样率441KHZ。

采样 :波是无限光滑的,采样的过程就是从波中抽取某些点的频率值,就是 把模拟信号数字化 。如下图所示:

采样频率 :单位时间内对模拟信号的采样次数。采样频率越高,声音的还原就越真实越自然,当然数据量就越大。采样频率一般共分为2205KHz、441KHz、48KHz三个等级。8KHz - 电话所用采样率, 对于人的说话已经足够,2205KHz只能达到FM广播的声音品质(适用于语音和中等品质的音乐),441KHz则是是最常见的采样率标准,理论上的CD音质界限,48KHz则更加精确一些(对于高于48KHz的采样频率人耳已无法辨别出来了,所以在电脑上没有多少使用价值)。

采样位数(也成量化级、样本尺寸、量化数据位数) :每个采样点能够表示的数据范围。采样位数通常有8bits或16bits两种,采样位数越大,所能记录声音的变化度就越细腻,相应的数据量就越大。8位字长量化(低品质)和16位字长量化(高品质),16 bit 是最常见的采样精度。

量化 :将采样后离散信号的幅度用二进制数表示出来的过程称为量化。(日常生活所说的量化,就是设定一个范围或者区间,然后看获取到的数据在这个条件内的收集出来)。

PCM : PCM(Pulse Code Modulation),即脉冲编码调制,对声音进行采样、量化过程,未经过任何编码和压缩处理。

编码 :采样和量化后的信号还不是数字信号,需要将它转化为数字编码脉冲,这一过程称为编码。模拟音频进采样、量化和编码后形成的二进制序列就是数字音频信号。

声道数 :声道数是指支持能不同发声的音响的个数,它是衡量音响设备的重要指标之一。

码率 :(也成位速、比特率) 是指在一个数据流中每秒钟能通过的信息量,代表了压缩质量。 比如MP3常用码率有128kbit/s、160kbit/s、320kbit/s等等,越高代表着声音音质越好。MP3中的数据有ID3和音频数据组成,ID3用于存储歌名、演唱者、专辑、音轨等我们可以常见的信息。

音频帧 :音频数据是流式的,本身没有明确的一帧帧的概念,在实际的应用中,为了音频算法处理/传输的方便,一般约定俗成取25ms~60ms为单位的数据量为一帧音频。这个时间被称之为“采样时间”,其长度没有特别的标准,它是根据编解码器和具体应用的需求来决定的。

模拟信号 -> 输入设备(传递电压值)-> 声卡(经过采样跟量化(即设置声音大小等各种值))-> 磁盘(文件) -> 声卡 -> 输出设备 -> 模拟信号

我们声音在物理上用波形表示,那么我们将这些波形称作为 模拟信号 。而我们计算机磁盘只能存储(01010101)的格式。我们将模拟信号转换成能够被磁盘存储的格式(010101)称之为 数字信号 。这个转换的过程我们叫 模数转换

我们发出来的声音(模拟信号)是连续的,我们如果要一直的对模拟信号进行转化,产生的数字信号会很大。那么我们就要采样,而采样精度就是每秒计算机对模拟信号进行采样的次数。最常见的采样精度就是上面提到的441khz/s,这个是经过大师们多年研究得出的数据,低于这个数据,效果就会很差,而高于这个数据,效果的差距不是很明显。

采样后就是变成了(0101010110100101),那声音的音量是有大小的,那这串数据,怎样表示声音的大小呢? 这就涉及到了比特率,它是指在一个数据流中每秒钟能通过的信息量。 比特率就是将声音的大小划分为多少等级。举例下:8比特,在二进制中,表示有8位,表示的十进制的值就是0(00000000)~256(11111111),那每个数值就代表着一个声音大小。

经过采样、量化、编码后转化成数字信号,然后存储为文件。

文件是用来装数字信号的 ,文件包括了比特率、采样率、声道、编码方式、以及被编码过后的数字信号。

文件格式 就是制造者自己规定的一种名称,在每个文件格式都会特定支持几种编码格式。 打个比方就是文件就是一个容器,里面可以装不同的水,有的可以装一种,有的可以装好几种。

经过采样后的数字信号很大,有时候我们不需要这么大的,所以我们就要进行编码压缩,当然压缩技术都是有损的。在不大影响音频的效果的情况下,舍弃掉一些高频或者低频的数据。

编码格式 可以理解为每种音频格式不同的编解码方式。

封装格式就是文件格式,编码就是编码格式。

了解了基础概念之后我们就可以列出一个经典的音频播放流程(以MP3为例):

在iOS系统中apple对上述的流程进行了封装并提供了不同层次的接口(引自 官方文档 )。

下面对其中的中高层接口进行功能说明:

可以看到apple提供的接口类型非常丰富,可以满足各种类别类需求:

>

Core Audio 是iOS和MAC系统中的关于数字音频处理的基础,它是应用程序用来处理音频的一组软件框架,所有关于iOS音频开发的接口都是由Core Audio来提供或者经过它提供的接口来进行封装的。

其实一句话,它是任何iOS或者MAC系统音频处理框架的基础。

具体可以用官方文档的一张图表示。

接下来我们就一起分析一下。

这里的高级别服务,更加接近于顶层,基本上我们很多关于音频开发的工作在这一层就可以完成。

它位于框架 AudioToolbox 中。

提供录制、播放、暂停、循环、和同步音频它自动采用必要的编解码器处理压缩的音频格式。

要在iOS设备上播放和录制音频,苹果推荐我们使用 AVFoundation 框架中的 AVAudioPlayer 和 AVAudioRecorder 类。虽然用法比较简单,但是不支持流式;这就意味着:在播放音频前,必须等到整个音频加载完成后,才能开始播放音频;录音时,也必须等到录音结束后,才能获取到录音数据。这给应用造成了很大的局限性。为了解决这个问题,我们就需要使用 Audio Queue Services 来播放和录制音频。感兴趣的可以看我前面写的几篇关于 Audio Queue Services 的文章。这里只是简单的给出录音和播放的原理图,具体原理和流程,看我前面写的那几篇,都有详细的介绍。

它位于框架 AVFoundation 中。

是专为IOS平台提供的基于Objective-C接口的音频播放类,可以支持iOS所支持的所有音频的播放,它主要支持以下音频格式。

这个是纯OC的实现,特点就是调用简单,下面简单的看一下他的API。

由 Audio File 与 Audio Converter 组合而成,提供压缩及无压缩音频文件的读写能力。

它与 Audio File Services 、 Audio File Stream Services 和 Audio Queue Services 等同时存在 AudioToolbox 框架中。 ExtendedAudioFile 相对 Audio File Services 和 Audio Converter Services ,API调用非常简单和明确,并且不需要去处理 AudioStreamPacketDescription ,在实际开发中逻辑更为清晰。

它就是存在框架 OpenAL 中。

是CoreAudio对OpenAL标准的实现,可以播放3D混音效果。

OpenAL 主要的功能是在来源物体、音效缓冲和收听者中编码。来源物体包含一个指向缓冲区的指标、声音的速度、位置和方向,以及声音强度。收听者物体包含收听者的速度、位置和方向,以及全部声音的整体增益。缓冲里包含 8 或 16 位元、单声道或立体声 PCM 格式的音效资料,表现引擎进行所有必要的计算,如距离衰减、多普勒效应等。

不同于 OpenGL 规格,OpenAL 规格包含两个API分支;以实际 OpenAL 函式组成的核心,和 ALC API , ALC 用于管理表现内容、资源使用情况,并将跨平台风格封在其中。还有 “ALUT ”程式库,提供高阶“易用”的函式,其定位相当于 OpenGL 的 GLUT 。

该层功能比较齐全,包括音频数据格式转换,音频文件读写,音频流解析,插件工作支持等。

它位于框架 AudioToolbox 中。

负责音频数据格式的转换

它位于框架 AudioToolbox 中。

负责音频数据的读写。

它位于框架 AudioToolbox 中。

支持均衡器和混音器等数字信号处理的插件。

它位于框架 AudioToolbox 中。

负责流解析。

它位于框架 Core Audio 中。

负责音频音频时钟同步。

该主要在MAC上的音频APP实现中并且需要最大限度的实时性能的情况下使用,大部分音频APP不需要使用该层的服务。而且,在iOS上也提供了具备较高实时性能的高层API达到你的需求。例如 OpenAL ,在游戏中具备与I/O直接调用的实时音频处理能力。

它在 IOKit 框架中,与硬件驱动交互。

获得用户空间访问硬件设备和驱动程序。 I / O Kit 框架通过设备接口机制实现对I / O Kit对象(驱动程序和结点)的非内核访问。

音频硬件抽象层,使API调用与实际硬件相分离,保持独立。

它位于 Core MIDI 框架中,与MIDI设备(如硬件键盘和合成器)进行通信。

Core MIDI 框架提供了用于与MIDI(乐器数字接口)设备(包括硬件键盘和合成器)进行通信的API。 使用基座连接器或网络从iOS设备进行连接。 有关使用基座连接器的更多信息,请参阅Apple的 MFi program 。

访问电脑硬件时钟。

只实现音频的播放,没有其他需求, AVAudioPlayer 就可以满足需求。它的接口使用简单,不用关心其中的细节,通常只提供给它一个播放源的URL地址,并且调用其play、pause、stop等方法进行控制,observer其播放状态更新UI即可。

APP需要对音频进行流播放,就需要 AudioFileStreamer 加 Audio Queue ,将网络或者本地的流读取到内存,提交给 AudioFileStreamer 解析分离音频帧,分离出来的音频帧可以送给 AudioQueue 进行解码和播放,可参考下面。

AudioStreamer

FreeStreamer

AFSoundManager

APP需要需要对音频施加音效(均衡器、混响器),就是除了数据的读取和解析以外还需要用到AudioConverter或者Codec来把音频数据转换成PCM数据,再由AudioUnit+AUGraph来进行音效处理和播放,可参考下面。

DouAudioStreamer

TheAmazingAudioEngine

AudioKit

1 iOS Audio Unit(一)

以上就是关于iOS利用FFmpeg解码音频数据并播放全部的内容,包括:iOS利用FFmpeg解码音频数据并播放、音频知识详解(一)、Core Audio框架详细解析(二) —— 基于CoreAudio的ios音频服务总结分析等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/10155007.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-05
下一篇2023-05-05

发表评论

登录后才能评论

评论列表(0条)

    保存