Architecture: - Remove Chrome extension (project fully device-side, no target-machine deps) - Update all docs from "three-layer" to "two-layer" privacy (video redact + network intercept) - Add comprehensive architecture docs (overview, subsystem designs) Services: - kvm_agent: hybrid planner (template/local/cloud), screen state detection, mouse-first architecture, app launcher, visual workflow tests - privacy_gateway: upload scanner, privacy LLM integration, REST API - doc_processor: new document processing service Deployment: - Add kvm-bridge, kvm-meta, kvm-privacy deb package definitions - New systemd services (doc-processor, kvm-gateway, rkllm-server) - Network deploy configs, journald forwarding - Remove secrets.env templates from packages Plans & Docs: - HDMI-TX DRM local output + OSD design (drm_output.c, VOP2 multi-plane) - AI Agent token optimization plan (72% savings via caching/pruning/fingerprint) - Model sync: all RKNN/ONNX models now in project directory - Native H.264 adaptive bitrate plan Submodules updated: - deps/KVM: WebUI i18n, RBAC, DDNS, Agent API, OCR models (LFS) - deps/embedding: models synced (LFS), benchmarks, Ollama backend - deps/info-privacy-rs: regex PII detection, face detection integration Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
7.0 KiB
7.0 KiB
原生视频管道架构
子系统: deps/KVM/src/video/ + go/internal/videopipe/
1. 概述
原生视频管道绕过 GStreamer,直接使用 RK3588 硬件加速器链:V4L2 采集 → RGA 色彩转换/缩放 → MPP H.264 编码。通过 CGo 桥接到 Go 层,最终由 pion/rtp 打包推送到 WebRTC 客户端。
2. 管道架构
HDMI-RX (/dev/video0)
│
▼ V4L2 MMAP (4 buffers, BGR24 或 NV12)
│
┌───▼──────────────────────────────────────┐
│ v4l2_capture.cpp │
│ ├─ pthread capture_thread (select loop) │
│ ├─ DMA-buf EXPBUF (零拷贝, 可选) │
│ └─ 回调: data + size + pts + buffer_idx │
└───┬──────────────────────────────────────┘
│
┌───▼──────────────────────────────────────┐
│ video_pipeline.cpp (internal_v4l2_callback)│
│ │
│ 1. BGR 快照回调 (snapshot_fps 控制频率) │
│ └─ NV12→BGR 转换 (如果源是 NV12) │
│ │
│ 2. 色彩转换 + 缩放 │
│ ├─ BGR→NV12: convert_bgr_to_nv12() │
│ ├─ BGR→NV12+resize: _resize() │
│ ├─ NV12→NV12 resize: resize_nv12() │
│ └─ NV12 直拷: memcpy │
│ │
│ 3. 隐私遮蔽 (mutex 保护) │
│ └─ redact_nv12_regions(nv12, bboxes) │
│ │
│ 4. MPP 编码 │
│ ├─ DMA-buf: mpp_encoder_encode_dmabuf │
│ └─ memcpy: mpp_encoder_encode_nv12 │
└───┬──────────────────────────────────────┘
│
┌───▼──────────────────────────────────────┐
│ mpp_encoder.cpp │
│ ├─ MppApi::encode_put_frame │
│ ├─ MppApi::encode_get_packet │
│ ├─ IDR 强制 (MPP_ENC_SET_IDR_FRAME) │
│ └─ 动态码率 (MPP_ENC_SET_RC_CFG) │
└───┬──────────────────────────────────────┘
│ H.264 NAL units
┌───▼──────────────────────────────────────┐
│ Go: cgo_bridge.go → pipeline.go │
│ ├─ onH264(data, pts, keyframe) │
│ ├─ RTPPacketizer (pion/rtp H.264) │
│ └─ AdaptiveController (PLI→码率调整) │
└───┬──────────────────────────────────────┘
│ RTP packets
▼ WebRTC PeerConnection → 浏览器
3. 源文件清单
C/C++ 层 (deps/KVM/src/video/)
| 文件 | 行数 | 职责 |
|---|---|---|
| video_pipeline.h | 55 | 公共 C API (create/start/stop/redact) |
| video_pipeline.cpp | 364 | 管道编排: 采集→转换→遮蔽→编码 |
| v4l2_capture.h | 55 | V4L2 采集 API (含 DMA-buf) |
| v4l2_capture.cpp | 354 | V4L2 MMAP + EXPBUF + capture thread |
| mpp_encoder.h | 30 | MPP 编码器 API (含 DMA-buf encode) |
| mpp_encoder.cpp | ~300 | Rockchip MPP H.264 编码 |
| color_convert.h | 20 | 色彩转换 API |
| color_convert.cpp | ~400 | BGR↔NV12 + RGA resize + NV12 redact |
| CMakeLists.txt | 45 | 构建 libmpp_video.so |
CGo 桥接层 (go/internal/videopipe/)
| 文件 | Build Tag | 职责 |
|---|---|---|
| cgo_bridge.go | cgo | Go→C 函数封装 + RedactBbox 类型 |
| cgo_exports.go | cgo | //export Go 回调 (H.264 + BGR snapshot) |
| cgo_shim.c | — | C 回调 shim (路由到 Go) |
| pipeline.go | — | NativePipeline 公共接口 |
| adaptive.go | — | AIMD 自适应码率控制 |
| rtp_packetizer.go | — | H.264 NAL→RTP 转换 |
4. 关键数据结构
VideoPipeline (C++)
struct VideoPipeline {
MppEncoder* encoder;
V4L2Capture* capture;
H264PacketCallback h264_callback;
BGRFrameCallback bgr_callback;
int width, height; // 编码目标分辨率
int cap_width, cap_height; // V4L2 实际采集分辨率
uint32_t cap_format; // BGR24 或 NV12
bool needs_resize; // 采集≠编码分辨率时启用
uint8_t* nv12_buffer; // 可复用转换缓冲区
uint8_t* bgr_buffer; // NV12→BGR 快照缓冲区
int snapshot_fps; // BGR 快照帧率 (0=每帧)
int snapshot_interval; // = capture_fps / snapshot_fps
float* redact_bboxes; // [x0,y0,w0,h0, x1,y1,w1,h1, ...]
int redact_count;
std::mutex redact_mutex; // 保护 bbox 更新
};
NativePipeline (Go)
type NativePipeline struct {
cfg Config // Device, Width, Height, FPS, Bitrate
onH264 func([]byte, int64, bool) // H.264 输出
onSnapshot func([]byte) // JPEG 快照
pipelineID int // C 回调路由 ID
}
5. DMA-buf 零拷贝路径
当满足以下条件时,跳过 CPU memcpy:
- V4L2 输出为 NV12(非 BGR)
- 无缩放(cap_width == width && cap_height == height)
- 无隐私遮蔽(redact_count == 0)
- DMA-buf 导出成功(VIDIOC_EXPBUF)
V4L2 DMA-buf fd → MPP mpp_buffer_import_with_tag → 零拷贝编码
节省 1080p@30fps 约 90MB/s 内存带宽。
6. 隐私遮蔽机制
调用链
Go: PrivacyHandler.ScanAndUpdateRedaction()
→ detectPIIBboxes() (regex: phone/id_card/bank_card/email)
→ onRedactUpdate(bboxes) callback
→ NativePipeline.SetRedactRegions(regions)
→ bridgeSetRedactBboxes() [CGo]
→ video_pipeline_set_redact_bboxes() [C, mutex 保护]
NV12 遮蔽算法 (color_convert.cpp)
对每个 bbox (归一化 0.0-1.0):
1. 转换为像素坐标 (对齐到 2 像素, NV12 色度采样)
2. Y 平面: memset 为 16 (BT.601 黑色)
3. UV 平面: memset 为 128 (中性色度)
7. 自适应码率
AIMD (Additive Increase Multiplicative Decrease) 算法:
- PLI (Picture Loss Indication) 作为拥塞信号
- 拥塞时码率减半 (multiplicative decrease ÷2)
- 稳定期线性增加 (additive increase)
- 码率范围: 100Kbps ~ 20Mbps
- FPS 范围: 1 ~ 60
8. 构建
# 构建 C 库 (需要 rockchip_mpp, rga 开发库)
cd deps/KVM
cmake -B build/video -S src/video -DCMAKE_BUILD_TYPE=Release
cmake --build build/video -j$(nproc)
# Go 构建 (链接 libmpp_video.so)
cd go
CGO_CFLAGS="-I../src/video" \
CGO_LDFLAGS="-L../build/video -lmpp_video -Wl,-rpath,/usr/lib/kvm" \
CGO_ENABLED=1 go build ./cmd/kvm-server/
安装位置: /usr/lib/kvm/libmpp_video.so