Multi-Camera Concurrent Mode (C/C++)
Starting from API version 18, devices support multi-camera concurrent mode, enabling applications to use both front and rear cameras simultaneously for capturing photos and recording videos.
NOTE
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.
- Flash
- Exposure
- Zoom
- Exposure compensation
- Focus
- Stabilization
- Color space
How to Develop
Read Camera for the API reference.
-
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 <string> #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" -
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) -
Call OH_CameraManager_GetCameraDevice to obtain the front and rear cameras.
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]); } -
Obtain the corresponding concurrent capability set.
Call OH_CameraManager_GetCameraConcurrentInfos to obtain an array of Camera_ConcurrentInfo objects, each of which includes the modes and output capabilities supported by the camera under the corresponding concurrent mode.
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; } } -
Create a PreviewOutput object based on the concurrency 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; } } -
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 concurrency 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; } } -
Implement the session flow. Configure the corresponding camera input stream Camera_Input and output stream. The following uses the preview output stream Camera_PreviewOutput as an example.
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; } -
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); }