MUSEPaper2 摄像头适配阶段性进展记录——从设备识别到完整拍照链路打通

在前期完成 OpenHarmony 系统基础适配后,我们开始推进 MUSEPaper2 平台上的摄像头功能适配工作。摄像头适配并不是简单地让 Camera App 能够打开设备,而是需要保证从底层硬件、V4L2 驱动、Camera HDI、Framework 到应用层之间的数据链路完整贯通。

本阶段主要完成了以下工作:

  1. 双摄设备识别与逻辑映射;

  2. V4L2 摄像头节点适配;

  3. OpenHarmony Camera 能力配置;

  4. 前后摄切换功能;

  5. 预览与拍照保存流程;

  6. 摄像头图像格式修正;

  7. 最终编译部署与整包验证。

最终实现 MUSEPaper2 上前后摄正常切换、实时预览、拍照保存,并解决前摄颜色异常问题。

一、摄像头设备识别与底层链路确认

刚开始进行适配时,Camera 应用打开后无法正常显示画面,因此首先需要确认系统是否真正识别到了摄像头设备。

OpenHarmony 中可以通过:

hidumper -s CameraService

查看 CameraService 当前状态。

检查后发现系统已经能够识别两个摄像头:

Camera ID: lcam001
Camera Position: Back

Camera ID: lcam002
Camera Position: Front

说明底层设备已经被系统发现,但此时系统只是知道存在两个 camera,并不知道它们在应用层应该对应前摄还是后摄。

因此首先在 V4L2 source node 中补充摄像头逻辑映射:

lcam001 -> CAMERA_FIRST
lcam002 -> CAMERA_SECOND

修改位置:

drivers/peripheral/camera/vdi_base/common/adapter/platform/v4l2/src/pipeline_core/nodes/v4l2_source_node/v4l2_source_node.cpp

通过这一阶段修改,使 OpenHarmony Camera 框架能够正确区分两个摄像头设备。

二、V4L2 与 OpenHarmony Camera 格式适配

完成设备识别后,下一步需要解决摄像头数据真正进入 Camera Pipeline 的问题。

MUSEPaper2 使用 V4L2 视频设备,而 OpenHarmony Camera Framework 使用自身定义的 Camera Format,两者格式并不是完全一致。

V4L2:

V4L2_PIX_FMT_NV12
V4L2_PIX_FMT_NV21

OpenHarmony:

CAMERA_FORMAT_YCBCR_420_SP
CAMERA_FORMAT_YCRCB_420_SP
CAMERA_FORMAT_BLOB

如果格式没有正确转换,会出现设备存在但是预览黑屏、stream 创建失败等问题。

因此补充格式映射:

CAMERA_FORMAT_YCBCR_420_SP -> V4L2_PIX_FMT_NV12

CAMERA_FORMAT_YCRCB_420_SP -> V4L2_PIX_FMT_NV21

CAMERA_FORMAT_BLOB -> V4L2_PIX_FMT_NV12

同时针对 MUSEPaper2 的 V4L2 设备名称增加匹配:

spacemit vivi
        |
        ↓
svivi-vid-cap-00


spacemit vivi2
        |
        ↓
svivi-vid-cap-01

完成后,摄像头从“系统能看到设备”进一步变成“能够正常输出图像数据”。

三、补充 Camera 能力配置,让系统正确认识摄像头能力

OpenHarmony Camera App 在启动时,并不会直接随意创建预览和拍照流,而是需要读取底层提供的 Camera metadata 和 HCS 配置。

因此需要在:

device/board/spacemit/musepaper2/hdf_config/uhdf/camera/hdi_impl/camera_host_config.hcs

中补充摄像头能力信息。

增加支持:

640x480

1280x960

1280x720

720x720

1920x1080

并暴露:

YCBCR_420_SP   预览格式

JPEG           拍照格式

同时修改:

drivers/peripheral/camera/vdi_base/v4l2/include/camera_host/metadata_enum_map.h

完善 metadata 映射。

完成后,通过:

hidumper -s CameraService

查看:

Basic Stream Info Size: 10

说明系统已经能够读取两个摄像头完整能力信息。

四、Camera 应用层适配,实现前后摄切换

底层识别完成后,还需要让 Camera 应用真正支持两个摄像头切换。

由于 MUSEPaper2 是 RISC-V 平台,但目标效果需要使用手机 Camera UI,因此调整产品设备类型:

const.product.devicetype="phone"

使 Camera App 使用 phone 模式界面。

同时修改应用层:

