1 # Camera组件<a name="ZH-CN_TOPIC_0000001101564782"></a> 2 3 - [Camera组件<a name="ZH-CN_TOPIC_0000001101564782"></a>](#camera组件) 4 - [简介<a name="section11660541593"></a>](#简介) 5 - [基本概念<a name="sectionbasicconcepts"></a>](#基本概念) 6 - [目录<a name="section176641621345"></a>](#目录) 7 - [使用说明<a name="section45377346241"></a>](#使用说明) 8 - [拍照<a name="section2071191842718"></a>](#拍照) 9 - [开始和停止预览<a name="section2094314213271"></a>](#开始和停止预览) 10 - [视频录像<a name="section1983913118271"></a>](#视频录像) 11 - [切换多个照相机设备<a name="sectionswitchcamera"></a>](#切换多个照相机设备) 12 - [设置闪光灯<a name="sectionsetflash"></a>](#设置闪光灯) 13 - [相关仓<a name="section16511040154318"></a>](#相关仓) 14 15 ## 简介<a name="section11660541593"></a> 16 17 相机组件支持相机业务的开发,开发者可以通过已开放的接口实现相机硬件的访问、操作和新功能开发,最常见的操作如:预览、拍照和录像等。 18 19 ### 基本概念<a name="sectionbasicconcepts"></a> 20 21 - 拍照 22 23 此功能用于拍摄采集照片。 24 25 - 预览 26 27 此功能用于在开启相机后,在缓冲区内重复采集摄像帧,支持在拍照或录像前进行摄像帧预览显示。 28 29 - 录像 30 31 此功能用于在开始录像后和结束录像前的时间段内,在缓冲区内重复采集摄像帧,支持视频录制。 32 33 **图 1** 相机组件架构图<a name="fig310889397"></a> 34 35  36 37 ## 目录<a name="section176641621345"></a> 38 39 仓目录结构如下: 40 41 ``` 42 /foundation/multimedia/camera_framework # 相机组件业务代码 43 ├── frameworks # 框架代码 44 │ ├── native # 内部接口实现 45 │ │ ├── camera # 相机框架实现 46 │ │ └── metadata # 元数据实现 47 │ └── js # 外部接口实现 48 │ └── camera_napi # 相机NAPI实现 49 ├── interfaces # 接口代码 50 │ ├── inner_api # 内部接口 51 │ └── kits # 外部接口 52 ├── LICENSE # 许可证文件 53 ├── ohos.build # 构建文件 54 ├── sa_profile # 服务配置文件 55 └── services # 服务代码 56 ├── camera_service # 相机服务实现 57 └── etc # 相机服务配置 58 ``` 59 60 ## 使用说明<a name="section45377346241"></a> 61 62 ### 拍照<a name="section2071191842718"></a> 63 64 拍照的步骤: 65 66 1. 创建缓冲区消费者端监听器(CaptureSurfaceListener)以保存图像。 67 ``` 68 class CaptureSurfaceListener : public IBufferConsumerListener { 69 public: 70 int32_t mode_; 71 sptr<Surface> surface_; 72 73 void OnBufferAvailable() override 74 { 75 int32_t flushFence = 0; 76 int64_t timestamp = 0; 77 OHOS::Rect damage; // initialize the damage 78 79 OHOS::sptr<OHOS::SurfaceBuffer> buffer = nullptr; 80 surface_->AcquireBuffer(buffer, flushFence, timestamp, damage); 81 if (buffer != nullptr) { 82 void* addr = buffer->GetVirAddr(); 83 int32_t size = buffer->GetSize(); 84 85 // Save the buffer(addr) to a file. 86 87 surface_->ReleaseBuffer(buffer, -1); 88 } 89 } 90 }; 91 ``` 92 93 2. 获取相机管理器实例并获取相机对象列表。 94 95 ``` 96 sptr<CameraManager> camManagerObj = CameraManager::GetInstance(); 97 std::vector<sptr<CameraInfo>> cameraObjList = camManagerObj->GetCameras(); 98 ``` 99 100 3. 使用相机对象创建相机输入来打开相机。 101 102 ``` 103 sptr<CaptureInput> cameraInput = camManagerObj->CreateCameraInput(cameraObjList[0]); 104 ``` 105 106 4. 创建采集会话。 107 108 ``` 109 sptr<CaptureSession> captureSession = camManagerObj->CreateCaptureSession(); 110 ``` 111 112 5. 开始配置采集会话。 113 114 ``` 115 int32_t result = captureSession->BeginConfig(); 116 ``` 117 118 6. 将相机输入添加到采集会话。 119 120 ``` 121 result = captureSession->AddInput(cameraInput); 122 ``` 123 124 7. 创建消费者 Surface 并注册监听器以监听缓冲区更新。拍照的宽和高可以配置为所支持的 1280x960 分辨率。 125 126 ``` 127 sptr<Surface> photoSurface = Surface::CreateSurfaceAsConsumer(); 128 int32_t photoWidth = 1280; 129 int32_t photoHeight = 960; 130 photoSurface->SetDefaultWidthAndHeight(photoWidth, photoHeight); 131 photoSurface->SetUserData(CameraManager::surfaceFormat, std::to_string(OHOS_CAMERA_FORMAT_JPEG)); 132 sptr<CaptureSurfaceListener> capturelistener = new(std::nothrow) CaptureSurfaceListener(); 133 capturelistener->mode_ = MODE_PHOTO; 134 capturelistener->surface_ = photoSurface; 135 photoSurface->RegisterConsumerListener((sptr<IBufferConsumerListener> &)capturelistener); 136 ``` 137 138 8. 使用上面创建的 Surface 创建拍照输出。 139 140 ``` 141 sptr<CaptureOutput> photoOutput = camManagerObj->CreatePhotoOutput(photoSurface); 142 ``` 143 144 9. 将拍照输出添加到采集会话。 145 146 ``` 147 result = captureSession->AddOutput(photoOutput); 148 ``` 149 150 10. 将配置提交到采集会话。 151 152 ``` 153 result = captureSession->CommitConfig(); 154 ``` 155 156 11. 拍摄照片。 157 158 ``` 159 result = ((sptr<PhotoOutput> &)photoOutput)->Capture(); 160 ``` 161 162 12. 释放采集会话资源。 163 164 ``` 165 captureSession->Release(); 166 ``` 167 168 13. 释放相机输入关闭相机。 169 170 ``` 171 cameraInput->Release(); 172 ``` 173 174 ### 开始和停止预览<a name="section2094314213271"></a> 175 176 开始和停止预览的步骤: 177 178 1. 获取相机管理器实例并获取相机对象列表。 179 180 ``` 181 sptr<CameraManager> camManagerObj = CameraManager::GetInstance(); 182 std::vector<sptr<CameraInfo>> cameraObjList = camManagerObj->GetCameras(); 183 ``` 184 185 2. 使用相机对象创建相机输入来打开相机。 186 187 ``` 188 sptr<CaptureInput> cameraInput = camManagerObj->CreateCameraInput(cameraObjList[0]); 189 ``` 190 191 3. 创建采集会话。 192 193 ``` 194 sptr<CaptureSession> captureSession = camManagerObj->CreateCaptureSession(); 195 ``` 196 197 4. 开始配置采集会话。 198 199 ``` 200 int32_t result = captureSession->BeginConfig(); 201 ``` 202 203 5. 将相机输入添加到采集会话。 204 205 ``` 206 result = captureSession->AddInput(cameraInput); 207 ``` 208 209 6. 使用从窗口管理器获得的 Surface 创建预览输出用以在显示上渲染。预览的宽和高可以配置为所支持的 640x480 或 832x480 分辨率,如果想保存到文件,可以按照拍照流程提到步骤,创建 Surface,注册监听器以监听缓冲区更新。 210 211 ``` 212 int32_t previewWidth = 640; 213 int32_t previewHeight = 480; 214 previewSurface->SetUserData(CameraManager::surfaceFormat, std::to_string(OHOS_CAMERA_FORMAT_YCRCB_420_SP)); 215 sptr<CaptureOutput> previewOutput = camManagerObj->CreateCustomPreviewOutput(previewSurface, previewWidth, previewHeight); 216 ``` 217 218 7. 将预览输出添加到采集会话。 219 220 ``` 221 result = captureSession->AddOutput(previewOutput); 222 ``` 223 224 8. 将配置提交到采集会话。 225 226 ``` 227 result = captureSession->CommitConfig(); 228 ``` 229 230 9. 开始预览。 231 232 ``` 233 result = captureSession->Start(); 234 ``` 235 236 10. 需要时停止预览。 237 238 ``` 239 result = captureSession->Stop(); 240 ``` 241 242 11. 释放采集会话资源。 243 244 ``` 245 captureSession->Release(); 246 ``` 247 248 12. 释放相机输入关闭相机。 249 250 ``` 251 cameraInput->Release(); 252 ``` 253 254 ### 视频录像<a name="section1983913118271"></a> 255 256 视频录像的步骤: 257 258 1. 获取相机管理器实例并获取相机对象列表。 259 260 ``` 261 sptr<CameraManager> camManagerObj = CameraManager::GetInstance(); 262 std::vector<sptr<CameraInfo>> cameraObjList = camManagerObj->GetCameras(); 263 ``` 264 265 2. 使用相机对象创建相机输入来打开相机。 266 267 ``` 268 sptr<CaptureInput> cameraInput = camManagerObj->CreateCameraInput(cameraObjList[0]); 269 ``` 270 271 3. 创建采集会话。 272 273 ``` 274 sptr<CaptureSession> captureSession = camManagerObj->CreateCaptureSession(); 275 ``` 276 277 4. 开始配置采集会话。 278 279 ``` 280 int32_t result = captureSession->BeginConfig(); 281 ``` 282 283 5. 将相机输入添加到采集会话。 284 285 ``` 286 result = captureSession->AddInput(cameraInput); 287 ``` 288 289 6. 通过 Surface 创建一个视频输出,来与音频合成并保存到文件,Surface 通过 Recoder 获取。如果想仅保存视频缓冲数据到文件里,可以按照拍照流程提到步骤,创建 Surface,注册监听器以监听缓冲区更新。录像的分辨率可以在录制器内配置为所支持的 1280x720 或 640x360 分辨率。 290 291 ``` 292 videoSurface->SetUserData(CameraManager::surfaceFormat, std::to_string(OHOS_CAMERA_FORMAT_YCRCB_420_SP)); 293 sptr<CaptureOutput> videoOutput = camManagerObj->CreateVideoOutput(videoSurface); 294 ``` 295 296 7. 将视频输出添加到采集会话。 297 298 ``` 299 result = captureSession->AddOutput(videoOutput); 300 ``` 301 302 8. 将配置提交到采集会话。 303 304 ``` 305 result = captureSession->CommitConfig(); 306 ``` 307 308 9. 开始视频录制。 309 310 ``` 311 result = ((sptr<VideoOutput> &)videoOutput)->Start(); 312 ``` 313 314 10. 需要时停止录制。 315 316 ``` 317 result = ((sptr<VideoOutput> &)videoOutput)->Stop(); 318 ``` 319 320 11. 释放采集会话的资源。 321 322 ``` 323 captureSession->Release(); 324 ``` 325 326 12. 释放相机输入关闭相机。 327 328 ``` 329 cameraInput->Release(); 330 ``` 331 332 ### 切换多个照相机设备<a name="sectionswitchcamera"></a> 333 334 以下演示如何切换多个照相机设备。最初在采集会话中有一个视频输出(video output)。如果用户想要切换其他 照相机,现存的相机输入和输出需要先移除并加入新的相机输入和输出(示例中使用的是photo output)。 335 336 1. 获取相机管理器实例并获取相机对象列表。 337 338 ``` 339 sptr<CameraManager> camManagerObj = CameraManager::GetInstance(); 340 std::vector<sptr<CameraInfo>> cameraObjList = camManagerObj->GetCameras(); 341 ``` 342 343 2. 使用相机对象创建相机输入来打开相机。 344 345 ``` 346 sptr<CaptureInput> cameraInput = camManagerObj->CreateCameraInput(cameraObjList[0]); 347 ``` 348 349 3. 创建采集会话。 350 351 ``` 352 sptr<CaptureSession> captureSession = camManagerObj->CreateCaptureSession(); 353 ``` 354 355 4. 开始配置采集会话。 356 357 ``` 358 int32_t result = captureSession->BeginConfig() 359 ``` 360 361 5. 将相机输入添加到采集会话。 362 363 ``` 364 result = captureSession->AddInput(cameraInput); 365 ``` 366 367 6. 通过Surface创建一个视频输出。 368 369 ``` 370 sptr<CaptureOutput> videoOutput = camManagerObj->CreateVideoOutput(videoSurface); 371 ``` 372 373 7. 将视频输出添加到采集会话。 374 375 ``` 376 result = captureSession->AddOutput(videoOutput); 377 ``` 378 379 8. 将配置提交到采集会话。 380 381 ``` 382 result = captureSession->CommitConfig(); 383 ``` 384 385 9. 开始录制视频。 386 387 ``` 388 result = ((sptr<VideoOutput> &)videoOutput)->Start(); 389 ``` 390 391 10. 需要时停止录制。 392 393 ``` 394 result = ((sptr<VideoOutput> &)videoOutput)->Stop(); 395 ``` 396 397 11. 重新配置会话并移除相机输入和输出。 398 399 ``` 400 int32_t result = captureSession->BeginConfig(); 401 ``` 402 403 12. 在新的会话配置中移除相机输入。 404 405 ``` 406 int32_t result = captureSession->RemoveInput(cameraInput); 407 ``` 408 409 13. 同样移除相机输出。 410 411 ``` 412 int32_t result = captureSession->RemoveOutut(videoOutput); 413 ``` 414 415 14. 创建新的相机输入,并把它添加到采集会话。 416 417 ``` 418 sptr<CaptureInput> cameraInput2 = camManagerObj->CreateCameraInput(cameraObjList[1]); 419 result = captureSession->AddInput(cameraInput2); 420 ``` 421 422 15. 创建拍照输出,成功创建后将拍照输出添加到采集会话。创建消费者 Surface 并注册监听器以监听新的拍照输出缓冲区更新。这个 Surface 用于新创建的拍照输出。 423 424 ``` 425 // Get the surface 426 sptr<Surface> photoSurface = Surface::CreateSurfaceAsConsumer(); 427 int32_t photoWidth = 1280; 428 int32_t photoHeight = 960; 429 photoSurface->SetDefaultWidthAndHeight(photoWidth, photoHeight); 430 photoSurface->SetUserData(CameraManager::surfaceFormat, std::to_string(OHOS_CAMERA_FORMAT_JPEG)); 431 sptr<CaptureSurfaceListener> capturelistener = new(std::nothrow) CaptureSurfaceListener(); 432 capturelistener->mode_ = MODE_PHOTO; 433 capturelistener->surface_ = photoSurface; 434 photoSurface->RegisterConsumerListener((sptr<IBufferConsumerListener> &)capturelistener); 435 436 // Create the Photo Output 437 sptr<CaptureOutput> photoOutput = camManagerObj->CreatePhotoOutput(photoSurface); 438 439 // Add the output to the capture session 440 result = captureSession->AddOutput(photoOutput); 441 ``` 442 443 16. 将配置提交到采集会话。 444 445 ``` 446 result = captureSession->CommitConfig(); 447 ``` 448 449 17. 释放被移出会话的相机输入。 450 451 ``` 452 cameraInput->Release(); 453 ``` 454 455 18. 拍摄照片。 456 457 ``` 458 result = ((sptr<PhotoOutput> &)photoOutput)->Capture(); 459 ``` 460 461 19. 释放采集会话资源。 462 463 ``` 464 captureSession->Release(); 465 ``` 466 467 20. 释放相机输入关闭相机。 468 469 ``` 470 cameraInput2->Release(); 471 ``` 472 473 ### 设置闪光灯<a name="sectionsetflash"></a> 474 475 拍照和录像前可以在相机输入里设置闪光灯。 476 477 1. 在照相中设置闪光灯。 478 479 ``` 480 cameraInput->LockForControl(); 481 cameraInput->SetFlashMode(OHOS_CAMERA_FLASH_MODE_OPEN); 482 cameraInput->UnlockForControl(); 483 ``` 484 485 2. 在录像中设置闪光灯。 486 487 ``` 488 cameraInput->LockForControl(); 489 cameraInput->SetFlashMode(OHOS_CAMERA_FLASH_MODE_ALWAYS_OPEN); 490 cameraInput->UnlockForControl(); 491 ``` 492 493 3. 关闭闪光灯。 494 495 ``` 496 cameraInput->LockForControl(); 497 cameraInput->SetFlashMode(OHOS_CAMERA_FLASH_MODE_CLOSE); 498 cameraInput->UnlockForControl(); 499 ``` 500 501 ## 相关仓<a name="section16511040154318"></a> 502 503 [multimedia\_camera\_framework](https://gitee.com/openharmony/multimedia_camera_framework) 504 505