相关动态
Android监控虚拟键 android手机虚拟摄像头手机IM「Android监控虚拟键 android手机虚拟摄像头」
2025-05-12 12:20


        在工作中,camera这一块上,可能会有各种各样的需求。比如有人想新增一个虚拟摄像头,当用户app打开摄像头设备时,打开的不是系统默认的camera hal代码,而是自己指定的代码,用自己事先准备好的视频数据,来喂给app;也有人想在系统默认的一套app框架上,新增一个外接的usbcamera,并且要能溶入到camera框架中。app只需要指定usbcamera的id,就能像打开普通摄像头那样,去打开我们的usbcamera;也有人,想在现有的框架上,同时兼容老的hal1+api1流程的android8.0之前的camera,又想新增一个符合android8.0的hidl接口规范的camera模块。

        上面所有的需求,归纳起来,核心的就是一点,即如何去新增一个camera hal模块。我这篇博客,是以在mtk android8.0上新增一个usbcamera hal模块来讲的。当然,新增虚拟摄像头,流程跟这个也是一模一样的。

        好了,既然是想在android8.0上新增一套符合hidl接口规范的camera流程,那么我们先要了解一下,android原生的hidl接口下的camera流程,下面我们先讲一讲这块。

        在android8.0之前,frameworks层的cameraservice和hal层的camera代码是在同一个进程的,这样不利于hal层部份独立升级。针对这个问题,8.0后,就推出了hidl机制,将frameworks层和hal层分成了两个进程,从而进行了解耦。借用网上的一张图片来大致的表明下这个区别:

Android监控虚拟键 android手机虚拟摄像头_androidO camera

        这么一来,看似调用变复杂了,但其实是殊途同归,hal层代码和之前基本上没有变化。具体到camera而言,就是在frameworks层和hal层中间,增加了一个cameraProvider来做为两方联系的桥梁。现在的调用流程,再借网上一张图一用:

Android监控虚拟键 android手机虚拟摄像头_androidO camera_02

        接下来以上面这张图来大致的说一下调用流程:

        1.) 开机注册cameraProvider(cameraProvider里会和具体的camera hal层对应起来)

        2.) 开机实例化cameraService

        3.) 查找并列出所有的cameraProvider(这一步会通过hw_get_module来将camera的hal层代码load出来)

        这基本上就是camera开机后从frameworks加载到hal层的路线了。下面再具体一步步来分析。

 

开机注册cameraProvider

        在我们的hardwareinterfacescameraprovider2.4default目录下,有一个android.hardware.camera.provider@2.4-service.rc文件

        当开机时,会自动调用这个文件去启动服务camera-provider-2-4,然后它会调用到/vendor/bin/hw/android.hardware.camera.provider@2.4-service这个文件。然后会调到hardwareinterfacescameraprovider2.4defaultservice.cpp

        然后这里会用hidl的标准接口去将我们的"legacy/0"注册到服务上去。

        在这里有一点要注意,这里的"legacy/0"必须要先在工程根目录 device芯片名/manifest.xml里先声明,否则即使这里注册了,后面也会因为找不到而报错.

 

开机实例化cameraService

        在frameworksavcameracameraserver里有个cameraserver.rc, 它在开机的时候,也会自动启动.

        然后它会调用到frameworksavcameracameraservermain_cameraserver.cpp

       在这个main函数里,我们只需要关注CameraService::instantiate();这行代码. 我们的CameraService继承了BinderService.h.这个:instantiate()调用到了BinderService.h里的代码

        从这个文件可以看出,instantiate最终还是调用到了IServiceManager里的addService, 将我们的cameraService注册到了系统的服务管理器里去了.

        这里调用到CameraService后, 因为是开机第一次调用,它的引用计数为1,所以会调用到CameraService::onFirstRef()这个函数. 这个函数是从CameraService的父类Refbase里继承过来的.该函数在强引用sp新增引用计数时调用,什么意思?就是当 有sp包装的类初始化的时候调用.我们再看看cameraService::onFirstRef()

        在这个函数里,我们只关注enumerateProviders(),这里就到了列出所有cameraProvider.

 

