多摄同开(C/C++)
===========

从API version 18开始支持多摄同开，即应用同时开启前置/后置相机进行预览和录像（前置/后置相机同时拍照功能待开放）。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/e7/v3/76bVJtdZTaq4m6gqqwnA_w/note_3.0-zh-cn.png?HW-CC-KV=V1&HW-CC-Date=20260612T073516Z&HW-CC-Expire=86400&HW-CC-Sign=3AD93FD71D586EA12CDDDD217CFBD627A91532FF875BBD8BA28AB2E90A19A237)

由于多摄同开需要前置/后置相机同时运行，所以对于相机功能有较大限制。当前版本仅支持以下七项基础功能，请勿对多摄同开开启的相机进行超出以下七种基础功能范围之外的查询、设置和使能。

1.  闪光灯。
2.  曝光。
3.  变焦。
4.  曝光补偿。
5.  对焦。
6.  防抖。
7.  色彩空间。

#### 开发步骤

详细的API说明请参考[Camera](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-oh-camera)。

1.  导入NDK接口，接口中提供了相机相关的属性和方法，导入方法如下。
    
    #include <cstdint>
    #include <unistd.h>
    #include <string>
    #include <thread>
    #include <cstdio>
    #include <fcntl.h>
    #include <map>
    #include <vector>
    #include <native\_buffer/native\_buffer.h>
    #include "iostream"
    #include "mutex"
    #include "hilog/log.h"
    #include "ohcamera/camera.h"
    #include "ohcamera/camera\_input.h"
    #include "ohcamera/capture\_session.h"
    #include "ohcamera/photo\_output.h"
    #include "ohcamera/preview\_output.h"
    #include "ohcamera/video\_output.h"
    #include "napi/native\_api.h"
    #include "ohcamera/camera\_manager.h"
    #include "common/log\_common.h"
    
2.  在CMake脚本中链接相关动态库。
    
    target\_link\_libraries(entry PUBLIC
       libohcamera.so
       libace\_napi.z.so
       libnative\_buffer.so
       libhilog\_ndk.z.so
       librawfile.z.so)
    
