Files
Velix-MPV-Core/DOCS/HARMONY_AUDIO_IMPLEMENTATION.md
T

6.6 KiB
Raw Blame History

HarmonyOS OHAudio Backend

状态:Phase 3 CODE COMPLETE / DEVICE VALIDATION PENDING。

代码、OHOS arm64 交叉编译和模拟器 H.264/AAC smoke test 已完成。实体设备上的真实输出路由、延迟、A/V sync 精度、蓝牙/耳机、多声道和长时间稳定性仍未宣称完成。

Architecture

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。延迟计算为:

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 自身许可使用,没有复制第三方实现源码。