1# Camera 2 3## Overview 4### Function 5 6The OpenHarmony camera driver model provides the camera hardware device interface (HDI) and the camera pipeline model to manage camera devices. The camera driver model is divided into three layers: 7 8+ HDI implementation layer: implements standard ohos (OpenHarmony operating system) APIs for cameras. 9+ Framework layer: interacts with the HDI implementation layer to set up data channels and operate camera devices. 10+ Device adaptation layer: supports different platforms by shielding the differences in underlying chips and operating systems. 11 12### Working Principles 13 14The camera module is used to initialize services and devices, set up data channels, and configure, create, deliver, and capture streams. The following figure shows the camera driver model. 15 16**Figure 1** HDF-based camera driver model 17 18 19 201. When the system starts, the camera_host process is created. The process enumerates underlying devices, creates a **DeviceManager** instance (to manage the device tree), an object for each underlying device, and a **CameraHost** instance, and registers the **CameraHost** instance with the user-mode HDF (UHDF) service. Through the UHDF service, the camera service can obtain the underlying **CameraDeviceHost** services to operate the hardware devices. The **DeviceManager** instance can also be created by using the configuration table. 21 222. The Camera Service obtains the **CameraHost** instance through the CameraDeviceHost service. 23 24 25The **CameraHost** instance can be used to obtain the underlying camera capabilities, turn on the flashlight, call **Open()** to start a camera and set up a connection with the camera, create a **DeviceManager** instance (to power on the hardware modules), and create a **CameraDevice** instance (to provide the device control interface for the upper layer). 26 27 When the **CameraDevice** instance is created, the PipelineCore modules will be instantiated. The StreamPipelineCore module creates pipelines, and the MetaQueueManager module reports metadata. 28 293. 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. 30 314. The Camera Service controls the stream operations through the **Stream** instance. 32 33 **AttachBufferQueue()** delivers the buffer queue requested from the display module to the bottom layer. The CameraDeviceDriverModel manages the buffer. After **Capture()** 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 in a callback. At the same time, the buffers are freed to the buffer queue for reuse. 34 355. The Camera Service delivers the photographing command through **Capture()**. **ChangeToOfflineStream()** 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 stream can be converted into an offline stream. Otherwise, the close process is executed. **ChangeToOfflineStream()** passes **StreamInfo** to enable the offline stream to obtain the stream information of the common stream, determines the node connection mode of the offline stream based on the configuration table, and creates the node connection for the offline stream (if the node connection has been created, the node required by the non-offline stream will be closed by **CloseCamera**.) When the buffer is transferred from the pipeline to the upper layer, the pipeline resources are released. 36 376. The Camera Service sends the **CaptureSetting** parameter to the CameraDeviceDriverModel through **UpdateSettings()** 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. 38 397. The Camera Service uses **EnableResult()** and **DisableResult()** to control the reporting of underlying metadata. 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. 40 418. The Camera Service calls **Close()** 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. 42 439. 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. 44 45 46 47## Development Guidelines 48 49 50### When to Use 51 52The camera module encapsulates camera operations in camera preview, photographing, and video streams to implement camera hardware operations and improve development efficiency. 53 54### Available APIs 55 56The following table describes the C++ APIs generated from the Interface Definition Language (IDL). For details about the interface declaration, see the IDL files in [https://gitee.com/openharmony/drivers_interface/tree/master/camera/v1_1/](https://gitee.com/openharmony/drivers_interface/tree/master/camera). 57 58The parameters passed in the HDI cannot exceed the capability range obtained by **GetCameraAbility**. Even if the parameters beyond the capability range can be passed in APIs such as **UpdateSettings**, **CommitStreams**, and **Capture** with no error returned, unexpected behavior may be caused. 59 60- icamera_device.h 61 62 | API | Description | 63 | ------------------------------------------------------------ | ------------------------------------------------------------ | 64 | int32_t GetStreamOperator_V1_1(const sptr\<OHOS::HDI::Camera::V1_0::IStreamOperatorCallback\>& callbackObj,sptr\<OHOS::HDI::Camera::V1_1::IStreamOperator\>& streamOperator) | Obtains the stream controller. | 65 66- icamera_host.h 67 68 | API | Description | 69 | ------------------------------------------------------------ | ------------------------------------------------------------ | 70 | int32_t OpenCamera_V1_1(const std::string& cameraId, const sptr\<OHOS::HDI::Camera::V1_0::ICameraDeviceCallback\>& callbackObj, sptr\<OHOS::HDI::Camera::V1_1::ICameraDevice\>& device) | Opens a camera. | 71 | int32_t PreLaunch(const PrelaunchConfig& config) | Pre-starts the camera. | 72 73- istream_operator.h 74 75 | API | Description | 76 | ------------------------------------------------------------ | ------------------------------------------------------------ | 77 | int32_t IsStreamsSupported_V1_1(OperationMode mode,<br>const std::vector<uint8_t>& modeSetting,<br>const std::vector<StreamInfo_V1_1>& infos,<br>StreamSupportType& type) | Checks whether a stream can be added. | 78 | int32_t CreateStreams_V1_1(const std::vector<StreamInfo_V1_1>& streamInfos) | Creates streams. | 79 80 81### How to Develop 82The camera driver development procedure is as follows: 83 841. Register a **CameraHost** instance. 85 86 Define the **HdfDriverEntry** structure to define the method for initializing **CameraHost**. For details about the code, see **drivers/peripheral/camera/interfaces/hdi_ipc/camera_host_driver.cpp**. 87 ```c++ 88 struct HdfDriverEntry g_cameraHostDriverEntry = { 89 .moduleVersion = 1, 90 .moduleName = "camera_service", 91 .Bind = HdfCameraHostDriverBind, 92 .Init = HdfCameraHostDriverInit, 93 .Release = HdfCameraHostDriverRelease, 94 }; 95 HDF_INIT(g_cameraHostDriverEntry); // Register the HdfDriverEntry structure with the HDF. 96 ``` 97 982. Initialize the **CameraHost** service. 99 100 The **HdfCameraHostDriverBind()** method defined in the **HdfDriverEntry** structure registers **CameraServiceDispatch()** and **CameraHostStubInstance()**. **CameraServiceDispatch()** is used to remotely call the **CameraHost** methods, such as **OpenCamera()** and **SetFlashlight()**. **CameraHostStubInstance()** is called during the system startup to initialize the camera. 101 102 ```c++ 103 static int HdfCameraHostDriverBind(struct HdfDeviceObject *deviceObject) 104 { 105 HDF_LOGI("HdfCameraHostDriverBind enter"); 106 107 auto *hdfCameraHostHost = new (std::nothrow) HdfCameraHostHost; 108 if (hdfCameraHostHost == nullptr) { 109 HDF_LOGE("%{public}s: failed to create HdfCameraHostHost object", __func__); 110 return HDF_FAILURE; 111 } 112 113 hdfCameraHostHost->ioService.Dispatch = CameraHostDriverDispatch; // Provide a method to remotely call a CameraHost method. 114 hdfCameraHostHost->ioService.Open = NULL; 115 hdfCameraHostHost->ioService.Release = NULL; 116 117 auto serviceImpl = ICameraHost::Get(true); 118 if (serviceImpl == nullptr) { 119 HDF_LOGE("%{public}s: failed to get of implement service", __func__); 120 delete hdfCameraHostHost; 121 return HDF_FAILURE; 122 } 123 124 hdfCameraHostHost->stub = OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl, 125 ICameraHost::GetDescriptor()); // Initialize the camera. 126 if (hdfCameraHostHost->stub == nullptr) { 127 HDF_LOGE("%{public}s: failed to get stub object", __func__); 128 delete hdfCameraHostHost; 129 return HDF_FAILURE; 130 } 131 132 deviceObject->service = &hdfCameraHostHost->ioService; 133 return HDF_SUCCESS; 134 } 135 ``` 136 137 The following functions are the implementation of the methods of the **CameraHost**: 138 139 ```c++ 140 int32_t CameraHostStub::CameraHostServiceStubOnRemoteRequest(int cmdId, MessageParcel &data, 141 MessageParcel &reply, MessageOption &option) 142 { 143 switch(cmdId) { 144 case CMD_CAMERA_HOST_SET_CALLBACK: { 145 return CameraHostStubSetCallback(data, reply, option); 146 } 147 case CMD_CAMERA_HOST_GET_CAMERAID: { 148 return CameraHostStubGetCameraIds(data, reply, option); 149 } 150 case CMD_CAMERA_HOST_GET_CAMERA_ABILITY: { 151 return CameraHostStubGetCameraAbility(data, reply, option); 152 } 153 case CMD_CAMERA_HOST_OPEN_CAMERA: { 154 return CameraHostStubOpenCamera(data, reply, option); 155 } 156 case CMD_CAMERA_HOST_SET_FLASH_LIGHT: { 157 return CameraHostStubSetFlashlight(data, reply, option); 158 } 159 default: { 160 HDF_LOGE("%s: not support cmd %d", __func__, cmdId); 161 return HDF_ERR_INVALID_PARAM; 162 } 163 } 164 return HDF_SUCCESS; 165 } 166 ``` 167 168 **CameraHostStubInstance()** finally calls **CameraHostImpl::Init()** to obtain the physical camera and initialize the DeviceManager and PipelineCore modules. 169 1703. Obtain the **CameraHost** service. 171 172 Use **Get()** to obtain the **CameraHost** from the **CameraService**. The **Get()** method is as follows: 173 174 ```c++ 175 sptr<ICameraHost> ICameraHost::Get(const char *serviceName) 176 { 177 do { 178 using namespace OHOS::HDI::ServiceManager::V1_0; 179 auto servMgr = IServiceManager::Get(); 180 if (servMgr == nullptr) { 181 HDF_LOGE("%s: IServiceManager failed!", __func__); 182 break; 183 } 184 auto remote = servMgr->GetService(serviceName); // Obtain the CameraHost based on serviceName. 185 if (remote != nullptr) { 186 sptr<CameraHostProxy> hostSptr = iface_cast<CameraHostProxy>(remote); // Return the CameraHostProxy object that contains interfaces such as OpenCamera() to the caller. 187 return hostSptr; 188 } 189 HDF_LOGE("%s: GetService failed! serviceName = %s", __func__, serviceName); 190 } while(false); 191 HDF_LOGE("%s: get %s failed!", __func__, serviceName); 192 return nullptr; 193 } 194 ``` 195 1964. Open a camera device. 197 198 The **CameraHostProxy** class provides **SetCallback()**, **GetCameraIds()**, **GetCameraAbility()**, **OpenCamera()**, and **SetFlashlight()**. The following describes **OpenCamera()**. 199 Use **OpenCamera()** to call the remote **CameraHostStubOpenCamera()** through the **CMD_CAMERA_HOST_OPEN_CAMERA** to obtain an **ICameraDevice** object. 200 201 ```c++ 202 int32_t CameraHostProxy::OpenCamera(const std::string& cameraId, const sptr<ICameraDeviceCallback>& callbackObj, 203 sptr<ICameraDevice>& device) 204 { 205 MessageParcel cameraHostData; 206 MessageParcel cameraHostReply; 207 MessageOption cameraHostOption(MessageOption::TF_SYNC); 208 209 if (!cameraHostData.WriteInterfaceToken(ICameraHost::GetDescriptor())) { 210 HDF_LOGE("%{public}s: failed to write interface descriptor!", __func__); 211 return HDF_ERR_INVALID_PARAM; 212 } 213 214 if (!cameraHostData.WriteCString(cameraId.c_str())) { 215 HDF_LOGE("%{public}s: write cameraId failed!", __func__); 216 return HDF_ERR_INVALID_PARAM; 217 } 218 219 if (!cameraHostData.WriteRemoteObject(OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(callbackObj, 220 ICameraDeviceCallback::GetDescriptor()))) { 221 HDF_LOGE("%{public}s: write callbackObj failed!", __func__); 222 return HDF_ERR_INVALID_PARAM; 223 } 224 225 int32_t cameraHostRet = Remote()->SendRequest(CMD_CAMERA_HOST_OPEN_CAMERA, cameraHostData, cameraHostReply, cameraHostOption); 226 if (cameraHostRet != HDF_SUCCESS) { 227 HDF_LOGE("%{public}s failed, error code is %{public}d", __func__, cameraHostRet); 228 return cameraHostRet; 229 } 230 231 device = hdi_facecast<ICameraDevice>(cameraHostReply.ReadRemoteObject()); 232 233 return cameraHostRet; 234 } 235 ``` 236 237 **Remote()->SendRequest** calls **CameraHostServiceStubOnRemoteRequest()**, locates **CameraHostStubOpenCamera()** based on **cmdId**, and finally calls **CameraHostImpl::OpenCamera()** to obtain a **CameraDevice** and power on the camera hardware. 238 239 ```c++ 240 int32_t CameraHostImpl::OpenCamera(const std::string& cameraId, const sptr<ICameraDeviceCallback>& callbackObj, 241 sptr<ICameraDevice>& device) 242 { 243 CAMERA_LOGD("OpenCamera entry"); 244 DFX_LOCAL_HITRACE_BEGIN; 245 if (CameraIdInvalid(cameraId) != RC_OK || callbackObj == nullptr) { 246 CAMERA_LOGW("open camera id is empty or callback is null."); 247 return INVALID_ARGUMENT; 248 } 249 250 auto itr = cameraDeviceMap_.find(cameraId); 251 if (itr == cameraDeviceMap_.end()) { 252 CAMERA_LOGE("camera device not found."); 253 return INSUFFICIENT_RESOURCES; 254 } 255 CAMERA_LOGD("OpenCamera cameraId find success."); 256 257 std::shared_ptr<CameraDeviceImpl> cameraDevice = itr->second; 258 if (cameraDevice == nullptr) { 259 CAMERA_LOGE("camera device is null."); 260 return INSUFFICIENT_RESOURCES; 261 } 262 263 CamRetCode ret = cameraDevice->SetCallback(callbackObj); 264 CHECK_IF_NOT_EQUAL_RETURN_VALUE(ret, HDI::Camera::V1_0::NO_ERROR, ret); 265 266 CameraHostConfig *config = CameraHostConfig::GetInstance(); 267 CHECK_IF_PTR_NULL_RETURN_VALUE(config, INVALID_ARGUMENT); 268 269 std::vector<std::string> phyCameraIds; 270 RetCode rc = config->GetPhysicCameraIds(cameraId, phyCameraIds); 271 if (rc != RC_OK) { 272 CAMERA_LOGE("get physic cameraId failed."); 273 return DEVICE_ERROR; 274 } 275 if (CameraPowerUp(cameraId, phyCameraIds) != RC_OK) { // Power on the camera hardware. 276 CAMERA_LOGE("camera powerup failed."); 277 CameraPowerDown(phyCameraIds); 278 return DEVICE_ERROR; 279 } 280 281 auto sptrDevice = deviceBackup_.find(cameraId); 282 if (sptrDevice == deviceBackup_.end()) { 283 #ifdef CAMERA_BUILT_ON_OHOS_LITE 284 deviceBackup_[cameraId] = cameraDevice; 285 #else 286 deviceBackup_[cameraId] = cameraDevice.get(); 287 #endif 288 } 289 device = deviceBackup_[cameraId]; 290 cameraDevice->SetStatus(true); 291 CAMERA_LOGD("open camera success."); 292 DFX_LOCAL_HITRACE_END; 293 return HDI::Camera::V1_0::NO_ERROR; 294 } 295 ``` 296 2975. Obtain streams. 298 299 **CameraDeviceImpl** defines **GetStreamOperator()**, **UpdateSettings()**, **SetResultMode()**, and **GetEnabledResult()**. Use **GetStreamOperator()** to obtain steams. 300 301 ```c++ 302 int32_t CameraDeviceImpl::GetStreamOperator(const sptr<IStreamOperatorCallback>& callbackObj, 303 sptr<IStreamOperator>& streamOperator) 304 { 305 HDI_DEVICE_PLACE_A_WATCHDOG; 306 DFX_LOCAL_HITRACE_BEGIN; 307 if (callbackObj == nullptr) { 308 CAMERA_LOGW("input callback is null."); 309 return INVALID_ARGUMENT; 310 } 311 312 spCameraDeciceCallback_ = callbackObj; 313 if (spStreamOperator_ == nullptr) { 314 #ifdef CAMERA_BUILT_ON_OHOS_LITE 315 // Create a spStreamOperator_ object and pass it to the caller for subsequent stream operations. 316 spStreamOperator_ = std::make_shared<StreamOperator>(spCameraDeciceCallback_, shared_from_this()); 317 #else 318 spStreamOperator_ = new(std::nothrow) StreamOperator(spCameraDeciceCallback_, shared_from_this()); 319 #endif 320 if (spStreamOperator_ == nullptr) { 321 CAMERA_LOGW("create stream operator failed."); 322 return DEVICE_ERROR; 323 } 324 spStreamOperator_->Init(); 325 ismOperator_ = spStreamOperator_; 326 } 327 streamOperator = ismOperator_; 328 #ifndef CAMERA_BUILT_ON_OHOS_LITE 329 CAMERA_LOGI("CameraDeviceImpl %{public}s: line: %{public}d", __FUNCTION__, __LINE__); 330 pipelineCore_->GetStreamPipelineCore()->SetCallback( 331 [this](const std::shared_ptr<CameraMetadata> &metadata) { 332 OnMetadataChanged(metadata); 333 }); 334 #endif 335 DFX_LOCAL_HITRACE_END; 336 return HDI::Camera::V1_0::NO_ERROR; 337 } 338 ``` 339 3406. Create streams. 341 342 Fill in the **StreamInfo** structure before creating streams by calling **CreateStreams()**. 343 344 ```c++ 345 using StreamInfo = struct _StreamInfo { 346 int streamId_; 347 int width_; // Stream width 348 int height_; // Stream height 349 int format_; // Stream format, for example, PIXEL_FMT_YCRCB_420_SP 350 int dataSpace_; 351 StreamIntent intent_; // StreamIntent, for example, PREVIEW 352 bool tunneledMode_; 353 ufferProducerSequenceable bufferQueue_; // Use streamCustomer->CreateProducer() to create a buffer queue for streams. 354 int minFrameDuration_; 355 EncodeType encodeType_; 356 }; 357 ``` 358 359 **CreateStreams()** is a method in the **StreamOperator** class (**StreamOperatorImpl** is the base class of **StreamOperator**). Use **CreateStreams()** to create a **StreamBase** object, which initializes operations such as **CreateBufferPool** through its **Init()** method. 360 361 ```c++ 362 int32_t StreamOperator::CreateStreams(const std::vector<StreamInfo>& streamInfos) 363 { 364 PLACE_A_NOKILL_WATCHDOG(requestTimeoutCB_); 365 DFX_LOCAL_HITRACE_BEGIN; 366 for (const auto& it : streamInfos) { 367 CHECK_IF_NOT_EQUAL_RETURN_VALUE(CheckStreamInfo(it), true, INVALID_ARGUMENT); 368 CAMERA_LOGI("streamId:%{public}d and format:%{public}d and width:%{public}d and height:%{public}d", 369 it.streamId_, it.format_, it.width_, it.height_); 370 if (streamMap_.count(it.streamId_) > 0) { 371 CAMERA_LOGE("stream [id = %{public}d] has already been created.", it.streamId_); 372 return INVALID_ARGUMENT; 373 } 374 std::shared_ptr<IStream> stream = StreamFactory::Instance().CreateShared( // Create a stream instance. 375 IStream::g_availableStreamType[it.intent_], it.streamId_, it.intent_, pipelineCore_, messenger_); 376 if (stream == nullptr) { 377 CAMERA_LOGE("create stream [id = %{public}d] failed.", it.streamId_); 378 return INSUFFICIENT_RESOURCES; 379 } 380 StreamConfiguration scg; 381 StreamInfoToStreamConfiguration(scg, it); 382 RetCode rc = stream->ConfigStream(scg); 383 if (rc != RC_OK) { 384 CAMERA_LOGE("configure stream %{public}d failed", it.streamId_); 385 return INVALID_ARGUMENT; 386 } 387 if (!scg.tunnelMode && (it.bufferQueue_)->producer_ != nullptr) { 388 CAMERA_LOGE("stream [id:%{public}d] is not tunnel mode, can't bind a buffer producer", it.streamId_); 389 return INVALID_ARGUMENT; 390 } 391 if ((it.bufferQueue_)->producer_ != nullptr) { 392 auto tunnel = std::make_shared<StreamTunnel>(); 393 CHECK_IF_PTR_NULL_RETURN_VALUE(tunnel, INSUFFICIENT_RESOURCES); 394 rc = tunnel->AttachBufferQueue((it.bufferQueue_)->producer_); 395 CHECK_IF_NOT_EQUAL_RETURN_VALUE(rc, RC_OK, INVALID_ARGUMENT); 396 if (stream->AttachStreamTunnel(tunnel) != RC_OK) { 397 CAMERA_LOGE("attach buffer queue to stream [id = %{public}d] failed", it.streamId_); 398 return INVALID_ARGUMENT; 399 } 400 } 401 { 402 std::lock_guard<std::mutex> l(streamLock_); 403 streamMap_[stream->GetStreamId()] = stream; 404 } 405 CAMERA_LOGI("create stream success [id:%{public}d] [type:%{public}s]", stream->GetStreamId(), 406 IStream::g_availableStreamType[it.intent_].c_str()); 407 } 408 DFX_LOCAL_HITRACE_END; 409 return HDI::Camera::V1_0::NO_ERROR; 410 } 411 ``` 412 4137. Configure streams. 414 415 Use **CommitStreams()** to configure streams, including initializing and creating **PipelineCore**. **CommitStreams()** must be called after the streams are created. 416 417 ```c++ 418 int32_t StreamOperator::CommitStreams(OperationMode mode, const std::vector<uint8_t>& modeSetting) 419 { 420 CAMERA_LOGV("enter"); 421 CHECK_IF_PTR_NULL_RETURN_VALUE(streamPipeline_, DEVICE_ERROR); 422 PLACE_A_NOKILL_WATCHDOG(requestTimeoutCB_); 423 if (modeSetting.empty()) { 424 CAMERA_LOGE("input vector is empty"); 425 return INVALID_ARGUMENT; 426 } 427 DFX_LOCAL_HITRACE_BEGIN; 428 429 std::vector<StreamConfiguration> configs = {}; 430 { 431 std::lock_guard<std::mutex> l(streamLock_); 432 std::transform(streamMap_.begin(), streamMap_.end(), std::back_inserter(configs), 433 [](auto &iter) { return iter.second->GetStreamAttribute(); }); 434 } 435 436 std::shared_ptr<CameraMetadata> setting; 437 MetadataUtils::ConvertVecToMetadata(modeSetting, setting); 438 DynamicStreamSwitchMode method = streamPipeline_->CheckStreamsSupported(mode, setting, configs); 439 if (method == DYNAMIC_STREAM_SWITCH_NOT_SUPPORT) { 440 return INVALID_ARGUMENT; 441 } 442 if (method == DYNAMIC_STREAM_SWITCH_NEED_INNER_RESTART) { 443 std::lock_guard<std::mutex> l(streamLock_); 444 for (auto it : streamMap_) { 445 it.second->StopStream(); 446 } 447 } 448 { 449 std::lock_guard<std::mutex> l(streamLock_); 450 for (auto it : streamMap_) { 451 if (it.second->CommitStream() != RC_OK) { 452 CAMERA_LOGE("commit stream [id = %{public}d] failed.", it.first); 453 return DEVICE_ERROR; 454 } 455 } 456 } 457 RetCode rc = streamPipeline_->PreConfig(setting); // Configure the device stream. 458 if (rc != RC_OK) { 459 CAMERA_LOGE("prepare mode settings failed"); 460 return DEVICE_ERROR; 461 } 462 rc = streamPipeline_->CreatePipeline(mode); // Create a pipeline. 463 if (rc != RC_OK) { 464 CAMERA_LOGE("create pipeline failed."); 465 return INVALID_ARGUMENT; 466 } 467 468 DFX_LOCAL_HITRACE_END; 469 return HDI::Camera::V1_0::NO_ERROR; 470 } 471 ``` 472 4738. Capture images. 474 475 Fill in the **CaptureInfo** structure before calling **Capture()**. 476 477 ```c++ 478 using CaptureInfo = struct _CaptureInfo { 479 int[] streamIds_; // IDs of the streams to capture. 480 unsigned char[] captureSetting_; // Use the camera ability obtained by GetCameraAbility() of CameraHost to fill in the settings. 481 bool enableShutterCallback_; 482 }; 483 ``` 484 485 Use the **Capture()** method in **StreamOperator** to capture data streams. 486 487 ```c++ 488 int32_t StreamOperator::Capture(int32_t captureId, const CaptureInfo& info, bool isStreaming) 489 { 490 CHECK_IF_EQUAL_RETURN_VALUE(captureId < 0, true, INVALID_ARGUMENT); 491 PLACE_A_NOKILL_WATCHDOG(requestTimeoutCB_); 492 DFX_LOCAL_HITRACE_BEGIN; 493 494 for (auto id : info.streamIds_) { 495 std::lock_guard<std::mutex> l(streamLock_); 496 auto it = streamMap_.find(id); 497 if (it == streamMap_.end()) { 498 return INVALID_ARGUMENT; 499 } 500 } 501 502 { 503 std::lock_guard<std::mutex> l(requestLock_); 504 auto itr = requestMap_.find(captureId); 505 if (itr != requestMap_.end()) { 506 return INVALID_ARGUMENT; 507 } 508 } 509 510 std::shared_ptr<CameraMetadata> captureSetting; 511 MetadataUtils::ConvertVecToMetadata(info.captureSetting_, captureSetting); 512 CaptureSetting setting = captureSetting; 513 auto request = 514 std::make_shared<CaptureRequest>(captureId, info.streamIds_.size(), setting, 515 info.enableShutterCallback_, isStreaming); 516 for (auto id : info.streamIds_) { 517 RetCode rc = streamMap_[id]->AddRequest(request); 518 if (rc != RC_OK) { 519 return DEVICE_ERROR; 520 } 521 } 522 523 { 524 std::lock_guard<std::mutex> l(requestLock_); 525 requestMap_[captureId] = request; 526 } 527 return HDI::Camera::V1_0::NO_ERROR; 528 } 529 ``` 530 5319. Cancel the capture and release the offline stream. 532 533 Use **CancelCapture()** in the **StreamOperatorImpl** class to cancel the stream capture based on **captureId**. 534 535 ```c++ 536 int32_t StreamOperator::CancelCapture(int32_t captureId) 537 { 538 CHECK_IF_EQUAL_RETURN_VALUE(captureId < 0, true, INVALID_ARGUMENT); 539 PLACE_A_NOKILL_WATCHDOG(requestTimeoutCB_); 540 DFX_LOCAL_HITRACE_BEGIN; 541 542 std::lock_guard<std::mutex> l(requestLock_); 543 auto itr = requestMap_.find(captureId); // Search for the CameraCapture object in the Map based on the captureId. 544 if (itr == requestMap_.end()) { 545 CAMERA_LOGE("can't cancel capture [id = %{public}d], this capture doesn't exist", captureId); 546 return INVALID_ARGUMENT; 547 } 548 549 RetCode rc = itr->second->Cancel(); // Call Cancel() in CameraCapture to cancel the stream capture. 550 if (rc != RC_OK) { 551 return DEVICE_ERROR; 552 } 553 requestMap_.erase(itr); // Erase the CameraCapture object. 554 555 DFX_LOCAL_HITRACE_END; 556 return HDI::Camera::V1_0::NO_ERROR; 557 } 558 ``` 559 560 Use **ReleaseStreams()** in the **StreamOperatorImpl** class to release the streams created by using **CreateStream()** and **CommitStreams()** and destroy the pipeline. 561 562 ```c++ 563 int32_t StreamOperator::ReleaseStreams(const std::vector<int32_t>& streamIds) 564 { 565 PLACE_A_NOKILL_WATCHDOG(requestTimeoutCB_); 566 DFX_LOCAL_HITRACE_BEGIN; 567 for (auto id : streamIds) { 568 std::lock_guard<std::mutex> l(streamLock_); 569 auto it = streamMap_.find(id); 570 if (it == streamMap_.end()) { 571 continue; 572 } 573 if (it->second->IsRunning()) { 574 it->second->StopStream(); 575 } 576 it->second->DumpStatsInfo(); 577 streamMap_.erase(it); 578 } 579 580 for (auto id : streamIds) { 581 CHECK_IF_EQUAL_RETURN_VALUE(id < 0, true, INVALID_ARGUMENT); 582 } 583 584 DFX_LOCAL_HITRACE_END; 585 return HDI::Camera::V1_0::NO_ERROR; 586 } 587 ``` 588 58910. Close the camera device. 590 591 Use **Close()** in the **CameraDeviceImpl** class to close the camera device. The **PowerDown()** in **DeviceManager** is called to power off the device. 592 593### Development Example 594 595There is a [ohos_camera_demo](https://gitee.com/openharmony/drivers_peripheral/tree/master/camera/test/demo) in the **/drivers/peripheral/camera/hal/test/demo** directory. After the system is started, the executable file **ohos_camera_demo** is generated in the **/vendor/bin** directory. This demo implements basic camera capabilities such as preview and photographing. 596The following uses the demo to describe how to use the HDI to implement **PreviewOn()** and **CaptureON()**. 597 5981. 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**. 599 600 ```c++ 601 int main(int argc, char** argv) 602 { 603 RetCode rc = RC_OK; 604 auto mainDemo = std::make_shared<CameraDemo>(); 605 rc = mainDemo->InitSensors(); // Initialize the CameraHost. 606 if (rc == RC_ERROR) { 607 CAMERA_LOGE("main test: mainDemo->InitSensors() error\n"); 608 return -1; 609 } 610 611 rc = mainDemo->InitCameraDevice(); // Initialize the CameraDevice. 612 if (rc == RC_ERROR) { 613 CAMERA_LOGE("main test: mainDemo->InitCameraDevice() error\n"); 614 return -1; 615 } 616 617 rc = PreviewOn(0, mainDemo); // Configure and enable streams. 618 if (rc != RC_OK) { 619 CAMERA_LOGE("main test: PreviewOn() error demo exit"); 620 return -1; 621 } 622 623 ManuList(mainDemo, argc, argv); // Print the menu to the console. 624 625 return RC_OK; 626 } 627 ``` 628 629 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: 630 631 ```c++ 632 RetCode OhosCameraDemo::InitSensors() 633 { 634 int rc = 0; 635 636 CAMERA_LOGD("demo test: InitSensors enter"); 637 638 if (demoCameraHost_ != nullptr) { 639 return RC_OK; 640 } 641 #ifdef CAMERA_BUILT_ON_OHOS_LITE 642 demoCameraHost_ = OHOS::Camera::CameraHost::CreateCameraHost(); 643 #else 644 constexpr const char *DEMO_SERVICE_NAME = "camera_service"; 645 demoCameraHost_ = ICameraHost::Get(DEMO_SERVICE_NAME, false); 646 #endif 647 if (demoCameraHost_ == nullptr) { 648 CAMERA_LOGE("demo test: ICameraHost::Get error"); 649 return RC_ERROR; 650 } 651 652 #ifdef CAMERA_BUILT_ON_OHOS_LITE 653 hostCallback_ = std::make_shared<DemoCameraHostCallback>(); 654 #else 655 hostCallback_ = new DemoCameraHostCallback(); 656 #endif 657 rc = demoCameraHost_->SetCallback(hostCallback_); 658 if (rc != HDI::Camera::V1_0::NO_ERROR) { 659 CAMERA_LOGE("demo test: demoCameraHost_->SetCallback(hostCallback_) error"); 660 return RC_ERROR; 661 } 662 663 CAMERA_LOGD("demo test: InitSensors exit"); 664 665 return RC_OK; 666 } 667 ``` 668 669 The function for initializing the **CameraDevice** is implemented as follows. The **GetCameraIds(cameraIds_)**, **GetCameraAbility(cameraId, ability_)**, and **OpenCamera(cameraIds\_.front(), callback, demoCameraDevice_)** methods are used to obtain the **demoCameraHost**. 670 671 ```c++ 672 RetCode OhosCameraDemo::InitCameraDevice() 673 { 674 int rc = 0; 675 676 CAMERA_LOGD("demo test: InitCameraDevice enter"); 677 678 if (demoCameraHost_ == nullptr) { 679 CAMERA_LOGE("demo test: InitCameraDevice demoCameraHost_ == nullptr"); 680 return RC_ERROR; 681 } 682 683 (void)demoCameraHost_->GetCameraIds(cameraIds_); 684 if (cameraIds_.empty()) { 685 return RC_ERROR; 686 } 687 const std::string cameraId = cameraIds_.front(); 688 demoCameraHost_->GetCameraAbility(cameraId, cameraAbility_); 689 690 MetadataUtils::ConvertVecToMetadata(cameraAbility_, ability_); 691 692 GetFaceDetectMode(ability_); 693 GetFocalLength(ability_); 694 GetAvailableFocusModes(ability_); 695 GetAvailableExposureModes(ability_); 696 GetExposureCompensationRange(ability_); 697 GetExposureCompensationSteps(ability_); 698 GetAvailableMeterModes(ability_); 699 GetAvailableFlashModes(ability_); 700 GetMirrorSupported(ability_); 701 GetStreamBasicConfigurations(ability_); 702 GetFpsRange(ability_); 703 GetCameraPosition(ability_); 704 GetCameraType(ability_); 705 GetCameraConnectionType(ability_); 706 GetFaceDetectMaxNum(ability_); 707 708 #ifdef CAMERA_BUILT_ON_OHOS_LITE 709 std::shared_ptr<CameraDeviceCallback> callback = std::make_shared<CameraDeviceCallback>(); 710 #else 711 sptr<DemoCameraDeviceCallback> callback = new DemoCameraDeviceCallback(); 712 #endif 713 rc = demoCameraHost_->OpenCamera(cameraIds_.front(), callback, demoCameraDevice_); 714 if (rc != HDI::Camera::V1_0::NO_ERROR || demoCameraDevice_ == nullptr) { 715 CAMERA_LOGE("demo test: InitCameraDevice OpenCamera failed"); 716 return RC_ERROR; 717 } 718 719 CAMERA_LOGD("demo test: InitCameraDevice exit"); 720 721 return RC_OK; 722 } 723 ``` 724 7252. Implement **PreviewOn()** to configure streams, enable preview streams, and start stream capture. After **PreviewOn()** 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. 726 727 ```c++ 728 static RetCode PreviewOn(int mode, const std::shared_ptr<OhosCameraDemo>& mainDemo) 729 { 730 RetCode rc = RC_OK; 731 CAMERA_LOGD("main test: PreviewOn enter"); 732 733 rc = mainDemo->StartPreviewStream(); // Configure the preview stream. 734 if (rc != RC_OK) { 735 CAMERA_LOGE("main test: PreviewOn StartPreviewStream error"); 736 return RC_ERROR; 737 } 738 739 if (mode == 0) { 740 rc = mainDemo->StartCaptureStream(); // Configure the capture stream. 741 if (rc != RC_OK) { 742 CAMERA_LOGE("main test: PreviewOn StartCaptureStream error"); 743 return RC_ERROR; 744 } 745 } else { 746 rc = mainDemo->StartVideoStream(); // Configure the video stream. 747 if (rc != RC_OK) { 748 CAMERA_LOGE("main test: PreviewOn StartVideoStream error"); 749 return RC_ERROR; 750 } 751 } 752 753 rc = mainDemo->CaptureON(STREAM_ID_PREVIEW, CAPTURE_ID_PREVIEW, CAPTURE_PREVIEW); 754 if (rc != RC_OK) { 755 CAMERA_LOGE("main test: PreviewOn mainDemo->CaptureON() preview error"); 756 return RC_ERROR; 757 } 758 759 CAMERA_LOGD("main test: PreviewOn exit"); 760 return RC_OK; 761 } 762 ``` 763 764 The **StartCaptureStream()**, **StartVideoStream()**, and **StartPreviewStream()** methods call **CreateStream()** with different input parameters. 765 766 Use **CreateStream()** to call an HDI API to configure and create streams. Specifically, **CreateStream()** calls the HDI to obtain a **StreamOperation** object and then creates a **StreamInfo** object. Call **CreateStreams()** and **CommitStreams()** to create and configure streams. 767 768 ```c++ 769 RetCode OhosCameraDemo::CreateStream(const int streamId, std::shared_ptr<StreamCustomer> &streamCustomer, 770 StreamIntent intent) 771 { 772 int rc = 0; 773 CAMERA_LOGD("demo test: CreateStream enter"); 774 775 GetStreamOpt(); // Obtain a StreamOperator object. 776 if (streamOperator_ == nullptr) { 777 CAMERA_LOGE("demo test: CreateStream GetStreamOpt() is nullptr\n"); 778 return RC_ERROR; 779 } 780 781 StreamInfo streamInfo = {0}; 782 783 SetStreamInfo(streamInfo, streamCustomer, streamId, intent); // Fills in the StreamInfo stream. 784 if (streamInfo.bufferQueue_->producer_ == nullptr) { 785 CAMERA_LOGE("demo test: CreateStream CreateProducer(); is nullptr\n"); 786 return RC_ERROR; 787 } 788 789 std::vector<StreamInfo> streamInfos; 790 streamInfos.push_back(streamInfo); 791 792 rc = streamOperator_->CreateStreams(streamInfos); // Create a stream. 793 if (rc != HDI::Camera::V1_0::NO_ERROR) { 794 CAMERA_LOGE("demo test: CreateStream CreateStreams error\n"); 795 return RC_ERROR; 796 } 797 798 rc = streamOperator_->CommitStreams(NORMAL, cameraAbility_); 799 if (rc != HDI::Camera::V1_0::NO_ERROR) { 800 CAMERA_LOGE("demo test: CreateStream CommitStreams error\n"); 801 std::vector<int> streamIds; 802 streamIds.push_back(streamId); 803 streamOperator_->ReleaseStreams(streamIds); 804 return RC_ERROR; 805 } 806 807 CAMERA_LOGD("demo test: CreateStream exit"); 808 809 return RC_OK; 810 } 811 ``` 812 813 Use **CaptureON()** to call the **Capture()** method of **StreamOperator** to obtain camera data, flip the buffer, and start a thread to receive data of the corresponding type. 814 815 ```c++ 816 RetCode OhosCameraDemo::CaptureON(const int streamId, 817 const int captureId, CaptureMode mode) 818 { 819 CAMERA_LOGI("demo test: CaptureON enter streamId == %{public}d and captureId == %{public}d and mode == %{public}d", 820 streamId, captureId, mode); 821 std::lock_guard<std::mutex> l(metaDatalock_); 822 if (mode == CAPTURE_SNAPSHOT) { 823 constexpr double latitude = 27.987500; // dummy data: Qomolangma latitde 824 constexpr double longitude = 86.927500; // dummy data: Qomolangma longituude 825 constexpr double altitude = 8848.86; // dummy data: Qomolangma altitude 826 constexpr size_t entryCapacity = 100; 827 constexpr size_t dataCapacity = 2000; 828 captureSetting_ = std::make_shared<CameraSetting>(entryCapacity, dataCapacity); 829 captureQuality_ = OHOS_CAMERA_JPEG_LEVEL_HIGH; 830 captureOrientation_ = OHOS_CAMERA_JPEG_ROTATION_270; 831 mirrorSwitch_ = OHOS_CAMERA_MIRROR_ON; 832 gps_.push_back(latitude); 833 gps_.push_back(longitude); 834 gps_.push_back(altitude); 835 captureSetting_->addEntry(OHOS_JPEG_QUALITY, static_cast<void*>(&captureQuality_), 836 sizeof(captureQuality_)); 837 captureSetting_->addEntry(OHOS_JPEG_ORIENTATION, static_cast<void*>(&captureOrientation_), 838 sizeof(captureOrientation_)); 839 captureSetting_->addEntry(OHOS_CONTROL_CAPTURE_MIRROR, static_cast<void*>(&mirrorSwitch_), 840 sizeof(mirrorSwitch_)); 841 captureSetting_->addEntry(OHOS_JPEG_GPS_COORDINATES, gps_.data(), gps_.size()); 842 } 843 844 std::vector<uint8_t> setting; 845 MetadataUtils::ConvertMetadataToVec(captureSetting_, setting); 846 captureInfo_.streamIds_ = {streamId}; 847 if (mode == CAPTURE_SNAPSHOT) { 848 captureInfo_.captureSetting_ = setting; 849 } else { 850 captureInfo_.captureSetting_ = cameraAbility_; 851 } 852 captureInfo_.enableShutterCallback_ = false; 853 854 int rc = streamOperator_->Capture(captureId, captureInfo_, true); // The capture starts, and buffer starts to flip. 855 if (rc != HDI::Camera::V1_0::NO_ERROR) { 856 CAMERA_LOGE("demo test: CaptureStart Capture error\n"); 857 streamOperator_->ReleaseStreams(captureInfo_.streamIds_); 858 return RC_ERROR; 859 } 860 861 if (mode == CAPTURE_PREVIEW) { 862 streamCustomerPreview_->ReceiveFrameOn(nullptr); // Create a preview thread to receive the passed buffer. 863 } else if (mode == CAPTURE_SNAPSHOT) { 864 streamCustomerCapture_->ReceiveFrameOn([this](void* addr, const uint32_t size) { // Create a capture thread to receive the passed buffer through the StoreImage callback. 865 StoreImage(addr, size); 866 }); 867 } else if (mode == CAPTURE_VIDEO) { 868 OpenVideoFile(); 869 870 streamCustomerVideo_->ReceiveFrameOn([this](void* addr, const uint32_t size) { // Create a video thread to receive the passed buffer through the StoreImage callback. 871 StoreVideo(addr, size); 872 }); 873 } 874 CAMERA_LOGD("demo test: CaptureON exit"); 875 876 return RC_OK; 877 } 878 ``` 879 8803. Implement **ManuList()** to obtain characters from the console through **fgets()**. Different characters correspond to different capabilities provided by the demo, and the functionality menu is printed. 881 882 ```c++ 883 static void ManuList(const std::shared_ptr<OhosCameraDemo>& mainDemo, 884 const int argc, char** argv) 885 { 886 int idx, c; 887 bool isAwb = true; 888 const char *shortOptions = "h:cwvaeqof:"; 889 c = getopt_long(argc, argv, shortOptions, LONG_OPTIONS, &idx); 890 while (1) { 891 switch (c) { 892 case 'h': 893 c = PutMenuAndGetChr(); // Print the menu. 894 break; 895 case 'f': 896 FlashLightTest(mainDemo); // Verify the flashlight capability. 897 c = PutMenuAndGetChr(); 898 break; 899 case 'o': 900 OfflineTest(mainDemo); // Verify the offline capability. 901 c = PutMenuAndGetChr(); 902 break; 903 case 'c': 904 CaptureTest(mainDemo); // Verify the capture capability. 905 c = PutMenuAndGetChr(); 906 break; 907 case 'w': // Verify the AWB capability. 908 if (isAwb) { 909 mainDemo->SetAwbMode(OHOS_CAMERA_AWB_MODE_INCANDESCENT); 910 } else { 911 mainDemo->SetAwbMode(OHOS_CAMERA_AWB_MODE_OFF); 912 } 913 isAwb = !isAwb; 914 c = PutMenuAndGetChr(); 915 break; 916 case 'a': // Verify the AE capability. 917 mainDemo->SetAeExpo(); 918 c = PutMenuAndGetChr(); 919 break; 920 case'e': // Verify the metadata operations. 921 mainDemo->SetMetadata(); 922 c = PutMenuAndGetChr(); 923 break; 924 case'v': // Verify the video function. 925 VideoTest(mainDemo); 926 c = PutMenuAndGetChr(); 927 break; 928 case 'q': // Exit the demo. 929 PreviewOff(mainDemo); 930 mainDemo->QuitDemo(); 931 return; 932 default: 933 CAMERA_LOGE("main test: command error please retry input command"); 934 c = PutMenuAndGetChr(); 935 break; 936 } 937 } 938 } 939 ``` 940 941 Use **PutMenuAndGetChr()** to print the menu of the demo and call **fgets()** to wait for commands from the console. 942 943 ```c++ 944 static int PutMenuAndGetChr(void) 945 { 946 constexpr uint32_t inputCount = 50; 947 int c = 0; 948 char strs[inputCount]; 949 Usage(stdout); 950 CAMERA_LOGD("pls input command(input -q exit this app)\n"); 951 fgets(strs, inputCount, stdin); 952 953 for (int i = 0; i < inputCount; i++) { 954 if (strs[i] != '-') { 955 c = strs[i]; 956 break; 957 } 958 } 959 return c; 960 } 961 ``` 962 963 The console outputs the menu details as follows: 964 965 ```c++ 966 "Options:\n" 967 "-h | --help Print this message\n" 968 "-o | --offline stream offline test\n" 969 "-c | --capture capture one picture\n" 970 "-w | --set WB Set white balance Cloudy\n" 971 "-v | --video capture Video of 10s\n" 972 "-a | --Set AE Set Auto exposure\n" 973 "-e | --Set Metadeta Set Metadata\n" 974 "-f | --Set Flashlight Set flashlight ON 5s OFF\n" 975 "-q | --quit stop preview and quit this app\n"); 976 ``` 977 9784. Compile and build the **ohos_camera_demo**. 979 Add **init:ohos_camera_demo** to **deps** in the **drivers/peripheral/camera/BUILD.gn** file. The sample code is as follows: 980 ``` 981 deps = [ 982 "vdi_base/common/buffer_manager:camera_buffer_manager", 983 "vdi_base/common/device_manager:camera_device_manager", 984 "vdi_base/common/hdi_impl:camera_host_service_1.0", 985 "vdi_base/common/pipeline_core:camera_pipeline_core", 986 "vdi_base/common/utils:camera_utils", 987 "test/common:ohos_camera_demo", 988 ] 989 ``` 990 991 The following uses RK3568 development board as an example. 992 1. Run the **./build.sh --product-name rk3568 --ccache** command to generate the executable binary file **ohos_camera_demo** in **out/rk3568/packages/phone/vendor/bin/**. 993 2. Import the executable file **ohos_camera_demo** to the development board, modify the permission, and run the file. 994 995## Reference 996 997### HCS Configuration 998 999The system provides default HCS configuration for the camera module. You can modify the HCS files as required. The HCS files of the camera module are located in **/vendor/hihope/rk3568/hdf_config/uhdf/camera**. 1000 1001- **./hdi_impl/camera_host_config.hcs**: defines the camera static capabilities, including the type and position of the lens, connection type, and supported exposure mode. Configure the camera static capabilities based on the specifications of your camera. 1002- **./pipeline_core/config.hcs**: defines the pipeline connection mode. The pipeline configuration includes the supported pipeline types, nodes in each pipeline, and connections between the nodes. 1003 1004 After compilation, the **congfig.c** and **congfig.h** files are generated in the **/drivers/periphera/camra/vdi_base/common/pipeline_core/pipeline_impl/src/strategy/config** directory. 1005- **./pipeline_core/ipp_algo_config.hcs**: provides algorithm configuration. 1006- **./pipeline_core/params.hcs**: defines the scenarios, stream types, and stream IDs. The pipeline uses the stream ID to identify the stream type. Therefore, you need to configure the stream information here. 1007 1008 After compilation, the **params.c** and **params.h** files are generated in the **/drivers/periphera/camra/vdi_base/common/pipeline_core/pipeline_impl/src/strategy/config** directory. 1009 1010### Camera Dump 1011 1012#### Function Overview 1013Camera dump can be used to test camera-related functions. You can enable this feature in the configuration file. Camera dump provides the following functionalities: 1014* Provides buffer dump in different phases to help quickly locate image problems and the related data. 1015* Dumps metadata to determine whether metadata parameters are correctly set and determine the impact of different parameters on image quality. 1016 1017#### Directory Structure 1018 1019 1020``` 1021/drivers/peripheral/camera/vdi_base/common/dump 1022├── include 1023│ └── camera_dump.h # Dump head file 1024└── src 1025 └── camera_dump.cpp # Dump core code 1026``` 1027 1028 1029#### Dump Configuration File 1030 1031You can find the dump configuration **dump.config** in the **/data/local/tmp** directory of the device. 1032 1033 **Table 1** Dump switch settings 1034 1035| **Switch**| **Value**| **Description**| **Application Scenarios**| **Output Data Format**| 1036| -------- | -------- | -------- | -------- | -------- | 1037| enableDQBufDump | true/false | The value **true** means to dump the data in the **DequeueBuffer** method defined in the **v4l2_buffer.cpp** file.| Preview, photo taking, and video recording| Onboard camera: YUV420<br>USB camera: YUV422| 1038| enableUVCNodeBufferDump | true/false | The value **true** means to dump the data to be converted by the **YUV422To420** method defined in the **uvc_node.cpp** file.| Preview, photo taking, and video recording| USB camera: YUV422| 1039| enableUVCNodeConvertedBufferDump | true/false | The value **true** means to dump the converted data returned by the **YUV422To420** method defined in the **uvc_node.cpp** file.| Preview, photo taking, and video recording| USB camera: YUV420| 1040| enableExifNodeConvertedBufferDump | true/false | The value **true** means to dump the data in the **DeliverBuffer** method defined in the **exif_node.cpp** file.| Photo taking| JPEG | 1041| enableFaceNodeConvertedBufferDump | true/false | The value **true** means to dump the data in the **DeliverBuffer** method defined in the **face_node.cpp** file.| Reserved for future use| NA| 1042| enableForkNodeConvertedBufferDump | true/false | The value **true** means to dump the data in the **DeliverBuffer** method defined in the **fork_node.cpp** file.| Preview, photo taking, and video recording| YUV422 | 1043| enableRKFaceNodeConvertedBufferDump | true/false | The value **true** means to dump the data in the **DeliverBuffer** method defined in the **rk_face_node.cpp** file.| Reserved for future use| NA| 1044| enableRKExifNodeConvertedBufferDump | true/false | The value **true** means to dump the data in the **DeliverBuffer** method defined in the **rk_exif_node.cpp** file.| Photo taking| JPEG | 1045| enableCodecNodeConvertedBufferDump | true/false | The value **true** means to dump the data in the **DeliverBuffer** method defined in the **codec_node.cpp** file.| Preview, photo taking, and video recording| JPEG, YUV420, RGBA8888| 1046| enableRKCodecNodeConvertedBufferDump | true/false | The value **true** means to dump the data in the **DeliverBuffer** method defined in the **rk_codec_node.cpp** file.| Preview, photo taking, and video recording| JPEG, H264, RGBA8888| 1047| enableSreamTunnelBufferDump | true/false | The value **true** means to dump the data in the **PutBuffer** method defined in the **stream_tunnel.cpp** file.| Preview, photo taking, and video recording| JPEG, H264, YUV420, RGBA8888| 1048| enableMetadataDump | true/false | The value **true** means to enable the dump metadata feature.| Preview, photo taking, and video recording| .meta | 1049 1050 1051You can also set the dump sampling interval, as described in the following table. 1052 1053 **Table 2** Dump sampling interval 1054 1055| Dump sampling interval| **Value**| **Description**| 1056| -------- | -------- | -------- | 1057| previewInterval | Integer greater than or equal to 1| Interval for dumping preview. The default value is **1**, which means to dump every frame.| 1058| videoInterval | Integer greater than or equal to 1| Interval for dumping video recording. The default value is **1**, which means to dump every frame.| 1059 1060#### Configuration Example 1061 1062Create a file named **dump.config** in any location on your PC and configure the related parameters. 1063 1064Complete configuration: 1065 1066>__enableDQBufDump=true__<br> 1067>enableUVCNodeBufferDump=false<br> 1068>enableUVCNodeConvertedBufferDump=false<br> 1069>enableExifNodeConvertedBufferDump=false<br> 1070>enableFaceNodeConvertedBufferDump=false<br> 1071>enableForkNodeConvertedBufferDump=false<br> 1072>enableRKFaceNodeConvertedBufferDump=false<br> 1073>enableRKExifNodeConvertedBufferDump=false<br> 1074>enableCodecNodeConvertedBufferDump=false<br> 1075>enableRKCodecNodeConvertedBufferDump=false<br> 1076>enableSreamTunnelBufferDump=false<br> 1077>**enableMetadataDump=true**<br> 1078>**previewInterval=3**<br> 1079>videoInterval=1<br> 1080 1081 1082Example: 1083 1084Dump **DequeueBuffer** data and metadata with a dump sampling interval of 3. 1085 1086#### Enabling Dump 10871. Transfer the configuration file to the **/data/local/tmp** directory of the target device. 1088 1089 ``` 1090 hdc file send dump.config /data/local/tmp 1091 ``` 1092 10932. Modify the permission on the dump directory. 1094 1095 ``` 1096 hdc shell mount -o rw,remount /data 1097 hdc shell chmod 777 /data/ -R 1098 ``` 1099 11003. Enable the dump feature. 1101 1102 ``` 1103 hdc shell "hidumper -s 5100 -a '-host camera_host -o'" 1104 ``` 1105 1106 * **-s 5100**: obtains all information about the ability whose ID is 5100. In this example, ability 5100 is camera. 1107 * **-a '-host camera_host -o'**: exports the specified ability information. 1108 * For details about how to use HiDumper, see [HiDumper](../../device-dev/subsystems/subsys-dfx-hidumper.md). 1109 1110 11114. Start the camera and perform operations, such as taking photos and videos, and previewing the photos and videos. 1112 1113#### Dumping Data 1114After the dump feature is enabled, a file containing the data dumped will be generated in the **/data/local/tmp** directory of the device. You can view the file after sending it to a PC. 1115``` 1116hdc file recv /data/local/tmp/xxxx.yuv ~/ 1117``` 1118