Справка платформы: V1.0.1 производителя (RK-KF-YF-355) описывает RMSL и API Linux SDK. Камера структурированного света 3D содержит проектор 30 тысяч точек, RGB-камеру 5 Мп, ИК-камеру 1 Мп с глобальным затвором и ИК-подсветку; применения — платежи, контроль доступа, распознавание жестов/тела и точное 3D-моделирование. Конкретные платы ArmSoM, ядра и BSP не проверены; проверьте питание USB, библиотеки и узлы. Производительность взята из оригинала, не измерена ArmSoM; команды не выполнялись. ZH использует китайские рисунки, EN/RU/DE — английские.
1. Интерфейс модуля RMSL
1.1 Обзор
Модуль Rockchip RMSL — USB-устройство plug-and-play с тремя одновременными выходами: Depth, RGB и IR. Depth выдаёт YUYV, RGB и IR — MJPG.
| Видео | Макс. разрешение |
Формат | Частота кадров |
Описание |
|---|---|---|---|---|
| Depth | 640x480 | YUYV | 15fps | Карта диспаратности; алгоритм преобразует её в карту глубины или облако точек |
| RGB | 1920x1080 | MJPG | 30fps | RGB-изображение с декодированием в NV12 |
| IR | 640x480 | MJPG | 15fps | ИК-изображение с декодированием в NV12 |
1.2 Модель RMSL
Модель RK RMSL определяется по серийному номеру SN. Поддерживаемые на момент документа модули структурированного света перечислены ниже.
| Модель | Соответствующий SN | Интерфейс |
|---|---|---|
| RMSL201-1301 | R2011301xxxxxxxxx | USB |
1.3 Настройка Buildroot
В Buildroot Linux SDK интерфейсы разработки и примеры расположены в app/demo/rmsl. По умолчанию программа не собирается. Включите 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 выполните следующую команду сборки модуля:
# make app_demo
Для повторной сборки используйте:
# make app_demo-dirclean
# make app_demo
После сборки создаются два исполняемых файла: rmsl_linux_demo и rmsl_tool.
# ls -1 /usr/bin/rmsl*
/usr/bin/rmsl_linux_demo
/usr/bin/rmsl_tool
Из-за большого числа зависимостей рекомендуется полная чистая сборка Buildroot после настройки по §1.3. Подключите RMSL и получите сведения об устройстве через rmsl_tool. Запрос узлов устройства:
# 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
В примере три узла /dev/video6, /dev/video8, /dev/video10 соответствуют DEPTH, RGB и IR. Также выводятся USB-узел, сведения о драйвере и прочие данные. Запрос SN и версии ПО RMSL:
# rmsl_tool --get_sn --get_version --device /dev/video6
SN: R2011301200801448
Version: 2.2.0
Перед получением потока инициализируйте устройство:
# rmsl_tool --init --device /dev/video6
После завершения потока выполните деинициализацию:
# rmsl_tool --deinit --device /dev/video6
После завершения потока можно также сбросить устройство:
# rmsl_tool --reset --device /dev/video6
После инициализации RMSL поток доступен стандартным инструментам, например v4l2-ctl и vlc; соблюдайте формат и размер потока. rmsl_linux_demo показывает полный цикл: инициализация, захват, декодирование, деинициализация и вывод. Пример сам инициализирует RMSL, поэтому предварительно вызывать rmsl_tool не требуется. Справка rmsl_linux_demo:
# 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
rmsl_linux_demo получает поток, сохраняет его в файл и отображает на экране. Вывод включён по умолчанию; параметр –no-display отключает его. Вывод изображения на экран:
# 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. Для Depth карта диспаратности непосредственно показывается как RGB565. Следующий пример отключает вывод и сохраняет декодированные кадры:
# 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 — кадры NV12 640x480; rgb.bin — NV12 640x480; depth.bin — данные глубины 640x480, 2 байта на пиксель. По умолчанию три потока имеют размер 640×480, но RGB-камера поддерживает 1080p. На ПК файлы можно просматривать YUVPlayer (Windows) или mplayer (Linux). Примеры команд mplayer:
# 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. Исходный код примера
Каталог app/demo/rmsl/ содержит настройки RMSL, интерфейсы запросов, захват, декодирование и вывод.
# tree app/demo/rmsl/
app/demo/rmsl/
├── CMakeLists.txt
├── main.c # main of rmsl_linux_demo
├── rkdrm_display.c # use DRM to display directly on Overlay Plane of
Rockchip devices
├── rkdrm_display.h
├── rmsl_api.h # RMSL API Definition
├── rmsl_ctrl.c # Implementation of rmsl control, query and other
routines
├── rmsl_depth.c # Implementation of depth image conversion
├── rmsl_tool.c # The rmsl_tool source code
├── vpu_decode.c # vpu jpeg hardware decoding interface
└── vpu_decode.h
2.1 Интерфейс управления RMSL
Получение версии:
int rmsl_get_version(int fd, char *ver, int size);
Параметры: fd — дескриптор узла /dev/video; ver — возвращаемая версия; size — размер массива ver, не меньше RMSL_DATA_SIZE_QUERY. Возвращается 0 при успехе, код ошибки при сбое. Получение серийного номера:
int rmsl_get_sn(int fd, char *sn, int size);
Параметры: fd — дескриптор /dev/video; sn — возвращаемый серийный номер; size — размер массива sn, не меньше RMSL_DATA_SIZE_QUERY. Возвращается 0 при успехе, код ошибки при сбое. Инициализация и деинициализация:
int rmsl_init_device(int fd);
int rmsl_deinit_device(int fd);
Инициализация/деинициализация управляет выдачей данных видеоузлом.
Параметр fd — дескриптор видеоузла. Возвращается 0 при успехе, код ошибки при сбое. Сброс устройства:
int rmsl_reset_device(int fd);
Параметр fd — дескриптор видеоузла. Возвращается 0 при успехе, код ошибки при сбое. Переход в режим suspend:
int rmsl_suspend_device(int fd);
Параметр fd — дескриптор видеоузла. Возвращается 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 отключает журнал, 0 выводит сообщения. Возвращается 0 при успехе, код ошибки при сбое. Преобразование Depth в облако точек и карту глубины:
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, 16 бит на пиксель; pc_out — облако точек, NULL отключает его вычисление; depth_out — карта глубины, NULL отключает её вычисление; width и height — ширина и высота. Возвращаемое значение 0 означает успешное вычисление.
Отрицательное значение означает ошибку. Английский оригинал пишет «A positive 0» для случая, когда исходный кадр уже является картой глубины и вычисление не требуется (такого случая пока нет); китайский текст указывает значение больше 0. Это расхождение оригиналов, а не новый код возврата.
2.2 Получение потока
rmsl_linux_demo получает поток через rkisp_api.so. В отличие от обычной USB-камеры нужна дополнительная инициализация. Подробности интерфейса rkisp_api.so см. в Rockchip_Developer_Guide_Linux_Camera_EN.pdf.
2.3 Декодирование
Пример декодирует MJPG библиотекой Rockchip MPP: поток rkisp_api передаётся MPP. Затем RGA может масштабировать/копировать декодированный буфер для вывода, поэтому буфер декодирования выделяется через RGA. Исходный код:
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; rga_bo.ptr — его виртуальный адрес.
2.4 Отображение
Для эффективной обработки с учётом возможностей разных SoC rmsl_linux_demo напрямую использует libdrm. RGA копирует три изображения по заданным смещениям целевого буфера, затем передаёт его в overlay-плоскость Rockchip VOP. Схема ниже.
Кадр MJPG RGB-камеры; кадр MJPG IR-камеры.

