目录

Multi-Camera Concurrent Mode (C/C++)

Starting from API version 18, multi-camera concurrent mode is supported, which allows an app to simultaneously open the front and rear cameras for preview and video recording. (Simultaneous photo capture with both front and rear cameras is coming soon.)

Operating both cameras at the same time imposes significant restrictions on available features. The current implementation supports seven core functions, as listed below. When using multi-camera concurrent mode, avoid accessing or enabling any capabilities beyond them.

  1. Flash
  2. Exposure
  3. Zoom
  4. Exposure compensation
  5. Focus
  6. Stabilization
  7. Color space

How to Develop

Read Camera for the API reference.

  1. Import the NDK, which provides camera-related properties and methods.

    #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"
  2. Link the dynamic libraries in the CMake script.

    target_link_libraries(entry PUBLIC
       libohcamera.so
       libace_napi.z.so
       libnative_buffer.so
       libhilog_ndk.z.so
       librawfile.z.so)
  3. Obtain the corresponding front camera and rear camera through the OH_CameraManager_GetCameraDevice method. If the API returns CAMERA_SERVICE_FATAL_ERROR, it indicates, based on the configuration in the example, that the current device does not support the default camera type at the specified position (front or rear), and multi-camera concurrent mode cannot be implemented.

    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;
        }
    
        // Obtain the rear camera.
        ret = OH_CameraManager_GetCameraDevice(cameraManager, Camera_Position::CAMERA_POSITION_BACK, Camera_Type::CAMERA_TYPE_DEFAULT, &cameras[0]);
    
        // Obtain the front camera.
        ret = OH_CameraManager_GetCameraDevice(cameraManager, Camera_Position::CAMERA_POSITION_FRONT, Camera_Type::CAMERA_TYPE_DEFAULT, &cameras[1]);
    }
  4. Obtain the corresponding concurrent capability set. Use the OH_CameraManager_GetCameraConcurrentInfos method to obtain the Camera_ConcurrentInfo camera concurrent capability set object array. The array contains the camera modes and camera output capabilities supported by the simultaneously opened front and rear cameras in the specified multi-camera concurrent mode. In the concurrent camera opening scenario, the configured mode and output capabilities must fall within the scope of the concurrent capability set.

    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. Create a PreviewOutput object based on the concurrent capability set.

    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. Open the camera. Call OH_CameraInput_OpenConcurrentCameras to open the specified camera in multi-camera concurrent mode. Before using this API, check whether the camera supports concurrent capabilities and call OH_CameraManager_GetCameraConcurrentInfos to obtain the concurrent capability set in the multi-camera concurrent mode. Do not use OH_CameraInput_OpenConcurrentCameras without querying the concurrent capability set, as this will result in camera opening failure.

    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;
        }
        // The current version supports opening the camera only in CAMERA_CONCURRENT_TYPE_LIMITED_CAPABILITY mode.
        ret = OH_CameraInput_OpenConcurrentCameras(cameraInput, Camera_ConcurrentType::CAMERA_CONCURRENT_TYPE_LIMITED_CAPABILITY);
        if (ret != CAMERA_OK) {
            return;
        }
    }
  7. Implement the session flow. Configure the corresponding camera input stream Camera_Input and the required camera output streams. This example uses the preview output stream Camera_PreviewOutput.

    void SessionFlowFn(Camera_CaptureSession *captureSession, Camera_Input *cameraInput, Camera_PreviewOutput *previewOutput)
    {
        // Start configuration for the session.
        Camera_ErrorCode ret = OH_CaptureSession_BeginConfig(captureSession);
    
        // Add the camera input stream to the session.
        ret = OH_CaptureSession_AddInput(captureSession, cameraInput);
    
        // Add the preview output stream to the session.
        ret = OH_CaptureSession_AddPreviewOutput(captureSession, previewOutput);
     
        // Commit the configuration.
        ret = OH_CaptureSession_CommitConfig(captureSession);
    
        // Start the session.
        ret = OH_CaptureSession_Start(captureSession);
     
        return;
    }
  8. The following provides examples of configurable capabilities for front and rear cameras in multi-camera concurrent mode. (Currently, only the seven core functions listed at the beginning of this document are supported.)

    // Flash.
    void HasFlashFn(uint32_t mode, Camera_CaptureSession *captureSession)
    {
        Camera_FlashMode flashMode = static_cast<Camera_FlashMode>(mode);
        // Check whether the camera device has flash.
        bool hasFlash = false;
        Camera_ErrorCode ret = OH_CaptureSession_HasFlash(captureSession, &hasFlash);
        if (captureSession == nullptr || ret != CAMERA_OK || !hasFlash) {
            return;
        }
    
        // Check whether a flash mode is supported.
        bool isSupported = false;
       ret = OH_CaptureSession_IsFlashModeSupported(captureSession, flashMode, &isSupported);
        if (ret != CAMERA_OK || !isSupported) {
            return;
        }
    
        // Set the flash mode.
        ret = OH_CaptureSession_SetFlashMode(captureSession, flashMode);
        if (ret != CAMERA_OK) {
            return;
        }
    
        // Obtain the flash mode in use.
        ret = OH_CaptureSession_GetFlashMode(captureSession, &flashMode);
     }
    
    // Exposure
    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);
    }