Open Headunit VideoDecoder重启策略源码解读SYNC_STALL看门狗设计【免费下载链接】open-headunitHeadunit App for displaying Android Auto项目地址: https://gitcode.com/GitHub_Trending/he/open-headunitOpen Headunit 是一款开源车载中控Head Unit应用可以把闲置的安卓平板或手机变成 Android Auto 车机屏幕实时解码并渲染手机投来的 H.264 / H.265 视频流。由于车机多为低端硬件视频解码器随时可能卡死导致黑屏、卡帧Open Headunit 的 VideoDecoder 因此内置了一套 SYNC_STALL 看门狗与多级重启策略。本文带你读懂这套2 秒发现真卡死、只在该重启时重启、永不无限循环的完整设计。为什么车机投屏容易假卡死车机 SoC 性能有限MediaCodec 解码时会出现三种长时间不出画面的场景而它们里只有一种真正需要重启手机侧空闲Android Auto 屏幕静止时停止发送视频数据——不是故障关键帧饥饿解码器中途重建后从 P 帧恢复渲染必须等到下一个 IDR 关键帧才能出画面而 Android Auto 的关键帧周期约 69 秒——此时重建反而重置等待越重启越黑屏真实卡死输入字节持续流入、却没有任何画面输出——这才是需要强制重启的解码器故障。实测数据源码注释中记录在 UNISOC MT50 上旧逻辑曾 33 秒内盲目重建 4 次耗尽重启预算之后 10~60 秒持续rendered0黑屏直到会话结束。SYNC_STALL 看门狗正是为终结这种恶性循环而设计的。看门狗四大参数2秒 / 8秒 / 60秒 / 4次四个常量集中定义在 VideoDecoder.kt参数取值作用SYNC_STALL_THRESHOLD_MS2000ms触发阈值已渲染过画面的解码器 2 秒内无新输出即怀疑卡死SYNC_STALL_COOLDOWN_MS8000ms冷却期两次强制重启之间至少要间隔 8 秒SYNC_STALL_RESET_MS60000ms复位窗口60 秒内不再触发重启则重启计数清零MAX_SYNC_STALL_RESTARTS4 次重启上限冷却期内最多只允许强制重启 4 次为什么需要独立的冷却与上限解码器还有另一条无帧重启阶梯连续 3 次重启未渲染出任何画面即触发编解码器类型回退但它只统计一帧都没出的重启。一台边缘性能设备——能出画面、只是偶尔慢——会轻松绕过这条阶梯如果看门狗不单独设限就会在临界硬件上无限重建 MediaCodec形成和重启预算无关的死循环。一个被实测喂出来的细节中途重建的解码器暖机可能很慢MT50 上从重建到首帧最长约 8 秒而正常出画面后的会话重建会享受 10 秒宽限期WARM_RECONFIGURE_FIRST_FRAME_GRACE_MS见 VideoDecoder.kt。冷启动则保持 2 秒短窗口保证真正死亡的组件快速失败。三分类裁决不该重启的绝不重启检测到2 秒无输出后DecoderStallCausePolicy.kt 的classify()会先做一次三向归因纯函数无时钟无日志便于单测PHONE_IDLE手机空闲2 秒内没有收到任何输入字节 → 手机只是停了流。此时刷新时间戳、保持沉默——这条分支曾误报重启被抑制让一整轮硬件排查被0/4 used的日志误导STARVED_OF_KEYFRAME关键帧饥饿输入在流、但该解码器实例从未解码出一个关键帧 → 不重建改为通过释放/重获焦点这一协议唯一杠杆请求关键帧请求节奏由 VideoRecoveryPolicy.kt 节流最多等待 15 秒KEYFRAME_STARVATION_PATIENCE_MS才升级回普通重建路径STALLED真卡死输入持续到达、关键帧也解出过、却无输出 → 进入看门狗重启流程。一个容易踩坑的判定关键帧必须以解码器输出端真的解出了为准而非喂进去了。中途丢包的关键帧头部仍带参数集扫描时会伪装成关键帧却解不出任何画面——若按喂入计数饥饿路径会被打回重建循环配套追踪器见 KeyframeRepairTracker.kt。重启阶梯从重建到换编解码器再到认输裁决为 STALLED 后检测主循环见 VideoDecoder.kt冷却期未满或已用满 4 次→ 不重启但每 10 秒节流打一条重启被抑制日志——否则耗尽重启预算后仍在卡死的解码器日志会和完全健康的解码器一模一样无从分辨冷却期已过且未超限→syncStallRestartCount调用scheduleRestart(sync_stall)见 VideoDecoder.kt只置一个标志位由下一次decode()入口统一停掉旧 MediaCodec 并重建避免跨线程销毁无帧重启阶梯若某次重建连一帧都没渲染出restartsSinceLastFrame1统计规则由 DecoderRestartPolicy.kt 裁决连续 3 次即触发 H.264 ↔ H.265 的一次性编解码器类型回退两种编码都失败则decoderPermanentlyFailed true彻底停止重启避免无限循环。仓库还内置了 1920×1080 的彩色屏幕测试图重启后肉眼核对车机出画面是否正常核心源码地图模块路径解码引擎 SYNC_STALL 看门狗decoder/video/VideoDecoder.kt卡死归因三分类decoder/video/DecoderStallCausePolicy.kt无帧重启计数裁决decoder/video/DecoderRestartPolicy.kt关键帧请求节流decoder/video/VideoRecoveryPolicy.kt关键帧修复追踪decoder/video/KeyframeRepairTracker.kt策略单元测试VideoFeedThrottlePolicyTest.kt小结SYNC_STALL 看门狗的设计哲学可以浓缩为三句话用输入字节流区分手机停了与解码器死了用冷却 上限 复位窗口给每次重启装上限让边缘硬件不会拖垮整个会话用节流日志保证不行动本身也留下证据。这套先归因、再设限、最后兜底的阶梯式恢复思路对任何要做播放器自愈的开发者都是很好的参考。【免费下载链接】open-headunitHeadunit App for displaying Android Auto项目地址: https://gitcode.com/GitHub_Trending/he/open-headunit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考