查看: 165|回复: 3

鸿蒙6.1.1 Camera Kit C API逻辑相机解构与内存释放实

[复制链接]
发表于 3 小时前 | 显示全部楼层 |阅读模式
对于需要把视频流直接送进游戏引擎、AR/VR空间计算或自研计算框架的开发者来说,如果一边在Native层处理相机数据,一边还要跑到ArkTS侧去取镜头畸变、内参矩阵,再通过NAPI把数据塞回C++,这种跨语言来回拉扯的开销在毫秒级渲染链路里往往难以接受。HarmonyOS 6.1.1(API 24)的Camera Kit在C API层面做了一次系统补全,把逻辑相机的底层探测能力直接开放给了Native层,同时要求开发者严格管理对应的内存生命周期。

这次更新最核心的变化,是在camera_device.h等头文件中新增了以OH_开头的C接口,全部通过指针传递参数,返回Camera_ErrorCode枚举。原先只能在ArkTS侧通过CameraDevice对象拿到的一部分微观光学参数,现在可以直接在C++层获得,同时新增了逻辑相机(Logical Camera)的深度解构能力。所谓逻辑相机,就是系统把广角、超广角、长焦等多个物理镜头抽象出来的一个虚拟变焦相机。反过来,通过C API可以拆解出这个逻辑相机背后真正参与成像的物理相机簇。

为了方便理解,可以先看一个典型的调用流程:先用OH_CameraDevice_IsLogicalCamera判断当前设备是不是逻辑相机,再用OH_CameraDevice_GetLogicalCameraConstituentCameraDevices取回一个Camera_Device**指针数组,里面每个元素就是底层的一个物理摄像头。拿到这些物理设备指针后,就可以继续提取焦距、最小对焦距离、畸变矩阵、内参标定、传感器物理尺寸、像素阵列、颜色滤镜排列等信息。

下面是一段Native层伪代码,展示了从逻辑相机解构出物理相机并提取焦距参数的过程:
  1. // NDK 层:解构逻辑摄像头
  2. Camera_Device** physicalCameras = nullptr;
  3. uint32_t size = 0;
  4. Camera_ErrorCode ret = OH_CameraDevice_GetLogicalCameraConstituentCameraDevices(
  5.     logicalCamera, &physicalCameras, &size);
  6. if (ret == CAMERA_OK && size > 0) {
  7.     for (uint32_t i = 0; i < size; i++) {
  8.         float focalLength = 0.0f;
  9.         OH_CameraDevice_GetLensFocalLength(physicalCameras[i], &focalLength);
  10.         // ...使用提取出的物理参数推入渲染器...
  11.     }
  12. }
  13. // 【绝对关键】用完后手动释放底层分配的内存
  14. OH_CameraDevice_DeleteConstituentCameraDevices(logicalCamera, physicalCameras, size);
复制代码

这段代码里最值得关注的是内存释放。OH_CameraDevice_GetLogicalCameraConstituentCameraDevices在底层会动态分配物理摄像头对象集合,这是当前Camera Kit C API中唯一一个要求调用方在使用完毕后必须主动释放的接口。如果开发者在渲染循环里每帧都去获取而不释放,应用会在极短时间内内存暴涨,最终被系统强杀。

同时,C API对空指针零容忍。像OH_CameraDevice_GetLensDistortion这类接口,传入未正确初始化的二级指针float**,会直接导致Core Dump。因此在使用前务必确认指针已经分配好内存,并检查每一步的返回值。

另外需要注意一个限制:虽然通过C API可以拿到物理摄像头指针,但不能拿这个物理设备对象去调用OH_CameraInput_Create来创建独立的数据流。底层视频流仍然要由顶层的逻辑相机作为Input对象整体调度,物理设备只是用于读取参数和标定数据。

如果要在ArkTS侧做一个可视化的演示,可以用NAPI调用模拟底层C++回调时序,在界面上看到每次函数的返回状态码和指针操作日志。比如在工程里新增一个CameraNativeDemo页面,模拟从NAPI发送指令到C++层,再由C++层调用OH_CameraDevice系列函数的过程,并在页面上显示CAMERA_OK、指针数组大小、焦距数据、传感器尺寸以及最后的内存释放日志。这样能在不开真机的情况下先验证调用链路的完整性。

这次C API体系的补全,等于为重度图形应用、游戏引擎以及AI计算机视觉场景打开了一条直接操作相机底层数据的通道。通过原生指针级别的交互,省去了跨语言通信的额外开销,也让逻辑相机背后的物理镜头簇变得可编程。不过,能力越底层,对内存管理的要求越严格。建议所有接入的团队都把OH_CameraDevice_DeleteConstituentCameraDevices的调用封装成RAII或统一的释放工具,避免每个业务方各自维护造成泄漏。
回复

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: 鸿蒙6.1.1 Camera Kit C API逻辑相机解构与内存释放实

楼主的分享很干货,尤其是内存释放那块确实关键——渲染循环里漏一次释放就是灾难。RAII封装建议非常认同,之前踩过类似native内存管理的坑,统一封装成作用域对象能省心很多。 想追问一个细节:`OH_CameraDevice_GetLensFocalLength`这类接口,传入的`physicalCameras`是刚从数组里取出来的单个元素指针,伪代码里写的是`&focalLength`,这个应该没问题。但像`GetLensDistortion`这种二级指针参数的接口,正确用法是不是先获取到一个`float*`指针,再传它的地址?有没有官方推荐的失败回滚流程?
回复 支持 反对

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: 鸿蒙6.1.1 Camera Kit C API逻辑相机解构与内存释放实

这篇文章写得很扎实,把 Camera Kit C API 在 Native 层解构逻辑相机的思路讲得非常清楚。尤其是内存释放那段,确实是这类底层接口最容易踩坑的地方,每帧获取不释放导致内存暴涨的场景太真实了。用 RAII 封装释放逻辑的建议也很实用,能在团队协作里省掉不少排查泄漏的时间。另外“物理设备只能读参数、不能独立建流”这个限制点也很关键,避免后面有人误用走了弯路。整体看完对这套 Native 链路有了更完整的认识,期待后续还能有更多类似底层的实战分享。
回复 支持 反对

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: 鸿蒙6.1.1 Camera Kit C API逻辑相机解构与内存释放实

感谢楼主的详细拆解,正好最近在折腾Camera Kit的Native层接入,这篇太及时了。特别是关于 `OH_CameraDevice_DeleteConstituentCameraDevices` 必须手动释放这一点,确实是个大坑,如果不做RAII封装,渲染循环里很容易就炸了。 想追问一下:逻辑相机拆出来的物理相机参数,比如焦距、畸变矩阵,实际使用中是怎么和变焦联动对应的?因为逻辑相机本身是抽象出来的,底层物理镜头切换和这些参数的关系,有没有推荐的映射策略?还是说需要自己根据焦距范围去匹配当前激活的物理摄像头?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-8-12 13:05 , Processed in 0.023951 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部