KunSpace
返回博客

FlexConnect:MS12 解码后的分流逻辑(DAP / SEI / 调音)

2026年7月26日
8 次阅读

读完了?别空手走啊 😏

白嫖可以,但点个赞显得有教养

写评论

读完了不评论,作者会以为你在沉思

这篇写什么?

FlexConnect 系列前几篇分别讲了:

本篇把 更上游 的 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. 整体链路(四段)

图1 从播放到出声:Soundbar + FlexConnect 四段链路图1 从播放到出声:Soundbar + FlexConnect 四段链路
做什么 关键模块
① 应用写入 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 分支:

图2 ms12_output() 分流决策图2 ms12_output() 分流决策
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_enableMS12_OUTPUT_MASK_SPEAKER 等相关。


4. 第 ③ 段:DAP 通路 vs Stereo 通路

SEI Soundbar 上,Speaker 不走 普通 TV 的 primary ALSA,而是走 SEI 专用路由

图3 DAP 通路:喇叭走 SEI,Master 不含 Speaker图3 DAP 通路:喇叭走 SEI,Master 不含 Speaker

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 多声道 独占 Speakerb_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 调参。

图4 FlexConnect tv_tuning(MAT 调音)并行通路图4 FlexConnect tv_tuning(MAT 调音)并行通路

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()

图5 SEI Speaker 最终输出链:TVSDX / bypass → wired delay → ALSA图5 SEI Speaker 最终输出链:TVSDX / bypass → wired delay → ALSA
多声道 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。

下游细节:


7. 三种典型场景对照

图6 三种典型场景:A 正常 DAP/FLAP · B DAP 关 stereo · C MAT tv_tuning图6 三种典型场景:A 正常 DAP/FLAP · B DAP 关 stereo · C MAT tv_tuning

场景 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 实践整理。

评论

还没有评论,来做第一个吧

读完了不评论,作者会以为你在沉思