【车机xxx视频需求实现 1】 - 需求分析 及 实现思路(车内DMS/AVR/ROA摄像头)
发布日期:2021-06-29 14:55:05 浏览次数:3 分类:技术文章

本文共 6920 字,大约阅读时间需要 23 分钟。

【车机xxx视频需求实现 1】 - 需求分析 及 实现思路(车内DMS/AVR/ROA摄像头)

本文链接:《》

本需求系列文章:

  1. 《》
  2. 《》
  3. 《》
  4. 《》
  5. 《》
  6. 《》
  7. 《》
  8. 《》
  9. 《》
  10. 《》
  11. 《》
  12. 《》
  13. 《》
  14. 《》
  15. 《》
  16. 《》

一、XXX视频通话 - 需求分析

先说下这个需求:

xxx 在车机投屏时,车机侧将DMS/AVR/ROA三个摄像头上报给xxx,相当于将车内三个摄像头虚拟化成手机端的摄像头。
xxx 手机使用虚拟化后的摄像头,xxx手机来与其他的xxx手机进行视频通话。

目前的问题点在于,在车机上,车机侧的DMS/AVR/ROA这三个摄像头是由ICM模块来控制,ICM模块与车机侧只有一路CVBS线连接,

也就是ICM模块可以同时打开三个摄像头,但由于与车机只有一路CVBS线,ICM模块在车机端以 /dev/video0 的形式存在,
所以,同一时间,ICM只能发送一路的摄像头数据给到车机系统。
换句话说,对于车机来说,同一时间,只能打开并获取到 DMS/AVR/ROA这三个摄像头中的一个,摄像头。

如下所示:

在这里插入图片描述

因此,为实现XXX这个需求,有如下两种方法:

  1. 方法一,XXX 打开摄像头之前,先下发一个切换摄像头命令给到车机

    车机与XXX 约定好摄像头切换命令,如 1: DMS 摄像头 2: AVR 摄像头 3: ROA 摄像头

    打开流程为:

    (1)xxx在打开摄像头之前,先发送切换命令给到车机端,车机端收到切换命令后,在Java层下发 CAN消息给到 ICM 模块,由ICM模块来实现切换摄像头通路。
    (2)接着xxx下发打开车机摄像头,车机侧直接通过open camera 方法打开/dev/video0 节点,获得Camera 数据后直接通过回调给到XXX。

  2. 方法二,在车机端将一个摄像头虚拟化成三个摄像头来上报给XXX

    在车机端将一个摄像头虚拟化成三个摄像头来上报XXX,这样 XXX 感知到的就是三个摄像头,

    打开流程为:

    (1)XXX指定打开三个摄像头中的一个,下发打开命令给到车机,
    (2)在车机端Native 层识别 XXX 下发打开的是哪个摄像头,
    (3)在车机Native层 下发CAN 报文消息给到ICM 模块,由ICM模块来实现切换摄像头
    (4)在车机Native层 通过open camera 打开 /dev/video0 节点,获得摄像头数据后,车机端将Camera 数据编码后通过回调发送给 xxx 手机。

两种方法比较,

第一种方法实现起来较快,相对比较简单,并且打开摄像头时走正常的Android CameraService 流程就可以了,但它的缺点是会修改XXX打开摄像头的流程,不具有普遍性,只能适配当前车机。

第二种方法需要在车机 Libdmsdpcamerahandler.so 中的来实现,实现起来相对复杂,整个发CAN报文、打开摄像头 流程都需要在 lib库中实现,就个人而言这种方法更有意思,当然花费的时间也会更多。

接下来,本文就第二种方法来实现这个需求。

本文链接:《》

二、xxx 畅连视频通话 - 需求分解

分解需求如下:

由于上海没有 DMS摄像头,使用USB UVC摄像头替代调试:

  1. 编译 libdmsdpcamerahandler.so
  2. 将USB UVC摄像头配置为 /dev/video14,确保打开 video14节点可以获取到 UVC摄像头的数据
  3. 禁用 xxxAndroid CameraService流程,强制通过 lib库中的open camera 来获取数据。
  4. libdmsdpcamerahandler.so 库扫描找到 /dev/video14 ,获取Camera 参数,后上报给 xxx

