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