applications/standard/camera/common/src/main/ets/default/camera/CameraService.ts

applications/standard/camera/common/src/main/ets/default/function/CameraBasicFunction.ts

applications/standard/camera/product/phone/src/main/ets/pages/FootBar.ets

主要完成:

  1. 根据实际 camera 数量更新能力;

  2. 显示摄像头切换按钮;

  3. 修正按钮点击区域;

  4. 支持 lcam001/lcam002 切换。

最终日志能够看到:

createCameraInput id = lcam002

说明切换操作已经真正进入前摄设备,而不是只有 UI 状态变化。

五、拍照保存功能适配

在完成预览和切换后,继续处理拍照功能。

当时的现象是:

  • 快门按钮正常响应;

  • CameraService 收到拍照请求;

  • 但是照片无法进入相册。

经过分析发现问题出现在 still capture 数据链路。

拍照流使用:

CAMERA_FORMAT_BLOB

但是底层部分路径没有正确识别 JPEG 编码类型。

因此在:

drivers/peripheral/camera/vdi_base/v4l2/src/stream_operator/stream_operator_vdi_impl.cpp

中补充:

STILL_CAPTURE or BLOB

        ↓

ENCODE_TYPE_JPEG

让拍照流进入正确 JPEG 处理流程。


遇到的关键问题:如何保证保存的是真实摄像头画面

在测试过程中发现,直接使用屏幕截图作为照片虽然可以看到画面,但是保存结果可能包含:

  • Camera UI 按钮;

  • 切换图标;

  • 黑屏情况。

这个问题我们和组长进行了讨论,经过分析,问题本质是:截图获取的是屏幕合成结果,而不是摄像头原始数据。因此调整方案:增加隐藏 PreviewOutput:

Camera Preview

        ↓

ImageReceiver

        ↓

缓存真实摄像头帧

拍照时优先走标准 PhotoOutput;如果 JPEG 数据没有及时返回,则使用缓存的真实预览帧生成照片。处理流程:

Preview Frame

      ↓

PixelMap

      ↓

JPEG编码

      ↓

Media Library

      ↓

保存相册

这样保存出的照片来自真实摄像头数据,而不是 UI 截图。

六、解决前摄颜色偏蓝问题

完成拍照后,又发现前摄存在明显颜色偏差:

  • 预览颜色偏蓝;

  • 保存照片颜色异常。

开始判断可能是 ISP 或白平衡问题,但进一步检查发现原因在 YUV 格式。

配置文件:

device/board/spacemit/musepaper2/camera/vdi_impl/v4l2/svivi_cam2.json

确认前摄输出:

NV12

而原来的保存逻辑按照:

NV21

解析。

两者区别:

NV12:

Y + UV


NV21:

Y + VU

由于 U/V 顺序相反,导致颜色出现偏冷。

这个问题在调试过程中我们和组长进行了沟通,确认需要从数据格式转换方向排查,而不是继续调整白平衡参数。

最终修改:

applications/standard/camera/common/src/main/ets/default/camera/CameraService.ts

根据实际帧格式创建 PixelMap:

NV12 frame

↓

NV12 decode

而不是统一按照 NV21 处理。

重新编译安装后:

  • 前摄预览恢复正常;

  • 保存照片颜色恢复;

  • 前后摄效果一致。


七、编译部署与最终验证

完成修改后,对相关模块进行重新编译:

包括:

  • Camera HDI

  • Pipeline

  • Camera Framework

  • Camera Service

  • Camera HAP

并通过 HDC 推送到设备验证。

最后进行完整产品构建:

./build.sh --product-name musepaper2

确认修改内容进入最终镜像。

最终效果

目前 MUSEPaper2 摄像头适配达到:系统识别双摄、前后摄正常切换、Camera App 正常打开、实时预览、拍照保存到相册、保存图片来自真实摄像头数据、修复前摄偏蓝问题、修改内容进入完整系统镜像。

总结

本阶段摄像头适配过程中,实际涉及的不只是摄像头驱动本身,而是一整套 OpenHarmony Camera 链路:

V4L2设备

↓

Camera HDI

↓

Pipeline

↓

Camera Framework

↓

Camera App

其中任何一层配置不匹配,都可能导致最终表现异常。

通过本次适配,我们完成了 MUSEPaper2 平台从“识别摄像头”到“完整使用摄像头”的过程,也进一步理解了 OpenHarmony 外设适配中硬件、系统服务和应用之间的协同关系。

这次工作的重点不仅是让摄像头运行起来,更是建立了一套从底层定位问题到系统级验证的适配流程。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