在上报 /dev/video14 节点成功后,如果 xxx 能通过 video14 节点获取到 UVC 数据的话,

整个 libdmsdpcamerahandler.so 库 的流程就通了,
接下来,需要考虑的就是将 DMS/AVR/ROA 三个摄像头虚拟化成三个摄像头了,
由于 DMS/AVR/ROA 三个摄像头在车机端的节点是 /dev/video0 ,将前面的 video14修改为video就可以了

  1. libdmsdpcamerahandler.so 库中将 video0 参数复制三份,修改上报的 Camera ID 分别为:DMS(1001) ROA(1002) AVR(1003)
  2. 在车机端open camera 中先对 Camera ID 截留判断,根据 1001、1002、1003 来下发不同的 CAN报文给到 ICM 模块。
  3. 接着车机端在lib 库中(Native层)打开 /dev/video0 节点,获取Camera 数据,如果Camera 数据不是 H264 ,还需要先进行H264编码,将编码后的数据回调给到 xxx 手机。
  4. 由于获取到的 DMS/AVR/ROA的数据是 NV21格式的RAW data,所以在上报前需要先对Camera 做下 H264编码,再回调

2.1 编译 libdmsdpcamerahandler.so库

有关 Windows 侧交叉编译so 库的方法,

可以参考我之前写的文章:《 》

2.2 将USB UVC摄像头配置为 /dev/video14

固定 /dev/video14 的修改,如下:

diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.cindex f5b17e5..37b1589 100644--- a/drivers/media/usb/uvc/uvc_driver.c+++ b/drivers/media/usb/uvc/uvc_driver.c@@ -1917,8 +1917,11 @@ static int uvc_register_video(struct uvc_device *dev,         * uvc_v4l2_open might race us.         */        video_set_drvdata(vdev, stream);+       // Fixed UVC camera on Video3 ++++       //ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);+       ret = video_register_device(vdev, VFL_TYPE_GRABBER, 14);+       // Fixed UVC camera on Video3 --- -       ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);        if (ret < 0) {
# vendor/etc/init/hw/init.freescale.rc将#setprop front_camera_name 		imx8_fpdlink_to_962_mipi_0,uvc#setprop front_camera_orient 	0修改为:setprop front_camera_name 		uvcsetprop front_camera_orient 	0

2.3 禁用 xxx 走Android CameraService流程

修改CameraService 代码,重新编译libcameraservice.so 库,

将 /system/lib/libcameraservice.so 和 /system/lib64/libcameraservice.so 均 push 到车机中。

代码修改如下:

# frameworks/av/services/camera/libcameraservice$ git diff .diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cppindex 2bf42b6..2b0346b 100644--- a/services/camera/libcameraservice/CameraService.cpp+++ b/services/camera/libcameraservice/CameraService.cpp@@ -1286,6 +1286,18 @@ Status CameraService::connectHelper(const sp
& cameraCb, const String8& (halVersion == -1) ? "default" : std::to_string(halVersion).c_str(), static_cast
(effectiveApiLevel)); + // 20201016 disable android camera ++++ if(clientName8 == "com.xxx.dmsdpdevice") {
+ ALOGI("com.huawei.dmsdpdevice is forbid, ID \"%s\"", cameraId.string());+ return STATUS_ERROR_FMT(ERROR_CAMERA_IN_USE,+ "com.huawei.dmsdpdevice is forbid, ID \"%s\"",+ cameraId.string());+ }+ // 20201016 disable android camera +++

2.4 在车机侧 so库中上报 /dev/video14,确保使用xxx 能成功获取到 video14 数据

打开/dev/video14时,由于系统开启了selinux ,所以报了AVC 权限错误,如下:

10-25 14:32:08.292  I CamSDK_3rdCamera: [CheckVideoFile] /dev/video14 +++ 10-25 14:32:08.291  W wei.dmsdpdevice: type=1400 audit(0.0:167): avc: denied {
ioctl } for path="/dev/video14" dev="tmpfs" ino=91051 ioctlcmd=0x564a scontext=u:r:system_app:s0 tcontext=u:object_r:video_device:s0 tclass=chr_file permissive=010-25 14:32:08.291 W wei.dmsdpdevice: type=1400 audit(0.0:168): avc: denied {
ioctl } for path="/dev/video14" dev="tmpfs" ino=91051 ioctlcmd=0x5615 scontext=u:r:system_app:s0 tcontext=u:object_r:video_device:s0 tclass=chr_file permissive=0

