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