25、音频策略与TV:电视音频路由特点、ARC/eARC路由、HDMI CEC与音频联动
电视音频路由,说实话,跟手机完全是两码事。
手机音频路由,核心是「谁插入了耳机」、「蓝牙连没连」、「扬声器要不要静音」。逻辑相对简单,状态切换也快。
但电视不一样。电视是一个家庭娱乐中心,它要跟 soundbar、功放、游戏机、机顶盒、蓝光播放器打交道。音频路由的复杂度,一下子就上来了。
我最早接触电视音频时,被 ARC 和 eARC 搞得有点懵。后来调了几个平台的 HDMI 驱动,才慢慢摸清楚这里面的门道。今天咱们就把它彻底讲透。
电视音频路由的核心矛盾
电视音频路由,说白了就两个问题:
- 音频从哪来?—— HDMI 输入、内置 Tuner、流媒体 App、USB 播放、蓝牙输入。
- 音频往哪去?—— 内置扬声器、耳机、HDMI ARC/eARC 输出、蓝牙输出、光纤/同轴输出。
你想想看,电视要同时处理这么多输入输出,还要保证切换时没有爆音、没有延迟、格式能正确协商。这比手机复杂多了。
核心差异点:手机音频路由是「点对点」的,电视音频路由是「多对多」的。而且电视还要考虑 HDMI CEC 的联动控制。
ARC 和 eARC 到底是什么?
ARC 全称 Audio Return Channel,音频回传通道。eARC 是它的增强版。
我简单解释一下:
传统 HDMI 连接,音频是从播放器(比如蓝光机)流向电视。但如果你想把电视自身的音频(比如 Netflix 流媒体)传到 soundbar 上播放,怎么办?
以前你需要单独拉一根光纤线。ARC 的出现,就是为了让这根光纤线「消失」—— 音频可以通过 HDMI 线从电视回传给 soundbar。
| 特性 | ARC | eARC |
|---|---|---|
| 带宽 | 约 1 Mbps | 约 37 Mbps |
| 最大声道数 | 5.1 声道 | 7.1 声道 + 对象音频 |
| 支持格式 | Dolby Digital, DTS | Dolby TrueHD, DTS-HD MA, Dolby Atmos, DTS:X |
| 延迟 | 较高(约 100ms) | 较低(约 5ms) |
| HDMI 版本 | HDMI 1.4 及以上 | HDMI 2.1 及以上 |
嗯,这里要注意:eARC 虽然带宽大,但它需要 HDMI 2.1 的硬件支持。很多老电视只有 ARC,播不了无损格式。
我的经验:我曾经在一款电视上调试 eARC,发现 soundbar 始终只能识别到 ARC 模式。查了半天,发现是 HDMI 线的问题——线缆不支持 2.1 的带宽。换了一根认证线,问题解决。所以,别小看线缆。
ARC/eARC 的路由逻辑
在 Android 音频框架中,ARC/eARC 被抽象为一个音频输出设备。但它的路由逻辑,跟普通设备不太一样。
我画了一张图,帮你理解 ARC/eARC 在电视中的位置:
从图上你可以看到,音频策略引擎是核心。它要决定:
- 当前播放的音频,应该走内置扬声器,还是走 ARC 输出到 soundbar?
- 如果走 ARC,格式要不要转码?比如电视只支持 Dolby Digital,但源是 PCM 多声道,要不要编码?
- 如果用户插了耳机,要不要自动 mute 掉 ARC?
这些逻辑,在 Android 的 AudioPolicyManager 中都有对应的实现。我建议你重点关注 getOutputForDevice() 和 getInputForDevice() 这两个函数。
HDMI CEC 与音频联动
CEC 的全称是 Consumer Electronics Control,消费电子控制。它允许通过 HDMI 线缆传输控制指令。
跟音频相关的 CEC 指令,主要有这几个:
| CEC 指令 | 作用 | 音频联动场景 |
|---|---|---|
<Active Source> |
通知谁当前是活跃源 | 切换 HDMI 输入时,音频路由自动切换 |
<System Audio Mode> |
开启/关闭系统音频模式 | 电视音频输出切换到 soundbar |
<Set System Audio Mode> |
请求开启系统音频模式 | soundbar 通知电视「音频交给我」 |
<Volume Up/Down> |
音量控制 | 电视遥控器控制 soundbar 音量 |
<Mute> |
静音 | 电视静音时同步静音 soundbar |
我举个例子,你感受一下 CEC 联动的流程:
- 用户按下电视遥控器的「音量+」键。
- 电视收到按键,判断当前音频输出设备是 ARC(soundbar)。
- 电视通过 CEC 发送
<Volume Up>指令到 soundbar。 - soundbar 收到指令,调高自身音量。
- 电视屏幕上显示音量条(从 soundbar 反馈回来的音量值)。
整个过程,用户感觉就像在控制电视自己的音量一样。这就是 CEC 联动的魅力。
注意:CEC 的兼容性是个大坑。不同品牌的设备,对 CEC 指令的实现不完全一致。我曾经遇到过一台索尼电视和三星 soundbar 之间,System Audio Mode 协商失败,导致 ARC 没有声音。最后发现是 CEC 的握手时序问题,需要在驱动层加一个 200ms 的延迟。
音频格式协商与转码
ARC/eARC 的路由,不仅仅是「把音频数据送过去」这么简单。格式协商才是真正的难点。
举个例子:
- 电视播放一个 Netflix 的 Dolby Atmos 流。
- 音频策略引擎检查 ARC 链路的 EDID(扩展显示标识数据),发现 soundbar 支持 Dolby Atmos。
- 直接透传,不做转码。
但如果 soundbar 只支持 Dolby Digital 呢?
- 策略引擎需要把 Dolby Atmos 降级为 Dolby Digital(5.1)。
- 或者,如果 soundbar 连 Dolby Digital 都不支持,那就只能降为 PCM 2.0。
这个降级逻辑,在 Android 中由 AudioPolicyManager 配合 AudioFlinger 完成。核心代码在 AudioPolicyManager::getOutputForDevice() 中,它会遍历所有可能的输出设备,找到第一个匹配的格式。
// 伪代码示意:格式协商逻辑
status_t AudioPolicyManager::selectOutputForFormat(
audio_format_t format,
audio_devices_t device) {
// 检查设备支持的格式列表
AudioDeviceDescriptor *desc = getDeviceDescriptor(device);
if (desc->supportsFormat(format)) {
// 直接透传
return OK;
}
// 降级:尝试 Dolby Digital
if (desc->supportsFormat(AUDIO_FORMAT_AC3)) {
return configureEncoder(AUDIO_FORMAT_AC3);
}
// 再降级:PCM
return configureEncoder(AUDIO_FORMAT_PCM_16BIT);
}
嗯,这里要注意:转码是有性能开销的。如果电视的 DSP 不够强,转码会导致延迟增加,甚至音画不同步。我建议你在做产品定义时,提前跟芯片厂商确认好 DSP 的转码能力。
避坑指南:我踩过的几个坑
做电视音频这么多年,我踩过不少坑。挑几个典型的分享给你:
- ARC 无声:我曾经遇到过一台电视,ARC 连接 soundbar 后没有声音。查了半天,发现是 HDMI 线缆的 19 针(ARC 专用针脚)接触不良。换线解决。
- eARC 握手失败:eARC 的握手协议比 ARC 复杂。如果 soundbar 和电视的 eARC 实现不完全兼容,可能会反复握手,导致音频断断续续。我当时的解决方案是在驱动层增加一个握手超时重试机制。
- CEC 音量不同步:电视遥控器按音量+,soundbar 音量增加了,但电视屏幕上的音量条没变。这是因为电视没有从 soundbar 读取到音量反馈。需要在 CEC 驱动中实现
<Report Audio Status>的解析。 - 格式降级导致音质差:用户抱怨电视接 soundbar 后音质变差。检查发现,策略引擎把 Dolby Digital Plus 降级成了 Dolby Digital。其实 soundbar 是支持 DD+ 的,只是 EDID 信息没写对。修改 EDID 后解决。
我的建议:如果你在开发电视音频,一定要准备一个 HDMI 分析仪。它能帮你抓取 EDID、CEC 指令、音频格式协商的细节。没有这个工具,调试 ARC/eARC 问题就像蒙着眼睛走路。
总结一下
电视音频路由,核心就是三件事:
- 多源到多输出的调度—— 由 AudioPolicyManager 负责。
- ARC/eARC 的格式协商与转码—— 由 AudioFlinger 和 DSP 配合完成。
- CEC 的音频联动控制—— 由 HDMI 驱动层实现。
这三件事,任何一个环节出问题,都会导致用户感知到的音频体验下降。做电视音频,耐心和细心比什么都重要。
公众号:蓝海资料掘金营,微信deep3321