• 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        // Check whether a flash mode is supported.
326        bool isSupported = false;
327        ret = OH_CaptureSession_IsFlashModeSupported(captureSession, flashMode, &isSupported);
328        if (ret != CAMERA_OK) {
329          OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_IsFlashModeSupported failed.");
330        }
331        if (isSupported) {
332          OH_LOG_INFO(LOG_APP, "isFlashModeSupported success");
333          // Set the flash mode.
334          ret = OH_CaptureSession_SetFlashMode(captureSession, flashMode);
335          if (ret == CAMERA_OK) {
336              OH_LOG_INFO(LOG_APP, "OH_CaptureSession_SetFlashMode success.");
337          } else {
338              OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_SetFlashMode failed. %{public}d ", ret);
339          }
340          // Obtain the flash mode in use.
341          ret = OH_CaptureSession_GetFlashMode(captureSession, &flashMode);
342          if (ret == CAMERA_OK) {
343              OH_LOG_INFO(LOG_APP, "OH_CaptureSession_GetFlashMode success. flashMode: %{public}d ", flashMode);
344          } else {
345              OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_GetFlashMode failed. %d ", ret);
346          }
347        } else {
348          OH_LOG_ERROR(LOG_APP, "isFlashModeSupported fail");
349        }
350
351        // Check whether the continuous auto focus is supported.
352        Camera_FocusMode focusMode = FOCUS_MODE_CONTINUOUS_AUTO;
353        bool isFocusModeSupported = false;
354        ret = OH_CaptureSession_IsFocusModeSupported(captureSession, focusMode, &isFocusModeSupported);
355        if (ret != CAMERA_OK) {
356          OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_IsFocusModeSupported failed.");
357        }
358        if (isFocusModeSupported) {
359          OH_LOG_INFO(LOG_APP, "isFocusModeSupported success");
360          ret = OH_CaptureSession_SetFocusMode(captureSession, focusMode);
361          if (ret != CAMERA_OK) {
362              OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_SetFocusMode failed. %{public}d ", ret);
363          }
364          ret = OH_CaptureSession_GetFocusMode(captureSession, &focusMode);
365          if (ret == CAMERA_OK) {
366              OH_LOG_INFO(LOG_APP, "OH_CaptureSession_GetFocusMode success. focusMode%{public}d ", focusMode);
367          } else {
368              OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_GetFocusMode failed. %d ", ret);
369          }
370        } else {
371          OH_LOG_ERROR(LOG_APP, "isFocusModeSupported fail");
372        }
373
374        // Obtain the zoom ratio range supported by the camera.
375        float minZoom;
376        float maxZoom;
377        ret = OH_CaptureSession_GetZoomRatioRange(captureSession, &minZoom, &maxZoom);
378        if (ret != CAMERA_OK) {
379          OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_GetZoomRatioRange failed.");
380        } else {
381          OH_LOG_INFO(LOG_APP, "OH_CaptureSession_GetZoomRatioRange success. minZoom: %{public}f, maxZoom:%{public}f",
382              minZoom, maxZoom);
383        }
384
385        // Set a zoom ratio.
386        ret = OH_CaptureSession_SetZoomRatio(captureSession, maxZoom);
387        if (ret == CAMERA_OK) {
388          OH_LOG_INFO(LOG_APP, "OH_CaptureSession_SetZoomRatio success.");
389        } else {
390          OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_SetZoomRatio failed. %{public}d ", ret);
391        }
392
393        // Obtain the zoom ratio of the camera.
394        ret = OH_CaptureSession_GetZoomRatio(captureSession, &maxZoom);
395        if (ret == CAMERA_OK) {
396          OH_LOG_INFO(LOG_APP, "OH_CaptureSession_GetZoomRatio success. zoom: %{public}f ", maxZoom);
397        } else {
398          OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_GetZoomRatio failed. %{public}d ", ret);
399        }
400
401        // Take photos without photo capture settings.
402        ret = OH_PhotoOutput_Capture(photoOutput);
403        if (ret == CAMERA_OK) {
404          OH_LOG_INFO(LOG_APP, "OH_PhotoOutput_Capture success ");
405        } else {
406          OH_LOG_ERROR(LOG_APP, "OH_PhotoOutput_Capture failed. %d ", ret);
407        }
408
409        // Stop the session.
410        ret = OH_CaptureSession_Stop(captureSession);
411        if (ret == CAMERA_OK) {
412          OH_LOG_INFO(LOG_APP, "OH_CaptureSession_Stop success ");
413        } else {
414          OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_Stop failed. %d ", ret);
415        }
416
417        // Release the camera input stream.
418        ret = OH_CameraInput_Close(cameraInput);
419        if (ret == CAMERA_OK) {
420          OH_LOG_INFO(LOG_APP, "OH_CameraInput_Close success ");
421        } else {
422          OH_LOG_ERROR(LOG_APP, "OH_CameraInput_Close failed. %d ", ret);
423        }
424
425        // Release the preview output stream.
426        ret = OH_PreviewOutput_Release(previewOutput);
427        if (ret == CAMERA_OK) {
428          OH_LOG_INFO(LOG_APP, "OH_PreviewOutput_Release success ");
429        } else {
430          OH_LOG_ERROR(LOG_APP, "OH_PreviewOutput_Release failed. %d ", ret);
431        }
432
433        // Release the photo output stream.
434        ret = OH_PhotoOutput_Release(photoOutput);
435        if (ret == CAMERA_OK) {
436          OH_LOG_INFO(LOG_APP, "OH_PhotoOutput_Release success ");
437        } else {
438          OH_LOG_ERROR(LOG_APP, "OH_PhotoOutput_Release failed. %d ", ret);
439        }
440
441        // Release the session.
442        ret = OH_CaptureSession_Release(captureSession);
443        if (ret == CAMERA_OK) {
444          OH_LOG_INFO(LOG_APP, "OH_CaptureSession_Release success ");
445        } else {
446          OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_Release failed. %d ", ret);
447        }
448
449        // Release the resources.
450        ret = OH_CameraManager_DeleteSupportedCameras(cameraManager, cameras, size);
451        if (ret != CAMERA_OK) {
452          OH_LOG_ERROR(LOG_APP, "Delete Cameras failed.");
453        } else {
454          OH_LOG_ERROR(LOG_APP, "OH_CameraManager_DeleteSupportedCameras. ok");
455        }
456        ret = OH_CameraManager_DeleteSupportedCameraOutputCapability(cameraManager, cameraOutputCapability);
457        if (ret != CAMERA_OK) {
458          OH_LOG_ERROR(LOG_APP, "Delete Cameras failed.");
459        } else {
460          OH_LOG_ERROR(LOG_APP, "OH_CameraManager_DeleteSupportedCameraOutputCapability. ok");
461        }
462        ret = OH_Camera_DeleteCameraManager(cameraManager);
463        if (ret != CAMERA_OK) {
464          OH_LOG_ERROR(LOG_APP, "Delete Cameras failed.");
465        } else {
466          OH_LOG_ERROR(LOG_APP, "OH_Camera_DeleteCameraManager. ok");
467        }
468    }
469    ```
470