Оба кадра декодируются MPP.
Кадр Depth-камеры; кадр RGB NV12; кадр IR NV12.
Для Depth: алгоритмическое вычисление или копирование RGA. Для RGB и IR: преобразование RGA в RGB565 и копирование.
Ветви алгоритма дают карту глубины и облако точек. Три изображения объединяются в буфер вывода.
Вывод через overlay-слой VOP.
Предполагается доступность только одного overlay-слоя, например на px30/rk3326. RGA копирует изображения по разным смещениям одного буфера. Карту диспаратности показывают как RGB565 только для демонстрации: оба формата имеют 16 бит на пиксель, поэтому контуры хорошо различимы. Дополнительное преобразование/копирование RGA ускоряется аппаратно. На px30, rk3288 и rk3399 пример показывает 15fps; максимум ограничен 15fps камер IR и Depth. Возможные улучшения: при нескольких overlay-плоскостях показывать NV12 непосредственно в отдельных плоскостях. Всего нужны три: RGB NV12, IR NV12 и Depth. Это позволяет пропустить преобразование/копирование RGA; RGB может достичь 30fps. Многопоточность улучшает параллелизм, особенно при обработке облака точек с вычислениями с плавающей точкой.
2.4.1 Интеграция с QT
Если QT рисует меню, кнопки и другой UI, зарезервируйте область главного окна для video overlay. Видео всегда находится над UI: если всплывающий диалог или меню пересекается с видео, временно скрывайте overlay-плоскость. Это лишь вариант архитектуры; проектируйте приложение по своим требованиям.
3. Частые вопросы
3.1 Отключение устройства после открытия камеры
Причина в недостаточном питании. Подключите устройство через USB-концентратор с внешним питанием.
Различия оригиналов
Противоречие «A positive 0» и китайского «больше 0» отмечено выше; проверяйте реальную библиотеку. Отличающиеся примеры другого оригинала ниже независимы, не объединяйте их в сценарий.
CN PDF p.8 · 37
# 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
