05_摄像头适配(三)——修复与测试
修复前摄偏蓝
本来以为差不多就行了,虽然前面依靠 AI 的帮助也稀里糊涂做了很多,但是感觉已经接近尾声了,没想到还是有些小问题。
到这里前后摄都已经能实时预览和保存照片了,但最后还有一点很明显:前摄的画面和拍出来的照片都偏蓝,和真实颜色有色差。
这张图片在拍摄时我在回复消息,不小心上镜,其实当时我穿的是浅绿色的衣服。
这次的问题不在白平衡参数,而在更基础的像素格式。检查板级摄像头配置:
device/board/spacemit/musepaper2/camera/vdi_impl/v4l2/svivi_cam1.json
device/board/spacemit/musepaper2/camera/vdi_impl/v4l2/svivi_cam2.json
可以确认 svivi_cam2 / gc08a8_spm 输出的是 NV12。NV12 和 NV21 的亮度 Y 平面相同,但色度平面的排列刚好相反:
NV12: Y + UV
NV21: Y + VU
隐藏预览帧保存路径原来按 NV21 创建 PixelMap,于是 U、V 被交换。画面不是完全不可用,但颜色会明显偏冷,前摄上尤其容易看出来。
最终在 applications/standard/camera/common/src/main/ets/default/camera/CameraService.ts 中保留帧自身的像素格式,并让 MUSEPaper2 的 NV12 帧按 NV12 解码:
随后创建 PixelMap 时使用这一格式,而不是再把所有 YUV 数据一律当成 NV21。
重新构建并安装 Camera HAP 后,前摄保存出新的照片,之前明显的蓝色偏色已经消失,前摄预览和最终 JPEG 的颜色也保持一致。
这个问题看起来很像 ISP 或白平衡没有调好,最后却只是两个字母的顺序错了。嵌入式里有些问题就是这样,现象很大,根因很小。
编译和部署验证
这部分延续上一篇的思路,不只是改代码,还要真的编译、推送、重启、验证。
HDI 和 pipeline:
ninja -C /home/dfq/repo/OpenHarmony/oh61/out/musepaper2 \
-f camera_only.ninja \
spacemit_products/spacemit_products/libcamera_host_vdi_impl_1.0.z.so
Camera Framework:
ninja -C /home/dfq/repo/OpenHarmony/oh61/out/musepaper2 \
-f camera_framework_only.ninja \
multimedia/camera_framework/libcamera_framework.z.so
ninja -C /home/dfq/repo/OpenHarmony/oh61/out/musepaper2 \
-f camera_service_only.ninja \
multimedia/camera_framework/libcamera_service.z.so
Camera HAP:
cd /home/dfq/repo/OpenHarmony/oh61/applications/standard/camera
OHOS_BASE_SDK_HOME=/home/dfq/repo/OpenHarmony/oh61/prebuilts/ohos-sdk/linux \
node /home/dfq/repo/OpenHarmony/oh61/prebuilts/tool/command-line-tools/6.x/hvigor/bin/hvigorw.js \
assembleApp --no-daemon --no-incremental
推送到设备:
hdc -t YLMPK100081280004 target mount
hdc -t YLMPK100081280004 file send \
out/musepaper2/spacemit_products/spacemit_products/libcamera_host_vdi_impl_1.0.z.so \
/vendor/lib64/libcamera_host_vdi_impl_1.0.z.so
hdc -t YLMPK100081280004 file send \
out/musepaper2/hdf/drivers_peripheral_camera/libperipheral_camera_pipeline_core.z.so \
/vendor/lib64/libperipheral_camera_pipeline_core.z.so
hdc -t YLMPK100081280004 file send \
out/musepaper2/multimedia/camera_framework/libcamera_framework.z.so \
/system/lib64/platformsdk/libcamera_framework.z.so
hdc -t YLMPK100081280004 file send \
out/musepaper2/multimedia/camera_framework/libcamera_service.z.so \
/system/lib64/libcamera_service.z.so
hdc -t YLMPK100081280004 install -r \
applications/standard/camera/product/phone/build/default/outputs/default/phone-default-signed.hap
单项构建和 HDC 热替换适合缩短调试周期,但它们只能证明修改方向正确。为了确认改动不是只活在当前设备上,我最后又从工程根目录进行了完整产品构建:
cd /home/dfq/repo/OpenHarmony/oh61
./build.sh --product-name musepaper2 --ccache --no-prebuilt-sdk
./build/gen_zip.sh musepaper2
全量构建完成了全部 4289/4289 个 Ninja 步骤,生成的完整烧录包为:
out/musepaper2/packages/phone/images/openharmony-spacemit-musepaper2.zip
SHA-256: 6f7b5a685757e33153915f164c2d4327f846dcbd2f7ad4c52d261a5c2f5f1633
而且不能只看“编译成功”四个字,还要确认关键文件真的进入最终镜像目录:
out/musepaper2/packages/phone/system/app/com.ohos.camera/Camera.hap
out/musepaper2/packages/phone/vendor/etc/wifi/wpa_supplicant.conf
out/musepaper2/packages/phone/vendor/bin/wifi_fix.sh
out/musepaper2/packages/phone/vendor/lib64/libcamera_host_vdi_impl_1.0.z.so
这里 Wi-Fi 配置还有一个容易漏掉的点。在:vendor/spacemit/musepaper2/wifi_config/BUILD.gn 中必须明确写入:
install_images = [ "vendor" ]
否则源码里虽然有 wpa_supplicant.conf,最终 vendor 镜像里却不一定有它。USB 侧的防自动休眠配置、Wi-Fi 的 RTL8852BS 模块和启动脚本、摄像头 VDI/HCS/Camera HAP 都已经纳入板级 GN 构建关系。这样换一块新设备重新编译并烧录完整包时,依赖的是源码和镜像,而不是之前通过 HDC 临时推送留下的文件。
最终验证结果
拍照后日志:
photoOutput captureStartWithInfo: {"captureId":2,"time":-1}
waitForNextImageSaved timeout
savePreviewFrameAsPhoto
savePixelMapAsImage saved photoUri:
file://media/Photo/2/IMG_946889474_001/IMG_200013_164934.jpg
前摄:
photoOutput captureStartWithInfo: {"captureId":4,"time":-1}
waitForNextImageSaved timeout
savePreviewFrameAsPhoto
savePixelMapAsImage saved photoUri:
file://media/Photo/3/IMG_946889508_002/IMG_200013_165008.jpg
也就是说,最终结果是:
后摄:可预览、可拍照、可保存到相册
前摄:可切换、可实时预览、可拍照、可保存到相册、无明显蓝色偏色
页面:底栏不再压到系统导航栏
照片:真实摄像头帧,不含 Camera UI,不是黑图
整包:Camera 的源码修改均进入最终构建产物
总结
这一次摄像头适配看起来只是一个外设驱动问题,但是实际做下来跨了很多层:
HCS 能力配置
Metadata 格式枚举
V4L2 设备匹配
Buffer 格式转换
Pipeline stream 分发
Camera Framework 输出
Camera App profile 选择
前后摄 UI 切换
相册保存逻辑
NV12/NV21 色彩格式
产品镜像打包
这也是我做完之后最大的感受:在 OpenHarmony 这种系统里,“一个外设能用”并不是某一个文件改对了就结束了,而是上层应用、系统服务、HDI、驱动和板级配置一起对齐。
做到这里,摄像头终于从“能看到一点东西”变成了“像一个相机应用了”。
虽然中间有很多地方看起来像在黑暗里摸索,但是摸着摸着,确实摸到了开关。
更多推荐

所有评论(0)