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