Rockchip RMSL Linux 开发指南
:::info 文档信息
文档标识:RK-KF-YF-355 · 发布版本:V1.0.1 · 发布日期:2020-12-14 · 页数:11 · 语言:中文
原始文档:Rockchip_Developer_Guide_Linux_RMSL_CN.pdf
:::
章节大纲
- Rockchip RMSL Linux 开发指南(P1)
- RMSL模组接口简介(P4)
- 概述(P4)
- RMSL模组的型号(P4)
- Buildroot中配置(P4)
- 编译和运行(P4)
- demo代码简介(P7)
- RMSL控制接口(P7)
- 获取数据流(P9)
- 解码(P9)
- 显示(P10)
- 与QT应用程序结合(P11)
- 常见QA(P11)
- 打开Camera后设备断开(P11)
- RMSL模组接口简介(P4)
在线预览
若预览无法显示,请直接下载 PDF 后用本地阅读器打开。
1. RMSL模组接口简介
1.1 概述
Rockchip RMSL模组是USB即插即用设备,它可以同时有三路输出,即Depth, RGB, IR。其中Depth输出YUYV数据,RGB及IR输出MJPG数据。
| Video | 最大分辨率 | 格式 | 帧率 | 描述 |
|---|---|---|---|---|
| Depth | 640x480 | YUYV | 15fps | 输出视差图,可根据算法转换成深度图或点云图 |
| RGB | 1920x1080 | MJPG | 30fps | 彩色视频输出,可解码为NV12格式 |
| IR | 640x480 | MJPG | 15fps | 红外视频输出,可解码为NV12格式 |
1.2 RMSL模组的型号
RK RMSL模组的型号可从SN码中获取,当前支持的RK结构光型号如下:
| 型号 | 匹配的SN码 | 接口 |
|---|---|---|
| RMSL201-1301 | R2011301xxxxxxxxx | USB |
1.3 Buildroot中配置
在Buildroot Linux SDK中,开发接口及参考demo位于app/demo/rmsl目录下。默认SDK发布版本没有编译该程序,需要用户将Buildroot编译宏开关 BR2_PACKAGE_APP_DEMO_RMSL 使能后才可以编译。该程序依赖的如下应用包也需要使能。
BR2_PACKAGE_CAMERA_ENGINE_RKISP,用于获取V4L2数据流BR2_PACKAGE_MPP,用于解码MJPG BR2_PACKAGE_LINUX_RGA,用于对YUV数据做处理,以便显示BR2_PACKAGE_LIBDRM,用于显示于屏幕上(可选)
注意:
若未发现该宏开关或无rmsl demo代码,请更新到最新SDK,或通过github仓库获取。external/camera_engine_rkisp/需要更新到 86dc5bf1 apps: rkisp_api: add usb camera supports 。若SDK未更新到最新,可通过github仓库获取。
1.4 编译和运行
在SDK目录下,通过如下命令进行模块编译,
| 1 # make app demo _ | |
|---|---|
| 1 | # make app demo _ |
如需要重新编译,可通过命令:
# make app_demo-dirclean
# make app_demo
编译完成后会生成两个可执行文件rmsl_linux_demo及rmsl_tool。
| 1 # ls -1 /usr/bin/rmsl* 2 /usr/bin/rmsl linux demo _ _ 3 /usr/bin/rmsl tool _ | |
|---|---|
| 1 2 3 | # ls -1 /usr/bin/rmsl* /usr/bin/rmsl linux demo _ _ /usr/bin/rmsl tool _ |
因为依赖较多,建议用户按1.3小节配置完后,重编译整个Buildroot。
接上RMSL模组,可通过rmsl_tool获取设备信息。
获取设备节点信息
| 1 # rmsl tool --list devices _ _ 2 Device /dev/video6 info: 3 usb interface: UVC DEPTH 4 driver name: uvcvideo 5 card type: RV1108 6 bus info: usb-ff340000.usb-1 _ 7 Device /dev/video8 info: 8 usb interface: UVC RGB 9 driver name: uvcvideo 10 card type: RV1108 11 bus info: usb-ff340000.usb-1 _ 12 Device /dev/video10 info: 13 usb interface: UVC IR 14 driver name: uvcvideo 15 card type: RV1108 16 bus info: usb-ff340000.usb-1 _ | |
|---|---|
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | # rmsl tool --list devices _ _ Device /dev/video6 info: usb interface: UVC DEPTH driver name: uvcvideo card type: RV1108 bus info: usb-ff340000.usb-1 _ Device /dev/video8 info: usb interface: UVC RGB driver name: uvcvideo card type: RV1108 bus info: usb-ff340000.usb-1 _ Device /dev/video10 info: usb interface: UVC IR driver name: uvcvideo card type: RV1108 bus info: usb-ff340000.usb-1 _ |
| 上例说 共 |
查询RMSL的SN码及软件版本
| 1 # rmsl tool --get sn --get version --device /dev/video6 _ _ _ 2 SN: R2011301200801448 3 Version: 2.2.0 | |
|---|---|
| 1 2 3 | # rmsl tool --get sn --get version --device /dev/video6 _ _ _ SN: R2011301200801448 Version: 2.2.0 |
在获取数据流前应首先初始化设备
| 1 # rmsl tool --init --device /dev/video6 _ | |
|---|---|
| 1 | # rmsl tool --init --device /dev/video6 _ |
在结束数据流之后应反初始化设备
| 1 # rmsl tool --deinit --device /dev/video6 _ | |
|---|---|
| 1 | # rmsl tool --deinit --device /dev/video6 _ |
在结束数据流之后,也可以reset设备
| 1 # rmsl tool --reset --device /dev/video6 _ | |
|---|---|
| 1 | # rmsl tool --reset --device /dev/video6 _ |
完成init之后,v4l2-ctl、vlc等开源工具是能够获取数据流的,需要注意数据流的格式及大小。
rmsl demo中提供的另外一个工具rmsl_linux_demo用于演示完整的init、获取数据流、解码、deinit、显示等功能。此时,不必先用rmsl_tool 工具做初始化工作。
查看rmsl_linux_demo的使用帮助
| 1 # rmsl linux demo --help _ _ 2 Usage of rmsl linux demo: _ _ 3 To display and/or save decode frames to files: 4 --screen-width, screen width, required if need display 5 --screen-height, screen height, required if need display 6 --no-display, disable display, by default it's enabled 7 --save-ir-to, path to save IR decoded frames in NV12 8 --save-depth-to, path to save DEPTH decoded frames with bpp = 16 9 --save-rgb-to, path to save RGB decoded frames in NV12 | |
|---|---|
| 1 2 3 4 5 6 7 8 9 | # rmsl linux demo --help _ _ Usage of rmsl linux demo: _ _ To display and/or save decode frames to files: --screen-width, screen width, required if need display --screen-height, screen height, required if need display --no-display, disable display, by default it's enabled --save-ir-to, path to save IR decoded frames in NV12 --save-depth-to, path to save DEPTH decoded frames with bpp = 16 --save-rgb-to, path to save RGB decoded frames in NV12 |
| 如上 |
能是打开的,如果不需要显示,使用--no-display参数禁用。
将图像显示在屏幕上
| 1 # rmsl linux demo --screen-width 1536 --screen-height 2048 _ _ 2 3 UVC DEPTH: /dev/video5: draw in (0, 480)[640 x 480] 4 UVC RGB: /dev/video7: draw in (320, 0)[640 x 480] 5 UVC IR: /dev/video9: draw in (640, 480)[640 x 480] 6 | |
|---|---|
| 1 2 3 4 5 6 | # rmsl linux demo --screen-width 1536 --screen-height 2048 _ _ UVC DEPTH: /dev/video5: draw in (0, 480)[640 x 480] UVC RGB: /dev/video7: draw in (320, 0)[640 x 480] UVC IR: /dev/video9: draw in (640, 480)[640 x 480] |
上图显示了在RK3288屏幕上(1536x2048)的三个视频,从上到下、左到右,分别为RGB,DEPTH,IR。大小都是640x480。其中深度图是直接将视差图以RGB565格式显示出来。
不显示图像,但将解码后的帧保存下来
| 1 # rmsl linux demo --no-display \ _ _ 2 --save-ir-to /tmp/ir.bin \ 3 --save-rgb-to /tmp/rgb.bin \ 4 --save-depth-to /tmp/depth.bin | |
|---|---|
| 1 2 3 4 | # rmsl linux demo --no-display \ _ _ --save-ir-to /tmp/ir.bin \ --save-rgb-to /tmp/rgb.bin \ --save-depth-to /tmp/depth.bin |
上例中禁用了显示功能,且将三路帧数据分别保存到文件中。其中,
ir.bin,保存640x480 NV12帧数据rgb.bin,保存640x480 NV12帧数据depth.bin,保存640x480 深度数据,每个像素2个字节
以上三例中,数据流大小默认都是640 * 480,但RGB摄像头可以支持1080p的输出。抓取的文件若在PC机上可以用YUVPlayer(windows环境)或mplayer(Linux环境)查看。其中,mplayer使用可以参考如下命令。
| 1 # mplayer /tmp/ir.bin -loop 0 -demuxer rawvideo -fps 15 \ 2 -rawvideo w=640:h=480:size=$((640*480*3/2)):format=nv12 3 4 # mplayer /tmp/rgb.bin -loop 0 -demuxer rawvideo -fps 15 \ 5 -rawvideo w=640:h=480:size=$((640*480*3/2)):format=nv12 6 7 # mplayer /tmp/depth.bin -loop 0 -demuxer rawvideo -fps 15 \ 8 -rawvideo w=640:h=480:size=$((640*480*2)):format=rgb16 | |
|---|---|
| 1 2 3 4 5 6 7 8 | # mplayer /tmp/ir.bin -loop 0 -demuxer rawvideo -fps 15 \ -rawvideo w=640:h=480:size=$((640*480*3/2)):format=nv12 # mplayer /tmp/rgb.bin -loop 0 -demuxer rawvideo -fps 15 \ -rawvideo w=640:h=480:size=$((640*480*3/2)):format=nv12 # mplayer /tmp/depth.bin -loop 0 -demuxer rawvideo -fps 15 \ -rawvideo w=640:h=480:size=$((640*480*2)):format=rgb16 |
2. demo代码简介
代码位于app/demo/rmsl/目录,包含了RMSL的设置、查询接口,获取数据流并解码、显示功能。
| 1 # tree app/demo/rmsl/ 2 app/demo/rmsl/ 3 ├── CMakeLists.txt 4 ├── main.c # rmsl linux demo的主程序 _ _ 5 ├── rkdrm display.c # 用于overlay直接显示 _ 6 ├── rkdrm display.h _ 7 ├── rmsl api.h # rmsl 主要接口定义 _ 8 ├── rmsl ctrl.c # rmsl 控制、查询等方法的实现 _ 9 ├── rmsl depth.c # 深度图转换的实现 _ 10 ├── rmsl tool.c # rmsl tool的主程序 _ _ 11 ├── vpu decode.c # vpu jpeg硬件解码接口 _ 12 └── vpu decode.h _ | |
|---|---|
| 1 2 3 4 5 6 7 8 9 10 11 12 | # tree app/demo/rmsl/ app/demo/rmsl/ ├── CMakeLists.txt ├── main.c # rmsl linux demo的主程序 _ _ ├── rkdrm display.c # 用于overlay直接显示 _ ├── rkdrm display.h _ ├── rmsl api.h # rmsl 主要接口定义 _ ├── rmsl ctrl.c # rmsl 控制、查询等方法的实现 _ ├── rmsl depth.c # 深度图转换的实现 _ ├── rmsl tool.c # rmsl tool的主程序 _ _ ├── vpu decode.c # vpu jpeg硬件解码接口 _ └── vpu decode.h _ |
| 2.1 R |
获取版本
| 1 int rmsl get version(int fd, char *ver, int size); _ _ | |
|---|---|
| 1 | int rmsl get version(int fd, char *ver, int size); _ _ |
参数说明:
fd,/dev/video节点对应的文件描述符ver,返回的版本号size,ver数组的大小,应不小RMSL_DATA_SIZE_QUERY
成功则返回0,其它值表示错误。
获取SN号
| 1 int rmsl get sn(int fd, char *sn, int size); _ _ | |
|---|---|
| 1 | int rmsl get sn(int fd, char *sn, int size); _ _ |
参数说明:
fd,/dev/video节点对应的文件描述符sn,返回的SN号size,sn数组的大小,应不小RMSL_DATA_SIZE_QUERY
成功则返回0,其它值表示错误。
初始化/反初始化设备
int rmsl_init_device(int fd);
int rmsl_deinit_device(int fd);
初始化或反初始化设备,使得video节点能够输出数据。
参数说明:
fd,/dev/video节点对应的文件描述符
成功则返回0,其它值表示错误。
重置设备
| 1 int rmsl reset device(int fd); _ _ | |
|---|---|
| 1 | int rmsl reset device(int fd); _ _ |
参数说明:
fd,/dev/video节点对应的文件描述符
成功则返回0,其它值表示错误。
进入待机
| 1 int rmsl suspend device(int fd); _ _ | |
|---|---|
| 1 | int rmsl suspend device(int fd); _ _ |
参数说明:
fd,/dev/video节点对应的文件描述符
成功则返回0,其它值表示错误。
获取各输出设备的节点名称
int rmsl_get_devices(char *dev_depth, char *dev_ir, char *dev_rgb, int
silent);
获取三个视频设备的节点名称,如/dev/video6, /dev/video8等参数说明:
dev_depth,返回Depth设备的路径dev_ir,返回IR设备的路径dev_rgb,返回RGB设备的路径silent,1表示不输出log;0会打印一些log
成功则返回0,其它值表示错误。
转换点云图及深度图
int rmsl_get_point_cloud_depth(const uint16_t *pIn, struct rmsl_pc *pc_out,
uint16_t *depth_out, int width, int height);
根据视差图转换点云图及深度图。
参数说明:
pIn,Depth 设备输出的视差图帧数据,BPP为16 pc_out,点云图输出结果。如果为NULL,不计算点云图depth_out,深度图输出结果。如果为NULL,不计算深度图width,图像的宽height,图像的高
返回值:
等于0表示成功计算小于0表示错误大于0表示模组原始的帧数据已经是深度图,不需要计算。(目前无此场景)
2.2 获取数据流
在rmsl_linux_demo中,使用到了rkisp_api.so获取数据流。与普通的USB Camera模组相比,要多一个初始化操作。
rkisp_api.so详细接口请参考《Rockchip_Developer_Guide_Linux_Camera_EN.pdf》。
2.3 解码
该demo中使用Rockchip MPP库解码MJPG。将从rkisp_api获取到的数据流交给MPP解码。MPP要求源数据拷贝一次,考虑到MJPG的每帧的数据量很小,性能上几无影响。解码后的Buffer由RGA分配,这里主要是因为后级需要有可能需要RGA拷贝以便显示。
主要接口:
| 1 ret = vpu decode jpeg init(&ctx->decoder, ctx->width, ctx->height); _ _ _ 2 while (has new frame) 3 vpu decode jpeg doing(&ctx->decoder, ctx->cur frame->buf, _ _ _ _ 4 ctx->cur frame->size, ctx->rga bo fd, ctx->rga bo.ptr); _ _ _ _ 5 vpu decode jpeg done(&ctx->decoder); _ _ _ | |
|---|---|
| 1 2 3 4 5 | ret = vpu decode jpeg init(&ctx->decoder, ctx->width, ctx->height); _ _ _ while (has new frame) vpu decode jpeg doing(&ctx->decoder, ctx->cur frame->buf, _ _ _ _ ctx->cur frame->size, ctx->rga bo fd, ctx->rga bo.ptr); _ _ _ _ vpu decode jpeg done(&ctx->decoder); _ _ _ |
其中:
decoder,vpu解码句柄rga_bo_fd,RGA buffer句柄rga_bo.ptr,RGA buffer的虚拟地址
2.4 显示
为尽可能高效地处理数据流并兼顾Rockchip不同芯片的特性,rmsl_linux_demo的显示直接使用了libdrm的接口,将三幅图像通过RGA拷贝到目标Buffer的具体偏移处,最后送到Rockchip VOP的overlay显示层。
主要流程如下图。
彩色Camera MJPG帧红外Camera MJPG帧
MPP解码MPP解码
深度Camera帧彩色NV12帧红外NV12帧
算法计算算法计算RGA拷贝RGA转码成rgb565并拷贝RGA转码rgb565并拷贝
深度图点云图三路图像合并后的显示Buffer
VOP overlay层显示
这里做了两个假设:
假设只有一个overlay层可用。因此使用RGA拷贝图像到目标Buffer的不同偏移中。例如px30/rk3326就只有一个overlay层将视差图以RGB565显示。显示主要是示例,RGB565的BPP刚好也是16,显示出来只为看清物体的轮廓
虽然多了一步RGA转码及拷贝,但RGA硬件能快速地完成。该demo在px30、rk3288、rk3399平台上能以15fps显示。因为IR及Depth Camera只有15fps,故最多也只有15fps的帧率。性能上可以考虑如下的优化方式:
如果有多个overlay层可用,NV12格式可以直接用单独的层显示。共需要三个overlay层,两个用作彩色及红外NV12帧显示,另一个给深度图显示。这样可以省去RGA转码及/或拷贝部分。RGB Camera也可以达到30fps的帧率。多线程化可提升并发性,特别是在需要处理点云图时,涉及到浮点运算
2.4.1 与QT应用程序结合
用户如需要QT应用程序来实现如菜单、按键等UI组件,可预留出视频区域,并在需要视频显示时,以rmsl_linux_demo作为参考,将overlay层固定到预留区域中。
需要注意的是,overlay层(视频)总是在UI之上,因此如有弹出对话框、菜单等与视频区域重叠,可将视频暂时隐去。
以上仅是提供一种参考思路,请开发工程师自由发挥。
3. 常见QA
3.1 打开Camera后设备断开
原因是供电不足导致,请使用外接电源的USB hub供电。