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