docs(harmony-audio): record implementation and validation

This commit is contained in:
BoatingCloud committed 2026-08-29 10:07:29 +08:00
1 parent dfda10b6d8
commit 9fdf08073e
9 files changed
+137 -19

No files matched your search

+1 -1
View File
@@ -57,7 +57,7 @@ MPV 源码仅增加明确的 `host_machine.system() == 'ohos'` 检测与 `ohos`
- 所有 prefix 静态库成员为 AArch64 ELF;
- `libmpv` 为 AArch64 ELF shared object;
- 动态依赖仅来自 HarmonyOS SDK allowlist;
- 动态依赖仅来自 HarmonyOS SDK allowlist(启用 `harmony-audio` 时包含 `libohaudio.so`);
- `.pc`/CMake/Ninja target metadata 无 Homebrew、`/usr/local`、`.dylib` 或 Apple framework;
- Client API 与 OpenGL Render API 必需符号存在。
+102
View File
@@ -0,0 +1,102 @@
# HarmonyOS OHAudio Backend
状态:Phase 3 CODE COMPLETE / DEVICE VALIDATION PENDING。
代码、OHOS arm64 交叉编译和模拟器 H.264/AAC smoke test 已完成。实体设备上的真实输出路由、延迟、A/V sync 精度、蓝牙/耳机、多声道和长时间稳定性仍未宣称完成。
## Architecture
```text
MPV decoder/filter
↓
MPV AO buffer (audio/out/buffer.c)
↓ pull callback
audio/out/ao_harmony.c
↓
OH_AudioRenderer write callback
↓
HarmonyOS audio device
```
`ao_harmony` 是 MPV pull AO。PCM 始终在 native 层流动;ArkTS 只负责播放控制和诊断展示,不参与持续 PCM 搬运。
实现文件:
- `audio/out/ao_harmony.c`:AO、OHAudio renderer、callback、时钟和统计。
- `audio/out/ao_harmony.h`:Playback Lab 使用的只读诊断 ABI。
- `audio/out/ao.c`、`meson.build`、`meson.options`:driver 注册和 `harmony-audio` feature。
## OHAudio API
实现以当前 API 24 SDK headers 为准:
- `ohaudio/native_audiostreambuilder.h`
- `ohaudio/native_audiorenderer.h`
- `ohaudio/native_audiostream_base.h`
- `multimedia/native_audio_channel_layout.h`
- 链接库:`libohaudio.so`
Builder 设置 `SamplingRate`、`ChannelCount`、`ChannelLayout`、`SampleFormat`、`EncodingType(RAW)`、`LatencyMode(NORMAL)`、`RendererInfo(USAGE_MOVIE)` 和 write/device/error callbacks,然后 `GenerateRenderer` 并销毁 Builder。Renderer 使用 `Start`、`Pause`、`Stop`、`Flush`、`Release`、`SetVolume`、`GetFrameSizeInCallback`、`GetLatency` 和 `GetAudioTimestampInfo`。
## MPV AO / callback model
`write` 保持 NULL,`start` 触发 OHAudio。OHAudio 回调只计算 frame 数、调用 `ao_read_data(..., pad_silence=true, blocking=false)`,不足部分填静音并更新轻量原子计数;不访问网络、不调用 N-API/ArkTS、不分配大对象、不逐回调打印日志。回调首包仅在 debug 日志中记录一次。
MPV AO buffer 是 producer,OHAudio callback 是 consumer。`ao_read_data` 返回的 PCM 只在当前 callback 内有效,系统提供的 `audioData` 由 OHAudio 所有;没有 AVFrame 或 PCM 指针跨生命周期保存。
## Format / sample rate / channel layout
- 仅接受 PCM;MPV float 优先映射 `AUDIOSTREAM_SAMPLE_F32LE`,创建失败时回退 `AF_FORMAT_S16` / `AUDIOSTREAM_SAMPLE_S16LE`。
- 采样率使用 MPV 请求值,不强制改成 48 kHz;设备拒绝时返回真实 renderer 创建错误,由 MPV 上层重新协商/重采样。
- 单声道映射 `CH_LAYOUT_MONO`,其余首版限制为双声道 `CH_LAYOUT_STEREO`;超过 2 声道先通过 MPV channel map downmix 到 stereo。没有声称 5.1/7.1/Atmos/Dolby 已支持,实体设备能力仍待验证。
模拟器实际日志:请求 48 kHz、5.1、floatp,经 MPV downmix 后创建 48 kHz、2 声道、float32 renderer。
## Pause / resume / stop / seek / flush
- pause:`OH_AudioRenderer_Pause`。
- resume/start:`OH_AudioRenderer_Start`。
- stop:MPV 的 stop/EOF 通过 AO reset/uninit 路径停止 renderer;不把 pause、stop、release 混为 destroy。
- seek/reset:先禁止新 callback,`Stop`,等待 inflight callback 清零,再 `Flush`;清空本地提交/播放 epoch,增加 `audioFlushCount` 与 `seekAudioResetCount`,下一次 `start` 重新开始。
- release:禁止 callback → Stop → 等待 callback → 停止并 join timestamp 线程 → Release renderer;回调不会持有释放后的 player/AO 指针。
所有 OHAudio 返回值都检查;失败通过 MPV AO error/reload 路径处理,使用 `AUDIO_BUILDER_FAILED`、`AUDIO_RENDERER_CREATE_FAILED`、`AUDIO_RENDERER_START_FAILED`、`AUDIO_FLUSH_FAILED`、`AUDIO_RELEASE_ERROR`、`AUDIO_UNSUPPORTED_FORMAT` 等明确日志。
## A/V clock and delay
timestamp 线程每 20 ms 调用 `OH_AudioRenderer_GetAudioTimestampInfo`。`submittedFrames` 在 callback 完成填充后递增;`playedFrames` 使用 renderer frame position 减去本次 Flush 的 timestamp origin,避免设备在 Flush 后继续返回旧 epoch。延迟计算为:
```text
pending = max(submittedFrames - playedFrames, 0)
estimatedDelayMs = rendererLatencyMs + pending * 1000 / sampleRate
```
`audioTimestamp` 保留 OHAudio 的 monotonic timestamp。MPV 播放倍速仍由 MPV 音频滤镜/时钟负责,不叠加 renderer speed。算法已编译并在模拟器观察到稳定计数;绝对 A/V 偏差与设备路由连续性必须实体机测量。
## Volume and underrun
Renderer volume 固定为 unity,最终音量由 MPV 软件 gain 处理,避免双重增益。API 24 当前没有可用的系统 underrun counter,因此不伪造 `systemUnderrun`;callback 返回帧不足时只增加 Velix-side `bufferStarvation`。
## Playback Lab diagnostics
Playback Lab 保持原有 video-only 启动路径,新增 `Audio On/Off`(切换 MPV `aid=auto/no`)和以下 native 状态:`audioBackend`、`sampleRate`、`sampleFormat`、`channels`、`channelLayout`、`submittedFrames`、`playedFrames`、`estimatedAudioDelayMs`、`audioBufferStarvation`、`audioFlushCount`、`seekAudioResetCount`、`audioState`。返回值使用 ArkTS Number,避免 BigInt 让 Inspector 无法序列化。
## Validation
- Audio-enabled:OHOS arm64 `libmpv.so.2.5.0` clean build,DT_NEEDED 新增 `libohaudio.so`,Playback Lab HAP 构建成功。
- Video-only:使用 `-Dharmony-audio=disabled` 的独立 Meson build 编译成功。
- Emulator smoke:H.264/AAC MP4 上确认 renderer create、start、callback PCM consumed、pause、resume、seek/flush、stop、release;示例观察到 `starvation=0`,模拟器日志无新增崩溃。
- 未验证:实体设备、真实 latency/A-V 偏差、蓝牙/有线/扬声器切换、系统 audio focus/interruption、5.1/7.1、30 分钟压力。
## Known limitations and physical TODO
1. 当前仅实现 OHAudio renderer;没有 OHCodec/hwdec、Vulkan、音频焦点业务和设备专属路由策略。
2. `systemUnderrun` 需要 SDK 提供真实接口后再接入;当前仅有 `bufferStarvation`。
3. 多声道真实 capability、采样率拒绝后的设备行为、timestamp 在路由切换后的连续性需要实体设备矩阵。
4. 上层应用负责电话/音频焦点策略;Core 只接受 pause/resume 或 AO reload。
Phase 4 不在本次变更中启动。未来 OHCodec 评估至少需要单独验证 surface/buffer 同步、stride/format、fence 与生命周期、零拷贝/DRM 约束、不同设备实现差异五类风险。
## License
本次仅修改 Velix-MPV-Core 内的 MPV 集成代码和 Playback Lab;MPV 原有 GPL/LGPL 许可保持不变。HarmonyOS SDK 头文件/系统库按 SDK 自身许可使用,没有复制第三方实现源码。
+8 -6
View File
@@ -1,5 +1,7 @@
# HarmonyOS Audio Research
> 状态:IMPLEMENTED(代码、OHOS arm64 编译、Playback Lab 模拟器音频 smoke test 已完成);实体设备输出路由、真实延迟、A/V sync 精度、多声道与长稳仍为 NEED PHYSICAL DEVICE VERIFY。
## 1. 推荐方案
新增 MPV 音频输出 `ao_harmony`,直接接 HarmonyOS OHAudio:
@@ -14,9 +16,9 @@ MPV audio pipeline -> native PCM ring/buffer -> OHAudio write callback -> AudioR
- headers:`ohaudio/native_audiostreambuilder.h`、`native_audiorenderer.h`、`native_audiostream_base.h`、`multimedia/native_audio_channel_layout.h`
- library:`libohaudio.so`
- baseline:API 10
- SDK 依据:当前 API 24 headers;builder 基础接口从 API 10 起,独立 write callback 从 API 12 起,`GetAudioTimestampInfo` 从 API 15 起,`GetLatency` 从 API 23 起。
- builder:采样率、声道数、sample format、encoding、latency mode、channel layout、usage、write callback、callback frame size
- renderer:Start、Pause、Stop、Flush、Release、timestamp、frames written、volume、speed、underflow count、latency
- renderer:Start、Pause、Stop、Flush、Release、`GetAudioTimestampInfo`、`SetVolume`、`GetLatency`;API 24 没有可用的系统 underrun counter,Velix 只记录 callback starvation。
API 24 还提供 advanced callback 等新接口,但首版使用最低且稳定的 callback API,避免无必要抬高最低版本。
@@ -27,10 +29,10 @@ API 24 还提供 advanced callback 等新接口,但首版使用最低且稳定
| PCM 格式协商 | `SetSamplingRate`、`SetChannelCount/Layout`、`SetSampleFormat` | `init()` 将 MPV `ao->format` 映射为 OHAudio;不支持时返回 unsupported,让 MPV 重采样 |
| 数据输出 | renderer write callback | 回调只读取 MPV AO buffer,禁止阻塞、分配大对象或调用 ArkTS |
| Pause/Resume | `OH_AudioRenderer_Pause/Start` | 与 MPV `control()` 状态串行化 |
| Stop/Seek | `Stop/Flush/Start` | Seek 时丢弃旧 PCM,并重建 MPV A/V sync 基准 |
| Volume | `OH_AudioRenderer_SetVolume` | 首版支持 0..1;MPV 软件音量仍可用,避免重复增益 |
| Stop/Seek | `Stop/Flush/Start` | Seek 时停止 callback、清空 OHAudio、重建 timestamp epoch,避免旧 PCM 泄漏 |
| Volume | `OH_AudioRenderer_SetVolume` | 系统 renderer 固定 unity;最终增益由 MPV 软件音量处理,避免重复增益 |
| Speed | MPV 音频滤镜为主 | 不直接用 Renderer speed 改变 MPV 时钟;系统 speed 仅后续专项验证 |
| A/V Sync | `GetTimestamp` / `GetFramesWritten` | 驱动 delay 由已提交帧与硬件播放位置计算,必须做单调性/路由切换测试 |
| A/V Sync | `GetAudioTimestampInfo` | 驱动 delay 由 callback 已提交帧与 timestamp epoch 内的硬件播放位置计算;路由切换仍需实体设备测试 |
| 低延迟 | `SetLatencyMode` | 视频播放默认 normal;fast 仅在设备支持和稳定性测试后启用 |
| 多声道 | channel layout + capability | 先 stereo;5.1/7.1 按设备能力协商,失败回退重混音,不 fake success |
@@ -54,4 +56,4 @@ API 24 还提供 advanced callback 等新接口,但首版使用最低且稳定
5. 播放速度与 MPV 时钟双重调整风险。
6. 多声道 layout 枚举和实际设备 route 不一致。
首版验收:PCM 正常播放;pause/resume/seek 无旧音频泄漏;1 小时无死锁;统计 underrun;A/V sync 偏差有真实测量。未完成这些测试前不宣称低延迟或多声道完成。
代码验收:PCM 正常播放;pause/resume/seek/flush/release 生命周期已在模拟器通过;starvation 与 timestamp metrics 已接入。1 小时稳定性、真实 underrun、A/V sync 偏差、路由与多声道仍需实体设备,不宣称低延迟或多声道完成。
+6 -6
View File
@@ -11,16 +11,16 @@ Phase 1 已在 DevEco Studio OpenHarmony SDK 6.1.1.125 / API 24 下生成真实
| MPV | `182fa6ca49f455cadb884858f386e2f00540aeb7` / 0.41.0-UNKNOWN |
| FFmpeg | `3acec0a1af2dda0a0838689b8b8649e7deb080a0` |
| libmpv | `build/ohos-arm64/prefix/lib/libmpv.so.2.5.0` |
| Size | 34,297,376 bytes |
| SHA-256 | `e70c5c4e81cb40f03f5334b9d9deae9afa836b7e420a950a7111099bb87e3a87` |
| Size | 34,308,568 bytes |
| SHA-256 | `2de66d76a91b167b632bb824a2149f644c8e667bb2ebbd003e18c6c7e7eeca46` |
| Architecture / ABI | ELF64, little-endian, AArch64, System V ABI, shared object, SONAME `libmpv.so.2` |
| Toolchain | OHOS Clang/LLD 15.0.4, target `aarch64-linux-ohos`, musl sysroot |
| Source patches | 1:MPV Meson 增加明确 `ohos` platform feature;依赖源码修改 0 |
| MPV / build files | 7:`ao_harmony.c/.h`、AO 注册、Meson feature、OHOS build script、依赖 allowlist;第三方依赖源码修改 0 |
| Build issues | 4,全部关闭 |
## Features
MPV enabled:`clone`、`ffmpeg`、`gl`、`glibc-thread-name`、`glob`、`glob-posix`、`gpl`、`libass`、`libdl`、`libplacebo`、`linux-fstatfs`、`memrchr`、`ohos`、`posix`、`posix-shm`、`ppoll`、`pthread-condattr-setclock`、`vector`、`vt.h`、`zlib`、`libmpv shared`、`plain-gl`。
MPV enabled:`clone`、`ffmpeg`、`gl`、`glibc-thread-name`、`glob`、`glob-posix`、`gpl`、`harmony-audio`、`libass`、`libdl`、`libplacebo`、`linux-fstatfs`、`memrchr`、`ohos`、`posix`、`posix-shm`、`ppoll`、`pthread-condattr-setclock`、`vector`、`vt.h`、`zlib`、`libmpv shared`、`plain-gl`。
FFmpeg enabled:软件解码、demux、network、HTTP/HTTPS/TCP/TLS、OpenSSL 3.6.4、SDK zlib、OHCodec H.264/HEVC decoder/encoder。FFmpeg GPL/version3/nonfree 均为 0。
@@ -30,10 +30,10 @@ Disabled:mpv CLI、tests、fuzzers、Lua/JavaScript、libcurl、桌面音视
- 最小 C/C++ 探针均为 OHOS AArch64 ELF;C++ 探针依赖 SDK `libc++_shared.so`。
- prefix 内 13 个静态库的全部可见 archive object 均通过 AArch64 ELF 检查。
- `libmpv.so.2.5.0` 动态依赖仅为 `libc.so`、`libz.so`、`libnative_media_vdec.so`、`libnative_media_venc.so`、`libnative_media_codecbase.so`、`libnative_media_core.so`、`libnative_window.so`。
- `libmpv.so.2.5.0` 动态依赖为 `libc.so`、`libz.so`、`libnative_media_vdec.so`、`libnative_media_venc.so`、`libnative_media_codecbase.so`、`libnative_media_core.so`、`libnative_window.so`、`libohaudio.so`;均来自 HarmonyOS SDK allowlist。
- target metadata 未发现 Homebrew、`/usr/local`、`.dylib`、Apple framework 或 Mach-O 污染。
- 已验证 `mpv_create`、`mpv_initialize`、`mpv_command`、`mpv_set_property`、`mpv_get_property`、`mpv_render_context_create`、`mpv_render_context_render`、`mpv_render_context_set_update_callback`、`mpv_render_context_free`。
- `scripts/build-all-ohos.sh` 已连续完成第二次全链路构建与最终校验。
- `scripts/build-all-ohos.sh` 已完成本次 Phase 3 全链路构建与最终校验(`verified_archives=13`)。
## Warnings
+4 -3
View File
@@ -1,12 +1,13 @@
# Velix-MPV-Core Memory
- 项目:独立 HarmonyOS MPV 播放内核,禁止混入 Velix 主应用源码。
- 当前阶段:Phase 2 Playback Lab 模拟器首帧与控制链路已验证;实体机验收待做。
- 当前阶段:Phase 3 OHAudio AO 代码完成;模拟器音频 smoke 已验证;实体设备验收待做。
- 基线:MPV `182fa6ca49f455cadb884858f386e2f00540aeb7`,分支 `harmony-port`。
- SDK:OpenHarmony API 24 / 6.1.1.125 / `aarch64-linux-ohos` / Clang 15.0.4。
- 关键结论:首版 GLES+EGL+libmpv Render API;OHAudio AO;官方 FFmpeg OHCodec 路线。
- Phase 1 产物:`build/ohos-arm64/prefix/lib/libmpv.so.2.5.0`,AArch64 ELF,OpenGL Render API symbols 完整。
- 远程:`origin` 为私有 Gitea 仓库,默认分支 `harmony-port`;`upstream` 为 MPV 官方仓库。
- Phase 2:`playback_lab/` 独立 HAP,XComponent/OHNativeWindow/EGL/libmpv/软件解码已通;未接音频、硬解、网络。
- 待办:实体机 H.264/AAC、HTTP/HTTPS/HLS、压力与 30 分钟稳定性;完成后再进入 Phase 3 音频。
- Phase 2:`playback_lab/` 独立 HAP,XComponent/OHNativeWindow/EGL/libmpv/软件解码已通;实体设备待验。
- Phase 3:`audio/out/ao_harmony.c` + OHAudio pull callback、pause/flush/clock/metrics 已通;保持 `hwdec=no`,未接 OHCodec。
- 待办:实体机 H.264/AAC、真实 A/V sync/路由/多声道、压力与 30 分钟稳定性;完成后再评估 Phase 4。
- 索引:`memory/projects.md`、`memory/infra.md`、`memory/lessons.md`、`memory/2026-08-28.md`。
+6
View File
@@ -3,3 +3,9 @@
文件变更: playback_lab/*, DOCS/PHASE2_PLAYBACK_REPORT.md, MEMORY.md, memory/*
教训: Surface 回调直接取得 OHNativeWindow;事件线程改为 20ms;ArkTS 状态计数使用 Number;hdc 文件需发送到应用沙箱。
标签: #phase2 #playback-lab #harmonyos #egl #libmpv #first-frame
[PROJECT:Velix-MPV-Core] 完成 Phase 3 OHAudio Native Audio Backend
结论: `audio/out/ao_harmony.c` 以 MPV pull AO 接入 API 24 OHAudio,float32/S16、mono/stereo、pause/resume/stop/flush/release、timestamp epoch、starvation/flush metrics 已实现;`build-all-ohos.sh`、video-only/audio-enabled 编译和 HAP 均通过。
文件变更: audio/out/ao_harmony.c, audio/out/ao_harmony.h, audio/out/ao.c, meson.build, meson.options, scripts/*, playback_lab/*, DOCS/HARMONY_AUDIO_*.md, memory/*
教训: MPV 音频开关使用 `aid=auto/no`;OHAudio reset 必须 Stop→等待 callback→Flush;模拟器可验证输出但不能代替实体机路由/A-V sync/压力验收。
标签: #phase3 #ohaudio #audio #emulator-smoke #pending-device
+2
View File
@@ -15,3 +15,5 @@
- hdc:`/Applications/DevEco-Studio.app/Contents/sdk/default/openharmony/toolchains/hdc`
- 模拟器目标:`127.0.0.1:5555`,HarmonyOS 6.1.0.126 / API 24
- Playback Lab 构建:在 `playback_lab/` 执行 `scripts/stage-mpv.sh` 后用 hvigor `--no-daemon assembleHap --mode module -p product=default`
- OHAudio:API 24 headers `ohaudio/native_audiostreambuilder.h` / `native_audiorenderer.h` / `native_audiostream_base.h`,动态库 `libohaudio.so`;Meson 使用 `-Dharmony-audio=enabled`。
- Phase 3 HAP:`playback_lab/entry/build/default/outputs/default/entry-default-unsigned.hap`;模拟器 H.264/AAC smoke target `127.0.0.1:5555`。
+4
View File
@@ -17,3 +17,7 @@
- `hdc file send` 语法为 `file send -b <bundle> <local> <remote>`;应用沙箱媒体必须发送到 `/data/storage/el2/base/haps/entry/files/`。
- libmpv 诊断计数返回 ArkTS Number;返回 BigInt 会导致 Inspector 无法序列化组件状态。
- MPV 事件线程需高频轮询;200ms 轮询会使属性/命令事件堆积,seek 报 `MPV_ERROR_EVENT_QUEUE_FULL`。
- MPV `audio` 是 `aid` 别名(音轨选择),不能传布尔 `yes/no`;Playback Lab 音频开关必须使用 `aid=auto/no`。
- OHAudio seek/reset 先 `Stop` 再 `Flush`,并等待 inflight callback;只 Flush 后重新 Start 在模拟器返回 `AUDIOSTREAM_ERROR_ILLEGAL_STATE`。
- OHAudio timestamp 在 Flush 后可能保留旧 epoch;统计需保存 raw frame origin,否则会出现 `playedFrames > submittedFrames`。
- `setup-ohos-env.sh` 在 zsh 中的循环变量 `path` 会覆盖特殊 PATH 数组;运行脚本应使用 `/bin/sh` 或避免 source 到交互 zsh。
+4 -3
View File
@@ -2,8 +2,9 @@
## Velix-MPV-Core
- 状态:Phase 2 Playback Lab 模拟器验证完成;最终实体机验收未完成。
- 状态:Phase 3 CODE COMPLETE / DEVICE VALIDATION PENDING;OHAudio 模拟器 smoke 完成,最终实体机验收未完成。
- 已完成:远程闭环、固定依赖、隔离工具链、C/C++ 探针、FFmpeg/OpenSSL/字体栈/libplacebo、AArch64 `libmpv.so.2.5.0`、ABI/符号/污染/许可证审计。
- 产物:`build/ohos-arm64/prefix/lib/libmpv.so.2.5.0`,34,297,376 bytes。
- 产物:`build/ohos-arm64/prefix/lib/libmpv.so.2.5.0`,34,308,568 bytes;DT_NEEDED 含 `libohaudio.so`。
- 已完成:独立 HAP、XComponent/OHNativeWindow、EGL ES3、libmpv OpenGL Render、软件解码本地 MP4 首帧、播放控制与释放重入。
- 待办:实体机与网络/音频/压力矩阵;报告见 `DOCS/PHASE2_PLAYBACK_REPORT.md`。
- 已完成:`ao_harmony` PCM float32→S16 fallback、采样率/mono-stereo 协商、pause/resume/stop/flush/release、timestamp epoch、starvation/flush metrics;`build-all-ohos.sh`、video-only/audio-enabled 构建和 Playback Lab HAP 均通过。
- 待办:实体机输出路由、真实延迟/A-V sync、蓝牙/耳机、多声道、30 分钟压力;报告见 `DOCS/HARMONY_AUDIO_IMPLEMENTATION.md` 与 `DOCS/PHASE2_PLAYBACK_REPORT.md`。