ACM 音频编码模块 · 编解码的统管者
ACM(Audio Coding Module)是音频编解码的统管层,连接上层的流对象和底层的编解码器与 NetEq。这一章讲清 ACM 在发送侧驱动编码、在接收侧把包送进 NetEq 的角色,以及它作为「音频编解码门面」的定位。
ACM 音频编码模块 · 编解码的统管者
编解码器有了,谁来驱动它们、并把它们接到收发流?是 ACM(Audio Coding Module,modules/audio_coding/)。它是音频编解码的统管门面,虽不像 NetEq、AEC3 那样有硬核算法,却是把音频编解码各部件粘合起来的关键。
ACM 的两副面孔
ACM 在发送和接收两侧各有职责:
发送侧,ACM 驱动编码器把采集的音频压缩成包;接收侧,ACM 把收到的包送进 NetEq,再取出解码后的音频。
- 发送侧(编码) —— APM 处理干净的音频交给 ACM,ACM 用协商好的编解码器(Opus)编码,产出压缩帧交给打包发送。它还管编码器的参数(码率、是否开 FEC/DTX)——拥塞控制的目标码率经它落到 Opus。
- 接收侧(解码) —— 收到的音频包交给 ACM,ACM 把它们喂进 NetEq(
InsertPacket);播放线程要音频时,ACM 从 NetEq 取出(GetAudio)处理好的音频。NetEq 就住在 ACM 的接收侧内部——ACM 是 NetEq 的宿主和门面。
所以 ACM 是“编解码器 + NetEq”的封装层:上层的 ChannelSend/ChannelReceive 只跟 ACM 打交道,不必直接摆弄编解码器和 NetEq 的细节。
为什么需要这层门面
直接让流对象操作编解码器和 NetEq 不行吗?ACM 这层门面的价值:
- 隐藏复杂度 —— NetEq 内部极其复杂(抖动缓冲、决策、PLC),ACM 把它包成简单的“塞包 / 取音频”两个动作,上层无需懂 NetEq 内幕。
- 统一编解码器管理 —— 一次通话可能协商多个编解码器、中途还可能切换,ACM 统一管理“当前用哪个编解码器解这个包”(payload type → 编解码器的映射)。
- 线程边界 —— 编码在发送相关的线程、解码 / NetEq 在播放线程(被声卡的取音频回调驱动),ACM 协调这个边界。
这又是 WebRTC 一贯的门面 / 抽象手法:用一个中间层,把下面一堆复杂部件收拢成简洁接口。
在管线里的位置
ACM 是音频编解码的中枢:发送侧它是编码器的驱动,接收侧它是 NetEq 的宿主。
小结与下一章
ACM(音频编码模块) 是音频编解码的统管门面:发送侧驱动 Opus 编码(并管码率 / FEC/DTX 参数);接收侧把包喂进 NetEq(InsertPacket)、取出处理好的音频(GetAudio)——NetEq 就住在 ACM 接收侧内部。这层门面隐藏了 NetEq 的复杂、统一管理多编解码器、协调线程边界。
现在进入音频接收侧的明珠——NetEq。它把抖动缓冲、丢包隐藏、时间伸缩融为一体,是实时音频最精妙的模块。下一章总览。👉 NetEq 总览。
参考资料
- [1] libwebrtc 源码.
modules/audio_coding/acm2/(AudioCodingModule)、api/audio_codecs/。 - [2] libwebrtc 源码.
modules/audio_coding/neteq/g3doc/index.md。 - [3] 关联音频管线总览。