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