前提
这一节,我们学习常用的音频的格式 AAC,
重点是2个:
1.掌握AAC (高级音频编码)的基本知识。
目的是:当我们在将PCM原始数据编码成AAC的时候,能够深入理解一些参数。
2.掌握 AAC的传输格式 ADTS 头部的信息。
目的是 : 当音频数据有问题的时候,如果是AAC的编码,在分析 头部信息的时候能够根据头部信息 判断问题是否出现在 头部。
1.AAC (高级音频编码)的基本知识
(Advanced Audio Coding,译为:高级音频编码)
AAC被设计为MP3格式的后继产品,通常在相同的比特率下可以获得比MP3更高的声音质量,是iPhone、iPod、iPad、iTunes的标准音频格式。
AAC相较于MP3的改进包含:
- 更多的采样率选择:AAC 的采样率 8kHz ~ 96kHz,MP3为16kHz ~ 48kHz
- 更高的声道数上限:AAC 可以支持 48个声道数,而MP3在MPEG-1模式下为最多双声道,MPEG-2模式下为5.1声道
我们可以看到在使用ffmpeg 中自带的 编码器 AAC中的 字段-ch_layouts,表示的是该 编码器支持的声道数 有哪些,注意,ch_layouts 是一个数组。数组中的每一项都应该是一个AVCHannelLayout 。
在后续的测试中,发现这一项为nullptr,猜测是由于AAC支持的声道数多达48个,因此ffmpeg 自带的AAC直接就不给值,不然给一个48项的数组有点多。
/**
* Array of supported channel layouts, terminated with a zeroed layout.
*/
///const AVChannelLayout *ch_layouts;
const AVChannelLayout *ch_layouts = avcodec->ch_layouts;
- 改进的压缩功能:以较小的文件大小提供更高的质量
- 改进的解码效率:需要较少的处理能力进行解码
1.1 AAC的规格(Profile)
AAC是一个庞大家族,为了适应不同场合的需要,它有很多种规格可供选择。下面列举其中的9种规格(Profile):
- MPEG-2 AAC LC:低复杂度规格(Low Complexity)
- MPEG-2 AAC Main:主规格
- MPEG-2 AAC SSR:可变采样率规格(Scaleable Sample Rate)
- MPEG-4 AAC LC:低复杂度规格(Low Complexity)
- 现在的手机比较常见的MP4文件中的音频部分使用了该规格
- MPEG-4 AAC Main:主规格
- MPEG-4 AAC SSR:可变采样率规格(Scaleable Sample Rate)
- MPEG-4 AAC LTP:长时期预测规格(Long Term Predicition)
- MPEG-4 AAC LD:低延迟规格(Low Delay)
- MPEG-4 AAC HE:高效率规格(High Efficiency)
最早是基于MPEG-2标准,称为:MPEG-2 AAC。后来MPEG-4标准在原来基础上增加了一些新技术,称为:MPEG-4 AAC。
1.2 详解上述规格中的LC和HE
虽然上面列举了9种规格,但我们目前只需要把注意力放在常用的LC和HE上。下图很好的展示了从LC到HE的发展历程。
下图中,PNS 是

1.2.1 LC
LC适合中等比特率,比如96kbps ~ 192kbps之间。
MPEG-4 AAC LC等价于:
- MPEG-2 AAC LC + PNS
PNS(Perceptual Noise Substitution)译为:感知噪声替代。
- PNS可以提高AAC的编码效率
1.2.2 HE
HE有v1和v2两个版本,适合低比特率:
- v1:适合48kbps ~ 64kbps
- v2:适合低于32kbps,可在低至32kbps的比特率下提供接近CD品质的声音
2 AAC 的编解码器:
常用的有两种,一种是 ffmpeg 自带的AAC,一种是第三方的 libfdk_aac
2.1 FFmpeg AAC
FFmpeg AAC
- 支持LC规格
- FFmpeg官方内置的AAC编解码器,在libavcodec库中
- 编解码器名字叫做aac
- 在开发过程中通过这个名字找到编解码器
2.1.1 FFmpeg AAC 对输入的PCM数据的参数要求
FFmpeg内部AAC格式只支持AV_SAMPLE_FMT_FLTP格式的PCM
因此如果我们要将 AV_SAMPLE_FMT_S16 的 pcm 通过 ffmpeg自带的编码器变成AAC,则先要音频重采样变成 AV_SAMPLE_FMT_FLTP ,然后再使用 ffmpeg自带的编码器编码成AAC。
2.2 FDK AAC
- 支持LC/HE规格, 也就是说,如果我们在代码中需要让编码出来的aac是HE规格的,就需要使用libfdk_aac
- 目前质量最高的AAC编解码器
- 可以集成到FFmpeg的libavcodec中
- 编解码器名字叫做libfdk_aac
- 在开发过程中通过这个名字找到编解码器,最后调用FDK AAC库的功能
在网上下载的编译版FFmpeg,通常都是没有集成libfdk_aac的。可以通过命令行查看FFmpeg目前集成的AAC编解码器。
# windows
ffmpeg -codecs | findstr aac
# mac
ffmpeg -codecs | grep aac
我这边的输出结果是:
DEAIL. aac AAC (Advanced Audio Coding) (decoders: aac aac_fixed )
D.AIL. aac_latm AAC LATM (Advanced Audio Coding LATM syntax)
很显然,并没有包含libfdk_aac。
这里给出1个比较推荐的方案:自己手动编译FFmpeg源码,将libfdk_aac集成到FFmpeg中。
- 自己手动编译的话,想集成啥就集成啥
- 可以把你想要的东西都塞到FFmpeg中,不想要的就删掉
- 也就是根据自己的需要对FFmpeg进行裁剪
2.2.1 FDK AAC 对输入的PCM数据是有参数要求的,如果参数不对,就会出现以下错误:
[libfdk_aac @ 0x7fa3db033000] Unable to initialize the encoder: SBR library initialization error
Error initializing output stream 0:0 -- Error while opening encoder for output stream #0:0 - maybe incorrect parameters such as bit_rate, rate, width or height
Conversion failed!
要求:采样格式
必须是16位整数PCM。
要求:采样率
支持的采样率有(Hz):
- 8000、11025、12000、16000、22050、24000、32000
- 44100、48000、64000、88200、96000
同理,如果我们要将 非AV_SAMPLE_FMT_S16 的PCM通过 FDK AAC


6447

被折叠的 条评论
为什么被折叠?



