Skip to content

fix(mpv): 修复内嵌 mpv 在 surface 销毁/EOF 后 VO 重建导致的 SIGABRT - #90

Merged
ModerRAS merged 1 commit into
masterfrom
codex/fix-mpv-eof-crash
Sep 17, 2026
Merged

ModerRAS merged 1 commit into
masterfrom
codex/fix-mpv-eof-crash

Conversation

@ModerRAS

Copy link
Copy Markdown
Owner

问题

内嵌 mpv(EXPERIMENTAL_MPV_EMBEDDED)退场或播到 EOF 时整个进程 SIGABRT,根因是 mpv 窗口型 VO 在 Android window 已失效时被重建:

14:38:12.373  cplayer: video EOF reached
14:38:13.796  W/mpv : detaching surface            ← App 退场先 detach 了 Surface
14:38:13.829  V/mpv : event: video-reconfig        ← mpv 的 VO 随即重建
14:38:13.834  F/libc: ../video/out/vo_mediacodec_embed.c:40 create_mediacodec_device_ref():
                      assertion "vo->opts->WinID != 0 && vo->opts->WinID != -1" failed
14:38:13.839  F/libc: Fatal signal 6 (SIGABRT) in tid (vo), pid com.miruplay.tv

mediacodec_embed 是 GLES2 设备(HK1)默认的 vo,它要求创建时 WinID 有效;而 App 在 release / surfaceDestroyed / 新播放接管旧会话时都会先 detachSurface(),mpv 的 vo 线程紧跟着做一次 video-reconfig,于是断言崩溃。

容易命中的三条路径(都在真机复现过,均 100% 崩):

  1. mpv 模式播到文件 EOF(30 s 测试片,启动后约 38 s 必崩)
  2. mpv 模式播放中按 BACK 退场(表层 detach 触发)
  3. 上一个播放还在收尾时直接起播新片源

前提:本 PR 的复现/验证依赖 #89(libc++ 打包修复)。没有 #89 时 libmpv.so 根本加载不了,mpv 模式连起播都到不了。

修复

  • surfaceDestroyed / releasePlayerAfterBegin:在 detachSurface() / destroy() 之前先把 vo 切到 null(音频继续播,不销毁会话),surfaceCreated() 再按 voInUse 恢复真实 vo。
  • applyRuntimeOptions():只在 surface 已附着时才重建 vo;surface 不在时仅记录 voInUse,等重新 attach 后恢复。
  • BaseMPVViewTest:更新 destroy 动作顺序断言(DISABLE_VIDEO_OUTPUT → DETACH),新增「无 surface 不应用 runtime vo」用例。

真机验证(HK1 RBOX K8,debug 构建,实际按键操作 + 观察)

场景 master 行为 本 PR 行为
mpv 播 30 s 文件到 EOF SIGABRT(Fatal signal 6,vo 线程) 进程存活,mpv 正常走完 end-file,无 assert;HDMI 稳定
mpv 播放中按 BACK SIGABRT(detach → video-reconfig) 进程存活,vo="null" → detach,无 assert
SDR → BACK → 立刻起播 HDR 长片 SIGABRT 进程存活,无 assert

其它验证:

  • 全新起播内嵌 mpv(LV999-S01E03,HEVC/HDR):HDMI 出画正常,logcat VO: [mediacodec_embed] 1920x1080;
  • ./gradlew :player-mpv-android:testDebugUnitTest:9/9 通过;
  • ./gradlew test lint:BUILD SUCCESSFUL;
  • 交叉检查:改动只在 player-mpv-android 的 surface/vo 生命周期,未触及 Exo/IJK/DSP 路径;默认 Exo 播放与字幕渲染不受影响。

已知遗留(不在本 PR 范围)

「新播放请求与旧 player screen 拆卸并发」这条路径在修复后不再崩溃,但偶发黑屏(新播放的 SurfaceView 未 attach,MPVLib 单例被旧视图的延迟 release 回收)。master 在同一条路径上是直接崩溃,所以这是升级不是回归;它属于 App 层 MiruMpvSurfaceView 跨屏复用/释放的生命周期问题,需要单独处理。已在 PR 描述与 checklist 里标注。

@coderabbitai

coderabbitai Bot commented Sep 16, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: ba530583-1eb4-4f47-81e3-a4d1dedc7f91


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@ModerRAS

Copy link
Copy Markdown
Owner Author

CI 红不是本分支代码问题:它基于当前 master,而 master 的 Setup Android SDK 步骤仍在装 Google 已移除的 legacy tools 包(Warning: Failed to find package 'tools')。该修复在 #89 的第二个 commit 里(三个 job 显式 packages: 'platform-tools')。

建议顺序:先合 #89 → 我把本 PR rebase 到新 master(CI 即绿,因为本分支只有 mpv 生命周期一处改动)→ 再合本 PR。另外运行时也依赖 #89:没有它 libmpv.so 加载不了,mpv 模式起播都到不了。

内嵌 mpv 退场或 EOF 时会先 detach Surface,而窗口型 VO(GLES2 设备默认的
mediacodec_embed)紧接着做 video-reconfig,mpv 随即在
vo_mediacodec_embed.c:40 断言失败,vo 线程 SIGABRT 掉整个进程:

  F/libc: ../video/out/vo_mediacodec_embed.c:40 create_mediacodec_device_ref():
    assertion "vo->opts->WinID != 0 && WinID != -1" failed
  F/libc: Fatal signal 6 (SIGABRT) in tid (vo), pid com.miruplay.tv

mpv 日志证据(时间顺序):video EOF reached → detaching surface →
event: video-reconfig → abort。

修复:
- surfaceDestroyed / releasePlayerAfterBegin 在 detachSurface / destroy 之前先把
  vo 切到 "null"(音频继续播),surfaceCreated 再按 voInUse 恢复真实 vo
- applyRuntimeOptions 只在 surface 已附着时重建 vo,避免无窗口时重建
- BaseMPVViewTest 覆盖 destroy 动作顺序与 vo 应用条件

注:真机复现/验证依赖 #89 的 libc++ 修复(否则 libmpv.so 根本加载不了)。
真机验证见 PR 描述。
@ModerRAS
ModerRAS force-pushed the codex/fix-mpv-eof-crash branch from fc7fb3c to 4ba5754 Compare September 17, 2026 02:17
@ModerRAS

Copy link
Copy Markdown
Owner Author

已按计划收尾:

  • rebase 到 master(fix(player): 修复 libc++ 打包冲突导致 libmpv/libass 无法加载、ASS 字幕不渲染 #89 已合并,61f86311),checklist 的两处冲突手工解掉(保留两侧新增:Native runtime packaging + Native lifecycle races、libass native host + Embedded mpv backend)
  • CI:build ✅ lint ✅(不再是 setup-android 的 infra 红)
  • rebase 后的树重新构建并装机复测:内嵌 mpv 播 30 s 文件到 EOF,进程存活、0 条 Fatal signal/assertion,vo="null" 关闭与恢复路径按预期执行;测试后设备 prefs 已还原为 STANDARD_EXO

diff 仍然只有 4 个文件(3 个 player-mpv-android + checklist 两行),随时可合。

@ModerRAS
ModerRAS merged commit eba31a3 into master Sep 17, 2026
9 checks passed
@ModerRAS
ModerRAS deleted the codex/fix-mpv-eof-crash branch September 17, 2026 02:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant