AAC Audio Codec的Profile及其在不同平台上的支
date
Mar 3, 2022
slug
2022-03-03-aac-audio-profile
status
Published
tags
音视频
AAC
type
Post
AI summary
summary
本文总结了AAC audio codec的不同profile类型,以及在各种平台上编程设置aac profile的流程。
AAC简介
AAC:Advanced Audio Codec。
AAC实际上是作为MP3音频编解码算法的继任者出现在历史舞台的。与MP3一样,AAC也是一种有损的音频编解码算法。相比于MP3而言,对于相同的音频数据进行处理,AAC编码出来的音频文件更小,而声音的质量还可以做到更高。
1997年,AAC作为一项国际标准由MPEG组织发布,具体的定义包含在MPEG-2的第7部分,和MPEG-4的第3部分。
AAC的不同类型(AAC Profile)
AAC-LC:Advanced Audio Codec-Low Complexity。
AAC-HE:Advanced Audio Codec-High Efficiency。
AAC-LD:Advanced Audio Codec-Low Delay。
可以看到,AAC audio codec按照两条独立的路线进行演进,演进的方向总是采用更复杂的技术,从而达到更好的性能指标:
- AAC-LC(MPEG2)—>AAC-LC(MPEG4)—>HE-AAC—>HE-AAC v2—>Extended HE-AAC(xHE);
- HE-AAC在AAC-LC的基础上增加了SBR技术;
- HE-AAC v2在HE-AAC基础上增加了PS技术;
- Extended HE-AAC则在HE-AAC v2的基础上增加了USAC技术;
- AAC-LD—>AAC-ELD—>AAC-ELD v2;
- AAC-ELD在AAC-LD的基础上增加了SBR技术;
- AAC-ELD v2则是在AAC-ELD的基础上增加了Low Delay MPS技术。
AAC的不同profile版本可以支持向后兼容。例如,MPEG4 AAC-LC Decoder可以对MPEG2 AAC-LC Encoder编码出来的数据正确解码;而MPEG4 HE-AAC的Decoder可以支持对MPEG2和MPEG4的AAC-LC Encoder编码出来的音频流正确解码。
基于FFmpeg实现AAC编码
常用的AAC的开源编解码库是libfdk_aac,libfaac,libaacplus等。
下面以libfdk_aac为例说明如何在ffmpeg中进行aac编码的流程。
--enable-libfdk_aac --enable-nonfree --enable-encoder=libfdk_aac
编译后使用以下命令测试libfdk_aac是否被正确的编译和链接进来:
ffmpeg -i <input file> -vcodec copy -acodec libfdk_aac -profile:a aac_he <output file>
使用以下代码段打开并配置aac codec进行音频编码:
AVCodecContext *encoder_ctx;
encoder_ctx->codec_id = AV_CODEC_ID_AAC;
encoder_ctx->sample_fmt = AV_SAMPLE_FMT_S16;
encoder_ctx->profile = FF_PROFILE_AAC_HE;//在此处指定aac编码的profile
encoder = avcodec_find_encoder_by_name("libfdk_aac");
// if you still try to open it using avcodec_find_encoder it will open libfaac only.
avcodec_open2(encoder_ctx, encoder, NULL);
参考文档4提供了一份更为详细的基于ffmpeg+libfdk_aac进行aac编码的操作说明。
Android的AAC编解码支持
Android对AAC Codec的支持情况如下图所示:
Android平台下是使用MediaCodec进行音视频Codec的创建和管理。
参考文档5中包含了一份在Android下进行音频麦克风采集+AAC压缩+ADTS流媒体打包封装+AAC解码的完整流程代码。
其中在对MediaCodec编码器进行设置的时候,就通过选项指定AAC-LC profile:MediaCodecInfo.CodecProfileLevel.AACObjectLC
MediaFormat format = MediaFormat.createAudioFormat(MIMETYPE_AUDIO_AAC, SAMPLE_RATE, CHANNEL_COUNT);
format.setInteger(MediaFormat.KEY_AAC_PROFILE,
MediaCodecInfo.CodecProfileLevel还能够支持的AAC codec profile包括:
public static final int AACObjectELD=39;//AAC-ELD
iOS的AAC编解码支持
在iOS SDK中使用AudioToolbox中的Audio Converter Services来实现对AAC的编解码。
参考文档7介绍了使用Audio Converter Services实现对PCM转码为AAC并保存的完整代码流程。
- 这篇文档并没有显式设置aac的profile。
在Audio Converter Services框架下,一般使用AudioConverterNew或者AudioConverterNewSpecific接口来创建音频编解码器,这两个接口都需要调用AudioStreamBasicDescription结构体来对音频编解码器的参数进行初始化:
struct AudioStreamBasicDescription {
Float64 mSampleRate; // sample frames per second
UInt32
当AudioStreamBasicDescription结构体mFormatID设置为kAudioFormatMPEG4AAC表示创建的是一个AAC的编码器,此时就可以使用mFormatFlags来指定这个AAC codec的profile。这种方式下iOS能够支持的AAC profile包括:
MPEG4ObjectID.aac_Main
MPEG4ObjectID.AAC_LC
MPEG4ObjectID.AAC_SSR
MPEG4ObjectID.AAC_LTP
MPEG4ObjectID.AAC_SBR
MPEG4ObjectID.aac_Scalable
MPEG4ObjectID.twinVQ
MPEG4ObjectID.CELP
MPEG4ObjectID.HVXC
此外,也可以在设置AudioStreamBasicDescription结构体的mFormatID的时候,直接把mFormatID初始化为以下列表中的一个aac编码器类型,这样就不需要使用mFormatFlags来指定AAC profile了:
kAudioFormatMPEG4AAC_HE
以下为一段初始化audio codec为AAC并设置aac profile的代码:
func setupAudioConverter() {
var outputFormat = AudioStreamBasicDescription.init(
mSampleRate: 44100,
mFormatID: kAudioFormatLinearPCM,
mFormatFlags: kLinearPCMFormatFlagIsSignedInteger,
mBytesPerPacket: 2,
mFramesPerPacket: 1,
mBytesPerFrame: 2,
mChannelsPerFrame: 1,
mBitsPerChannel: 16,
mReserved: 0)
var inputFormat = AudioStreamBasicDescription.init(
mSampleRate: 44100,
mFormatID: kAudioFormatMPEG4AAC,//此处设置audio codec为aac
mFormatFlags: UInt32(MPEG4ObjectID.AAC_LC.rawValue),//此处设置aac profile为aac_lc
mBytesPerPacket: 0,
mFramesPerPacket: 0,
mBytesPerFrame: 0,
mChannelsPerFrame: 1,
mBitsPerChannel: 0,
mReserved: 0)
let status: OSStatus = AudioConverterNew(&inputFormat, &outputFormat, &audioConverter)
if (status != 0) {
print("setup converter error, status: \(status)")
}
}