From d3b2ef1102b8e7c6ae3743027166a6ed6c555a8e Mon Sep 17 00:00:00 2001 From: CaoWangrenbo Date: Thu, 13 Aug 2026 08:55:01 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E8=AE=B0=E5=BD=95=20RTSP=20=E4=BD=8E?= =?UTF-8?q?=E5=BB=B6=E8=BF=9F=E8=B0=83=E7=A0=94=E7=BB=93=E8=AE=BA=E4=B8=8E?= =?UTF-8?q?=20rtsp-client-android=20=E9=9B=86=E6=88=90=E5=86=B3=E7=AD=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - AGENTS.md: RTSP 视频流章节重写——现状(ExoPlayer)、延迟根因分析、 决策(弃用 ExoPlayer 视频渲染,集成 rtsp-client-android v5.6.5)、 库的关键技术要点(零缓冲架构/仅TCP/H.265 FU/内置延迟统计/已知坑) - TODO.md: 视频低延迟改造拆解为 7 个可执行任务 --- AGENTS.md | 26 +++++++++++++++++++++++++- TODO.md | 14 +++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 7982dad..ed9fb5b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -113,7 +113,31 @@ Yaw = (左履带 - 右履带) / 2 ## RTSP 视频流 -使用 `MediaPlayer` + `SurfaceView` 或 `ExoPlayer` 拉取 RTSP 流。视频层作为 UI 最底层背景,摇杆等控件覆盖其上(半透明)。 +视频层作为 UI 最底层背景,摇杆等控件覆盖其上(半透明)。 + +### 当前实现(将废弃) + +- 使用 **Media3 ExoPlayer + RTSP 扩展**(`media3-exoplayer-rtsp:1.5.1`),实现见 `video/RtspVideoPlayer.kt` +- 已做:最小缓冲 LoadControl(200/500/100/200ms、无回退缓存、时间优先)、RTSP 自动重连(指数退避 1s→30s)、`VideoCodec` 枚举(AUTO/FORCE_HW/FORCE_SW_H264/FORCE_SW_H265)→ `MediaCodecSelector` +- 默认 `MediaItem.fromUri(url)`,未自定义 `RtspMediaSource.Factory`(Media3 默认 UDP 优先、收不到数据自动回退 TCP interleaved) + +### 延迟问题与决策(2026-08 调研结论) + +- 现象:RTSP/TCP 延迟高、缓冲大;H.265 解码不高效 +- **根因**:不是解码器也不是 TCP 协议本身,而是 ExoPlayer 播放器架构(缓冲水位 + presentationTime pacing 渲染同步)为"平滑播放"设计,非实时 +- **决策**:弃用 ExoPlayer 的视频渲染路径,集成第三方库 **rtsp-client-android**(alexeyvasilyev,v5.6.5,纯 Kotlin 零缓冲直出架构) +- 库源码位于:`/tmp/rtsp-client-android`(工作区外临时目录,后续需拷入项目,见 TODO) + +### rtsp-client-android 关键技术要点(集成时必读) + +- 架构:RTSP **仅 TCP interleaved**(无 UDP)→ RTP 解析(H.264/H.265)→ `FrameQueue(60)` → MediaCodec 直解 → 立即渲染。**无播放时钟 pacing,帧到即解即渲染** = 零缓冲低延迟(宣传 20ms 解码延迟) +- H.265:`RtpH265Parser` 支持 single NAL + FU 分片重组;**AP 聚合包未实现**(有 TODO) +- 硬解优先,`MediaCodecUtils.getLowLatencyDecoder` 挑专用低延迟解码器,失败自动回退软解;`MediaCodecHelper.setDecoderLowLatencyOptions` 设 `KEY_LOW_LATENCY` +- 实验性 SPS 改写(仅 H.264):`maxDecFrameBuffering=1, numReorderFrames=0`,可砍半部分硬解器延迟 +- **内置延迟统计**:`RtspSurfaceView.statistics` → `videoDecoderLatencyMsec`(解码渲染)+ `networkLatencyMsec`(网络),无需自写埋点 +- **已知坑**:`RtspProcessor` 拼 CSD 顺序为 `sps+pps+vps`(H.265 标准应为 VPS→SPS→PPS),多数硬解器容错,若 H.265 起播黑屏第一嫌疑在此 +- 依赖:`androidx.media3:media3-exoplayer`(仅用工具类如 NalUnitUtil,可剔除)、`androidx.camera`(YUV→BMP)、`org.jcodec`(SPS 改写) +- 库活跃:2026-06 更新(v5.6.5),全库约 6300 行,无 JNI/无预编译 so,全量可改 --- diff --git a/TODO.md b/TODO.md index 7150791..15f1953 100644 --- a/TODO.md +++ b/TODO.md @@ -2,7 +2,19 @@ ## 待办 -- [ ] 视频进一步延迟优化:探索更激进的低延迟策略(跳过 Media3 ExoPlayer,直接使用 MediaCodec + SurfaceView) +### 视频低延迟改造(进行中,分支 feature/rtsp-low-latency) + +- [ ] 集成 rtsp-client-android:将 `/tmp/rtsp-client-android/library-client-rtsp` 拷贝为本地模块(如 `rtspclientlibrary/`),替换 ExoPlayer 视频渲染 +- [ ] Compose 封装:`RtspSurfaceView` 包 `AndroidView`,替换 `video/RtspVideoPlayer.kt` 的 `PlayerView`;保留现有 `VideoCodec` 枚举映射到 `DecoderType.HARDWARE/SOFTWARE`,设置界面 `video_codec` 选项复用 +- [ ] 保留 RTSP 自动重连:rtsp-client-android 无内置重连,移植现有指数退避逻辑(1s→30s,URL/codec 变化重置) +- [ ] 接入延迟统计:`RtspSurfaceView.statistics` 的 `videoDecoderLatencyMsec`/`networkLatencyMsec` 显示到状态栏或日志,验证延迟改善 +- [ ] 起播黑屏排查:若 H.265 起播黑屏,检查 `RtspProcessor` CSD 拼装顺序(sps+pps+vps,应为 VPS→SPS→PPS) +- [ ] 可选:`FrameQueue(60)` 改小(10~20)进一步压缓冲;剔除 media3/camera 依赖(仅需 jcodec) +- [ ] 删除 ExoPlayer RTSP 依赖与 `RtspVideoPlayer.kt` 旧实现(保留 `VideoCodec`/`VideoResizeMode` 枚举迁移) + +### 其他 + +- [ ] 视频进一步延迟优化:探索更激进的低延迟策略(跳过 Media3 ExoPlayer,直接使用 MediaCodec + SurfaceView)——已由上方 rtsp-client-android 集成方案承接 ## 已完成