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![](figures/camera-driver-model-architecture.png)
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