Silent1566
|
2a56751af0
|
修复:MPV 几乎所有片源报「加载媒体失败」,根因是两份 libc++ 撞 soname
现象:MPV 内核下大部分视频直接失败,统一弹「MPV 加载媒体失败」。
logcat 给出真正的错误:`MPV_LOAD_FAILED: dlopen failed: failed to link
libmpv.so` —— 是原生库链接失败,不是媒体问题。
那句文案本身有歧义,这也是排查绕远的原因:`error_play_mpv_load_failed`
不只代表媒体打不开,它同样是原生库加载失败的出口。`openCurrent()` 第一句就
调用 `ensureInitialized()`,其中 `MPVLib.ensureLoaded()` 失败抛 IOException,
被同方法的 `catch (Throwable)` 收走;此时没有任何 `sawXxx` 证据位,
`classifyLoadError` 落到兜底分支 ERROR_LOAD_FAILED,最终映射成这句话。
「每个片源都给同一句」正是一次原生加载失败被反复复现的特征。
根因链(逐环已验证):
`nodejs` 模块(`79bbb3e01d` 引入)用 `ndkVersion 28.2.13676358` 配
`-DANDROID_STL=c++_shared`,于是把 NDK 28 那份 libc++_shared.so 打进
APK 的 `lib/<abi>/` —— 链接器默认命名空间的搜索路径。而 MPV 预编译产物
锁定 NDK 29(`third_party/mpv-native-lock.json`)。用 llvm-nm 核对:
`libmpv.so` 有两个未定义符号 `std::__ndk1::__from_chars_floating_point
<double>/<float>`,NDK 29 那份导出(2 个),NDK 28 sysroot 那份导出 0 个。
soname 在一个命名空间内只解析到一份,被 NDK 28 占住后,MPV 即使按绝对
路径 `System.load` 自己那份也改不了 `libmpv.so` 的 DT_NEEDED 解析结果,
缺符号 dlopen 失败,`libplayer.so` 依赖它跟着失败。
为什么突然坏:此提交之前仓库里根本没有 libc++_shared.so(git 历史核对),
MPV 自带的 NDK 29 那份从 assets 解出后独占 soname,一切正常。nodejs 模块
一进来就往 `lib/<abi>/` 塞了个版本更低的同名库,把独占抢走了。与 MPV 自身
代码无关。
修法两处:
1. `nodejs` 改 `-DANDROID_STL=c++_static`。该 shim 只用到 17 个基础运行时
符号(operator new/delete 与 __cxa_* 异常桩),静态链接体积代价很小。
改后 `libcnode.so` 的 DT_NEEDED 只剩 liblog/libdl/libm/libc。
2. 把 NDK 29 那份签入 `app/src/main/jniLibs/<abi>/`。运行时下载的
`libnode.so` 自身 DT_NEEDED 仍需要 libc++_shared.so,而 NDK 29 那份是
三方符号需求的超集:libnode 需 120 个 C++ 符号、cnode 17 个、libmpv 138
个,NDK 29 对三者均缺 0 个(libnode 唯一缺的
`_ZTHN2v88internal12trap_handler21g_thread_in_wasm_codeE` 是 V8 的 TLS
符号,由 libnode 自身解析,与 libc++ 无关)。
顺带修一处同域缺陷:`ensureInitialized()` 原先在 `mpvTryCreate()` 之前就
`nativeContextOwner = this`,创建失败抛异常时不回滚。而进接管分支时前一个
owner 已被置 released 并释放,没有别的地方会再重置它,于是进程级 owner 永久
指向一个 `initialized == false` 的死实例,之后每次播放都走接管分支去释放一个
从未创建的 context,反复失败直到重启 App —— 把单次失败放大成永久失败。改为
创建成功后才赋值,失败路径显式清 null。
验证:实机(模拟器 5556,mobile arm64,覆盖安装保留数据)确认修复有效,
三条独立证据 —— `/proc/<pid>/maps` 里 libmpv.so 与 libplayer.so 均已映射
(修复前正是这两个缺失),本次运行 dlopen 失败计数 0;应用内运行时信息显示
`decoder MPV mediacodec-copy`、`vo gpu / context android`、`A-V 0ms`;
播放位置 11 秒采样窗口内从 26.2s 推进到 37.3s,1:1 跟随真实时间。
双 flavor 编译通过。
|
2026-08-26 09:25:55 +08:00 |
|