【基于openharmony的多路摄像头功能:USB设备插拔检测】
前言
最近项目接触的模块比较繁多而杂,因此开始写文章记录下用以总结。
目前在做的是基于openharmony3.2的多camera功能主要涉及HDF(HAL)层与framework层。
本文章涉及多路摄像头功能的第一步:支持USB摄像头插拔检测。
内容
目前openharmony在HDF层支持的camera模式有V4L2和MPP,除了海思芯片大多用的linux通用的V4L2模式,因此在devicemanager中启动的是V4L2DeviceManager。
初始化
在V4L2DeviceManager::Init会创建一个EnumeratorManager并调用其Init。
RetCode EnumeratorManager::Init()
{uvcVideo_ = std::make_shared<HosV4L2UVC>();if (uvcVideo_ == nullptr) {CAMERA_LOGE("%s Create HosV4L2UVC fail", __FUNCTION__);return RC_ERROR;}uvcVideo_->V4L2UvcDetectInit([&](const std::string& hardwareName,std::vector<DeviceControl>& deviceControl,std::vector<DeviceFormat>& deviceFormat, bool uvcState) {UvcCallBack(hardwareName, deviceControl, deviceFormat, uvcState);});return RC_OK;
}
可以看到上面代码初始化了一个HosV4L2UVC对象并调用其V4L2UvcDetectInit
RetCode HosV4L2UVC::V4L2UvcDetectInit(UvcCallback cb)
{// set callbackuvcCallbackFun_ = cb;uDevFd_ = socket(PF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);if (uDevFd_ < 0) {CAMERA_LOGE("UVC:V4L2Detect socket() error\n");return RC_ERROR;}memset_s(&nls, sizeof(nls), 0, sizeof(nls));nls.nl_family = AF_NETLINK;nls.nl_pid = getpid();nls.nl_groups = 1;rc = bind(uDevFd_, (struct sockaddr *)&nls, sizeof(nls));eventFd_ = eventfd(0, 0);uvcDetectThread_ = new (std::nothrow) std::thread(&HosV4L2UVC::loopUvcDevice, this);
}
聪明的朋友应该已经看出来了,这里起了个线程执行loopUvcDevice通过监听NETLINK消息来循环检测USBcamera设备的插入。
USB设备检测
void HosV4L2UVC::loopUvcDevice()
{V4L2UvcEnmeDevices();...while (g_uvcDetectEnable) {int rc = select(((uDevFd > eventFd) ? uDevFd : eventFd) + 1, &fds, &fds, NULL, NULL);if (rc > 0 && FD_ISSET(uDevFd, &fds)) {usleep(delayTime);constexpr uint32_t buffSize = 4096;char buf[buffSize] = {};unsigned int len = recv(uDevFd, buf, sizeof(buf), 0);if (CheckBuf(len, buf)) {return;}...}
}
loopUvcDevice起了个无限循环,通过select监听之前创建的fd。从fd的创建参数NETLINK_KOBJECT_UEVENT可以知道是监听的udev设备文件创建的事件。
收到后会调用CheckBuf来处理。因为会收到所有的udev事件,所以需要过滤下
int HosV4L2UVC::CheckBuf(unsigned int len, char *buf)
{constexpr uint32_t UVC_DETECT_ENABLE = 0;constexpr uint32_t UVC_DETECT_DISABLE = -1;if (len > 0 && (strstr(buf, "video4linux") != nullptr)) {std::lock_guard<std::mutex> lock(g_uvcDetectLock);if (!g_uvcDetectEnable) {return UVC_DETECT_DISABLE;}std::string action = "";std::string subsystem = "";std::string devnode = "";V4L2GetUsbString(action, subsystem, devnode, buf, len);UpdateV4L2UvcMatchDev(action, subsystem, devnode);}return UVC_DETECT_ENABLE;
每次udev信息传递都会调用CheckBuf处理,感觉这里有优化空间。
从日志看我们会收到SUBSYSTEM为video4linux,创建的设备节点为video9的消息。

由于是USB设备,也可以看下当前设备插入USB camera后的USB枚举情况

可以看到此设备匹配的uvcvideo驱动。关于底层驱动我没有去适配,应该linux系统自动支持了,后续找机会了解下。
MatchDev
因为之前获取到了devnode设备节点,因此就可以直接通过设备节点访问设备了。
V4L2UvcGetCap
检测到了设备后通过VIDIOC_QUERYCAP向设备节点查询设备能力,
struct v4l2_capability {__u8 driver[16];__u8 card[32];__u8 bus_info[32];__u32 version;__u32 capabilities;__u32 device_caps;__u32 reserved[3];};
struct v4l2_capability cap;
rc = ioctl(fd, VIDIOC_QUERYCAP, &cap);
其中capabilities就是设备能力,查看是否支持V4L2_CAP_VIDEO_CAPTURE和V4L2_CAP_STREAMING。
camera驱动的本质就是将硬件采集到的流数据传递给用户侧。正常情况下用户侧可以使用read接口从内核读取出数据,但是这就涉及到了内核态数据和用户态数据的拷贝了。对于camera这种频繁且数据大的流效率会很低,所以目前主流都是使用内层映射的机制。
V4L2_CAP_STREAMING能力就是表示支持内存映射的方式建立buffer传递流数据。由于内核态直接将一块buffer空间映射到用户态,因此HAL层可以直接从该内存空间去除数据提高了效率。
V4L2_CAP_VIDEO_CAPTURE 则是表示这个设备是个视频捕捉设备,以此判断是否camera设备
V4L2UvcMatchDev
void HosV4L2UVC::V4L2UvcMatchDev(const std::string name, const std::string v4l2Device, bool inOut)
{....if ((sprintf_s(devName, sizeof(devName), "%s", name.c_str())) < 0) {CAMERA_LOGE("%s: sprintf devName failed", __func__);return;}if (inOut) {std::lock_guard<std::mutex> l(HosV4L2Dev::deviceFdLock_);iter = HosV4L2Dev::deviceMatch.insert(std::make_pair(std::string(devName), v4l2Device));.....} else {HosV4L2Dev::deviceMatch.erase(std::string(devName));}V4L2UvcSearchCapability(std::string(devName), v4l2Device, inOut);uvcCallbackFun_(std::string(devName), control_, format_, inOut);
}
这个接口就是将驱动name与设备节点作为一个pair插入到HosV4L2Dev::deviceMatch表中。
之后当HAL层需要访问设备时就通过驱动name找到设备节点最终访问设备。
这里有一个问题,如果插入了多个设备并且这些设备节点都是用的同一个驱动name,那就无法区分出硬件了。因此后续还需要进行优化,使用cameraID来更细化区分,这块等实现后更新到另外的博客。
之后还需要进一步获取设备的FMT能力,也就是设备支持的分辨率、帧率等信息。
void HosV4L2UVC::V4L2UvcSearchCapability(const std::string devName, const std::string v4l2Device, bool inOut)
{....std::shared_ptr<HosFileFormat> fileFormat = nullptr;fileFormat = std::make_shared<HosFileFormat>();fileFormat->V4L2GetFmtDescs(fd, format_);....std::shared_ptr<HosV4L2Control> control = nullptr;control = std::make_shared<HosV4L2Control>();control->V4L2GetControls(fd, control_);
}
V4L2GetFmtDescs在v4l2_fileformat.cpp中实现。下一章meta数据添加会再介绍,这里就不细讲了。主要是通过V4L2GetFmtDescs查询视频格式。
V4L2GetControls在v4l2_control.cpp中实现。通过VIDIOC_QUERYCTRL命令可以查到当前设备支持的控制命令信息。这些控制命令比如有对比度、饱和度、白平衡、曝光度等等。

最后再看看uvcCallbackFun_。
V4L2UvcDetectInit是在最开始初始化时传入的参数,倒回去看下初始化贴的代码可以知道这个回调是EnumeratorManager::UvcCallBack。然后这里又是被其他模块注册了回调。也就是最开始介绍的V4L2DeviceManager。
void EnumeratorManager::UvcCallBack(const std::string hardwareName,std::vector<DeviceControl>& deviceControl,std::vector<DeviceFormat>& deviceFormat, bool uvcState)
{uvcCb_(hardwareName, deviceControl, deviceFormat, uvcState);
}void V4L2DeviceManager::SetHotplugDevCallBack(HotplugDevCb cb)
{uvcCb_ = cb;enumeratorManager_->SetCallBack([&](const std::string hardwareName, std::vector<DeviceControl>& deviceControl,std::vector<DeviceFormat>& deviceFormat, bool uvcState) {UvcCallBack(hardwareName, deviceControl, deviceFormat, uvcState);});
}
因此USB设备插入检测后最终会通知给V4L2DeviceManager。参数是驱动name、上面查到的控制信息、视频格式、状态(插入还是移除)。
相关文章:
【基于openharmony的多路摄像头功能:USB设备插拔检测】
前言 最近项目接触的模块比较繁多而杂,因此开始写文章记录下用以总结。 目前在做的是基于openharmony3.2的多camera功能主要涉及HDF(HAL)层与framework层。 本文章涉及多路摄像头功能的第一步:支持USB摄像头插拔检测。 内容 目前openharmony在HDF层…...
uni-app:实现数字文本框,以及左右加减按钮
效果 代码 <template><view><view classline3><view classline3_position><view classleft>数量<text>*</text></view> <view class"right"><view class"quantity_btn"><view class"…...
跨平台开发框架Qt:面向对象、丰富API
Qt是一个跨平台C图形用户界面应用程序开发框架,它具有以下三大优势: 优良的跨平台特性:Qt支持多种操作系统,包括Windows、Linux、Solaris、HP-UX、Irix、FreeBSD等,使开发人员能够在不同平台上开发和部署应用程序&…...
An unexpected error has occurred. Conda has prepared the above report
今日在服务器上创建anaconda虚拟环境的时候,出现了如下报错 An unexpected error has occurred. Conda has prepared the above report 直接上解决方案 在终端中输入如下指令 conda config --show-sources 如果出现以下提示,说明多了一个文件 输入以下…...
考研C语言进阶题库——更新6-10题
目录 6输入一个字符串,输出其中字母的个数 7用递归求函数值x1,f(x)10,x>1.f(x)f(x-1)2 8所给字符串正序反序连接,形成新串并输出 9输入若干个整数以-1标记为结束输出其中的最大值 10求矩阵的两条对角线之和 6输入一个字符串,输出其中…...
汽车BOOTLOADER开发经历
鄙人参与电动汽车BOOTLOADER开发近三年,从完全没有这方面的基础到参与国内外大小知名或不知名车企的电动车三大件的BOOTLOADER开发,总结了以下一点学习心得。 1.熟悉基本术语含义 诊断、寻址方式、FBL、擦除、驱动 2.熟悉国际标准、UDS服务格式 汽车的…...
适配器模式(C++)
定义 将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。 应用场景 在软件系统中,由于应用环境的变化,常常需要将“一些现存的对象 ”放在新的环境中应用,但是新环境要求…...
HTTP连接之出现400 Bad Request分析
1、400简介 400是一种HTTP状态码,告诉客户端它发送了一条异常请求。400页面是当用户在打开网页时,返回给用户界面带有400提示符的页面。其含义是你访问的页面域名不存在或者请求错误。主要分为两种。 1、语义有误,当前请求无法被服务器理解…...
后端开发, 接口幂等性是什么意思
在后端开发中,接口的幂等性是指同一个请求的多次执行所产生的效果与执行一次的效果相同。简而言之,对于同一个接口请求,无论发送多少次,其对资源的状态修改结果都是一致的。 幂等性在接口设计和实现中非常重要,特别是在涉及数据修改或资源状态变更的情况下。如果一个接口…...
k8s手动发布镜像的方法
kubectl edit deploy编辑对应的文件,并:wq!保存即可...
十二、ESP32控制步进电机
1. 运行效果 2. 步进电机 最大特点:能够控制旋转一定的角度 3. 步进电机原理...
利用openTCS实现车辆调度系统(六)openTCS订单的使用
运输订单 由类的实例表示,描述了由车辆执行的进程。 通常,此过程是货物从一个地点到另一个地点的实际运输。 然而,A也可以只描述车辆到目的地位置的运动以及要执行的可选车辆操作。TransportOrderTransportOrder 以下所有内容都是 openTCS …...
第一天 什么是CSRF ?
✅作者简介:大家好,我是Cisyam,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉 🍎个人主页:Cisyam-Shark的博客 💞当前专栏: 每天一个知识点 ✨特色专…...
知识图谱推荐系统研究综述
基于协同过滤的推荐是当前应用最为广泛的推荐方法,但也存在着新用户或新项目的冷启动以及数据稀疏等问题。针对上述两种方法出现的问题,研究者进一步提出了混合推荐系统。混合推荐系统结合上述两种方法的优点,可以有效缓解其中的不足,增加推荐的准确性。但是,混合推荐系统…...
基于Centos7的Nginx源码安装
目录 1、准备安装环境 2、获取tar包: 3、解压创建软链接 4、创建用户和组 5、执行安装 6、创建服务脚本 7、开启nginx:编辑编辑 1、准备安装环境 yum insatall -y make gcc gcc-c pcre-devel #pcre-devel -- pcre库 #安装openssl-devel yum …...
Ubuntu 20.04 安装 Stable Diffusionn
步骤 1:安装 wget、git、Python3 和 Python3虚拟环境(如果已安装可忽略这步骤) sudo apt install wget git python3 python3-venv步骤 2:克隆 SD 项目到本地 git clone https://github.com/AUTOMATIC1111/stable-diffusion-webu…...
vue name命名错误 Do not use built-in or reserved HTML elements as component
描述: Do not use built-in or reserved HTML elements as component id: header 这里指的是components的名称命名不正确。 在项目中我使用的是header 作为组件名称,但是在前端html中这个是内置组件来的,名称已被占用不能再使用这些名称了。…...
知识付费系统开发:构建高效智能的付费内容平台
随着数字化时代的来临,知识付费正迅速崭露头角,为知识创作者和求知者带来了全新的商机。在这个背景下,开发一款高效智能的知识付费系统成为了一项重要的任务。本文将深入探讨如何基于Python编程语言和相关技术构建一个智能的知识付费内容平台…...
数据结构----结构--线性结构--递归
数据结构----结构–线性结构–递归 1.递归的概念 递归:将一个问题拆解成解决方案完全相同的子问题,并且有一个明确的终点 看如下递归代码理解一下递归 void fun(int n){if(n4){printf("%d",n);return;}fun(n1);printf("%d",n); …...
在Windows批处理程序中实现延时功能
方法1:使用PowerShell echo off:: 使用 PowerShell 的 Start-Sleep 命令来实现精确延时 powershell -command "Start-Sleep -Milliseconds 3000"echo Delay complete. 不过,通常Win7专业版和旗舰版中都会默认安装了PowerShell,但是标准版和家…...
深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...
大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...
PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建
制造业采购供应链管理是企业运营的核心环节,供应链协同管理在供应链上下游企业之间建立紧密的合作关系,通过信息共享、资源整合、业务协同等方式,实现供应链的全面管理和优化,提高供应链的效率和透明度,降低供应链的成…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...
第7篇:中间件全链路监控与 SQL 性能分析实践
7.1 章节导读 在构建数据库中间件的过程中,可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中,必须做到: 🔍 追踪每一条 SQL 的生命周期(从入口到数据库执行)&#…...
Linux系统部署KES
1、安装准备 1.版本说明V008R006C009B0014 V008:是version产品的大版本。 R006:是release产品特性版本。 C009:是通用版 B0014:是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存:1GB 以上 硬盘…...
uniapp 实现腾讯云IM群文件上传下载功能
UniApp 集成腾讯云IM实现群文件上传下载功能全攻略 一、功能背景与技术选型 在团队协作场景中,群文件共享是核心需求之一。本文将介绍如何基于腾讯云IMCOS,在uniapp中实现: 群内文件上传/下载文件元数据管理下载进度追踪跨平台文件预览 二…...
