OrangePi3588Media/docs/Plan.md
2026-02-28 17:34:47 +08:00

11 KiB
Raw Blame History


总体思路

  • 每个阶段都交付一个可运行的“小产品”(而不是一堆库)
  • 优先把 RK3588 的硬件链路打通(解码 → 前处理 → NPU → 编码)
  • 最简单的“转码网关” 一步步进化到 “智能分析+报警+录像”

建议整体 roadmap ≈ 7~8 个迭代:

  1. Sprint 0环境&硬件打底
  2. Sprint 1最小可用媒体服务器纯转码网关
  3. Sprint 2插件框架 + DAG 图 & 队列打通
  4. Sprint 3AI 推理链路preprocess + ai_yolo + OSD
  5. Sprint 4报警 + 录像插件,打通完整“安防通道”
  6. Sprint 5配置系统templates/instances+ 热更新 + Drain
  7. Sprint 6监控指标 + Web 控制台基础
  8. Sprint 7多路性能调优 + 长稳测试

下面每个 Sprint 我都给一个目标 / 核心任务 / 关键里程碑


Sprint 0环境准备 & 板子打通(已完成)

目标: 所有开发人员都能在本地和 RK3588 板子上编译、部署、跑官方 demo。

核心任务:

  • 建工程骨架:
    • 建 Git 仓库 + 基础目录结构(src/, include/, plugins/, cmake/ 等)
    • CMake + Ninja 构建脚本
  • 搭建交叉编译环境:
    • 配置 aarch64-linux-gnu-gcc
    • 能在 x86 上编译并在 RK3588 板子上运行“hello world”
  • 验证 RK 官方 SDK
    • 跑 MPP 解码 demo本地 H264 文件 → 屏幕或 /dev/null
    • 跑 RKNN demo官方示例图片 → 得到推理结果)
  • CI 基础:
    • 至少有一个自动构建(例如 push 后自动编译)

关键里程碑:

  • 在 RK3588 板子上成功运行:
    • 一个 MPP 解码 demo
    • 一个 RKNN 推理 demo
  • media-server 空壳程序(打印版本号)能从 CI 输出产物并部署到板子上运行

Sprint 1最小可用媒体服务器纯转码网关

目标: 实现一个最小可用产品

从 RTSP 拉流 → 解码 → 编码 → 再推 RTSP/HLS
还没有 AI、报警、录像只是转码网关。

