1# Photo Capture Sample (C/C++) 2 3Before developing a camera application, request permissions by following the instructions provided in [Camera Development Preparations](camera-preparation.md). 4 5This topic provides sample code that covers the complete photo capture process and the API calling sequence. For details about a single process (such as device input, session management, and photo capture), see the corresponding C/C++ development guide links provided in [Camera Development Preparations](camera-preparation.md). 6 7## Development Process 8 9After obtaining the output stream capabilities supported by the camera, create a photo stream. The development process is as follows: 10 11 12 13## Sample Code 14 151. Link the dynamic library in the CMake script. 16 ```txt 17 target_link_libraries(entry PUBLIC 18 libace_napi.z.so 19 libhilog_ndk.z.so 20 libnative_buffer.so 21 libohcamera.so 22 libohimage.so 23 libohfileuri.so 24 ) 25 ``` 26 272. Import the NDK APIs on the C++ side, and perform photo capture based on the surface ID passed in. 28 ```c++ 29 #include "camera_manager.h" 30 #include "hilog/log.h" 31 #include "ohcamera/camera.h" 32 #include "ohcamera/camera_input.h" 33 #include "ohcamera/capture_session.h" 34 #include "ohcamera/photo_output.h" 35 #include "ohcamera/preview_output.h" 36 #include "ohcamera/video_output.h" 37 #include "ohcamera/camera_manager.h" 38 39 void CaptureSessionOnFocusStateChange(Camera_CaptureSession* session, Camera_FocusState focusState) 40 { 41 OH_LOG_INFO(LOG_APP, "CaptureSessionOnFocusStateChange"); 42 } 43 44 void CaptureSessionOnError(Camera_CaptureSession* session, Camera_ErrorCode errorCode) 45 { 46 OH_LOG_INFO(LOG_APP, "CaptureSessionOnError = %{public}d", errorCode); 47 } 48 49 CaptureSession_Callbacks* GetCaptureSessionRegister(void) 50 { 51 static CaptureSession_Callbacks captureSessionCallbacks = { 52 .onFocusStateChange = CaptureSessionOnFocusStateChange, 53 .onError = CaptureSessionOnError 54 }; 55 return &captureSessionCallbacks; 56 } 57 58 void PreviewOutputOnFrameStart(Camera_PreviewOutput* previewOutput) 59 { 60 OH_LOG_INFO(LOG_APP, "PreviewOutputOnFrameStart"); 61 } 62 63 void PreviewOutputOnFrameEnd(Camera_PreviewOutput* previewOutput, int32_t frameCount) 64 { 65 OH_LOG_INFO(LOG_APP, "PreviewOutputOnFrameEnd = %{public}d", frameCount); 66 } 67 68 void PreviewOutputOnError(Camera_PreviewOutput* previewOutput, Camera_ErrorCode errorCode) 69 { 70 OH_LOG_INFO(LOG_APP, "PreviewOutputOnError = %{public}d", errorCode); 71 } 72 73 PreviewOutput_Callbacks* GetPreviewOutputListener(void) 74 { 75 static PreviewOutput_Callbacks previewOutputListener = { 76 .onFrameStart = PreviewOutputOnFrameStart, 77 .onFrameEnd = PreviewOutputOnFrameEnd, 78 .onError = PreviewOutputOnError 79 }; 80 return &previewOutputListener; 81 } 82 83 void OnCameraInputError(const Camera_Input* cameraInput, Camera_ErrorCode errorCode) 84 { 85 OH_LOG_INFO(LOG_APP, "OnCameraInput errorCode = %{public}d", errorCode); 86 } 87 88 CameraInput_Callbacks* GetCameraInputListener(void) 89 { 90 static CameraInput_Callbacks cameraInputCallbacks = { 91 .onError = OnCameraInputError 92 }; 93 return &cameraInputCallbacks; 94 } 95 96 void CameraManagerStatusCallback(Camera_Manager* cameraManager, Camera_StatusInfo* status) 97 { 98 OH_LOG_INFO(LOG_APP, "CameraManagerStatusCallback is called"); 99 } 100 101 CameraManager_Callbacks* GetCameraManagerListener() 102 { 103 static CameraManager_Callbacks cameraManagerListener = { 104 .onCameraStatus = CameraManagerStatusCallback 105 }; 106 return &cameraManagerListener; 107 } 108 109 static void *bufferCb = nullptr; 110 Camera_ErrorCode NDKCamera::RegisterBufferCb(void *cb) { 111 OH_LOG_INFO(LOG_APP, " RegisterBufferCb start"); 112 if (cb == nullptr) { 113 OH_LOG_INFO(LOG_APP, " RegisterBufferCb invalid error"); 114 return CAMERA_INVALID_ARGUMENT; 115 } 116 bufferCb = cb; 117 118 return CAMERA_OK; 119 } 120 void OnPhotoAvailable(Camera_PhotoOutput *photoOutput, OH_PhotoNative *photo) { 121 OH_LOG_INFO(LOG_APP, "OnPhotoAvailable start!"); 122 OH_ImageNative *imageNative; 123 Camera_ErrorCode errCode = OH_PhotoNative_GetMainImage(photo, &imageNative); 124 OH_LOG_INFO(LOG_APP, "OnPhotoAvailable errCode:%{public}d imageNative:%{public}p", errCode, imageNative); 125 // Read the size attribute of OH_ImageNative. 126 Image_Size size; 127 Image_ErrorCode imageErr = OH_ImageNative_GetImageSize(imageNative, &size); 128 OH_LOG_INFO(LOG_APP, "OnPhotoAvailable imageErr:%{public}d width:%{public}d height:%{public}d", imageErr, 129 size.width, size.height); 130 // Read the number of elements in the component list of OH_ImageNative. 131 size_t componentTypeSize = 0; 132 imageErr = OH_ImageNative_GetComponentTypes(imageNative, nullptr, &componentTypeSize); 133 OH_LOG_INFO(LOG_APP, "OnPhotoAvailable imageErr:%{public}d componentTypeSize:%{public}zu", imageErr, 134 componentTypeSize); 135 // Read the component list of OH_ImageNative. 136 uint32_t *components = new uint32_t[componentTypeSize]; 137 imageErr = OH_ImageNative_GetComponentTypes(imageNative, &components, &componentTypeSize); 138 OH_LOG_INFO(LOG_APP, "OnPhotoAvailable OH_ImageNative_GetComponentTypes imageErr:%{public}d", imageErr); 139 // Read the buffer object corresponding to the first component of OH_ImageNative. 140 OH_NativeBuffer *nativeBuffer = nullptr; 141 imageErr = OH_ImageNative_GetByteBuffer(imageNative, components[0], &nativeBuffer); 142 OH_LOG_INFO(LOG_APP, "OnPhotoAvailable OH_ImageNative_GetByteBuffer imageErr:%{public}d", imageErr); 143 // Read the size of the buffer corresponding to the first component of OH_ImageNative. 144 size_t nativeBufferSize = 0; 145 imageErr = OH_ImageNative_GetBufferSize(imageNative, components[0], &nativeBufferSize); 146 OH_LOG_INFO(LOG_APP, "OnPhotoAvailable imageErr:%{public}d nativeBufferSize:%{public}zu", imageErr, 147 nativeBufferSize); 148 // Read the row stride corresponding to the first component of OH_ImageNative. 149 int32_t rowStride = 0; 150 imageErr = OH_ImageNative_GetRowStride(imageNative, components[0], &rowStride); 151 OH_LOG_INFO(LOG_APP, "OnPhotoAvailable imageErr:%{public}d rowStride:%{public}d", imageErr, rowStride); 152 // Read the pixel stride corresponding to the first component of OH_ImageNative. 153 int32_t pixelStride = 0; 154 imageErr = OH_ImageNative_GetPixelStride(imageNative, components[0], &pixelStride); 155 OH_LOG_INFO(LOG_APP, "OnPhotoAvailable imageErr:%{public}d pixelStride:%{public}d", imageErr, pixelStride); 156 // Map the ION memory to the process address space. 157 void *virAddr = nullptr; // Point to the virtual address of the mapped memory. After unmapping, the pointer is invalid. 158 int32_t ret = OH_NativeBuffer_Map(nativeBuffer, &virAddr); // After mapping, the start address of the memory is returned through the parameter virAddr. 159 OH_LOG_INFO(LOG_APP, "OnPhotoAvailable OH_NativeBuffer_Map err:%{public}d", ret); 160 // Pass the processed buffer to the ArkTS side through the callback for image display or storage (using a security component). For details, see Photo Capture (C/C++). 161 auto cb = (void (*)(void *, size_t))(bufferCb); 162 cb(virAddr, nativeBufferSize); 163 // After the processing is complete, unmap and release the buffer. 164 ret = OH_NativeBuffer_Unmap(nativeBuffer); 165 if (ret != 0) { 166 OH_LOG_ERROR(LOG_APP, "OnPhotoAvailable OH_NativeBuffer_Unmap error:%{public}d", ret); 167 } 168 } 169 170 NDKCamera::NDKCamera(char *previewId) 171 { 172 Camera_Manager* cameraManager = nullptr; 173 Camera_Device* cameras = nullptr; 174 Camera_CaptureSession* captureSession = nullptr; 175 Camera_OutputCapability* cameraOutputCapability = nullptr; 176 const Camera_Profile* previewProfile = nullptr; 177 const Camera_Profile* photoProfile = nullptr; 178 Camera_PreviewOutput* previewOutput = nullptr; 179 Camera_PhotoOutput* photoOutput = nullptr; 180 Camera_Input* cameraInput = nullptr; 181 uint32_t size = 0; 182 uint32_t cameraDeviceIndex = 0; 183 char* previewSurfaceId = previewId; 184 // Create a CameraManager object. 185 Camera_ErrorCode ret = OH_Camera_GetCameraManager(&cameraManager); 186 if (cameraManager == nullptr || ret != CAMERA_OK) { 187 OH_LOG_ERROR(LOG_APP, "OH_Camera_GetCameraMananger failed."); 188 } 189 // Listen for camera status changes. 190 ret = OH_CameraManager_RegisterCallback(cameraManager, GetCameraManagerListener()); 191 if (ret != CAMERA_OK) { 192 OH_LOG_ERROR(LOG_APP, "OH_CameraManager_RegisterCallback failed."); 193 } 194 195 // Obtain the camera list. 196 ret = OH_CameraManager_GetSupportedCameras(cameraManager, &cameras, &size); 197 if (cameras == nullptr || size < 0 || ret != CAMERA_OK) { 198 OH_LOG_ERROR(LOG_APP, "OH_CameraManager_GetSupportedCameras failed."); 199 } 200 201 // Create a camera input stream. 202 ret = OH_CameraManager_CreateCameraInput(cameraManager, &cameras[cameraDeviceIndex], &cameraInput); 203 if (cameraInput == nullptr || ret != CAMERA_OK) { 204 OH_LOG_ERROR(LOG_APP, "OH_CameraManager_CreateCameraInput failed."); 205 } 206 207 // Listen for camera input errors. 208 ret = OH_CameraInput_RegisterCallback(cameraInput, GetCameraInputListener()); 209 if (ret != CAMERA_OK) { 210 OH_LOG_ERROR(LOG_APP, "OH_CameraInput_RegisterCallback failed."); 211 } 212 213 // Open the camera. 214 ret = OH_CameraInput_Open(cameraInput); 215 if (ret != CAMERA_OK) { 216 OH_LOG_ERROR(LOG_APP, "OH_CameraInput_Open failed."); 217 } 218 219 // Obtain the output streams supported by the camera. 220 ret = OH_CameraManager_GetSupportedCameraOutputCapability(cameraManager, &cameras[cameraDeviceIndex], 221 &cameraOutputCapability); 222 if (cameraOutputCapability == nullptr || ret != CAMERA_OK) { 223 OH_LOG_ERROR(LOG_APP, "OH_CameraManager_GetSupportedCameraOutputCapability failed."); 224 } 225 226 if (cameraOutputCapability->previewProfilesSize < 0) { 227 OH_LOG_ERROR(LOG_APP, "previewProfilesSize == null"); 228 } 229 previewProfile = cameraOutputCapability->previewProfiles[0]; 230 231 if (cameraOutputCapability->photoProfilesSize < 0) { 232 OH_LOG_ERROR(LOG_APP, "photoProfilesSize == null"); 233 } 234 photoProfile = cameraOutputCapability->photoProfiles[0]; 235 236 237 // Create a preview output stream, with the previewSurfaceId parameter set to the ID of the surface provided by the XComponent. 238 ret = OH_CameraManager_CreatePreviewOutput(cameraManager, previewProfile, previewSurfaceId, &previewOutput); 239 if (previewProfile == nullptr || previewOutput == nullptr || ret != CAMERA_OK) { 240 OH_LOG_ERROR(LOG_APP, "OH_CameraManager_CreatePreviewOutput failed."); 241 } 242 243 // Listen for preview output errors. 244 ret = OH_PreviewOutput_RegisterCallback(previewOutput, GetPreviewOutputListener()); 245 if (ret != CAMERA_OK) { 246 OH_LOG_ERROR(LOG_APP, "OH_PreviewOutput_RegisterCallback failed."); 247 } 248 249 // Create a photo output stream. 250 ret_ = OH_CameraManager_CreatePhotoOutputWithoutSurface(cameraManager, photoProfile, &photoOutput); 251 252 // Listen for the one-time photo capture callback. 253 ret_ = OH_PhotoOutput_RegisterPhotoAvailableCallback(photoOutput, OnPhotoAvailable); 254 255 // Create a session. 256 ret = OH_CameraManager_CreateCaptureSession(cameraManager, &captureSession); 257 if (captureSession == nullptr || ret != CAMERA_OK) { 258 OH_LOG_ERROR(LOG_APP, "OH_CameraManager_CreateCaptureSession failed."); 259 } 260 261 // Listen for session errors. 262 ret = OH_CaptureSession_RegisterCallback(captureSession, GetCaptureSessionRegister()); 263 if (ret != CAMERA_OK) { 264 OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_RegisterCallback failed."); 265 } 266 267 // Start configuration for the session. 268 ret = OH_CaptureSession_BeginConfig(captureSession); 269 if (ret != CAMERA_OK) { 270 OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_BeginConfig failed."); 271 } 272 273 // Add the camera input stream to the session. 274 ret = OH_CaptureSession_AddInput(captureSession, cameraInput); 275 if (ret != CAMERA_OK) { 276 OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_AddInput failed."); 277 } 278 279 // Add the preview output stream to the session. 280 ret = OH_CaptureSession_AddPreviewOutput(captureSession, previewOutput); 281 if (ret != CAMERA_OK) { 282 OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_AddPreviewOutput failed."); 283 } 284 285 // Add the photo output stream to the session. 286 ret = OH_CaptureSession_AddPhotoOutput(captureSession, photoOutput); 287 if (ret != CAMERA_OK) { 288 OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_AddPhotoOutput failed."); 289 } 290 291 // Commit the session configuration. 292 ret = OH_CaptureSession_CommitConfig(captureSession); 293 if (ret != CAMERA_OK) { 294 OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_CommitConfig failed."); 295 } 296 297 // Start the session. 298 ret = OH_CaptureSession_Start(captureSession); 299 if (ret != CAMERA_OK) { 300 OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_Start failed."); 301 } 302 303 // Check whether the camera has flash. 304 Camera_FlashMode flashMode = FLASH_MODE_AUTO; 305 bool hasFlash = false; 306 ret = OH_CaptureSession_HasFlash(captureSession, &hasFlash); 307 if (ret != CAMERA_OK) { 308 OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_HasFlash failed."); 309 } 310 if (hasFlash) { 311 OH_LOG_INFO(LOG_APP, "hasFlash success"); 312 } else { 313 OH_LOG_ERROR(LOG_APP, "hasFlash fail"); 314 } 315 // Check whether a flash mode is supported. 316 bool isSupported = false; 317 ret = OH_CaptureSession_IsFlashModeSupported(captureSession, flashMode, &isSupported); 318 if (ret != CAMERA_OK) { 319 OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_IsFlashModeSupported failed."); 320 } 321 if (isSupported) { 322 OH_LOG_INFO(LOG_APP, "isFlashModeSupported success"); 323 // Set the flash mode. 324 ret = OH_CaptureSession_SetFlashMode(captureSession, flashMode); 325 if (ret == CAMERA_OK) { 326 OH_LOG_INFO(LOG_APP, "OH_CaptureSession_SetFlashMode success."); 327 } else { 328 OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_SetFlashMode failed. %{public}d ", ret); 329 } 330 // Obtain the flash mode in use. 331 ret = OH_CaptureSession_GetFlashMode(captureSession, &flashMode); 332 if (ret == CAMERA_OK) { 333 OH_LOG_INFO(LOG_APP, "OH_CaptureSession_GetFlashMode success. flashMode: %{public}d ", flashMode); 334 } else { 335 OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_GetFlashMode failed. %d ", ret); 336 } 337 } else { 338 OH_LOG_ERROR(LOG_APP, "isFlashModeSupported fail"); 339 } 340 341 // Check whether the continuous auto focus is supported. 342 Camera_FocusMode focusMode = FOCUS_MODE_CONTINUOUS_AUTO; 343 bool isFocusModeSupported = false; 344 ret = OH_CaptureSession_IsFocusModeSupported(captureSession, focusMode, &isFocusModeSupported); 345 if (ret != CAMERA_OK) { 346 OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_IsFocusModeSupported failed."); 347 } 348 if (isFocusModeSupported) { 349 OH_LOG_INFO(LOG_APP, "isFocusModeSupported success"); 350 ret = OH_CaptureSession_SetFocusMode(captureSession, focusMode); 351 if (ret != CAMERA_OK) { 352 OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_SetFocusMode failed. %{public}d ", ret); 353 } 354 ret = OH_CaptureSession_GetFocusMode(captureSession, &focusMode); 355 if (ret == CAMERA_OK) { 356 OH_LOG_INFO(LOG_APP, "OH_CaptureSession_GetFocusMode success. focusMode%{public}d ", focusMode); 357 } else { 358 OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_GetFocusMode failed. %d ", ret); 359 } 360 } else { 361 OH_LOG_ERROR(LOG_APP, "isFocusModeSupported fail"); 362 } 363 364 // Obtain the zoom ratio range supported by the camera. 365 float minZoom; 366 float maxZoom; 367 ret = OH_CaptureSession_GetZoomRatioRange(captureSession, &minZoom, &maxZoom); 368 if (ret != CAMERA_OK) { 369 OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_GetZoomRatioRange failed."); 370 } else { 371 OH_LOG_INFO(LOG_APP, "OH_CaptureSession_GetZoomRatioRange success. minZoom: %{public}f, maxZoom:%{public}f", 372 minZoom, maxZoom); 373 } 374 // Set a zoom ratio. 375 ret = OH_CaptureSession_SetZoomRatio(captureSession, maxZoom); 376 if (ret == CAMERA_OK) { 377 OH_LOG_INFO(LOG_APP, "OH_CaptureSession_SetZoomRatio success."); 378 } else { 379 OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_SetZoomRatio failed. %{public}d ", ret); 380 } 381 // Obtain the zoom ratio of the camera. 382 ret = OH_CaptureSession_GetZoomRatio(captureSession, &maxZoom); 383 if (ret == CAMERA_OK) { 384 OH_LOG_INFO(LOG_APP, "OH_CaptureSession_GetZoomRatio success. zoom: %{public}f ", maxZoom); 385 } else { 386 OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_GetZoomRatio failed. %{public}d ", ret); 387 } 388 389 // Take photos without photo capture settings. 390 ret = OH_PhotoOutput_Capture(photoOutput); 391 if (ret == CAMERA_OK) { 392 OH_LOG_INFO(LOG_APP, "OH_PhotoOutput_Capture success "); 393 } else { 394 OH_LOG_ERROR(LOG_APP, "OH_PhotoOutput_Capture failed. %d ", ret); 395 } 396 397 // Stop the session. 398 ret = OH_CaptureSession_Stop(captureSession); 399 if (ret == CAMERA_OK) { 400 OH_LOG_INFO(LOG_APP, "OH_CaptureSession_Stop success "); 401 } else { 402 OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_Stop failed. %d ", ret); 403 } 404 405 // Release the camera input stream. 406 ret = OH_CameraInput_Close(cameraInput); 407 if (ret == CAMERA_OK) { 408 OH_LOG_INFO(LOG_APP, "OH_CameraInput_Close success "); 409 } else { 410 OH_LOG_ERROR(LOG_APP, "OH_CameraInput_Close failed. %d ", ret); 411 } 412 413 // Release the preview output stream. 414 ret = OH_PreviewOutput_Release(previewOutput); 415 if (ret == CAMERA_OK) { 416 OH_LOG_INFO(LOG_APP, "OH_PreviewOutput_Release success "); 417 } else { 418 OH_LOG_ERROR(LOG_APP, "OH_PreviewOutput_Release failed. %d ", ret); 419 } 420 421 // Release the photo output stream. 422 ret = OH_PhotoOutput_Release(photoOutput); 423 if (ret == CAMERA_OK) { 424 OH_LOG_INFO(LOG_APP, "OH_PhotoOutput_Release success "); 425 } else { 426 OH_LOG_ERROR(LOG_APP, "OH_PhotoOutput_Release failed. %d ", ret); 427 } 428 429 // Release the session. 430 ret = OH_CaptureSession_Release(captureSession); 431 if (ret == CAMERA_OK) { 432 OH_LOG_INFO(LOG_APP, "OH_CaptureSession_Release success "); 433 } else { 434 OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_Release failed. %d ", ret); 435 } 436 437 // Release the resources. 438 ret = OH_CameraManager_DeleteSupportedCameras(cameraManager, cameras, size); 439 if (ret != CAMERA_OK) { 440 OH_LOG_ERROR(LOG_APP, "Delete Cameras failed."); 441 } else { 442 OH_LOG_ERROR(LOG_APP, "OH_CameraManager_DeleteSupportedCameras. ok"); 443 } 444 ret = OH_CameraManager_DeleteSupportedCameraOutputCapability(cameraManager, cameraOutputCapability); 445 if (ret != CAMERA_OK) { 446 OH_LOG_ERROR(LOG_APP, "Delete Cameras failed."); 447 } else { 448 OH_LOG_ERROR(LOG_APP, "OH_CameraManager_DeleteSupportedCameraOutputCapability. ok"); 449 } 450 ret = OH_Camera_DeleteCameraManager(cameraManager); 451 if (ret != CAMERA_OK) { 452 OH_LOG_ERROR(LOG_APP, "Delete Cameras failed."); 453 } else { 454 OH_LOG_ERROR(LOG_APP, "OH_Camera_DeleteCameraManager. ok"); 455 } 456 } 457 ``` 458