# rtsp-demo **Repository Path**: sklink/rtsp-demo ## Basic Information - **Project Name**: rtsp-demo - **Description**: RV1126B+imx415摄像头实现手机VLC音视频传输,以及本地屏幕显示。 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2026-10-19 - **Last Updated**: 2026-10-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # rtsp_demo_0:两进程架构的摄像头本地显示 + RTSP 推流(纯 C) 在 `rtsp_demo` 基础上拆分出的新工程,核心改动: 1. **摄像头画面在屏幕显示**:`capture_display` 进程通过 V4L2 多平面采集 IMX415 (rkisp mainpath,NV12),顺时针旋转 90° 后(RGA 硬件,无 RGA 时软件) 再经 DRM/KMS 上屏(XRGB8888 1:1 提交,RGA/软件完成缩放与 YUV->RGB); 无 DRM 时自动回退 `/dev/fb0` 软件转换。旋转对推流同样生效, 手机端看到的也是旋转后的竖屏画面。 2. **左上角实时时间**:采集进程在把画面“显示”和“推流”之前,用纯 C 位图字体 把时间画进 NV12 帧(深色底带 + 白色文字),因此**屏幕画面和 RTSP 推流画面 都带同一份时间**。 3. **两个进程,彻底解耦**:采集/显示进程(生产者)与 RTSP 推流进程(消费者) 之间只通过**共享内存环形缓冲**(POSIX shm + 命名信号量)传 NV12 帧, 互不感知对方实现细节;消费者跟不上时生产者自动丢帧,不阻塞本地显示。 ## 目录结构 ```text src/ app/capture_display_main.c 进程1 主程序(采集/显示/发布) capture/ V4L2 采集 + NV12 时间叠加 display/ DRM/FB/RGA/旋转 显示后端 common/ 日志、共享内存环形缓冲 rtsp/ 进程2:appsrc、RTSP server、ALSA 自检 tools/ SDP/收包验证脚本、launch 解析调试工具 ``` ## 构建 ```bash cd rtsp_demo_0 ./build.sh ``` 产物:`build/capture_display`、`build/rtsp_server`(aarch64,拷到开发板运行)。 交叉工具链默认取 `~/atk_rv1126b/buildroot/output/alientek_rv1126b`, 路径不同时用 `BUILDROOT_OUTPUT=/你的路径 ./build.sh` 覆盖。 ## 运行(开发板) ```bash # 一键启动(会自动杀 pulseaudio、初始化录音通道) ./run.sh # 或手动分两个进程 ./capture_display & # 采集 + 叠加 + 显示 + 共享内存 ./rtsp_server --audio-init # 共享内存取帧 + H.264/AAC + RTSP 推流 ``` 手机 VLC / 电脑 ffplay 播放: ```text rtsp://<开发板IP>:8554/live ``` ## capture_display 参数 ```text -v, --vdevice DEVICE 摄像头视频节点 (默认 /dev/video23) --width N 视频宽度 (默认 1920) --height N 视频高度 (默认 1080) --fps N 帧率 (默认 30,0=由驱动决定) --shm-name NAME 共享内存名 (默认 /rtsp_demo_0_ring) --shm-slots N 共享内存槽位数 1-4 (默认 3) -d, --display MODE 显示后端 drm|fb|none|auto (默认 auto) --rotate N 旋转角度 0/90/180/270 (默认 90,适配竖屏) --no-overlay 关闭时间叠加 --overlay-scale N 时间字号放大倍数 1 或 2 (默认 2) --overlay-x N 时间左上角 X 坐标 (默认 16) --overlay-y N 时间左上角 Y 坐标 (默认 12) --rgb-order MODE DRM 输出字节序 xrgb|xbgr (默认 xrgb,偏蓝时试 xbgr) --no-rga-display 显示强制软件转换(排查 RGA 颜色问题) --time-format FMT 时间 strftime 格式 (默认 %Y-%m-%d %H:%M:%S) --log-level N 日志级别 0-3 (默认 2) ``` ## rtsp_server 参数 ```text -p, --port PORT RTSP 端口 (默认 8554) -m, --path PATH RTSP 路径 (默认 /live) --width/--height 编码宽高 (默认 1080x1920,即旋转后) --fps N 编码帧率 (默认 30) -b, --bitrate KBPS 视频码率 (默认 3000) --shm-name NAME 共享内存名 (默认 /rtsp_demo_0_ring) --audio-device DEV ALSA 采集设备 (默认 default;被 pulseaudio 占用时先 pulseaudio --kill) -a, --audio-codec C 音频编码 aac|alaw|off (默认 aac) --audio-rate N AAC 采样率 (默认 48000) --audio-channels N AAC 声道数 (默认 2) --audio-bitrate N AAC 码率 (默认 64000) -t, --transport T RTP 传输 udp|tcp|udp+tcp (默认 udp+tcp) --no-shared 每个客户端独立建管道(默认共享) --audio-test 麦克风自检:抓几秒 PCM,打印各 ALSA 设备音量后退出 --local-audio 板载喇叭本地监听:麦克风声音同时从板子喇叭播出(默认关) --audio-init 启动前用 amixer 初始化 ES8389 录音通道(音量/输入源) --log-level N 日志级别 0-3 (默认 2) ``` ## 常见问题 ### Q1:屏幕没画面 - 确认显示后端:日志出现 `drm: 初始化完成` 即 DRM 上屏;`fb` 则用 framebuffer。 - 偏蓝/偏色:加 `--rgb-order xbgr` 或 `--no-rga-display` 排查。 - 屏幕拉伸变形:检查 `--rotate` 与面板方向是否匹配(本项目默认 90° 竖屏)。 ### Q2:手机 VLC 没画面 - 先确认手机和开发板同一网段,`rtsp://<开发板IP>:8554/live`。 - 试 `-t tcp`(部分路由器/手机对 UDP 不友好)。 - 看服务端日志 `appsrc: 统计: 已推送 N 帧`,N 持续增长说明编码正常。 ### Q3:画面时间不更新/位置不对 - 时间每秒重绘,确认系统时间正确(`date`)。 - 调整 `--overlay-x/--overlay-y/--overlay-scale/--time-format`。 ### Q4:推流没有声音 ES8389 录音音量寄存器复位值接近静音,板上又没恢复混音器状态, 首次使用先执行一次(或加 `--audio-init`): ```bash ./rtsp_server --audio-test # 看哪个设备有声音 ./rtsp_server --audio-init # 自动设置录音通道/音量再推流 ``` 仍无声再查硬件:`arecord -l`、`amixer -c 0 contents | grep -i -E 'capture|mic'`。 > 音频 SDP 修复记录(2026-08-16): > 1. 本板 rootfs 的 `rtpmp4gpay` 是精简版,**没有 `config-interval` 属性**。 > 管道里写 `rtpmp4gpay ... config-interval=-1` 会被 gst_parse_launch 当作可恢复错误, > 整个 pay1 被丢弃,SDP 只有 `m=video`。已从 launch 字符串中移除该属性。 > 2. 不要在 `aacparse` 后手工加 `audio/mpeg,...,codec_data=(buffer)XXXX` 静态 caps: > aacparse 输出的真实 codec_data(如 119056e500)与静态值不匹配会造成协商失败、 > `avenc_aac: encoder not initialized`、DESCRIBE 返回 503。直接 `aacparse ! rtpmp4gpay` 即可, > 真实 caps 会由 aacparse 带上并写入 SDP fmtp(config=...)。 > 3. 推流前记得 `pulseaudio --kill`(run.sh 已自动处理),否则 alsasrc 打不开采集口。 ### Q5:推流帧率低于采集 消费者(编码/推流)跟不上时生产者会丢帧,这是设计行为;本地显示始终满帧。 调低 `--bitrate` 或改用 `-t tcp` 可改善。 ## 验证工具(tools/) ```bash # 检查 SDP 是否包含 m=video 和 m=audio python3 tools/sdp_check.py <开发板IP> # RTSP/TCP 收包统计(视频/音频 RTP 包数) python3 tools/rtsp_av_check.py <开发板IP> # 解析 launch 字符串并列出管道元素(验证 pay0/pay1 都在) ./build/parse_dump "launch-line" ```