核心任务:

  • 定义最初版 Frame 结构(至少包含:宽高、格式、 pts、dma_fd
  • 实现最简单的线性 pipeline(先不用 DAG
    • input_rtsp 插件:
      • 拉 RTSP 流,断线重连
      • 用 MPP 解码为 NV12/YUV
    • publish 插件:
      • 用 MPP VENC 编码 H264/H265
      • 启动简单 RTSP server 或 HLS 输出
  • 初版线程模型:
    • 1 个拉流/解码线程
    • 1 个编码/推流线程
    • 中间通过 SPSC 队列传 shared_ptr<Frame>
  • 配置文件:
    • 简单 JSON只支持一条通道
      {
        "graphs": [
          {
            "name": "cam1",
            "nodes": [...],
            "edges": [...]
          }
        ]
      }
      

关键里程碑:

  • 在 RK3588 板子上:
    • 从外部摄像头 / NVR 拉一路 RTSP
    • 在本机 8554 端口重新发布 RTSP或 8080 HLS
    • VLC / ffplay 打开 rtsp://board_ip:8554/live/cam1 能稳定观看
  • 初始版本 Frame + 队列已经固定下来,后面不会大改接口

Sprint 2插件框架 + DAG 图 & 队列体系

目标: 从「硬编码 pipeline」升级为「插件 + DAG 驱动」,让架构进入你 PRD 描述的形态。

核心任务:

  • 定义 INode 接口(含 Init/Start/Process/UpdateConfig/Drain/Stop
  • 完成插件加载系统:
    • .so 动态加载dlopen
    • REGISTER_NODE 宏 + GetNodeType/GetAbiVersion
  • 实现 GraphMgr
    • 支持从 JSON 读取 graphs[nodes + edges]
    • 根据 type 创建节点、连接 edges
    • 每条 edge 对应一个 SPSC 队列
  • 多分支 DAG 支持:
    • 允许一个节点连接多个下游GraphMgr 为每条边创建独立队列
  • 把 Sprint1 的 input/publish 改造成插件形式,跑在 DAG 上:
    • Graphinput_rtsp -> publish

关键里程碑:

  • 支持通过 JSON 配置任意组合节点(至少:in→pubin→pre→pub 两种)
  • 节点以 .so 的形式存在,可以单独编译、加载/卸载
  • 框架已支持一对多分支(即使当前下游还只有一个,这点结构上要打好)

Sprint 3AI 链路打通preprocess + ai_yolo + OSD

目标: 打通一条完整的 AI 视觉链路

拉流 → 前处理 → YOLO 推理RKNN → 叠框 OSD → 推流

核心任务:

  • 完整定义 Detection / DetectionResult / 扩展版 Frame 结构(含 det
  • 实现 preprocess 插件:
    • RGA 缩放(例如 1080p → 640×640
    • NV12 → RGB/BGR 格式转换
  • 实现 AiScheduler
    • 提供提交/回调接口
    • 内部管理 RKNN 上下文和 NPU 资源
    • 暂时可只支持单路/单 batch先打通功能
  • 实现 ai_yolo 插件:
    • 加载 .rknn 模型
    • 调用 AiScheduler 做推理
    • 将输出写入 Frame::det
  • 实现 osd 插件:
    • 根据 Frame::det 在原图上画框/标签
    • 输出 NV12/YUV 帧(可以软绘+回写,也可以用 RGA
  • 在 JSON 中构建一条完整 AI pipeline
    • input_rtsp -> preprocess -> ai_yolo -> osd -> publish

关键里程碑:

  • 在板子上:
    • 拉一条实际摄像头画面
    • web/RTSP 观看输出画面时,能看到实时的检测框
  • 基础性能满足:
    • 单路 1080p 流畅运行(不明显掉帧)
    • CPU/NPU 占用在可接受范围内(不超出预期天花板)

Sprint 4报警 + 录像插件(完成一条“安防通道”)

目标: 在 AI 结果基础上,增加 报警逻辑 + 录像,形成完整“安防产品”的基本形态。

核心任务:

  • 实现 alarm 插件:
    • 支持按规则配置object 类型、ROI、最小持续时间、时间段类似你 PRD 里的 rules
    • 支持 HTTP/MQTT 等方式发报警(先做 HTTP
  • 实现 storage 插件:
    • 支持 continuous 模式(持续录像,分段保存)
    • 文件切片(segment_sec
    • 先不做 event 模式,后续可以扩展 pre/post-event 缓冲
  • 在 DAG 上实现典型拓扑:
    • ai_yolo → alarm(分支 1
    • ai_yolo → osd → storage(分支 2
    • osd → publish(分支 3
  • 简单报警可视化:
    • HTTP 回调到一个简单日志服务,或直接打印到日志,先验证链路

关键里程碑:

  • 配置一个规则:例如“白天有人进入 ROI 区域触发报警”
  • 摄像头对准测试区域:
    • 屏幕上能看到检测框
    • 有人进 ROI 时,后台收到 HTTP 报警请求(或日志输出)
    • 同时有录像文件被写入(在 /rec/cam1 下能找到)

Sprint 5配置系统完善 + 模板/实例 + 热更新 & Drain

目标: 从“能跑”升级到“好配、好改”:
实现 templates/instances、节点 enable/override、热更新、Drain/Stop 正常运转。

核心任务:

  • P0热更新前置Stop/Drain 语义对齐 & 线程/资源可回收:

    • Drain():不再接收新输入/不再产生新任务,仅负责把内部缓冲“处理完/落盘/发送完”
    • Stop():在 Drain() 之后调用,必须保证内部线程退出并 join、句柄/资源释放,可幂等
    • 至少覆盖 alarmHttpAction/ClipAction 等动作线程 Stop 后可回收,避免多次热更新/重建图堆线程
  • 完善配置结构:

    • globaltemplatesinstancesgraphs
    • 节点通用字段(enable, role, queue
  • 模板 + 实例展开逻辑:

    • 支持 ${placeholder} 替换
    • 支持实例级 override(开启/关闭某节点、覆盖某些参数)
  • 实现 UpdateConfig

    • 对一部分节点alarm/publish/storage支持参数热更新
  • 实现图的热更新流程:

    • inotify 监控 config
    • 构建新图 → 校验 → 若成功则原子切换
    • 对旧节点按顺序调用 Drain()Stop()
    • 失败则回滚旧配置
  • 对 "enable=false" 节点的处理:

    • 构图时直接忽略该节点和相关 edges
    • 或者实现旁路逻辑(看你最终选哪种,在代码里统一)

关键里程碑:

  • 连续热更新/重建图 N 次后:

    • action/node 线程数不随次数增长(至少 alarm 的 http/clip 线程不会残留)
    • Drain/Stop 无死锁Stop 后资源可回收
  • 不重启进程的前提下:

    • 通过修改 config把某一路的 ai_yolo.enable 改为 false → 该通道立即变成纯转码网关
    • 再改回 true恢复智能分析
  • 热更新时:

    • 流“几乎不断”(允许 1 秒内小抖动)
    • 没有崩溃 / 明显内存泄漏 / 死锁

Sprint 6监控指标 + Web 控制台基础

目标: 增加可观测性,让系统变成“可视化可管理”的产品,而不是黑盒程序。

核心任务:

  • 指标采集模块:
    • 节点级input/output fps、queue 长度、drop 数、error 数、平均处理时长
    • 图级:总 fps、报警数、当前推流客户端数
  • HTTP API
    • GET /api/graphs
    • GET /api/graphs/{name}
    • GET /api/nodes/{id}/metrics
    • (可选)POST /api/nodes/{id}/config 调用 UpdateConfig
  • Web 控制台Vue第一版
    • 简单展示通道列表、节点状态、关键指标
    • 不必太花哨能看到“通道是否绿”、“fps 大概多少”即可
  • 日志查看:
    • 提供简单接口/页面看到最近日志(或直接解析 log 文件)

关键里程碑:

  • 打开 Web 页面:
    • 能看到所有通道以及每个通道的状态Running/Stopped/Error
    • 能看到某通道底下的节点链条in→pre→ai→osd→alarm/storage/publish
    • 能看到每个节点的大致 fps & 队列深度
  • 模拟异常(例如关闭摄像头):
    • Web 页面能看到该通道出现错误/掉线状态,日志中有清晰错误信息

Sprint 7多路性能调优 + 长稳测试

目标: 把系统从 demo 提升到「能上生产」的水平:多路、低延迟、长时间稳定。

核心任务:

  • 多路场景压测:
    • 逐步从 2 路 → 4 路 → 8 路 → 16 路(根据目标)
    • 观察 CPU、NPU、内存占用和延迟
  • 性能调优点:
    • 队列策略(drop_oldest vs block
    • OSD 放在 RGA/CPU 侧的性能权衡
    • AiScheduler 模式(是否可以 batch、是否减少多线程抢 NPU
    • 绑核策略input/ai/stroage/publish 分布在大/小核)
  • 长稳测试:
    • 7×24 小时连续跑,统计:
      • 内存占用曲线
      • CPU/NPU 曲线
      • 崩溃/重启次数
  • 回归测试:
    • 关键功能场景(报警、录像、推流、热更新)跑完一遍

关键里程碑:

  • 在目标多路场景(例如 8×1080p
    • 系统端到端延迟满足 PRD 要求
    • CPU/NPU 占用在目标范围内(如 CPU <30%NPU >90%
  • 连续运行 7×24 小时:
    • 无崩溃 / 无明显内存泄漏(内存曲线稳定)
    • 所有通道仍在正常推流/录制/报警