1# Video Recording Practices (C/C++) 2<!--Kit: Camera Kit--> 3<!--Subsystem: Multimedia--> 4<!--Owner: @qano--> 5<!--SE: @leo_ysl--> 6<!--TSE: @xchaosioda--> 7 8Before developing a camera application, request permissions by following the instructions provided in [Requesting Camera Development Permissions](camera-preparation.md). 9 10This topic provides sample code that covers the complete video recording process and the API calling sequence. For details about a single process (such as device input, session management, and video recording), see the corresponding C/C++ development guide links provided in [Requesting Camera Development Permissions](camera-preparation.md). 11 12## Development Process 13 14After obtaining the output stream capabilities supported by the camera, create a video stream. The development process is as follows: 15 16 17 18## Sample Code 19 201. Link the dynamic library in the CMake script. 21 ```txt 22 target_link_libraries(entry PUBLIC 23 libace_napi.z.so 24 libohcamera.so 25 libhilog_ndk.z.so 26 ) 27 ``` 28 292. Create the header file **ndk_camera.h**. 30 ```c++ 31 #include "ohcamera/camera.h" 32 #include "ohcamera/camera_input.h" 33 #include "ohcamera/capture_session.h" 34 #include "ohcamera/photo_output.h" 35 #include "ohcamera/preview_output.h" 36 #include "ohcamera/video_output.h" 37 #include "ohcamera/camera_manager.h" 38 39 class NDKCamera { 40 public: 41 ~NDKCamera(); 42 NDKCamera(char* previewId, char* videoId); 43 }; 44 ``` 45 463. Import the NDK APIs on the C++ side, and perform video recording based on the surface ID passed in. 47 ```c++ 48 #include "hilog/log.h" 49 #include "ndk_camera.h" 50 #include <cmath> 51 52 bool IsAspectRatioEqual(float videoAspectRatio, float previewAspectRatio) 53 { 54 float epsilon = 1e-6f; 55 return fabsf(videoAspectRatio - previewAspectRatio) <= epsilon; 56 } 57 58 void OnCameraInputError(const Camera_Input* cameraInput, Camera_ErrorCode errorCode) 59 { 60 OH_LOG_INFO(LOG_APP, "OnCameraInput errorCode = %{public}d", errorCode); 61 } 62 63 CameraInput_Callbacks* GetCameraInputListener(void) 64 { 65 static CameraInput_Callbacks cameraInputCallbacks = { 66 .onError = OnCameraInputError 67 }; 68 return &cameraInputCallbacks; 69 } 70 71 void CaptureSessionOnFocusStateChange(Camera_CaptureSession* session, Camera_FocusState focusState) 72 { 73 OH_LOG_INFO(LOG_APP, "CaptureSessionOnFocusStateChange"); 74 } 75 76 void CaptureSessionOnError(Camera_CaptureSession* session, Camera_ErrorCode errorCode) 77 { 78 OH_LOG_INFO(LOG_APP, "CaptureSessionOnError = %{public}d", errorCode); 79 } 80 81 CaptureSession_Callbacks* GetCaptureSessionRegister(void) 82 { 83 static CaptureSession_Callbacks captureSessionCallbacks = { 84 .onFocusStateChange = CaptureSessionOnFocusStateChange, 85 .onError = CaptureSessionOnError 86 }; 87 return &captureSessionCallbacks; 88 } 89 90 void VideoOutputOnFrameStart(Camera_VideoOutput* videoOutput) 91 { 92 OH_LOG_INFO(LOG_APP, "VideoOutputOnFrameStart"); 93 } 94 95 void VideoOutputOnFrameEnd(Camera_VideoOutput* videoOutput, int32_t frameCount) 96 { 97 OH_LOG_INFO(LOG_APP, "VideoOutput frameCount = %{public}d", frameCount); 98 } 99 100 void VideoOutputOnError(Camera_VideoOutput* videoOutput, Camera_ErrorCode errorCode) 101 { 102 OH_LOG_INFO(LOG_APP, "VideoOutput errorCode = %{public}d", errorCode); 103 } 104 105 VideoOutput_Callbacks* GetVideoOutputListener(void) 106 { 107 static VideoOutput_Callbacks videoOutputListener = { 108 .onFrameStart = VideoOutputOnFrameStart, 109 .onFrameEnd = VideoOutputOnFrameEnd, 110 .onError = VideoOutputOnError 111 }; 112 return &videoOutputListener; 113 } 114 115 void CameraManagerStatusCallback(Camera_Manager* cameraManager, Camera_StatusInfo* status) 116 { 117 OH_LOG_INFO(LOG_APP, "CameraManagerStatusCallback is called"); 118 } 119 120 CameraManager_Callbacks* GetCameraManagerListener() 121 { 122 static CameraManager_Callbacks cameraManagerListener = { 123 .onCameraStatus = CameraManagerStatusCallback 124 }; 125 return &cameraManagerListener; 126 } 127 128 NDKCamera::NDKCamera(char* previewId, char* videoId) 129 { 130 Camera_Manager* cameraManager = nullptr; 131 Camera_Device* cameras = nullptr; 132 Camera_CaptureSession* captureSession = nullptr; 133 Camera_OutputCapability* cameraOutputCapability = nullptr; 134 Camera_VideoOutput* videoOutput = nullptr; 135 const Camera_Profile* previewProfile = nullptr; 136 const Camera_Profile* photoProfile = nullptr; 137 const Camera_VideoProfile* videoProfile = nullptr; 138 Camera_PreviewOutput* previewOutput = nullptr; 139 Camera_PhotoOutput* photoOutput = nullptr; 140 Camera_Input* cameraInput = nullptr; 141 uint32_t size = 0; 142 uint32_t cameraDeviceIndex = 0; 143 char* videoSurfaceId = videoId; 144 char* previewSurfaceId = previewId; 145 // Create a CameraManager object. 146 Camera_ErrorCode ret = OH_Camera_GetCameraManager(&cameraManager); 147 if (cameraManager == nullptr || ret != CAMERA_OK) { 148 OH_LOG_ERROR(LOG_APP, "OH_Camera_GetCameraManager failed."); 149 return; 150 } 151 // Listen for camera status changes. 152 ret = OH_CameraManager_RegisterCallback(cameraManager, GetCameraManagerListener()); 153 if (ret != CAMERA_OK) { 154 OH_LOG_ERROR(LOG_APP, "OH_CameraManager_RegisterCallback failed."); 155 return; 156 } 157 158 // Obtain the camera list. 159 ret = OH_CameraManager_GetSupportedCameras(cameraManager, &cameras, &size); 160 if (cameras == nullptr || size <= 0 || ret != CAMERA_OK) { 161 OH_LOG_ERROR(LOG_APP, "OH_CameraManager_GetSupportedCameras failed."); 162 return; 163 } 164 165 for (int index = 0; index < size; index++) { 166 OH_LOG_ERROR(LOG_APP, "cameraId = %{public}s ", cameras[index].cameraId); // Obtain the camera ID. 167 OH_LOG_ERROR(LOG_APP, "cameraPosition = %{public}d ", cameras[index].cameraPosition); // Obtain the camera position. 168 OH_LOG_ERROR(LOG_APP, "cameraType = %{public}d ", cameras[index].cameraType); // Obtain the camera type. 169 OH_LOG_ERROR(LOG_APP, "connectionType = %{public}d ", cameras[index].connectionType); // Obtain the camera connection type. 170 } 171 172 if (size < cameraDeviceIndex + 1) { 173 OH_LOG_ERROR(LOG_APP, "cameraDeviceIndex is invalid."); 174 return; 175 } 176 177 // Obtain the output stream capability supported by the camera. 178 ret = OH_CameraManager_GetSupportedCameraOutputCapability(cameraManager, &cameras[cameraDeviceIndex], 179 &cameraOutputCapability); 180 if (cameraOutputCapability == nullptr || ret != CAMERA_OK) { 181 OH_LOG_ERROR(LOG_APP, "OH_CameraManager_GetSupportedCameraOutputCapability failed."); 182 return; 183 } 184 185 if (cameraOutputCapability->previewProfiles == nullptr) { 186 OH_LOG_ERROR(LOG_APP, "previewProfiles == null"); 187 return; 188 } 189 previewProfile = cameraOutputCapability->previewProfiles[0]; 190 OH_LOG_INFO(LOG_APP, "previewProfile width: %{public}, height: %{public}.", previewProfile->size.width, 191 previewProfile->size.height); 192 if (cameraOutputCapability->photoProfiles == nullptr) { 193 OH_LOG_ERROR(LOG_APP, "photoProfiles == null"); 194 return; 195 } 196 photoProfile = cameraOutputCapability->photoProfiles[0]; 197 198 if (cameraOutputCapability->videoProfiles == nullptr) { 199 OH_LOG_ERROR(LOG_APP, "videoProfiles == null"); 200 return; 201 } 202 // Ensure that the aspect ratio of the preview stream is the same as that of the video stream. To record HDR videos, choose Camera_VideoProfile that supports HDR. 203 Camera_VideoProfile** videoProfiles = cameraOutputCapability->videoProfiles; 204 for (int index = 0; index < cameraOutputCapability->videoProfilesSize; index++) { 205 bool isEqual = IsAspectRatioEqual((float)videoProfiles[index]->size.width / videoProfiles[index]->size.height, 206 (float)previewProfile->size.width / previewProfile->size.height); 207 // The profile of CAMERA_FORMAT_YUV_420_SP is used by default. 208 if (isEqual && videoProfiles[index]->format == Camera_Format::CAMERA_FORMAT_YUV_420_SP) { 209 videoProfile = videoProfiles[index]; 210 OH_LOG_INFO(LOG_APP, "videoProfile width: %{public}, height: %{public}.", videoProfile->size.width, 211 videoProfile->size.height); 212 break; 213 } 214 } 215 if (videoProfile == nullptr) { 216 OH_LOG_ERROR(LOG_APP, "Get videoProfile failed."); 217 return; 218 } 219 // Create a VideoOutput instance. 220 ret = OH_CameraManager_CreateVideoOutput(cameraManager, videoProfile, videoSurfaceId, &videoOutput); 221 if (videoOutput == nullptr || ret != CAMERA_OK) { 222 OH_LOG_ERROR(LOG_APP, "OH_CameraManager_CreateVideoOutput failed."); 223 return; 224 } 225 226 // Listen for video output errors. 227 ret = OH_VideoOutput_RegisterCallback(videoOutput, GetVideoOutputListener()); 228 if (ret != CAMERA_OK) { 229 OH_LOG_ERROR(LOG_APP, "OH_VideoOutput_RegisterCallback failed."); 230 } 231 232 // Create a session. 233 ret = OH_CameraManager_CreateCaptureSession(cameraManager, &captureSession); 234 if (captureSession == nullptr || ret != CAMERA_OK) { 235 OH_LOG_ERROR(LOG_APP, "OH_CameraManager_CreateCaptureSession failed."); 236 return; 237 } 238 // Listen for session errors. 239 ret = OH_CaptureSession_RegisterCallback(captureSession, GetCaptureSessionRegister()); 240 if (ret != CAMERA_OK) { 241 OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_RegisterCallback failed."); 242 } 243 244 // Start configuration for the session. 245 ret = OH_CaptureSession_BeginConfig(captureSession); 246 if (ret != CAMERA_OK) { 247 OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_BeginConfig failed."); 248 return; 249 } 250 251 // Create a camera input stream. 252 ret = OH_CameraManager_CreateCameraInput(cameraManager, &cameras[cameraDeviceIndex], &cameraInput); 253 if (cameraInput == nullptr || ret != CAMERA_OK) { 254 OH_LOG_ERROR(LOG_APP, "OH_CameraManager_CreateCameraInput failed."); 255 return; 256 } 257 258 // Listen for camera input errors. 259 ret = OH_CameraInput_RegisterCallback(cameraInput, GetCameraInputListener()); 260 if (ret != CAMERA_OK) { 261 OH_LOG_ERROR(LOG_APP, "OH_CameraInput_RegisterCallback failed."); 262 } 263 264 // Open the camera. 265 ret = OH_CameraInput_Open(cameraInput); 266 if (ret != CAMERA_OK) { 267 OH_LOG_ERROR(LOG_APP, "OH_CameraInput_Open failed."); 268 return; 269 } 270 271 // Add the camera input stream to the session. 272 ret = OH_CaptureSession_AddInput(captureSession, cameraInput); 273 if (ret != CAMERA_OK) { 274 OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_AddInput failed."); 275 return; 276 } 277 278 // Create a preview output stream. For details about the surfaceId parameter, see the XComponent. The preview stream is the surface provided by the XComponent. 279 ret = OH_CameraManager_CreatePreviewOutput(cameraManager, previewProfile, previewSurfaceId, &previewOutput); 280 if (previewProfile == nullptr || previewOutput == nullptr || ret != CAMERA_OK) { 281 OH_LOG_ERROR(LOG_APP, "OH_CameraManager_CreatePreviewOutput failed."); 282 return; 283 } 284 285 // Add the preview output stream to the session. 286 ret = OH_CaptureSession_AddPreviewOutput(captureSession, previewOutput); 287 if (ret != CAMERA_OK) { 288 OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_AddPreviewOutput failed."); 289 return; 290 } 291 292 // Add the video output stream to the session. 293 ret = OH_CaptureSession_AddVideoOutput(captureSession, videoOutput); 294 if (ret != CAMERA_OK) { 295 OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_AddVideoOutput failed."); 296 return; 297 } 298 299 // Commit the session configuration. 300 ret = OH_CaptureSession_CommitConfig(captureSession); 301 if (ret != CAMERA_OK) { 302 OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_CommitConfig failed."); 303 return; 304 } 305 306 // Start the session. 307 ret = OH_CaptureSession_Start(captureSession); 308 if (ret != CAMERA_OK) { 309 OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_Start failed."); 310 return; 311 } 312 313 // Start the video output stream. 314 ret = OH_VideoOutput_Start(videoOutput); 315 if (ret != CAMERA_OK) { 316 OH_LOG_ERROR(LOG_APP, "OH_VideoOutput_Start failed."); 317 return; 318 } 319 320 // Call avRecorder.start() on the TS side to start video recording. 321 322 // Stop the video output stream. 323 ret = OH_VideoOutput_Stop(videoOutput); 324 if (ret != CAMERA_OK) { 325 OH_LOG_ERROR(LOG_APP, "OH_VideoOutput_Stop failed."); 326 } 327 328 // Call avRecorder.stop() on the TS side to stop video recording. 329 330 // Stop the session. 331 ret = OH_CaptureSession_Stop(captureSession); 332 if (ret == CAMERA_OK) { 333 OH_LOG_INFO(LOG_APP, "OH_CaptureSession_Stop success "); 334 } else { 335 OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_Stop failed. %d ", ret); 336 } 337 338 // Release the camera input stream. 339 ret = OH_CameraInput_Close(cameraInput); 340 if (ret == CAMERA_OK) { 341 OH_LOG_INFO(LOG_APP, "OH_CameraInput_Close success "); 342 } else { 343 OH_LOG_ERROR(LOG_APP, "OH_CameraInput_Close failed. %d ", ret); 344 } 345 346 // Release the preview output stream. 347 ret = OH_PreviewOutput_Release(previewOutput); 348 if (ret == CAMERA_OK) { 349 OH_LOG_INFO(LOG_APP, "OH_PreviewOutput_Release success "); 350 } else { 351 OH_LOG_ERROR(LOG_APP, "OH_PreviewOutput_Release failed. %d ", ret); 352 } 353 354 // Release the video output stream. 355 ret = OH_VideoOutput_Release(videoOutput); 356 if (ret == CAMERA_OK) { 357 OH_LOG_INFO(LOG_APP, "OH_VideoOutput_Release success "); 358 } else { 359 OH_LOG_ERROR(LOG_APP, "OH_VideoOutput_Release failed. %d ", ret); 360 } 361 362 // Release the session. 363 ret = OH_CaptureSession_Release(captureSession); 364 if (ret == CAMERA_OK) { 365 OH_LOG_INFO(LOG_APP, "OH_CaptureSession_Release success "); 366 } else { 367 OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_Release failed. %d ", ret); 368 } 369 370 // Release the resources. 371 ret = OH_CameraManager_DeleteSupportedCameras(cameraManager, cameras, size); 372 if (ret != CAMERA_OK) { 373 OH_LOG_ERROR(LOG_APP, "Delete Cameras failed."); 374 } else { 375 OH_LOG_ERROR(LOG_APP, "OH_CameraManager_DeleteSupportedCameras. ok"); 376 } 377 ret = OH_CameraManager_DeleteSupportedCameraOutputCapability(cameraManager, cameraOutputCapability); 378 if (ret != CAMERA_OK) { 379 OH_LOG_ERROR(LOG_APP, "Delete Cameras failed."); 380 } else { 381 OH_LOG_ERROR(LOG_APP, "OH_CameraManager_DeleteSupportedCameraOutputCapability success"); 382 } 383 ret = OH_Camera_DeleteCameraManager(cameraManager); 384 if (ret != CAMERA_OK) { 385 OH_LOG_ERROR(LOG_APP, "Delete Cameras failed."); 386 } else { 387 OH_LOG_ERROR(LOG_APP, "OH_Camera_DeleteCameraManager success"); 388 } 389 } 390 ``` 391