解决方法为在 system_app 中添加 ioctolcmd :

sec01@sec01-Precision-3630-Tower:/home1/abnercen/workspaces/debug/P90/device/fsl/imx8q/sepolicy_qg$ git diff .diff --git a/imx8q/sepolicy_qg/system_app.te b/imx8q/sepolicy_qg/system_app.teindex 8ad4a61..def9907 100644--- a/imx8q/sepolicy_qg/system_app.te+++ b/imx8q/sepolicy_qg/system_app.te@@ -97,7 +97,7 @@ allow system_app audio_device:dir r_dir_perms; allow system_app vfat:dir create_dir_perms; allow system_app vfat:file create_file_perms; allow system_app video_device:chr_file rw_file_perms;-allowxperm system_app video_device:chr_file ioctl {
0x5600 0x5602 0x5604 0x5605 0x5608 0x5609 0x560f 0x5611 0x5612 0x5613 };+allowxperm system_app video_device:chr_file ioctl {
0x5600 0x5602 0x5604 0x5605 0x5608 0x5609 0x560f 0x5611 0x5612 0x5613 0x564a 0x5615 }; allow system_app i2c_device:dir rw_dir_perms; allow system_app i2c_device:chr_file rw_file_perms; allowxperm system_app i2c_device:chr_file ioctl {
0x706 };sec01@sec01-Precision-3630-Tower:/home1/abnercen/workspaces/debug/P90/device/fsl/imx8q/sepolicy_qg$ cd ..

修改代码后,重新remake 编译,下载 vendor.img 即可,下载完毕后需要清除下userdate数据。

实测,下载vendor.img 后,打开 /dev/video14节点成功,在投屏xxx 后成功取到UVC 视频数据,通过UVC摄像头畅连视频通话成功。

2.5 在车机侧 so库中虚拟化 DMS/AVR/ROA为三个摄像头,并上报给xxx

目前走到这一步了,在 libdmsdpcamerahandler.so 中将 UVC 摄像头虚拟化成三个出来,再将虚拟化出来的三个摄像头,上报给到xxx 中。

摄像头虚拟化代码修改 及 代码流程分析见

《》

2.6 在车机侧 so库中发送 CAN报文消息给到ICM,切换摄像头

待研究倒车 CAN 报文发送代码,参考它来实现在 lib 库中发送 CAN报文。

# \reverse-new\reverse\event\EventManager.cppvoid EventManager::SendTrackLineEvent() {
char cmd[CANBUS_HEADER_LEN + CMD_AVM_LEN8]; memset(cmd, 0, CANBUS_HEADER_LEN + CMD_AVM_LEN8); cmd[0] = AVM_TOUCH_CMD_ID; cmd[1] = CMD_AVM_LEN8; cmd[CANBUS_HEADER_LEN + 3] = 0x40; ALOGD("@@SendTrackLineEvent:0x%x-0x%x-0x%x-0x%x-0x%x-0x%x-0x%x-0x%x-0x%x-0x%x\n", cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6], cmd[7], cmd[8], cmd[9]); canbus_control(0x1, (char*)cmd);}

2.7 在车机侧 so库中对Camera 数据做 H264 编码

待研究,参考它来实现,调用车机的硬件编解码来实现对 Camera RAW Data 进行 H264 编码。

参考: native的可以参考 frameworks/av/cmds/screenrecord

转载地址:https://ciellee.blog.csdn.net/article/details/109235992 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:【LeetCode #47 题解】 带重复全排列 II(递归回溯法、非递归实现)
下一篇:【FFmpeg解码实战】(5)实现FFmpeg4.3 + SDL2视频播放器(添加独立线程和队列)(C++)

发表评论

最新留言

逛到本站,mark一下
[***.202.152.39]2024年04月08日 11时30分55秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章