• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 录像实现方案(C/C++)
2
3在开发相机应用时,需要先参考开发准备[申请相关权限](camera-preparation.md)。
4
5当前示例提供完整的录像流程及其接口调用顺序的介绍。对于单个流程(如设备输入、会话管理、录像)的介绍请参考[相机开发指导(Native)](camera-preparation.md)的具体章节。
6
7## 开发流程
8
9在获取到相机支持的输出流能力后,开始创建录像流,开发流程如下。
10
11![Recording Development Process](figures/recording-ndk-development-process.png)
12
13## 完整示例
14
151. 在CMake脚本中链接相关动态库。
16    ```txt
17        target_link_libraries(entry PUBLIC libohcamera.so libhilog_ndk.z.so)
18    ```
19
202. 创建头文件ndk_camera.h21   ```c++
22   #include "ohcamera/camera.h"
23   #include "ohcamera/camera_input.h"
24   #include "ohcamera/capture_session.h"
25   #include "ohcamera/photo_output.h"
26   #include "ohcamera/preview_output.h"
27   #include "ohcamera/video_output.h"
28   #include "ohcamera/camera_manager.h"
29
30   class NDKCamera {
31   public:
32       ~NDKCamera();
33       NDKCamera(char *previewId, char *videoId);
34   };
35   ```
36
373. cpp侧导入NDK接口,并根据传入的SurfaceId进行录像。
38    ```c++
39    #include "hilog/log.h"
40    #include "ndk_camera.h"
41
42    void OnCameraInputError(const Camera_Input* cameraInput, Camera_ErrorCode errorCode)
43    {
44        OH_LOG_INFO(LOG_APP, "OnCameraInput errorCode = %{public}d", errorCode);
45    }
46
47    CameraInput_Callbacks* GetCameraInputListener(void)
48    {
49        static CameraInput_Callbacks cameraInputCallbacks = {
50            .onError = OnCameraInputError
51        };
52        return &cameraInputCallbacks;
53    }
54
55    void CaptureSessionOnFocusStateChange(Camera_CaptureSession* session, Camera_FocusState focusState)
56    {
57        OH_LOG_INFO(LOG_APP, "CaptureSessionOnFocusStateChange");
58    }
59
60    void CaptureSessionOnError(Camera_CaptureSession* session, Camera_ErrorCode errorCode)
61    {
62        OH_LOG_INFO(LOG_APP, "CaptureSessionOnError = %{public}d", errorCode);
63    }
64
65    CaptureSession_Callbacks* GetCaptureSessionRegister(void)
66    {
67        static CaptureSession_Callbacks captureSessionCallbacks = {
68            .onFocusStateChange = CaptureSessionOnFocusStateChange,
69            .onError = CaptureSessionOnError
70        };
71        return &captureSessionCallbacks;
72    }
73
74    void VideoOutputOnFrameStart(Camera_VideoOutput* videoOutput)
75    {
76        OH_LOG_INFO(LOG_APP, "VideoOutputOnFrameStart");
77    }
78
79    void VideoOutputOnFrameEnd(Camera_VideoOutput* videoOutput, int32_t frameCount)
80    {
81        OH_LOG_INFO(LOG_APP, "VideoOutput frameCount = %{public}d", frameCount);
82    }
83
84    void VideoOutputOnError(Camera_VideoOutput* videoOutput, Camera_ErrorCode errorCode)
85    {
86        OH_LOG_INFO(LOG_APP, "VideoOutput errorCode = %{public}d", errorCode);
87    }
88
89    VideoOutput_Callbacks* GetVideoOutputListener(void)
90    {
91        static VideoOutput_Callbacks videoOutputListener = {
92            .onFrameStart = VideoOutputOnFrameStart,
93            .onFrameEnd = VideoOutputOnFrameEnd,
94            .onError = VideoOutputOnError
95        };
96        return &videoOutputListener;
97    }
98
99    void CameraManagerStatusCallback(Camera_Manager* cameraManager, Camera_StatusInfo* status)
100    {
101        OH_LOG_INFO(LOG_APP, "CameraManagerStatusCallback is called");
102    }
103
104    CameraManager_Callbacks* GetCameraManagerListener()
105    {
106        static CameraManager_Callbacks cameraManagerListener = {
107            .onCameraStatus = CameraManagerStatusCallback
108        };
109        return &cameraManagerListener;
110    }
111
112    NDKCamera::NDKCamera(char *previewId, char *videoId)
113    {
114        Camera_Manager* cameraManager = nullptr;
115        Camera_Device* cameras = nullptr;
116        Camera_CaptureSession* captureSession = nullptr;
117        Camera_OutputCapability* cameraOutputCapability = nullptr;
118        Camera_VideoOutput* videoOutput = nullptr;
119        const Camera_Profile* previewProfile = nullptr;
120        const Camera_Profile* photoProfile = nullptr;
121        const Camera_VideoProfile* videoProfile = nullptr;
122        Camera_PreviewOutput* previewOutput = nullptr;
123        Camera_PhotoOutput* photoOutput = nullptr;
124        Camera_Input* cameraInput = nullptr;
125        uint32_t size = 0;
126        uint32_t cameraDeviceIndex = 0;
127        char* videoSurfaceId = videoId;
128        char* previewSurfaceId = previewId;
129        // 创建CameraManager对象。
130        Camera_ErrorCode ret = OH_Camera_GetCameraManager(&cameraManager);
131        if (cameraManager == nullptr || ret != CAMERA_OK) {
132            OH_LOG_ERROR(LOG_APP, "OH_Camera_GetCameraMananger failed.");
133        }
134        // 监听相机状态变化。
135        ret = OH_CameraManager_RegisterCallback(cameraManager, GetCameraManagerListener());
136        if (ret != CAMERA_OK) {
137            OH_LOG_ERROR(LOG_APP, "OH_CameraManager_RegisterCallback failed.");
138        }
139
140        // 获取相机列表。
141        ret = OH_CameraManager_GetSupportedCameras(cameraManager, &cameras, &size);
142        if (cameras == nullptr || size < 0 || ret != CAMERA_OK) {
143            OH_LOG_ERROR(LOG_APP, "OH_CameraManager_GetSupportedCameras failed.");
144        }
145
146        for (int index = 0; index < size; index++) {
147            OH_LOG_ERROR(LOG_APP, "cameraId  =  %{public}s ", cameras[index].cameraId);              // 获取相机ID。
148            OH_LOG_ERROR(LOG_APP, "cameraPosition  =  %{public}d ", cameras[index].cameraPosition);  // 获取相机位置。
149            OH_LOG_ERROR(LOG_APP, "cameraType  =  %{public}d ", cameras[index].cameraType);          // 获取相机类型。
150            OH_LOG_ERROR(LOG_APP, "connectionType  =  %{public}d ", cameras[index].connectionType);  // 获取相机连接类型。
151        }
152
153        // 获取相机设备支持的输出流能力。
154        ret = OH_CameraManager_GetSupportedCameraOutputCapability(cameraManager, &cameras[cameraDeviceIndex],
155                                                                &cameraOutputCapability);
156        if (cameraOutputCapability == nullptr || ret != CAMERA_OK) {
157            OH_LOG_ERROR(LOG_APP, "OH_CameraManager_GetSupportedCameraOutputCapability failed.");
158        }
159
160        if (cameraOutputCapability->previewProfilesSize < 0) {
161            OH_LOG_ERROR(LOG_APP, "previewProfilesSize == null");
162        }
163        previewProfile = cameraOutputCapability->previewProfiles[0];
164
165        if (cameraOutputCapability->photoProfilesSize < 0) {
166            OH_LOG_ERROR(LOG_APP, "photoProfilesSize == null");
167        }
168        photoProfile = cameraOutputCapability->photoProfiles[0];
169
170        if (cameraOutputCapability->videoProfilesSize < 0) {
171            OH_LOG_ERROR(LOG_APP, "videorofilesSize == null");
172        }
173        videoProfile = cameraOutputCapability->videoProfiles[0];
174
175        // 创建VideoOutput对象。
176        ret = OH_CameraManager_CreateVideoOutput(cameraManager, videoProfile, videoSurfaceId, &videoOutput);
177        if (videoProfile == nullptr || videoOutput == nullptr || ret != CAMERA_OK) {
178            OH_LOG_ERROR(LOG_APP, "OH_CameraManager_CreateVideoOutput failed.");
179        }
180
181        // 监听视频输出错误信息。
182        ret = OH_VideoOutput_RegisterCallback(videoOutput, GetVideoOutputListener());
183        if (ret != CAMERA_OK) {
184            OH_LOG_ERROR(LOG_APP, "OH_VideoOutput_RegisterCallback failed.");
185        }
186
187        //创建会话。
188        ret = OH_CameraManager_CreateCaptureSession(cameraManager, &captureSession);
189        if (captureSession == nullptr || ret != CAMERA_OK) {
190            OH_LOG_ERROR(LOG_APP, "OH_CameraManager_CreateCaptureSession failed.");
191        }
192        // 监听session错误信息。
193        ret = OH_CaptureSession_RegisterCallback(captureSession, GetCaptureSessionRegister());
194        if (ret != CAMERA_OK) {
195            OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_RegisterCallback failed.");
196        }
197
198        // 开始配置会话。
199        ret = OH_CaptureSession_BeginConfig(captureSession);
200        if (ret != CAMERA_OK) {
201            OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_BeginConfig failed.");
202        }
203
204        // 创建相机输入流。
205        ret = OH_CameraManager_CreateCameraInput(cameraManager, &cameras[cameraDeviceIndex], &cameraInput);
206        if (cameraInput == nullptr || ret != CAMERA_OK) {
207            OH_LOG_ERROR(LOG_APP, "OH_CameraManager_CreateCameraInput failed.");
208        }
209
210        // 监听cameraInput错误信息。
211        ret = OH_CameraInput_RegisterCallback(cameraInput, GetCameraInputListener());
212        if (ret != CAMERA_OK) {
213            OH_LOG_ERROR(LOG_APP, "OH_CameraInput_RegisterCallback failed.");
214        }
215
216        // 打开相机。
217        ret = OH_CameraInput_Open(cameraInput);
218        if (ret != CAMERA_OK) {
219            OH_LOG_ERROR(LOG_APP, "OH_CameraInput_Open failed.");
220        }
221
222        // 向会话中添加相机输入流。
223        ret = OH_CaptureSession_AddInput(captureSession, cameraInput);
224        if (ret != CAMERA_OK) {
225            OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_AddInput failed.");
226        }
227
228        // 创建预览输出流,其中参数 surfaceId 参考下面 XComponent 组件,预览流为XComponent组件提供的surface。
229        ret = OH_CameraManager_CreatePreviewOutput(cameraManager, previewProfile, previewSurfaceId, &previewOutput);
230        if (previewProfile == nullptr || previewOutput == nullptr || ret != CAMERA_OK) {
231            OH_LOG_ERROR(LOG_APP, "OH_CameraManager_CreatePreviewOutput failed.");
232        }
233
234        // 向会话中添加预览输出流。
235        ret = OH_CaptureSession_AddPreviewOutput(captureSession, previewOutput);
236        if (ret != CAMERA_OK) {
237            OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_AddPreviewOutput failed.");
238        }
239
240        // 向会话中添加录像输出流。
241        ret = OH_CaptureSession_AddVideoOutput(captureSession, videoOutput);
242        if (ret != CAMERA_OK) {
243            OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_AddVideoOutput failed.");
244        }
245
246        // 提交会话配置。
247        ret = OH_CaptureSession_CommitConfig(captureSession);
248        if (ret != CAMERA_OK) {
249            OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_CommitConfig failed.");
250        }
251
252        // 启动会话。
253        ret = OH_CaptureSession_Start(captureSession);
254        if (ret != CAMERA_OK) {
255            OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_Start failed.");
256        }
257
258        // 启动录像输出流。
259        ret = OH_VideoOutput_Start(videoOutput);
260        if (ret != CAMERA_OK) {
261            OH_LOG_ERROR(LOG_APP, "OH_VideoOutput_Start failed.");
262        }
263
264        // 开始录像 ts侧调用avRecorder.start()。
265
266        // 停止录像输出流。
267        ret = OH_VideoOutput_Stop(videoOutput);
268        if (ret != CAMERA_OK) {
269            OH_LOG_ERROR(LOG_APP, "OH_VideoOutput_Stop failed.");
270        }
271
272        // 停止录像 ts侧调用avRecorder.stop()。
273
274        // 停止当前会话。
275        ret = OH_CaptureSession_Stop(captureSession);
276        if (ret == CAMERA_OK) {
277            OH_LOG_INFO(LOG_APP, "OH_CaptureSession_Stop success ");
278        } else {
279            OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_Stop failed. %d ", ret);
280        }
281
282        // 释放相机输入流。
283        ret = OH_CameraInput_Close(cameraInput);
284        if (ret == CAMERA_OK) {
285            OH_LOG_INFO(LOG_APP, "OH_CameraInput_Close success ");
286        } else {
287            OH_LOG_ERROR(LOG_APP, "OH_CameraInput_Close failed. %d ", ret);
288        }
289
290        // 释放预览输出流。
291        ret = OH_PreviewOutput_Release(previewOutput);
292        if (ret == CAMERA_OK) {
293            OH_LOG_INFO(LOG_APP, "OH_PreviewOutput_Release success ");
294        } else {
295            OH_LOG_ERROR(LOG_APP, "OH_PreviewOutput_Release failed. %d ", ret);
296        }
297
298        // 释放录像输出流。
299        ret = OH_VideoOutput_Release(videoOutput);
300        if (ret == CAMERA_OK) {
301            OH_LOG_INFO(LOG_APP, "OH_VideoOutput_Release success ");
302        } else {
303            OH_LOG_ERROR(LOG_APP, "OH_VideoOutput_Release failed. %d ", ret);
304        }
305
306        // 释放会话。
307        ret = OH_CaptureSession_Release(captureSession);
308        if (ret == CAMERA_OK) {
309            OH_LOG_INFO(LOG_APP, "OH_CaptureSession_Release success ");
310        } else {
311            OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_Release failed. %d ", ret);
312        }
313
314        // 资源释放。
315        ret = OH_CameraManager_DeleteSupportedCameras(cameraManager, cameras, size);
316        if (ret != CAMERA_OK) {
317          OH_LOG_ERROR(LOG_APP, "Delete Cameras failed.");
318        } else {
319          OH_LOG_ERROR(LOG_APP, "OH_CameraManager_DeleteSupportedCameras. ok");
320        }
321        ret = OH_CameraManager_DeleteSupportedCameraOutputCapability(cameraManager, cameraOutputCapability);
322        if (ret != CAMERA_OK) {
323          OH_LOG_ERROR(LOG_APP, "Delete Cameras failed.");
324        } else {
325          OH_LOG_ERROR(LOG_APP, "OH_CameraManager_DeleteSupportedCameraOutputCapability. ok");
326        }
327        ret = OH_Camera_DeleteCameraManager(cameraManager);
328        if (ret != CAMERA_OK) {
329          OH_LOG_ERROR(LOG_APP, "Delete Cameras failed.");
330        } else {
331          OH_LOG_ERROR(LOG_APP, "OH_Camera_DeleteCameraManager. ok");
332        }
333    }
334    ```