查找并列出所有的cameraProvider


        这个函数里,创建了一个CameraProviderManager对象,并调进行了初始化.

        在这个初始化函数里,我们只关注addProviderLocked, 我们可以看到,这个函数传进了一个kLegacyProviderName, 它的值定义在这个文件的上面:

        const std::string kLegacyProviderName("legacy/0");

        大家注意到了没有,它的值和我们之前hardwareinterfacescameraprovider2.4defaultservice.cpp里注册服务时return defaultPassthroughServiceImplementation<ICameraProvider>("legacy/0", 6); 以及manifest.xml里<instance>legacy/0</instance>的值都是一致的. 如果这个值不致,则会调用不成功.

        好了,再回到addProviderLocked这个函数来, 这个函数的作用, 就是去加载camera对应的hal层代码, 并将它的信息保存在ProviderInfo里,后面我们就可以通过这个ProviderInfo, 去实行addDevice、getCameraInfo等操作。

        这里先检查一下,传进来的newProvider是不是已经添加过,如果已经添加了,就不再处理,直接返回。如果没添加过,就会进行下一步的操作。这里的interface = mServiceProxy->getService(newProvider);,会调用到hardwareinterfacescameraprovider2.4defaultCameraProvider.cpp的HIDL_FETCH_ICameraProvider函数。

        在这个函数里,会创建一个CameraProvider对象。

        在这个初始化函数中,会看到一个我们非常熟悉的函数hw_get_module。到这里,就跟我们android8.0之前的流程一模一样的了,都是去直接和hal层打交道了。

        在CameraProvider里有一个地方值得大家注意

        从这里看来,如果我们的camera使用了hidl和hal打交道的话,我们hal里的版本号,必须是1.0或者是大于3.2的,如果我们的hal层的的版本号为3.0或3.1的话,是不能正确的加载成功的。

 

        上面用到的图片,引用了这个博客的,大家也可以去这篇博客看看。启动流程都是一致的,这博主也讲得比较详细。

 

        好了,上面就将android8.0上camera hal层代码的加载流程基本讲完了。有了上面的基础,下面我们再来一步步的讲下,怎么去新增一个camera hal。

###############################################################################################################################################################################################################################################################################################################

移植一个camera hal,需要做的有以下几点:

1.)在devicemediatekmt6580manifest.xml里新增要增加的camera的instance

2.)在frameworksavservicescameralibcameraservicecommonCameraProviderManager.cpp里,将要添加的camera provider给addProviderLocked进来

3.)在hardwareinterfacescameraprovider2.4defaultCameraProvider.cpp里将要增加的camera,通过hw_get_module这样给load进来。

4.)准备好对应的camera hal代码

 

配置manifest.xml

        因为mtkcamera已经有了一个camera hal1,名字为internal/0, 所以我们的usbcamera对应的名字跟在它的后面即可。注意,“legacy/1”这个名字的前面“legacy”这串,可以随便取,比如可以叫”abc/1",只要其他用到的地方都叫这个名字就可以。但是这个后面的“1”,不能弄错。前面已经为0了,这个就必须为1,同理,如果还有一个摄像头,就要为2了。因为在CameraProviderManager.cpp里的ProviderInfo::parseDeviceName,是通过后面这个数字,来取对应的id值的。如果我们将这个usbcamera的id也写为0,即名字为“legacy/0”,那么在ProviderInfo::parseDeviceName这里取出来的id,就会和前面的已经有了的主摄冲突。

 

添加camera的ProviderInfo

        在frameworksavservicescameralibcameraservicecommonCameraProviderManager.cpp的initialize函数里,将kLegacyProviderName改成"legacy/1"

        在hardwareinterfacescameraprovider2.4defaultservice.cpp里的main函数里,将"legacy/1"注册上来

        在hardwareinterfacescameraprovider2.4defaultCameraProvider.cpp里,将kLegacyProviderName改成"legacy/1";它会被HIDL_FETCH_ICameraProvider调用。

 

hw_get_module对应camera的hal代码

        在hardwareinterfacescameraprovider2.4defaultCameraProvider.cpp里的initialize()函数里,hw_get_module参数传进去的名字,改成我们usbcamera hal里指定的名字

        int err = hw_get_module("usbcamera", (const hw_module_t **)&rawModule);

 

