这篇写什么?
FlexConnect 系列前几篇分别讲了:
- 声道 remap — MS12 8ch 怎么对上物理 I2S 槽
- Speaker Sync 与本机 20ms 补偿 — 测出无线偏差后再补偿本机
本篇把 更上游 的 HAL 路由串起来:
MS12 解码完成后,PCM 怎么分成 DAP / Stereo / 码流?Soundbar 喇叭和 eARC/I2S 谁写谁?FlexConnect 调音(MAT)又走哪条路?
按「从播放到出声」顺序,用流程图把分流原理讲清楚。
建议阅读顺序:图 1 四段总览 → 图 2 ms12_output 分流 → 图 3 DAP vs Master → 图 4 tv_tuning → 图 5 SEI 最终链 → 图 6 场景对照。
0. 一句话总结
MS12 解码后按 pcm_type 分成 DAP 多声道、Stereo 立体声、码流三路;
Soundbar 喇叭统一走 SEI → TVSDX/bypass → alsaPORT-pcm;
I2S / eARC 走 ms12_output_master(Soundbar 上强制 2ch,不含 Speaker);
FlexConnect 调音时 MAT 的 8ch 经 ring buffer 只从 dap 路径进 SEI,stereo 路径被掐断,避免双写杂音。
1. 整体链路(四段)
| 段 | 做什么 | 关键模块 |
|---|---|---|
| ① 应用写入 | App / Netflix / Tuning Tool → HAL | out_write_new() |
| ② MS12 解码 | 解码 + DAP/FLAP + 多端口输出 | dolby_ms12_main_process() → ms12_output() |
| ③ HAL 分流 | 按 pcm_type / 格式分支 | dap_pcm_output / stereo_pcm_output / mc_pcm_output / bitstream_output |
| ④ 物理输出 | Speaker 走 SEI;外接走 Master | soundbar_*_route_sei vs ms12_output_master |
2. 第 ① 段:播放数据怎么进 MS12
| 步骤 | 函数 / 模块 | 做什么 |
|---|---|---|
| 1 | out_write_new() |
所有 PCM / 码流写入的 HAL 入口 |
| 2 | FlexConnect 调试 | 每次 write 更新 adev->is_tv_tuning_mode(来自 AML_DEBUG_AUDIOHAL_TVTUNING) |
| 3 | dolby_ms12_main_process() |
把 DDP / AC4 / MAT / PCM 喂给 MS12 |
| 4 | MS12 内部图 | 解码 → 可选 DAP/FLAP → 产生多种输出端口 |
| 5 | dolby_ms12_register_output_callback(ms12_output) |
MS12 解码完成后回调 HAL |
2.1 MS12 输出掩码
初始化时配置 MS12_OUTPUT_MASK_*:
| 掩码 | 含义 |
|---|---|
| STEREO | 立体声 PCM |
| SPEAKER | Speaker 多声道(DAP 处理后) |
| DAP | 启用 DAP 处理图 |
| MAT / DDP / DD | 码流编码输出 |
2.2 FlexConnect 关键:Config W + FLAP
#ifdef ENABLE_FLEXCONNECT
if (adev->is_ms12_flexr_sconf && adev->is_ms12_flexr_dconf
&& (get_ms12_config_level(adev) == MS12_CONFIG_W)) {
dap_init_mode = 3; // flap is on
}
#endif
...
dolby_ms12_set_dap2_initialisation_mode(dap_init_mode);
含义: 设备 JSON 配了 Config W,且 FlexConnect 的 stream / device config 都就绪 → FLAP(FlexConnect 空间音频调音)打开。
这与 声道 remap 篇 的 dap_init_mode=3 是同一套机制。
3. 第 ② 段:MS12 解码后如何分流
核心分发在 ms12_output(),按 数据类型 和 pcm_type 分支:
if (audio_is_linear_pcm(output_format) && ms12_info) {
if (ms12_info->pcm_type == MC_LPCM) {
mc_pcm_output(...);
} else if (ms12_info->pcm_type == DAP_LPCM) {
dap_pcm_output(...);
} else {
stereo_pcm_output(...);
}
} else {
// 非 PCM:DDP / AC3 / MAT 码流
bitstream_output(...) / hbr_bitstream_output(...)
}
| pcm_type | 函数 | 典型用途 |
|---|---|---|
DAP_LPCM |
dap_pcm_output() |
DAP/FLAP 处理后的多声道 → Soundbar 主通路 |
NORMAL_LPCM |
stereo_pcm_output() |
普通立体声 downmix → Master + 条件性 SEI |
MC_LPCM |
mc_pcm_output() |
原生多声道 → Master |
| 非 PCM | bitstream_output() |
DDP / MAT 码流 → eARC / SPDIF |
DAP 是否启用 由 is_dolbyms12_dap_enable() 决定(内部走 is_audio_postprocessing_add_dolbyms12_dap()),与 effect_ctrl.dap_enable、MS12_OUTPUT_MASK_SPEAKER 等相关。
4. 第 ③ 段:DAP 通路 vs Stereo 通路
在 SEI Soundbar 上,Speaker 不走 普通 TV 的 primary ALSA,而是走 SEI 专用路由。
4.1 DAP 开启 → dap_pcm_output()
if (is_dolbyms12_dap_enable(aml_out) || ms12->dap_only_enable) {
#ifdef ENABLE_SOUNDBAR_DEVICES
soundbar_dap_pcm_route_sei(aml_out, buffer, size, output_format, ms12_info);
#else
ms12_output_master(buffer, priv_data, size, output_format, ms12_info);
#endif
}
soundbar_dap_pcm_route_sei() 链路:
MS12 DAP_LPCM (6/8ch)
→ processing_multich_pcm() / sei_processing_multich_pcm()
→ sei_audio_speaker_output()
→ TVSDX DSP(或 FlexConnect bypass)
→ alsaPORT-pcm · Soundbar 喇叭
要点:
- DAP 多声道 独占 Speaker(
b_speaker_use_dap_pcm = true) - 不再 让
ms12_output_master往 Speaker 写 8ch(避免 I2S underrun)
4.2 DAP 关闭 → stereo_pcm_output()
Soundbar 上典型逻辑:
#ifdef ENABLE_SOUNDBAR_DEVICES
soundbar_stereo_pcm_route_sei(...); // 条件性走 SEI speaker
...
if (is_dolbyms12_dap_enable(...) || ms12->dap_only_enable) {
ring_buffer_write(&ms12->spdif_ring_buffer, ...); // stereo 备份给 SPDIF ring
}
ms12_output_master(...); // I2S/HDMI/eARC,不含 Speaker
#endif
soundbar_stereo_pcm_route_sei() 仅在以下条件 同时满足 才走 SEI:
| 条件 | 说明 |
|---|---|
| 是 Soundbar | is_SBR |
| 输出配置含 SPEAKER | MS12_OUTPUT_MASK_SPEAKER |
| DAP 未开启 | 无 DAP 多声道独占 |
| 非蓝牙 A2DP | 避免与 BT 路由冲突 |
4.3 ms12_output_master() 在 Soundbar 上的角色
#ifdef ENABLE_SOUNDBAR_DEVICES
if (is_SBR(adev) && !adev->b_dap_8ch_hdmiout) {
data_info.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
data_info.target_audio_device_out = AUDIO_DEVICE_OUT_HDMI; // 不含 SPEAKER
}
#endif
| 输出目标 | 谁负责 | 声道 | ALSA 端口 |
|---|---|---|---|
| Soundbar 喇叭 | soundbar_*_route_sei → TVSDX/bypass |
2 / 5 / 8ch | PCM_DEVICE (alsaPORT-pcm) |
| I2S AUX / 外接 | ms12_output_master |
强制 2ch | I2S |
| eARC / SPDIF | ms12_output_master → hdmi / optical |
2ch PCM 或码流 | eARC / SPDIF |
这是 Soundbar 项目的核心分工:Speaker 归 SEI,Master 只保 stereo I2S + eARC,避免双写和 2→8 upmix 导致 underrun。
5. FlexConnect 专用:tv_tuning 调音模式
FlexConnect 调音是一套 独立于正常播放 的并行通路,用于 MAT 输入 下的 FLAP 调参。
5.1 启用条件
| 条件 | 来源 |
|---|---|
vendor.media.audio.ms12.tv_tuning = 1 |
属性,MS12 打开 tuning 图 |
输入格式 = AUDIO_FORMAT_MAT |
MAT 调音信号 |
AML_DEBUG_AUDIOHAL_TVTUNING |
每次 write 设 is_tv_tuning_mode |
| Config W + flexr sconf/dconf | FLAP 就绪 |
MS12 初始化 MAT + tv_tuning 时:
if (ms12->tv_tuning_flag && (input_format == AUDIO_FORMAT_MAT)) {
dolby_ms12_set_tv_tuning_flag(ms12->tv_tuning_flag);
output_config |= MS12_OUTPUT_MASK_SPEAKER;
}
并注册 tv_tuning 回调 → 把 MS12 内部 8ch float PCM 写入 tv_tuning_ring_buffer。
5.2 数据流与为何要掐断 stereo
MS12 tuning 图 → ms12_tv_tuning_callback → tv_tuning_ring_buffer (write)
dap_pcm_output (focus=MAT + is_tv_tuning_mode):
ring_buffer_read → soundbar_dap_pcm_route_sei → SEI → 喇叭 ✅
stereo_pcm_output (同条件):
memset 静音 + early return ❌ (跳过 step1 hw_write)
为什么要 stereo 提前 return?
tuning 时 Speaker 已由 dap_pcm_output → SEI 喂数据。若 stereo_pcm_output 的 step1 仍走 aml_audio_pcm_output(HEADPHONE/SPDIF),会与 SEI 并行写 ALSA → Broken pipe / XRUN → 持续杂音。
对应代码:
if (adev->is_tv_tuning_mode && focus_stream_out
&& (adev->ms12.focus_audioformat == AUDIO_FORMAT_MAT)) {
memset(buffer, 0, size);
return ret; // 在 step1 之前就返回
}
// dap_pcm_output 侧:
if (adev->is_tv_tuning_mode && focus_stream_out
&& (adev->ms12.focus_audioformat == AUDIO_FORMAT_MAT)) {
ring_buffer_read(..., tv_tuning_pcm_buffer, ...);
soundbar_dap_pcm_route_sei(...); // tuning PCM → SEI Speaker
return ret;
}
6. SEI Speaker 最终输出
无论来自 DAP 还是 Stereo 路由,最终都进 sei_audio_speaker_output():
多声道 PCM32 (processing_multich_pcm)
→ bypass_tvsdx?
是 → sei_audio_processing() [FlexConnect FLAP,见 remap 篇]
否 → tvsdx_process_buffer() [空间音频 DSP · JSON 如 SEI_5ch_ISS]
→ FlexConnect 本机 ch1–5 延迟补偿 [见 Speaker Sync / 补偿篇]
→ audio_virtual_buf (underrun 检测)
→ aml_alsa_output_write_new() → PCM_DEVICE
TVSDX 会根据 JSON 设备描述做声道映射、FlexConnect 空间渲染。写 ALSA 前还有 virtual_buf 监控写晚 underrun。
下游细节:
- Remap: MS12 声道与 I2S 匹配
- 本机补偿: Speaker Sync 测出偏差后再补偿
7. 三种典型场景对照
场景 A:正常播放,DAP/FLAP 开(FlexConnect Config W)
App → MS12(解码 + DAP + FLAP)
├─ DAP_LPCM → dap_pcm_output → SEI/TVSDX → Soundbar 喇叭 ✅
└─ NORMAL_LPCM → stereo_pcm_output
├─ spdif_ring_buffer(备份 stereo 给 eARC)
└─ ms12_output_master → I2S 2ch + eARC/SPDIF
场景 B:DAP 关,纯 stereo 内容
App → MS12(解码,无 DAP)
└─ NORMAL_LPCM → stereo_pcm_output
├─ soundbar_stereo_pcm_route_sei → SEI/TVSDX → 喇叭 ✅
└─ ms12_output_master → I2S + eARC
场景 C:FlexConnect tv_tuning(MAT 调音)
MAT 调音信号 → MS12 tuning 图
├─ tv_tuning_callback → ring_buffer(8ch)
├─ dap_pcm_output 读 ring → SEI → 喇叭 ✅(唯一 Speaker 源)
└─ stereo_pcm_output 直接 return(不写 ALSA)❌
8. 关键开关 / 配置速查
| 名称 | 作用 |
|---|---|
MS12_CONFIG_W |
FlexConnect FLAP 所需 MS12 配置级别 |
is_ms12_flexr_sconf / dconf |
FlexConnect stream/device 配置是否就绪 |
dap_init_mode = 3 |
FLAP 开启 |
vendor.media.audio.ms12.tv_tuning |
MS12 内部 tuning 处理图 |
is_tv_tuning_mode |
HAL 侧 tuning 路由开关 |
focus_audioformat == MAT |
判定当前 focus 流是否为 MAT tuning |
vendor.media.audiohal.tvsxd.bypass |
跳过 TVSDX,直写 ALSA(FlexConnect FLAP) |
effect_ctrl.dap_enable |
DAP 效果开关 |
b_speaker_use_dap_pcm |
DAP 多声道独占 Speaker |
9. 排查清单
| 现象 | 优先查 |
|---|---|
| 喇叭无声但 eARC 有声 | DAP 是否 enable · soundbar_*_route_sei 是否被调用 |
| I2S underrun / 杂音 | DAP 8ch 与 Master 是否双写 Speaker |
| MAT 调音杂音 / Broken pipe | stereo_pcm_output 是否在 tuning 时 early-return |
| FLAP 不生效 | Config W · flexr sconf/dconf · dap_init_mode=3 |
| 高度声道异常 | TVSDX bypass · remap 篇 |
| 本机快于无线音箱 | Speaker Sync / 补偿篇 |
| 播 C 时 L 大于 C | 不足 8ch / Level Matching 篇 |
真机 dump:
dumpsys media.audio_flinger --hal | grep -A30 FlexConnect
dumpsys media.audio_flinger --hal | grep -A10 MS12
HAL dump 中关注 FlexConnect / FLAP / remap 相关字段即可。
10. FlexConnect 系列阅读顺序
| 顺序 | 文章 | 侧重 |
|---|---|---|
| 1 | Dolby FlexConnect 概览 | 产品模块 |
| 2 | 硬件 RF → 校准六层链路 | Bridge · 校准 App |
| 3 | 本篇 | MS12 解码后 HAL 分流 · DAP/SEI/Master |
| 4 | MS12 声道 remap | 逻辑序 → 物理 I2S |
| 5 | Speaker Sync 与本机补偿 | 测出偏差 → 本机 ch1–5 补偿 |
| 6 | 不足 8ch dconf / Level Matching | 7ch 补齐再走 8ch CTA |
| 7 | FlexConnect 全流程 | 打包到校准 / Tuning 总览 |
本篇是 ③,搞清「数据从 MS12 出来后往哪条路走」;④⑤ 是 SEI 链路上的下游细节。
基于 Amlogic SEI Soundbar HAL + Dolby MS12 FlexConnect 实践整理。
评论
还没有评论,来做第一个吧
读完了不评论,作者会以为你在沉思