3.  通过[OH\_CameraManager\_GetCameraDevice](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-camera-manager-h#oh_cameramanager_getcameradevice)方法获取对应的前置相机和后置相机。如果接口返回值为CAMERA\_SERVICE\_FATAL\_ERROR，基于示例中的配置信息，表示当前设备不支持指定位置（前置/后置）的默认类型相机，无法实现多摄同开功能。
    
    void GetSupportedCameras(Camera\_Manager \*cameraManager)
    {
        Camera\_Device \*cameras;
        uint32\_t size = 0;
        Camera\_ErrorCode ret = OH\_CameraManager\_GetSupportedCameras(cameraManager, &cameras, &size);
        if (cameras == nullptr || &size == nullptr || ret != CAMERA\_OK) {
            return;
        }
    
        // 获取后置相机。
        ret = OH\_CameraManager\_GetCameraDevice(cameraManager, Camera\_Position::CAMERA\_POSITION\_BACK, Camera\_Type::CAMERA\_TYPE\_DEFAULT, &cameras\[0\]);
    
        // 获取前置相机。
        ret = OH\_CameraManager\_GetCameraDevice(cameraManager, Camera\_Position::CAMERA\_POSITION\_FRONT, Camera\_Type::CAMERA\_TYPE\_DEFAULT, &cameras\[1\]);
    }
    
4.  获取对应的并发能力集。通过[OH\_CameraManager\_GetCameraConcurrentInfos](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-camera-manager-h#oh_cameramanager_getcameraconcurrentinfos)方法，获取[Camera\_ConcurrentInfo](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-oh-camera-camera-concurrentinfo)相机并发能力集对象数组，数组包含了前置和后置同时开启的相机在指定多摄同开模式下支持的相机模式和相机输出能力，**在多摄同开场景下设置的模式和输出能力必须在并发能力集的范围之内**。
    
    void GetSupportedOutputCapability(Camera\_Manager \*cameraManager, Camera\_Device \*cameras)
    {
        Camera\_ConcurrentInfo\* cameraConcurrentInfo;
        uint32\_t infoSize = 0;
        Camera\_ErrorCode ret = OH\_CameraManager\_GetCameraConcurrentInfos(cameraManager, cameras, 2, &cameraConcurrentInfo, &infoSize);
        if (cameraConcurrentInfo == nullptr || cameraConcurrentInfo->outputCapabilities == nullptr
            || cameraConcurrentInfo->outputCapabilities->previewProfiles == nullptr || ret != CAMERA\_OK) {
            return;
       }
    }
    
5.  对应并发能力集创建PreviewOutput对象。
    
    void CreatePreviewOutput(Camera\_Manager \*cameraManager, Camera\_ConcurrentInfo\* cameraConcurrentInfo, char\* previewSurfaceId)
    {
        Camera\_Profile \*profile = cameraConcurrentInfo->outputCapabilities->previewProfiles\[0\];
        if (profile == nullptr) {
            return;
        }
        Camera\_PreviewOutput \*previewOutput;
        Camera\_ErrorCode ret = OH\_CameraManager\_CreatePreviewOutput(cameraManager, profile, previewSurfaceId, &previewOutput);
        if (previewOutput == nullptr || ret != CAMERA\_OK) {
            return;
        }
    }
    
6.  打开相机。通过[OH\_CameraInput\_OpenConcurrentCameras](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-camera-input-h#oh_camerainput_openconcurrentcameras)以并发状态打开指定相机，在使用该接口前，请先查询接口是否支持并发能力集，并优先调用[OH\_CameraManager\_GetCameraConcurrentInfos](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-camera-manager-h#oh_cameramanager_getcameraconcurrentinfos)方法，获取多摄同开状态下的相机并发能力集。请勿在未查询并发能力集的情况下使用[OH\_CameraInput\_OpenConcurrentCameras](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-camera-input-h#oh_camerainput_openconcurrentcameras)，否则会导致打开相机失败。
    
    void CameraInputOpen(Camera\_Manager \*cameraManager, Camera\_Device \*cameras)
    {
        Camera\_Input \*cameraInput;
        Camera\_ErrorCode ret = OH\_CameraManager\_CreateCameraInput(cameraManager, &cameras\[0\], &cameraInput);
        if (cameraInput == nullptr || ret != CAMERA\_OK) {
            return;
        }
        // 当前版本只支持CAMERA\_CONCURRENT\_TYPE\_LIMITED\_CAPABILITY模式并发打开。
        ret = OH\_CameraInput\_OpenConcurrentCameras(cameraInput, Camera\_ConcurrentType::CAMERA\_CONCURRENT\_TYPE\_LIMITED\_CAPABILITY);
        if (ret != CAMERA\_OK) {
            return;
        }
    }
    
7.  会话流程。配置对应的相机输入流[Camera\_Input](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-oh-camera-camera-input)和需要的相机输出流，此处以预览输出流[Camera\_PreviewOutput](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-oh-camera-camera-previewoutput)为例 。
    
    void SessionFlowFn(Camera\_CaptureSession \*captureSession, Camera\_Input \*cameraInput, Camera\_PreviewOutput \*previewOutput)
    {
        // 开始配置会话。
        Camera\_ErrorCode ret = OH\_CaptureSession\_BeginConfig(captureSession);
    
        // 向会话中添加相机输入流。
        ret = OH\_CaptureSession\_AddInput(captureSession, cameraInput);
    
        // 向会话中添加预览输出流。
        ret = OH\_CaptureSession\_AddPreviewOutput(captureSession, previewOutput);
     
        // 提交配置信息。
        ret = OH\_CaptureSession\_CommitConfig(captureSession);
    
        // 开始会话。
        ret = OH\_CaptureSession\_Start(captureSession);
     
        return;
    }
    
8.  在多摄同开状态下，前/后置相机可配置的能力示例如下（当前版本仅支持本文开头部分所示的七项基础功能）。
    
    // 闪光灯能力。
    void HasFlashFn(uint32\_t mode, Camera\_CaptureSession \*captureSession)
    {
        Camera\_FlashMode flashMode = static\_cast<Camera\_FlashMode>(mode);
        // 检查闪光灯。
        bool hasFlash = false;
        Camera\_ErrorCode ret = OH\_CaptureSession\_HasFlash(captureSession, &hasFlash);
        if (captureSession == nullptr || ret != CAMERA\_OK || !hasFlash) {
            return;
        }
    
        // 检查闪光灯模式是否支持。
        bool isSupported = false;
       ret = OH\_CaptureSession\_IsFlashModeSupported(captureSession, flashMode, &isSupported);
        if (ret != CAMERA\_OK || !isSupported) {
            return;
        }
    
        // 设置闪光灯模式。
        ret = OH\_CaptureSession\_SetFlashMode(captureSession, flashMode);
        if (ret != CAMERA\_OK) {
            return;
        }
    
        // 获取当前设备的闪光灯模式。
        ret = OH\_CaptureSession\_GetFlashMode(captureSession, &flashMode);
     }
    
    // 曝光。
    void IsExposureModeSupportedFn(uint32\_t mode, Camera\_CaptureSession \*captureSession)
    {
        Camera\_ExposureMode exposureMode = static\_cast<Camera\_ExposureMode>(mode);
        bool isExposureModeSupported = false;
        Camera\_ErrorCode ret = OH\_CaptureSession\_IsExposureModeSupported(captureSession, exposureMode, &isExposureModeSupported);
        if (&isExposureModeSupported == nullptr || ret != CAMERA\_OK) {
            return;
        }
        ret = OH\_CaptureSession\_SetExposureMode(captureSession, exposureMode);
        if (ret != CAMERA\_OK) {
            return;
        }
        ret = OH\_CaptureSession\_GetExposureMode(captureSession, &exposureMode);
    }