准备好对应的camera hal代码

       我们的usbcamera hal代码,我们放在hardwarelibhardwaremodulescameralibuvccamera下面。在这个目录里,有个HalModule.cpp文件,里面定义了camera_module_t的结构体,它的id就是"usbcamera", 在CameraProvider.cpp里hw_get_module时,发现这里定义的id和它要找的id一致,就会load到我们的usbcamera了。

        大家可能会发现,在getCameraInfo函数里,我将cameraId写死成了0,但是前面我们不是刚说过,我们的usbcamera是第二个摄像头,id要为1么?其实这里的id,和前面说的那个id,不是同一个意思。在这里之所以写成0,是因为我们这套usbcamera hal代码上面,只挂了一个摄像头,这个摄像头对应的代码放在Camera *cams[]数组里,这个数组里只放了一个对象,所以id自然就要为0了。然后我们在我们的halModule.cpp里操作getCameraInfo或openDevice时,就会通过这个数组调用到static Camera mainCamera;这里定义的这个Camera对象了。这个Camera,也是我们自己写的代码:

 

 

        大家请注意,在Camera.cpp的Camera()里调用了common.version  = CAMERA_DEVICE_API_VERSION_3_2;  在cameraInfo里调用了info->device_version = CAMERA_DEVICE_API_VERSION_3_2; 这里表示,我们的hal的版本定义为了hal3.2。

        我们的HalModule.cpp的get_camera_info指向了HalModule::getCameraInfo,  getCameraInfo里又调用到了Camera::cameraInfo,然后Camera::cameraInfo通过staticCharacteristics来,获取我们usbcamera的属性。这样在app上就可以通过getCameraInfo来获取我们usbcamera的属性了。也可以使用下面的方法来获取我们预览或者拍尺寸等:

        我这个usbcamera,可以同时兼容api1和api2,当然,如果想要让api2也来调用的话,camera_metadata_t *mStaticCharacteristics;这个值要配好,必须按api2的规范来,该有的值一个都不能少,要不然app在调用getStreamConfigurationMap去获取属性时,就有可能会因为获取不到对应的值而报错。

       比如一开始,我在staticCharacteristics这个函数里,没有配置ANDROID_REQUEST_AVAILABLE_CAPABILITIES相关的属性。然后app在用api2的接口去getStreamConfigurationMap的时候,就因为找不到REQUEST_AVAILABLE_CAPABILITIES而报错了。至于api2都需要哪些配置项,大家可以参考frameworksbasecorejavaandroidhardwarecamera2implCamerametadataNative.java里的getStreamConfigurationMap()这个函数,这里需要的,都给加上,都必须加上。

        后来报错后,我在staticCharacteristics这个函数里,加下了如下代码,就可以了:

        到这里,我们一个完整的usbcamera hal就添加完成了。当然,虚拟摄像头也是一样的。唯一不同的是camera.cpp里的processCaptureRequest这个函数。我们的usbcamera是真正的一个摄像头,是可以取到实景的,所以就按照v4l2的标准来读取,然后按camera hal的规范来填充就可以。 但是虚拟摄像头因为是没有真正的摄像头的,它取的景,是底层事先录好一个视频,然后喂给buff的。所以虚拟摄像头,需要修改processCaptureRequest这个函数。

        虚拟摄像头,只需要在这个函数里,按照app设置的帧率来循环读取视频里的数据,然后abgr的格式,喂给processCaptureResult这个函数,这个函数,再通过回调mCallbackOps->process_capture_result,返回给上面即可。

       

    以上就是本篇文章【Android监控虚拟键 android手机虚拟摄像头手机IM「Android监控虚拟键 android手机虚拟摄像头」】的全部内容了,欢迎阅览 ! 文章地址:http://ww.kub2b.com/news/22854.html
     栏目首页      相关文章      动态      同类文章      热门文章      网站地图      返回首页 企库往资讯移动站 http://ww.kub2b.com/mobile/ , 查看更多   
最新文章
惠聚美好 | 春茶抢“鲜”忙!博罗柏塘万亩茶园飘香
春分时节茶山醒,青山翠垄采撷忙。眼下正值春茶采摘期,走进博罗县柏塘镇万亩茶园,只见层层叠叠的茶树随山势起伏,茶农们挎着竹
俄战轰将驻扎美军面前,印尼勇猛助力普京?澳方否认俄方沉默
2025年4月,关于俄罗斯战略轰炸机可能驻扎印尼马努瓦空军基地的消息在国际社会引发高度关注。英国权威军事媒体《简氏防务周刊》
在场|尝尝博山“春”的味道:博山区饮食行业协会发布六款春季菜品
春日的博山,空气中浮动着香椿与花椒芽的淡淡香气。4月8日,一场名为“乘时为贵”的春季品鉴会上,40余位名厨围绕时令食材,把“
如何选择流量卡手机流量卡「如何选择流量卡」
▲现在的三大电信运营商的老用户可选的流量套餐都是贵出天际,以广东这里的移动公司来说,最便宜的含流量是39元5个G,不含宽带的
清明节不能说快乐,只能祝“安康”?答案令人意外……
在今天的互联网传说里,有两个传统佳节是禁止“快乐”的,一个是端午,另一个就是清明。我们曾发文讲解过,所谓“端午不能‘快乐
手机QQ怎么发邮件到别人邮箱 QQ邮箱手机怎么注册手机qq邮箱登录入口「手机QQ怎么发邮件到别人邮箱 QQ邮箱手机怎么注册」
该手游近期很受玩家的欢迎,在游戏的过程中我们经常会遇到许多的问题,就有玩家问小编有关手机QQ怎么发邮件到别人邮箱 QQ邮箱手
*ST工智股票连续三个交易日涨幅偏离值超12%
雷达财经 文|杨洋 编|李亦辉4月16日,(证券代码:000584)发布股票交易异常波动公告。公司股票在2025年4月14日至16日连续三个交
搞机无悔,挚爱数码诺基亚n73手机qq「搞机无悔,挚爱数码」
第一部手机是2007年购入,至今已有10年,这十年从数码白痴到狂热的数码爱好者,一路走来,体验过众多手机和数码产品,那种最原始
苹果手机耗电太快怎么办手机电量消耗快怎么办「苹果手机耗电太快怎么办」
苹果手机以其卓越的性能和流畅的用户体验赢得了全球用户的喜爱,但不少用户在使用过程中都会遇到手机耗电过快的问题。这不仅影响
华为P30 Pro手机外观、参数、拍照、性能、续航及系统全面评测华为P30PRO手机参数「华为P30 Pro手机外观、参数、拍照、性能、续航及系统全面评测」
五、充电续航:40W超级闪充+4200毫安时电池成就续航怪兽在以往,华为P系列因主打极致轻薄设计,不得不缩减机身体积,进而其电池

loading