1# Camera 2 3## Overview<a name="1"></a> 4### Camera<a name="2"></a> 5 6The OpenHarmony camera driver model implements the camera hardware device interface (HDI) and the camera pipeline model to manage camera devices. 7The camera driver model consists of the following layers: 8 9+ HDI implementation layer: implements standard ohos (OpenHarmony operating system) APIs for cameras. 10+ Framework layer: connects to the HDI implementation layer for control instruction and stream transfer, establishes data channels, and manages camera devices. 11+ Device adaptation layer: shields the differences between underlying chips and OSs for multi-platform adaptation. 12 13### Working Principles<a name="3"></a> 14 15The camera module is used to initialize services and devices, set up data channels, and configure, create, deliver, and capture streams. The figure below illustrates camera driver model. 16 17**Figure 1** HDF-based camera driver model 18 19 20 211. When the system starts, the camera_host process is created. The process enumerates underlying devices, creates a **DeviceManager** instance that manages the device tree, an object for each underlying device, and a **CameraHost** instance, and registers the **CameraHost** instance with the UHDF service. Through the UHDF service, the camera service can obtain the underlying **CameraDeviceHost** services to operate the hardware devices. Note that the **DeviceManager** instance can also be created by using the configuration table. 22 232. The Camera Service obtains the **CameraHost** instance through the CameraDeviceHost service. The **CameraHost** instance can be used to obtain the bottom-layer camera capabilities, turn on the flashlight, call the **Open()** interface to start the camera and create a connection, create a **DeviceManager** instance (powering on the bottom-layer hardware modules), and create a **CameraDevice** instance (providing the device control interface for the upper layer). When the **CameraDevice** instance is created, each submodule of PipelineCore is instantiated. Among the submodules, StreamPipelineCore is responsible for creating pipelines, and MetaQueueManager is responsible for reporting metadata. 24 253. The Camera Service configures stream and creates a **Stream** class through the CameraDevice module. The StreamPipelineStrategy module creates the node connection mode of the corresponding stream by using the mode issued by the upper layer and querying the configuration table. The StreamPipelineBuilder module creates a node and returns the pipeline to the StreamPipelineDispatcher module through the connection. The StreamPipelineDispatcher module dispatches pipelines. 26 274. The Camera Service controls the stream operations through the **Stream** instance. The **AttachBufferQueue()** interface is used to deliver the buffer queue requested from the display module to the bottom layer. The CameraDeviceDriverModel manages the buffer. After the **Capture()** interface is called to deliver commands, the bottom layer transfers the buffer to the upper layer. The Image Signal Processor (ISP) node obtains a specified number of buffers from the buffer queue and delivers the buffers to the bottom-layer ISP hardware. After filling the buffers, the ISP hardware transfers the buffers to the CameraDeviceDriverModel. The CameraDeviceDriverModel fills the created pipeline with the received buffers by using a loop thread. Each node processes the pipeline data and transfers the data to the upper layer by using a callback. At the same time, the buffers are freed for reuse. 28 295. The Camera Service delivers the photographing command through the **Capture()** interface. The **ChangeToOfflineStream()** interface is used to query the position of the photographing buffer. If the ISP hardware has output an image and sent the image data to the IPP node, the common photographing streams can be converted into offline streams. Otherwise, the close process is executed. The **ChangeToOfflineStream()** interface transfers **StreamInfo** to enable the offline stream to obtain the stream information of the common stream, confirms the node connection mode of the offline stream based on the configuration table, and creates the node connection of the offline stream. If the node connection has been created, the interface releases the node required by the non-offline stream through **CloseCamera()**. It then waits for the buffer to return from the bottom-layer pipeline to the upper layer and then releases the pipeline resources. 30 316. The Camera Service sends the **CaptureSetting** parameter to the CameraDeviceDriverModel through the **UpdateSettings()** interface of the **CameraDevice** instance. The CameraDeviceDriverModel forwards the parameter to each node through the StreamPipelineDispatcher module. The **CaptureSetting** parameter carried in **StartStreamingCapture()** and **Capture()** is forwarded to the node to which the stream belongs through the StreamPipelineDispatcher module. 32 337. The Camera Service controls underlying metadata reporting through the **EnableResult()** and **DisableResult()** interfaces. If the underlying metadata needs to be reported, the pipeline creates a buffer queue in the CameraDeviceDriverModel to collect and transfer metadata, queries the configuration table based on the StreamPipelineStrategy module, and creates and connects to the specified node through the StreamPipelineBuilder module. The MetaQueueManager module delivers the buffer to the bottom layer, and the bottom-layer node fills in data. The MetaQueueManager module then invokes the upper-layer callback to transfer the data to the upper layer. 34 358. The Camera Service calls the **Close()** interface of the **CameraDevice** class, and the **CameraDevice** instance calls the corresponding DeviceManager module to power off each hardware. If an offline stream exists in the subpipeline of the IPP node, the offline stream must be reserved until the execution is complete. 36 379. To implement dynamic frame control, a CollectBuffer thread is started in the StreamOperator. The CollectBuffer thread obtains a buffer from the buffer queue of each stream. If the frame rate of a stream needs to be controlled (1/n of the sensor output frame rate), the CollectBuffer thread can control the buffer packaging of each frame as required, and determine whether to collect the buffer of the stream. For example, if the output frame rate of the sensor is 120 fps and the preview stream frame rate is 30 fps, the CollectBuffer thread collects the buffer of the preview stream every 4 fps. 38 39 40 41## Development Guidelines<a name="4"></a> 42 43 44### When to Use<a name="5"></a> 45 46The camera module encapsulates camera operations in camera preview, photographing, and video streams to facilitate camera hardware operations and improve development efficiency. 47 48### Available APIs<a name="6"></a> 49 50- icamera_device.h 51 52 | API | Description | 53 | ------------------------------------------------------------ | ---------------------------- | 54 | CamRetCode GetStreamOperator(<br> const OHOS::sptr<IStreamOperatorCallback> &callback,<br> OHOS::sptr<IStreamOperator> &streamOperator) | Obtains the stream controller. | 55 | CamRetCode UpdateSettings(const std::shared_ptr<CameraSetting> &settings) | Updates device control parameters. | 56 | CamRetCode SetResultMode(const ResultCallbackMode &mode) | Sets the result callback mode and function.| 57 | CamRetCode GetEnabledResults(std::vector<MetaType> &results) | Obtains the enabled ResultMeta. | 58 | CamRetCode EnableResult(const std::vector<MetaType> &results) | Enables specific ResultMeta. | 59 | CamRetCode DisableResult(const std::vector<MetaType> &results) | Disables specific ResultMeta. | 60 | void Close() | Closes the camera device. | 61 62- icamera_device_callback.h 63 64 | API | Description | 65 | ------------------------------------------------------------ | ------------------------------------------------------------ | 66 | void OnError(ErrorType type, int32_t errorCode) | Called when an error occurs on the device to return error information. You need to implement this interface.| 67 | void OnResult(uint64_t timestamp, const std::shared_ptr<CameraMetadata> &result) | Callback invoked to report metadata related to the camera device. | 68 69 70- icamera_host.h 71 72 | API | Description | 73 | ------------------------------------------------------------ | ------------------------------ | 74 | CamRetCode SetCallback(const OHOS::sptr<ICameraHostCallback> &callback) | Sets the **ICameraHostCallback** API. | 75 | CamRetCode GetCameraIds(std::vector\<std::string\> &cameraIds) | Obtains the IDs of available camera devices.| 76 | CamRetCode GetCameraAbility(const std::string &cameraId,<br> std::shared_ptr<CameraAbility> &ability) | Obtains the abilities of a camera device. | 77 | CamRetCode OpenCamera(const std::string &cameraId,<br> const OHOS::sptr<ICameraDeviceCallback> &callback,<br> OHOS::sptr<ICameraDevice> &device) | Opens a camera. | 78 | CamRetCode SetFlashlight(const std::string &cameraId, bool &isEnable) | Turns on or off the flash. | 79 80- icamera_host_callback.h 81 82 | API | Description | 83 | ------------------------------------------------------------ | ---------------------- | 84 | void OnCameraStatus(const std::string &cameraId, CameraStatus status) | Reports camera status changes.| 85 | void OnFlashlightStatus(const std::string &cameraId, FlashlightStatus status) | Callback invoked to report the flash status changes. | 86 87- ioffline_stream_operator.h 88 89 | API | Description | 90 | ------------------------------------------------------------ | -------------- | 91 | CamRetCode CancelCapture(int captureId) | Cancels a capture request. | 92 | CamRetCode ReleaseStreams(const std::vector<int> &streamIds) | Releases streams. | 93 | CamRetCode Release() | Releases all offline streams.| 94 95- istream_operator.h 96 97 | API | Description | 98 | ------------------------------------------------------------ | -------------------------------- | 99 | CamRetCode IsStreamsSupported(<br> OperationMode mode,<br> const std::shared_ptr\<Camera::CameraMetadata\> &modeSetting,<br> const std::vector<std::shared_ptr<StreamInfo>> &info,<br> StreamSupportType &type) | Checks whether a stream can be added. | 100 | CamRetCode CreateStreams(const std::vector<std::shared_ptr<StreamInfo>> &streamInfos) | Creates streams. | 101 | CamRetCode ReleaseStreams(const std::vector<int> &streamIds) | Releases streams. | 102 | CamRetCode CommitStreams(OperationMode mode,<br> const std::shared_ptr<CameraMetadata> &modeSetting) | Configure streams. | 103 | CamRetCode GetStreamAttributes(<br> std::vector<std::shared_ptr<StreamAttribute>> &attributes) | Obtain stream attributes. | 104 | CamRetCode AttachBufferQueue(int streamId, const OHOS::sptr\<OHOS::IBufferProducer\> &producer) | Attaches a producer handle to a stream. | 105 | CamRetCode DetachBufferQueue(int streamId) | Detaches a producer handle from a stream.| 106 | CamRetCode Capture(int captureId,<br> const std::shared_ptr<CaptureInfo> &info, bool isStreaming) | Captures images. | 107 | CamRetCode CancelCapture(int captureId) | Cancels a capture. | 108 | CamRetCode ChangeToOfflineStream(const std::vector<int> &streamIds,<br> OHOS::sptr<IStreamOperatorCallback> &callback,<br> OHOS::sptr<IOfflineStreamOperator> &offlineOperator) | Changes a stream into an offline stream. | 109 110- istream_operator_callback.h 111 112 | API | Description | 113 | ------------------------------------------------------------ | ---------------------------------------- | 114 | void OnCaptureStarted(int32_t captureId, const std::vector<int32_t> &streamIds) | Called when a capture starts. | 115 | void OnCaptureEnded(int32_t captureId,<br> const std::vector<std::shared_ptr<CaptureEndedInfo>> &infos) | Called when a capture ends. | 116 | void OnCaptureError(int32_t captureId,<br> const std::vector<std::shared_ptr<CaptureErrorInfo>> &infos) | Called when an error occurs during the capture.| 117 | void OnFrameShutter(int32_t captureId,<br> const std::vector<int32_t> &streamIds, uint64_t timestamp) | Called when a frame is captured. | 118 119### How to Develop<a name="7"></a> 120To camera driver development procedure is as follows: 121 1221. Register a **CameraHost**. 123 124 Define the **HdfDriverEntry** structure to define the method for initializing a **CameraHost**. 125 ``` 126 struct HdfDriverEntry g_cameraHostDriverEntry = { 127 .moduleVersion = 1, 128 .moduleName = "camera_service", 129 .Bind = HdfCameraHostDriverBind, 130 .Init = HdfCameraHostDriverInit, 131 .Release = HdfCameraHostDriverRelease, 132 }; 133 HDF_INIT(g_cameraHostDriverEntry); // Register the HdfDriverEntry structure with the HDF. 134 ``` 135 1362. Initialize the **CameraHost**. 137 138 **HdfCameraHostDriverBind** defined in the **HdfDriverEntry** structure provides the registration of **CameraServiceDispatch()** and **CameraHostStubInstance()**. **CameraServiceDispatch()** is used to remotely call a method of the **CameraHost**, such as **OpenCamera()** and **SetFlashlight()**. **CameraHostStubInstance()** is used to initialize the camera device, which is called during system startup. 139 140 ``` 141 int HdfCameraHostDriverBind(HdfDeviceObject *deviceObject) 142 { 143 HDF_LOGI("HdfCameraHostDriverBind enter!"); 144 if (deviceObject == nullptr) { 145 HDF_LOGE("HdfCameraHostDriverBind: HdfDeviceObject is NULL !"); 146 return HDF_FAILURE; 147 } 148 HdfCameraService *hdfCameraService = reinterpret_cast<HdfCameraService *>(OsalMemAlloc(sizeof(HdfCameraService))); 149 if (hdfCameraService == nullptr) { 150 HDF_LOGE("HdfCameraHostDriverBind OsalMemAlloc HdfCameraService failed!"); 151 return HDF_FAILURE; 152 } 153 hdfCameraService->ioservice.Dispatch = CameraServiceDispatch; // Used to call methods of the CameraHost. 154 hdfCameraService->ioservice.Open = nullptr; 155 hdfCameraService->ioservice.Release = nullptr; 156 hdfCameraService->instance = CameraHostStubInstance(); // Initialize the camera device. 157 deviceObject->service = &hdfCameraService->ioservice; 158 return HDF_SUCCESS; 159 } 160 ``` 161 162 The following functions are the implementation of the methods of the **CameraHost**: 163 164 ``` 165 int32_t CameraHostStub::CameraHostServiceStubOnRemoteRequest(int cmdId, MessageParcel &data, 166 MessageParcel &reply, MessageOption &option) 167 { 168 switch(cmdId) { 169 case CMD_CAMERA_HOST_SET_CALLBACK: { 170 return CameraHostStubSetCallback(data, reply, option); 171 } 172 case CMD_CAMERA_HOST_GET_CAMERAID: { 173 return CameraHostStubGetCameraIds(data, reply, option); 174 } 175 case CMD_CAMERA_HOST_GET_CAMERA_ABILITY: { 176 return CameraHostStubGetCameraAbility(data, reply, option); 177 } 178 case CMD_CAMERA_HOST_OPEN_CAMERA: { 179 return CameraHostStubOpenCamera(data, reply, option); 180 } 181 case CMD_CAMERA_HOST_SET_FLASH_LIGHT: { 182 return CameraHostStubSetFlashlight(data, reply, option); 183 } 184 default: { 185 HDF_LOGE("%s: not support cmd %d", __func__, cmdId); 186 return HDF_ERR_INVALID_PARAM; 187 } 188 } 189 return HDF_SUCCESS; 190 } 191 ``` 192 193 **CameraHostStubInstance()** finally calls **CameraHostImpl::Init()** to obtain the physical camera and initialize the DeviceManager and PipelineCore modules. 194 1953. Obtain the **CameraHost**. 196 197 Call the **Get()** interface to obtain the **CameraHost** from the **CameraService**. The **Get()** interface is as follows: 198 199 ``` 200 sptr<ICameraHost> ICameraHost::Get(const char *serviceName) 201 { 202 do { 203 using namespace OHOS::HDI::ServiceManager::V1_0; 204 auto servMgr = IServiceManager::Get(); 205 if (servMgr == nullptr) { 206 HDF_LOGE("%s: IServiceManager failed!", __func__); 207 break; 208 } 209 auto remote = servMgr->GetService(serviceName); // Obtain the CameraHost based on serviceName. 210 if (remote != nullptr) { 211 sptr<CameraHostProxy> hostSptr = iface_cast<CameraHostProxy>(remote); // Return the CameraHostProxy object that contains interfaces such as OpenCamera() to the caller. 212 return hostSptr; 213 } 214 HDF_LOGE("%s: GetService failed! serviceName = %s", __func__, serviceName); 215 } while(false); 216 HDF_LOGE("%s: get %s failed!", __func__, serviceName); 217 return nullptr; 218 } 219 ``` 220 2214. Implement the **OpenCamera\(\)** interface. 222 223 The **CameraHostProxy** class provides five interfaces: **SetCallback()**, **GetCameraIds()**, **GetCameraAbility()**, **OpenCamera()**, and **SetFlashlight()**. The following describes **OpenCamera()**. 224 The **OpenCamera()** interface calls the remote **CameraHostStubOpenCamera()** interface through the CMD_CAMERA_HOST_OPEN_CAMERA to obtain an **ICameraDevice** object. 225 226 ``` 227 CamRetCode CameraHostProxy::OpenCamera(const std::string &cameraId, const OHOS::sptr<ICameraDeviceCallback> &callback, OHOS::sptr<ICameraDevice> &pDevice) 228 { 229 int32_t ret = Remote()->SendRequest(CMD_CAMERA_HOST_REMOTE_OPEN_CAMERA, data, reply, option); 230 if (ret != HDF_SUCCESS) { 231 HDF_LOGE("%{public}s: SendRequest failed, error code is %{public}d", __func__, ret); 232 return INVALID_ARGUMENT; 233 } 234 CamRetCode retCode = static_cast<CamRetCode>(reply.ReadInt32()); 235 bool flag = reply.ReadBool(); 236 if (flag) { 237 sptr<IRemoteObject> remoteCameraDevice = reply.ReadRemoteObject(); 238 if (remoteCameraDevice == nullptr) { 239 HDF_LOGE("%{public}s: CameraHostProxy remoteCameraDevice is null", __func__); 240 } 241 pDevice = OHOS::iface_cast<ICameraDevice>(remoteCameraDevice); 242 } 243 return retCode; 244 } 245 ``` 246 247 **Remote()->SendRequest** calls **CameraHostServiceStubOnRemoteRequest()**, enters the **CameraHostStubOpenCamera()** interface based on **cmdId**, and finally calls **CameraHostImpl::OpenCamera()** to obtain a **CameraDevice** and power on the camera hardware. 248 249 ``` 250 CamRetCode CameraHostImpl::OpenCamera(const std::string &cameraId, const OHOS::sptr<ICameraDeviceCallback> &callback, OHOS::sptr<ICameraDevice> &device) 251 { 252 std::shared_ptr<CameraDeviceImpl> cameraDevice = std::static_pointer_cast<CameraDeviceImpl>(itr->second); 253 if (cameraDevice == nullptr) { 254 CAMERA_LOGE("camera device is null."); 255 return INSUFFICIENT_RESOURCES; 256 } 257 CamRetCode ret = cameraDevice->SetCallback(callback); 258 if (ret != NO_ERROR) { 259 CAMERA_LOGW("set camera device callback failed."); 260 return ret; 261 } 262 CameraHostConfig *config = CameraHostConfig::GetInstance(); 263 if (config == nullptr) { 264 return INVALID_ARGUMENT; 265 } 266 std::vector<std::string> phyCameraIds; 267 RetCode rc = config->GetPhysicCameraIds(cameraId, phyCameraIds); 268 if (rc != RC_OK) { 269 CAMERA_LOGE("get physic cameraId failed."); 270 return DEVICE_ERROR; 271 } 272 if (CameraPowerUp(cameraId, phyCameraIds) != RC_OK) { // Power on the camera hardware. 273 CAMERA_LOGE("camera powerup failed."); 274 CameraPowerDown(phyCameraIds); 275 return DEVICE_ERROR; 276 } 277 278 auto sptrDevice = deviceBackup_.find(cameraId); 279 if (sptrDevice == deviceBackup_.end()) { 280 deviceBackup_[cameraId] = cameraDevice.get(); 281 } 282 device = deviceBackup_[cameraId]; 283 cameraDevice->SetStatus(true); 284 return NO_ERROR; 285 } 286 ``` 287 2885. Implement the **GetStreamOperator\(\)** interface. 289 290 **CameraDeviceImpl** defines interfaces such as **GetStreamOperator()**, **UpdateSettings()**, **SetResultMode()**, and **GetEnabledResult()**. The following is an example of implementing the **GetStreamOperator()** interface: 291 292 ``` 293 CamRetCode CameraDeviceImpl::GetStreamOperator(const OHOS::sptr<IStreamOperatorCallback> &callback, 294 OHOS::sptr<IStreamOperator> &streamOperator) 295 { 296 if (callback == nullptr) { 297 CAMERA_LOGW("input callback is null."); 298 return INVALID_ARGUMENT; 299 } 300 spCameraDeviceCallback_ = callback; 301 if (spStreamOperator_ == nullptr) { 302 // Here, an spStreamOperator object is created and passed to the caller for stream operations. 303 spStreamOperator_ = new(std::nothrow) StreamOperatorImpl(spCameraDeviceCallback_, shared_from_this()); 304 if (spStreamOperator_ == nullptr) { 305 CAMERA_LOGW("create stream operator failed."); 306 return DEVICE_ERROR; 307 } 308 ismOperator_ = spStreamOperator_; 309 } 310 streamOperator = ismOperator_; 311 312 spStreamOperator_->SetRequestCallback([this](){ 313 spCameraDeviceCallback_->OnError(REQUEST_TIMEOUT, 0); 314 }); 315 } 316 ``` 317 3186. Create a stream. 319 320 Fill in the **StreamInfo** structure before creating a stream by calling **CreateStreams()**. 321 322 ``` 323 using StreamInfo = struct _StreamInfo { 324 int streamId_; 325 int width_; // Stream width 326 int height_; // Stream height 327 int format_; // Stream format, for example, PIXEL_FMT_YCRCB_420_SP 328 int dataSpace_; 329 StreamIntent intent_; // StreamIntent, for example, PREVIEW 330 bool tunneledMode_; 331 OHOS::sptr<OHOS::IBufferProducer> bufferQueue_; // The stream buffer queue can be created by using the streamCustomer->CreateProducer() interface. 332 int minFrameDuration_; 333 EncodeType encodeType_; 334 }; 335 ``` 336 337 The **CreateStreams()** interface in the **StreamOperatorImpl** class is used to create a **StreamBase** instance, which can then be used to initialize operations such as **CreateBufferPool()** by using the **init()** interface. 338 339 ``` 340 RetCode StreamOperatorImpl::CreateStream(const std::shared_ptr<StreamInfo>& streamInfo) 341 { 342 static std::map<StreamIntent, std::string> typeMap = { 343 {PREVIEW, "PREVIEW"}, 344 {VIDEO, "VIDEO"}, 345 {STILL_CAPTURE, "STILL_CAPTURE"}, 346 {POST_VIEW, "POST_VIEW"}, {ANALYZE, "ANALYZE"}, 347 {CUSTOM, "CUSTOM"} 348 }; 349 350 auto itr = typeMap.find(streamInfo->intent_); 351 if (itr == typeMap.end()) { 352 CAMERA_LOGE("do not support stream type. [type = %{public}d]", streamInfo->intent_); 353 return RC_ERROR; 354 } 355 std::shared_ptr<StreamBase> stream = StreamFactory::Instance().CreateShared(itr->second); // Create a StreamBase instance. 356 RetCode rc = stream->Init(streamInfo); 357 return RC_OK; 358 } 359 ``` 360 3617. Configure the stream. 362 363 Use the **CommitStreams()** interface to configure the stream, including PipelineCore initialization and creation. It must be called after the stream is created. 364 365 ``` 366 CamRetCode StreamOperatorImpl::CommitStreams(OperationMode mode, const std::shared_ptr<Camera::CameraMetadata>& modeSetting) 367 { 368 auto cameraDevice = cameraDevice_.lock(); 369 if (cameraDevice == nullptr) { 370 CAMERA_LOGE("camera device closed."); 371 return CAMERA_CLOSED; 372 } 373 std::shared_ptr<IPipelineCore> PipelineCore = 374 std::static_pointer_cast<CameraDeviceImpl>(cameraDevice)->GetPipelineCore(); 375 if (PipelineCore == nullptr) { 376 CAMERA_LOGE("Failed to obtain PipelineCore."); 377 return CAMERA_CLOSED; 378 } 379 380 streamPipeCore_ = PipelineCore->GetStreamPipelineCore(); 381 if (streamPipeCore_ == nullptr) { 382 CAMERA_LOGE("Failed to obtain the stream PipelineCore."); 383 return DEVICE_ERROR; 384 } 385 386 RetCode rc = streamPipeCore_->Init(); // Initialize the PipelineCore. 387 if (rc != RC_OK) { 388 CAMERA_LOGE("Failed to initialize the stream PipelineCore."); 389 return DEVICE_ERROR; 390 } 391 rc = streamPipeCore_->CreatePipeline(mode); // Create a pipeline. 392 if (rc != RC_OK) { 393 CAMERA_LOGE("Failed to create pipeline."); 394 return INVALID_ARGUMENT; 395 } 396 return NO_ERROR; 397 } 398 ``` 399 4008. Capture images. 401 402 Fill in the **CaptureInfo** structure before calling the **Capture()** method. 403 404 ``` 405 using CaptureInfo = struct _CaptureInfo { 406 std::vector<int> streamIds_; // IDs of streams to be captured 407 std::shared_ptr<Camera::CameraMetadata> captureSetting_; // Camera ability can be obtained through the GetCameraAbility() interface of CameraHost. 408 bool enableShutterCallback_; 409 }; 410 ``` 411 412 Use the **Capture()** interface in **StreamOperatorImpl** to call the **CreateCapture()** interface to capture streams. 413 414 ``` 415 CamRetCode StreamOperatorImpl::Capture(int captureId, const std::shared_ptr<CaptureInfo>& captureInfo, bool isStreaming) 416 { 417 if (!ValidCaptureInfo(captureId, captureInfo)) { 418 CAMERA_LOGE("capture streamIds is empty. [captureId = %d]", captureId); 419 return INVALID_ARGUMENT; 420 } 421 std::shared_ptr<CameraCapture> cameraCapture = nullptr; 422 RetCode rc = CreateCapture(captureId, captureInfo, isStreaming, cameraCapture); 423 if (rc != RC_OK) { 424 CAMERA_LOGE("create capture is failed."); 425 return DEVICE_ERROR; 426 } 427 428 { 429 std::unique_lock<std::mutex> lock(captureMutex_); 430 camerCaptureMap_.insert(std::make_pair(captureId, cameraCapture)); 431 } 432 433 rc = StartThread(); 434 if (rc != RC_OK) { 435 CAMERA_LOGE("preview start failed."); 436 return DEVICE_ERROR; 437 } 438 return NO_ERROR; 439 } 440 ``` 441 4429. Cancel the capture and release the offline stream. 443 444 Use the **CancelCapture()** interface in the **StreamOperatorImpl** class to cancel the stream capture based on **captureId**. 445 446 ``` 447 CamRetCode StreamOperatorImpl::CancelCapture(int captureId) 448 { 449 auto itr = camerCaptureMap_.find(captureId); // Search for the CameraCapture object in the Map based on the captureId. 450 RetCode rc = itr->second->Cancel(); // Call the Cancel() interface in CameraCapture to cancel the stream capture. 451 std::unique_lock<std::mutex> lock(captureMutex_); 452 camerCaptureMap_.erase(itr); // Erase the CameraCapture object. 453 return NO_ERROR; 454 } 455 ``` 456 457 Use the **ReleaseStreams()** interface in the **StreamOperatorImpl** class t release the streams created by using **CreateStream()** and **CommitStreams()** and destroy the pipeline. 458 459 ``` 460 CamRetCode StreamOperatorImpl::ReleaseStreams(const std::vector<int>& streamIds) 461 { 462 RetCode rc = DestroyStreamPipeline(streamIds); // Destroy the pipeline based on streamIds. 463 rc = DestroyHostStreamMgr(streamIds); 464 rc = DestroyStreams(streamIds); // Destroy the stream specified by streamIds. 465 return NO_ERROR; 466 } 467 ``` 468 46910. Close the camera device. 470 471 Use the **Close()** interface in the **CameraDeviceImpl** class to close the camera device. This interface calls **PowerDown()** in the **DeviceManager** to power off the device. 472 473### Development Example<a name = "8"></a> 474 475There is a camera demo in the **/drivers/peripheral/camera/hal/init** directory. After system startup, the executable file **ohos_camera_demo** is generated in the **/vendor/bin** directory. This demo can implement basic camera capabilities such as preview and photographing. The following uses the demo as an example to describe how to use the HDI to write the **PreviewOn()** and **CaptureON()** instances. For details, see [ohos_camera_demo](https://gitee.com/openharmony/drivers_peripheral/tree/master/camera/hal/init). 476 4771. Construct a CameraDemo object in the **main** function. This object contains methods for initializing the camera and starting, stopping, and releasing streams. The **mainDemo->InitSensors()** function is used to initialize the **CameraHost**, and the **mainDemo->InitCameraDevice()** function is used to initialize the **CameraDevice**. 478 479 ``` 480 int main(int argc, char** argv) 481 { 482 RetCode rc = RC_OK; 483 auto mainDemo = std::make_shared<CameraDemo>(); 484 rc = mainDemo->InitSensors(); // Initialize the CameraHost. 485 if (rc == RC_ERROR) { 486 CAMERA_LOGE("main test: mainDemo->InitSensors() error\n"); 487 return -1; 488 } 489 490 rc = mainDemo->InitCameraDevice(); // Initialize the CameraDevice. 491 if (rc == RC_ERROR) { 492 CAMERA_LOGE("main test: mainDemo->InitCameraDevice() error\n"); 493 return -1; 494 } 495 496 rc = PreviewOn(0, mainDemo); // Configure and enable streams. 497 if (rc != RC_OK) { 498 CAMERA_LOGE("main test: PreviewOn() error demo exit"); 499 return -1; 500 } 501 502 ManuList(mainDemo, argc, argv); // Print the menu to the console. 503 504 return RC_OK; 505 } 506 ``` 507 508 The function used to initialize the **CameraHost** is implemented as follows, where the HDI **ICameraHost::Get()** is called to obtain the **demoCameraHost** and set the callback: 509 510 ``` 511 RetCode CameraDemo::InitSensors() 512 { 513 demoCameraHost_ = ICameraHost::Get(DEMO_SERVICE_NAME); 514 if (demoCameraHost_ == nullptr) { 515 CAMERA_LOGE("demo test: ICameraHost::Get error"); 516 return RC_ERROR; 517 } 518 519 hostCallback_ = new CameraHostCallback(); 520 rc = demoCameraHost_->SetCallback(hostCallback_); 521 return RC_OK; 522 } 523 ``` 524 525 The implementation of the function for initializing the **CameraDevice** is as follows, where the **GetCameraIds(cameraIds_)**, **GetCameraAbility(cameraId, ability_)**, and **OpenCamera(cameraIds_.front(), callback, demoCameraDevice_)** interfaces are called to obtain the **demoCameraHost**. 526 527 ``` 528 RetCode CameraDemo::InitCameraDevice() 529 { 530 (void)demoCameraHost_->GetCameraIds(cameraIds_); 531 const std::string cameraId = cameraIds_.front(); 532 demoCameraHost_->GetCameraAbility(cameraId, ability_); 533 534 sptr<CameraDeviceCallback> callback = new CameraDeviceCallback(); 535 rc = demoCameraHost_->OpenCamera(cameraIds_.front(), callback, demoCameraDevice_); 536 return RC_OK; 537 } 538 ``` 539 5402. Implement the **PreviewOn()** interface to configure streams, enable preview streams, and start stream capture. After this interface is called, the camera preview channel starts running. Two streams are enabled: preview stream and capture or video stream. Only the preview stream will be captured. 541 542 ``` 543 static RetCode PreviewOn(int mode, const std::shared_ptr<CameraDemo>& mainDemo) 544 { 545 rc = mainDemo->StartPreviewStream(); // Configure the preview stream. 546 if (mode == 0) { 547 rc = mainDemo->StartCaptureStream(); // Configure the capture stream. 548 } else { 549 rc = mainDemo->StartVideoStream(); // Configure the video stream. 550 } 551 552 rc = mainDemo->CaptureON(STREAM_ID_PREVIEW, CAPTURE_ID_PREVIEW, CAPTURE_PREVIEW); // Capture the preview stream. 553 return RC_OK; 554 } 555 ``` 556 557 The **StartCaptureStream()**, **StartVideoStream()**, and **StartPreviewStream()** interfaces call the **CreateStream()** interface with different input parameters. 558 559 ``` 560 RetCode CameraDemo::StartVideoStream() 561 { 562 RetCode rc = RC_OK; 563 if (isVideoOn_ == 0) { 564 isVideoOn_ = 1; 565 rc = CreateStream(STREAM_ID_VIDEO, streamCustomerVideo_, VIDEO); // To enable the preview stream or capture stream, change the input parameters. 566 } 567 return RC_OK; 568 } 569 ``` 570 571 The **CreateStream()** interface calls the HDI to configure and create a stream. Specifically, the interface first calls the HDI to obtain a **StreamOperation** object and then creates a **StreamInfo** object. Call **CreateStreams()** and **CommitStreams()** to create and configure a stream. 572 573 ``` 574 RetCode CameraDemo::CreateStreams(const int streamIdSecond, StreamIntent intent) 575 { 576 std::vector<std::shared_ptr<StreamInfo>> streamInfos; 577 std::vector<std::shared_ptr<StreamInfo>>().swap(streamInfos); 578 GetStreamOpt(); // Obtain a StreamOperator object. 579 std::shared_ptr<StreamInfo> previewStreamInfo = std::make_shared<StreamInfo>(); 580 SetStreamInfo(previewStreamInfo, streamCustomerPreview_, STREAM_ID_PREVIEW, PREVIEW); // Fill in the StreamInfo. 581 if (previewStreamInfo->bufferQueue_ == nullptr) { 582 CAMERA_LOGE("demo test: CreateStream CreateProducer(); is nullptr\n"); 583 return RC_ERROR; 584 } 585 streamInfos.push_back(previewStreamInfo); 586 587 std::shared_ptr<StreamInfo> secondStreamInfo = std::make_shared<StreamInfo>(); 588 if (streamIdSecond == STREAM_ID_CAPTURE) { 589 SetStreamInfo(secondStreamInfo, streamCustomerCapture_, STREAM_ID_CAPTURE, intent); 590 } else { 591 SetStreamInfo(secondStreamInfo, streamCustomerVideo_, STREAM_ID_VIDEO, intent); 592 } 593 594 if (secondStreamInfo->bufferQueue_ == nullptr) { 595 CAMERA_LOGE("demo test: CreateStreams CreateProducer() secondStreamInfo is nullptr\n"); 596 return RC_ERROR; 597 } 598 streamInfos.push_back(secondStreamInfo); 599 600 rc = streamOperator_->CreateStreams(streamInfos); // Create a stream. 601 if (rc != Camera::NO_ERROR) { 602 CAMERA_LOGE("demo test: CreateStream CreateStreams error\n"); 603 return RC_ERROR; 604 } 605 606 rc = streamOperator_->CommitStreams(Camera::NORMAL, ability_); 607 if (rc != Camera::NO_ERROR) { 608 CAMERA_LOGE("demo test: CreateStream CommitStreams error\n"); 609 std::vector<int> streamIds = {STREAM_ID_PREVIEW, streamIdSecond}; 610 streamOperator_->ReleaseStreams(streamIds); 611 return RC_ERROR; 612 } 613 return RC_OK; 614 } 615 ``` 616 617 The **CaptureON()** interface calls the **Capture()** interface of **StreamOperator** to obtain camera data, rotate the buffer, and start a thread to receive data of the corresponding type. 618 619 ``` 620 RetCode CameraDemo::CaptureON(const int streamId, const int captureId, CaptureMode mode) 621 { 622 std::shared_ptr<Camera::CaptureInfo> captureInfo = std::make_shared<Camera::CaptureInfo>(); // Create and fill in CaptureInfo. 623 captureInfo->streamIds_ = {streamId}; 624 captureInfo->captureSetting_ = ability_; 625 captureInfo->enableShutterCallback_ = false; 626 627 int rc = streamOperator_->Capture(captureId, captureInfo, true);// The stream capture starts, and buffer recycling starts. 628 if (mode == CAPTURE_PREVIEW) { 629 streamCustomerPreview_->ReceiveFrameOn(nullptr); // Create a preview thread to receive the passed buffers. 630 } else if (mode == CAPTURE_SNAPSHOT) { 631 streamCustomerCapture_->ReceiveFrameOn([this](void* addr, const uint32_t size) { // Create a capture thread to receive the passed buffers through the StoreImage callback. 632 StoreImage(addr, size); 633 }); 634 } else if (mode == CAPTURE_VIDEO) { 635 OpenVideoFile(); 636 streamCustomerVideo_->ReceiveFrameOn([this](void* addr, const uint32_t size) {// Create a video thread to receive the passed buffer by calling the StoreVideo callback. 637 StoreVideo(addr, size); 638 }); 639 } 640 return RC_OK; 641 } 642 ``` 643 6443. Implement the **ManuList()** function to obtain characters from the console through the **fgets()** interface. Different characters correspond to different capabilities provided by the demo, and the functionality menu is printed. 645 646 ``` 647 static void ManuList(const std::shared_ptr<CameraDemo>& mainDemo, 648 const int argc, char** argv) 649 { 650 int idx, c; 651 int awb = 1; 652 constexpr char shortOptions[] = "h:cwvaqof:"; 653 c = getopt_long(argc, argv, shortOptions, longOptions, &idx); 654 while(1) { 655 switch (c) { 656 case 'h': 657 c = PutMenuAndGetChr(); // Print the menu. 658 break; 659 660 case 'f': 661 FlashLightTest(mainDemo); // Test the flashlight capability. 662 c = PutMenuAndGetChr(); 663 break; 664 case 'o': 665 OfflineTest(mainDemo); // Test the offline capability. 666 c = PutMenuAndGetChr(); 667 break; 668 case 'c': 669 CaptureTest(mainDemo); // Test the capture capability. 670 c = PutMenuAndGetChr(); 671 break; 672 case 'w': // Test the AWB capability. 673 if (awb) { 674 mainDemo->SetAwbMode(OHOS_CAMERA_AWB_MODE_INCANDESCENT); 675 } else { 676 mainDemo->SetAwbMode(OHOS_CAMERA_AWB_MODE_OFF); 677 } 678 awb = !awb; 679 c = PutMenuAndGetChr(); 680 break; 681 case 'a': // Test the AE capability. 682 mainDemo->SetAeExpo(); 683 c = PutMenuAndGetChr(); 684 break; 685 case 'v': // Test the video capability. 686 VideoTest(mainDemo); 687 c = PutMenuAndGetChr(); 688 break; 689 case 'q': // Exit the demo. 690 PreviewOff(mainDemo); 691 mainDemo->QuitDemo(); 692 exit(EXIT_SUCCESS); 693 694 default: 695 CAMERA_LOGE("main test: command error please retry input command"); 696 c = PutMenuAndGetChr(); 697 break; 698 } 699 } 700 } 701 ``` 702 703 The **PutMenuAndGetChr()** interface prints the menu of the demo and calls **fgets()** to wait for commands from the console. 704 705 ``` 706 static int PutMenuAndGetChr(void) 707 { 708 constexpr uint32_t inputCount = 50; 709 int c = 0; 710 char strs[inputCount]; 711 Usage(stdout); 712 CAMERA_LOGD("pls input command(input -q exit this app)\n"); 713 fgets(strs, inputCount, stdin); 714 715 for (int i = 0; i < inputCount; i++) { 716 if (strs[i] != '-') { 717 c = strs[i]; 718 break; 719 } 720 } 721 return c; 722 } 723 ``` 724 725 The console outputs the menu details as follows: 726 727 ``` 728 "Options:\n" 729 "-h | --help Print this message\n" 730 "-o | --offline stream offline test\n" 731 "-c | --capture capture one picture\n" 732 "-w | --set WB Set white balance Cloudy\n" 733 "-v | --video capture Video of 10s\n" 734 "-a | --Set AE Set Auto exposure\n" 735 "-f | --Set Flashlight Set flashlight ON 5s OFF\n" 736 "-q | --quit stop preview and quit this app\n"); 737 ``` 738 739 740