1# 录像实现方案(C/C++) 2 3在开发相机应用时,需要先参考开发准备[申请相关权限](camera-preparation.md)。 4 5当前示例提供完整的录像流程及其接口调用顺序的介绍。对于单个流程(如设备输入、会话管理、录像)的介绍请参考[相机开发指导(Native)](camera-preparation.md)的具体章节。 6 7## 开发流程 8 9在获取到相机支持的输出流能力后,开始创建录像流,开发流程如下。 10 11 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 ```