# Camera组件 - [Camera组件](#camera组件) - [简介](#简介) - [基本概念](#基本概念) - [目录](#目录) - [使用说明](#使用说明) - [拍照](#拍照) - [开始和停止预览](#开始和停止预览) - [视频录像](#视频录像) - [切换多个照相机设备](#切换多个照相机设备) - [设置闪光灯](#设置闪光灯) - [相关仓](#相关仓) ## 简介 相机组件支持相机业务的开发,开发者可以通过已开放的接口实现相机硬件的访问、操作和新功能开发,最常见的操作如:预览、拍照和录像等。 ### 基本概念 - 拍照 此功能用于拍摄采集照片。 - 预览 此功能用于在开启相机后,在缓冲区内重复采集摄像帧,支持在拍照或录像前进行摄像帧预览显示。 - 录像 此功能用于在开始录像后和结束录像前的时间段内,在缓冲区内重复采集摄像帧,支持视频录制。 **图 1** 相机组件架构图 ![](figures/camera-architecture-zh.png "camera-architecture-zh") ## 目录 仓目录结构如下: ``` /foundation/multimedia/camera_framework # 相机组件业务代码 ├── frameworks # 框架代码 │ ├── native # 内部接口实现 │ │ ├── camera # 相机框架实现 │ │ └── metadata # 元数据实现 │ └── js # 外部接口实现 │ └── camera_napi # 相机NAPI实现 ├── interfaces # 接口代码 │ ├── inner_api # 内部接口 │ └── kits # 外部接口 ├── LICENSE # 许可证文件 ├── ohos.build # 构建文件 ├── sa_profile # 服务配置文件 └── services # 服务代码 ├── camera_service # 相机服务实现 └── etc # 相机服务配置 ``` ## 使用说明 ### 拍照 拍照的步骤: 1. 创建缓冲区消费者端监听器(CaptureSurfaceListener)以保存图像。 ``` class CaptureSurfaceListener : public IBufferConsumerListener { public: int32_t mode_; sptr surface_; void OnBufferAvailable() override { int32_t flushFence = 0; int64_t timestamp = 0; OHOS::Rect damage; // initialize the damage OHOS::sptr buffer = nullptr; surface_->AcquireBuffer(buffer, flushFence, timestamp, damage); if (buffer != nullptr) { void* addr = buffer->GetVirAddr(); int32_t size = buffer->GetSize(); // Save the buffer(addr) to a file. surface_->ReleaseBuffer(buffer, -1); } } }; ``` 2. 获取相机管理器实例并获取相机对象列表。 ``` sptr camManagerObj = CameraManager::GetInstance(); std::vector> cameraObjList = camManagerObj->GetCameras(); ``` 3. 使用相机对象创建相机输入来打开相机。 ``` sptr cameraInput = camManagerObj->CreateCameraInput(cameraObjList[0]); ``` 4. 创建采集会话。 ``` sptr captureSession = camManagerObj->CreateCaptureSession(); ``` 5. 开始配置采集会话。 ``` int32_t result = captureSession->BeginConfig(); ``` 6. 将相机输入添加到采集会话。 ``` result = captureSession->AddInput(cameraInput); ``` 7. 创建消费者 Surface 并注册监听器以监听缓冲区更新。拍照的宽和高可以配置为所支持的 1280x960 分辨率。 ``` sptr photoSurface = Surface::CreateSurfaceAsConsumer(); int32_t photoWidth = 1280; int32_t photoHeight = 960; photoSurface->SetDefaultWidthAndHeight(photoWidth, photoHeight); photoSurface->SetUserData(CameraManager::surfaceFormat, std::to_string(OHOS_CAMERA_FORMAT_JPEG)); sptr capturelistener = new(std::nothrow) CaptureSurfaceListener(); capturelistener->mode_ = MODE_PHOTO; capturelistener->surface_ = photoSurface; photoSurface->RegisterConsumerListener((sptr &)capturelistener); ``` 8. 使用上面创建的 Surface 创建拍照输出。 ``` sptr photoOutput = camManagerObj->CreatePhotoOutput(photoSurface); ``` 9. 将拍照输出添加到采集会话。 ``` result = captureSession->AddOutput(photoOutput); ``` 10. 将配置提交到采集会话。 ``` result = captureSession->CommitConfig(); ``` 11. 拍摄照片。 ``` result = ((sptr &)photoOutput)->Capture(); ``` 12. 释放采集会话资源。 ``` captureSession->Release(); ``` 13. 释放相机输入关闭相机。 ``` cameraInput->Release(); ``` ### 开始和停止预览 开始和停止预览的步骤: 1. 获取相机管理器实例并获取相机对象列表。 ``` sptr camManagerObj = CameraManager::GetInstance(); std::vector> cameraObjList = camManagerObj->GetCameras(); ``` 2. 使用相机对象创建相机输入来打开相机。 ``` sptr cameraInput = camManagerObj->CreateCameraInput(cameraObjList[0]); ``` 3. 创建采集会话。 ``` sptr captureSession = camManagerObj->CreateCaptureSession(); ``` 4. 开始配置采集会话。 ``` int32_t result = captureSession->BeginConfig(); ``` 5. 将相机输入添加到采集会话。 ``` result = captureSession->AddInput(cameraInput); ``` 6. 使用从窗口管理器获得的 Surface 创建预览输出用以在显示上渲染。预览的宽和高可以配置为所支持的 640x480 或 832x480 分辨率,如果想保存到文件,可以按照拍照流程提到步骤,创建 Surface,注册监听器以监听缓冲区更新。 ``` int32_t previewWidth = 640; int32_t previewHeight = 480; previewSurface->SetUserData(CameraManager::surfaceFormat, std::to_string(OHOS_CAMERA_FORMAT_YCRCB_420_SP)); sptr previewOutput = camManagerObj->CreateCustomPreviewOutput(previewSurface, previewWidth, previewHeight); ``` 7. 将预览输出添加到采集会话。 ``` result = captureSession->AddOutput(previewOutput); ``` 8. 将配置提交到采集会话。 ``` result = captureSession->CommitConfig(); ``` 9. 开始预览。 ``` result = captureSession->Start(); ``` 10. 需要时停止预览。 ``` result = captureSession->Stop(); ``` 11. 释放采集会话资源。 ``` captureSession->Release(); ``` 12. 释放相机输入关闭相机。 ``` cameraInput->Release(); ``` ### 视频录像 视频录像的步骤: 1. 获取相机管理器实例并获取相机对象列表。 ``` sptr camManagerObj = CameraManager::GetInstance(); std::vector> cameraObjList = camManagerObj->GetCameras(); ``` 2. 使用相机对象创建相机输入来打开相机。 ``` sptr cameraInput = camManagerObj->CreateCameraInput(cameraObjList[0]); ``` 3. 创建采集会话。 ``` sptr captureSession = camManagerObj->CreateCaptureSession(); ``` 4. 开始配置采集会话。 ``` int32_t result = captureSession->BeginConfig(); ``` 5. 将相机输入添加到采集会话。 ``` result = captureSession->AddInput(cameraInput); ``` 6. 通过 Surface 创建一个视频输出,来与音频合成并保存到文件,Surface 通过 Recoder 获取。如果想仅保存视频缓冲数据到文件里,可以按照拍照流程提到步骤,创建 Surface,注册监听器以监听缓冲区更新。录像的分辨率可以在录制器内配置为所支持的 1280x720 或 640x360 分辨率。 ``` videoSurface->SetUserData(CameraManager::surfaceFormat, std::to_string(OHOS_CAMERA_FORMAT_YCRCB_420_SP)); sptr videoOutput = camManagerObj->CreateVideoOutput(videoSurface); ``` 7. 将视频输出添加到采集会话。 ``` result = captureSession->AddOutput(videoOutput); ``` 8. 将配置提交到采集会话。 ``` result = captureSession->CommitConfig(); ``` 9. 开始视频录制。 ``` result = ((sptr &)videoOutput)->Start(); ``` 10. 需要时停止录制。 ``` result = ((sptr &)videoOutput)->Stop(); ``` 11. 释放采集会话的资源。 ``` captureSession->Release(); ``` 12. 释放相机输入关闭相机。 ``` cameraInput->Release(); ``` ### 切换多个照相机设备 以下演示如何切换多个照相机设备。最初在采集会话中有一个视频输出(video output)。如果用户想要切换其他 照相机,现存的相机输入和输出需要先移除并加入新的相机输入和输出(示例中使用的是photo output)。 1. 获取相机管理器实例并获取相机对象列表。 ``` sptr camManagerObj = CameraManager::GetInstance(); std::vector> cameraObjList = camManagerObj->GetCameras(); ``` 2. 使用相机对象创建相机输入来打开相机。 ``` sptr cameraInput = camManagerObj->CreateCameraInput(cameraObjList[0]); ``` 3. 创建采集会话。 ``` sptr captureSession = camManagerObj->CreateCaptureSession(); ``` 4. 开始配置采集会话。 ``` int32_t result = captureSession->BeginConfig() ``` 5. 将相机输入添加到采集会话。 ``` result = captureSession->AddInput(cameraInput); ``` 6. 通过Surface创建一个视频输出。 ``` sptr videoOutput = camManagerObj->CreateVideoOutput(videoSurface); ``` 7. 将视频输出添加到采集会话。 ``` result = captureSession->AddOutput(videoOutput); ``` 8. 将配置提交到采集会话。 ``` result = captureSession->CommitConfig(); ``` 9. 开始录制视频。 ``` result = ((sptr &)videoOutput)->Start(); ``` 10. 需要时停止录制。 ``` result = ((sptr &)videoOutput)->Stop(); ``` 11. 重新配置会话并移除相机输入和输出。 ``` int32_t result = captureSession->BeginConfig(); ``` 12. 在新的会话配置中移除相机输入。 ``` int32_t result = captureSession->RemoveInput(cameraInput); ``` 13. 同样移除相机输出。 ``` int32_t result = captureSession->RemoveOutut(videoOutput); ``` 14. 创建新的相机输入,并把它添加到采集会话。 ``` sptr cameraInput2 = camManagerObj->CreateCameraInput(cameraObjList[1]); result = captureSession->AddInput(cameraInput2); ``` 15. 创建拍照输出,成功创建后将拍照输出添加到采集会话。创建消费者 Surface 并注册监听器以监听新的拍照输出缓冲区更新。这个 Surface 用于新创建的拍照输出。 ``` // Get the surface sptr photoSurface = Surface::CreateSurfaceAsConsumer(); int32_t photoWidth = 1280; int32_t photoHeight = 960; photoSurface->SetDefaultWidthAndHeight(photoWidth, photoHeight); photoSurface->SetUserData(CameraManager::surfaceFormat, std::to_string(OHOS_CAMERA_FORMAT_JPEG)); sptr capturelistener = new(std::nothrow) CaptureSurfaceListener(); capturelistener->mode_ = MODE_PHOTO; capturelistener->surface_ = photoSurface; photoSurface->RegisterConsumerListener((sptr &)capturelistener); // Create the Photo Output sptr photoOutput = camManagerObj->CreatePhotoOutput(photoSurface); // Add the output to the capture session result = captureSession->AddOutput(photoOutput); ``` 16. 将配置提交到采集会话。 ``` result = captureSession->CommitConfig(); ``` 17. 释放被移出会话的相机输入。 ``` cameraInput->Release(); ``` 18. 拍摄照片。 ``` result = ((sptr &)photoOutput)->Capture(); ``` 19. 释放采集会话资源。 ``` captureSession->Release(); ``` 20. 释放相机输入关闭相机。 ``` cameraInput2->Release(); ``` ### 设置闪光灯 拍照和录像前可以在相机输入里设置闪光灯。 1. 在照相中设置闪光灯。 ``` cameraInput->LockForControl(); cameraInput->SetFlashMode(OHOS_CAMERA_FLASH_MODE_OPEN); cameraInput->UnlockForControl(); ``` 2. 在录像中设置闪光灯。 ``` cameraInput->LockForControl(); cameraInput->SetFlashMode(OHOS_CAMERA_FLASH_MODE_ALWAYS_OPEN); cameraInput->UnlockForControl(); ``` 3. 关闭闪光灯。 ``` cameraInput->LockForControl(); cameraInput->SetFlashMode(OHOS_CAMERA_FLASH_MODE_CLOSE); cameraInput->UnlockForControl(); ``` ## 相关仓 [multimedia\_camera\_framework](https://gitee.com/openharmony/multimedia_camera_framework)