Skip to main content

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)

在线预览​

若预览无法显示,请直接下载 PDF 后用本地阅读器打开。


1. RMSL模组接口简介​

1.1 概述​

Rockchip RMSL模组是USB即插即用设备,它可以同时有三路输出,即Depth, RGB, IR。其中Depth输出YUYV数据,RGB及IR输出MJPG数据。

Video最大分辨率格式帧率描述
Depth640x480YUYV15fps输出视差图,可根据算法转换成深度图或点云图
RGB1920x1080MJPG30fps彩色视频输出,可解码为NV12格式
IR640x480MJPG15fps红外视频输出,可解码为NV12格式

1.2 RMSL模组的型号​

RK RMSL模组的型号可从SN码中获取,当前支持的RK结构光型号如下:

型号匹配的SN码接口
RMSL201-1301R2011301xxxxxxxxxUSB

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); _ _
1int 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); _ _
1int 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); _ _
1int rmsl reset device(int fd); _ _

参数说明:

fd,/dev/video节点对应的文件描述符

成功则返回0,其它值表示错误。

进入待机

1 int rmsl suspend device(int fd); _ _
1int 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 5ret = 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供电。