driver-peripherals-camera-des.md 49.5 KB
Newer Older
A
annie_wangli 已提交
1
# Camera
Z
zengyawen 已提交
2

A
Annie_wang 已提交
3 4
## Overview
### Function
Z
zengyawen 已提交
5

A
Annie_wang 已提交
6 7
The 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:
Z
zengyawen 已提交
8

A
annie_wangli 已提交
9
+ HDI implementation layer: implements standard ohos (OpenHarmony operating system) APIs for cameras.
A
Annie_wang 已提交
10 11
+ Framework layer: interacts with the HDI implementation layer to set up data channels and operate camera devices.
+ Device adaptation layer: supports different platforms by shielding the differences in underlying chips and operating systems.
Z
zengyawen 已提交
12

A
Annie_wang 已提交
13
### Working Principles
Z
zengyawen 已提交
14

A
Annie_wang 已提交
15
The 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.
Z
zengyawen 已提交
16

A
annie_wangli 已提交
17
**Figure 1** HDF-based camera driver model
Z
zengyawen 已提交
18

A
annie_wangli 已提交
19
![](figures/camera-driver-model-architecture.png)
Z
zengyawen 已提交
20

A
Annie_wang 已提交
21
1. 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.
Z
zengyawen 已提交
22

A
Annie_wang 已提交
23 24 25 26 27
2. The Camera Service obtains the **CameraHost** instance through the CameraDeviceHost service. 

   The **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). 

   When the **CameraDevice** instance is created, the PipelineCore modules will be instantiated. The StreamPipelineCore module creates pipelines, and the MetaQueueManager module reports metadata.
Z
zengyawen 已提交
28

A
annie_wangli 已提交
29
3. 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.
Z
zengyawen 已提交
30

A
Annie_wang 已提交
31
4. The Camera Service controls the stream operations through the **Stream** instance. 
Z
zengyawen 已提交
32

A
Annie_wang 已提交
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.
Z
zengyawen 已提交
34

A
Annie_wang 已提交
35
5. 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.
Z
zengyawen 已提交
36

A
Annie_wang 已提交
37
6. 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.
Z
zengyawen 已提交
38

A
Annie_wang 已提交
39 40 41
7. 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.

8. 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.
Z
zengyawen 已提交
42

A
annie_wangli 已提交
43
9. 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.
Z
zengyawen 已提交
44

A
annie_wangli 已提交
45
   
Z
zengyawen 已提交
46

A
Annie_wang 已提交
47
## Development Guidelines
Z
zengyawen 已提交
48

W
wusongqing 已提交
49

A
Annie_wang 已提交
50
### When to Use
W
wusongqing 已提交
51

A
Annie_wang 已提交
52
The camera module encapsulates camera operations in camera preview, photographing, and video streams to implement camera hardware operations and improve development efficiency.
W
wusongqing 已提交
53

A
Annie_wang 已提交
54
### Available APIs
W
wusongqing 已提交
55

A
Annie_wang 已提交
56 57
The following table describes the C++ APIs generated from the Interface Definition Language (IDL) interface description. For details about the interface declaration, see the .idl file in **/drivers/interface/camera/v1_0/**.        
The 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.
A
annie_wangli 已提交
58
- icamera_device.h
W
wusongqing 已提交
59

A
Annie_wang 已提交
60 61 62 63 64 65 66 67 68
  | API                 | Description                    |
  | ---------------------------- | ------------------------------------------------------------ |
  | int32_t GetStreamOperator(const sptr<IStreamOperatorCallback>& callbackObj, sptr<IStreamOperator>& streamOperator) | Obtains the stream controller.                |
  | int32_t UpdateSettings(const std::vector<uint8_t>& settings) | Updates device control parameters.            |
  | int32_t SetResultMode(ResultCallbackMode mode) | Sets the result callback mode and function.|
  | int32_t GetEnabledResults(std::vector<int32_t>& results) | Obtains the enabled ResultMeta.        |
  | int32_t EnableResult(const std::vector<int32_t>& results) | Enables specific ResultMeta.        |
  | int32_t DisableResult(const std::vector<int32_t>& results) | Disables specific ResultMeta.        |
  | int32_t Close() | Closes the camera device.              |
Z
zengyawen 已提交
69

A
annie_wangli 已提交
70
- icamera_device_callback.h
Z
zengyawen 已提交
71

A
Annie_wang 已提交
72
  | API                                                          | Description                                                  |
A
annie_wangli 已提交
73
  | ------------------------------------------------------------ | ------------------------------------------------------------ |
A
Annie_wang 已提交
74 75
  | int32_t OnError(ErrorType type, int32_t errorCode)           | Called when an error occurs on the camera device. The caller needs to implement this API. |
  | int32_t OnResult(uint64_t timestamp, const std::vector<uint8_t>& result) | Called to report metadata related to the camera device.      |
Z
zengyawen 已提交
76 77


A
annie_wangli 已提交
78
- icamera_host.h
Z
zengyawen 已提交
79

A
Annie_wang 已提交
80 81 82 83 84 85 86
  | API                                                    | Description                                         |
  | ------------------------------------------------------------ | ------------------------------------------------------------ |
  | int32_t SetCallback(const sptr<ICameraHostCallback>& callbackObj) | Sets the **ICameraHostCallback** API. |
  | int32_t GetCameraIds(std::vector<std::string>& cameraIds) | Obtains the IDs of available camera devices. |
  | int32_t GetCameraAbility(const std::string& cameraId, std::vector<uint8_t>& cameraAbility) | Obtains the abilities of a camera device. |
  | int32_t OpenCamera(const std::string& cameraId, const sptr<ICameraDeviceCallback>& callbackObj, sptr<ICameraDevice>& device) | Opens a camera. |
  | int32_t SetFlashlight(const std::string& cameraId, bool isEnable) | Turns on or off the flash. |
Z
zengyawen 已提交
87

A
annie_wangli 已提交
88
- icamera_host_callback.h
Z
zengyawen 已提交
89

A
Annie_wang 已提交
90 91 92 93 94
  | API                                                    | Description                                         |
  | ------------------------------------------------------------ | ------------------------------------------------------------ |
  | int32_t OnCameraStatus(const std::string& cameraId, CameraStatus status) | Called to report camera status changes. |
  | int32_t OnFlashlightStatus(const std::string& cameraId, FlashlightStatus status) | Called to report the flash status changes. |
  | int32_t OnCameraEvent(const std::string& cameraId, CameraEvent event) | Called to report a camera event. |
Z
zengyawen 已提交
95

A
annie_wangli 已提交
96
- ioffline_stream_operator.h
Z
zengyawen 已提交
97

A
Annie_wang 已提交
98 99 100 101 102
  | API                                         | Description                              |
  | ----                                         | ----                              |
  | int32_t CancelCapture(int32_t captureId)                      | Cancels a capture request. |
  | int32_t ReleaseStreams(const std::vector<int32_t>& streamIds) | Releases streams. |
  | int32_t Release()                                         | Releases all offline streams.            |
Z
zengyawen 已提交
103

A
annie_wangli 已提交
104
- istream_operator.h
Z
zengyawen 已提交
105

A
Annie_wang 已提交
106 107 108 109 110 111 112 113 114 115 116 117
  | API                                                    | Description                                         |
  | ------------------------------------------------------------ | ------------------------------------------------------------ |
  | int32_t IsStreamsSupported(OperationMode mode,<br>const std::vector<uint8_t>& modeSetting,<br>const std::vector<StreamInfo>& infos,<br> StreamSupportType& type) | Checks whether a stream can be added. |
  | int32_t CreateStreams(const std::vector<StreamInfo>& streamInfos) | Creates streams. |
  | int32_t ReleaseStreams(const std::vector<int32_t>& streamIds) | Releases streams. |
  | int32_t CommitStreams(OperationMode mode, const std::vector<uint8_t>& modeSetting) | Configure streams. |
  | int32_t GetStreamAttributes(std::vector<StreamAttribute>& attributes) | Obtain stream attributes. |
  | int32_t AttachBufferQueue(int32_t streamId, const sptr<BufferProducerSequenceable>& bufferProducer) | Attaches a producer handle to a stream. |
  | int32_t DetachBufferQueue(int32_t streamId)                   | Detaches a producer handle from a stream. |
  | int32_t Capture(int32_t captureId, const CaptureInfo& info, bool isStreaming) | Captures images. |
  | int32_t CancelCapture(int32_t captureId)                      | Cancels a capture.    |
  | int32_t ChangeToOfflineStream(const std::vector<int32_t>& streamIds,<br>const sptr<IStreamOperatorCallback>& callbackObj,<br>sptr<IOfflineStreamOperator>& offlineOperator) | Changes a stream into an offline stream. |
Z
zengyawen 已提交
118

A
annie_wangli 已提交
119
- istream_operator_callback.h
W
wusongqing 已提交
120

A
Annie_wang 已提交
121 122 123 124 125 126
  | API                                                          | Description                                     |
  | ------------------------------------------------------------ | ----------------------------------------------- |
  | int32_t OnCaptureStarted(int32_t captureId, const std::vector<int32_t>& streamIds) | Called when a capture starts.                   |
  | int32_t OnCaptureEnded(int32_t captureId, const std::vector<CaptureEndedInfo>& infos) | Called when a capture ends.                     |
  | int32_t OnCaptureError(int32_t captureId, const std::vector<CaptureErrorInfo>& infos) | Called when an error occurs during the capture. |
  | int32_t OnFrameShutter(int32_t captureId, const std::vector<int32_t>& streamIds, uint64_t timestamp) | Called when a frame is captured.                |
Z
zengyawen 已提交
127

A
Annie_wang 已提交
128 129
### How to Develop
The camera driver development procedure is as follows:
Z
zengyawen 已提交
130

A
Annie_wang 已提交
131
1. Register a **CameraHost** instance.
Z
zengyawen 已提交
132

A
Annie_wang 已提交
133 134
    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**.
    ```c++
A
annie_wangli 已提交
135 136 137 138 139 140 141 142 143
   struct HdfDriverEntry g_cameraHostDriverEntry = {
       .moduleVersion = 1,
       .moduleName = "camera_service",
       .Bind = HdfCameraHostDriverBind,
       .Init = HdfCameraHostDriverInit,
       .Release = HdfCameraHostDriverRelease,
   };
   HDF_INIT(g_cameraHostDriverEntry); // Register the HdfDriverEntry structure with the HDF.
   ```
Z
zengyawen 已提交
144

A
Annie_wang 已提交
145
2. Initialize the **CameraHost** service.
Z
zengyawen 已提交
146

A
Annie_wang 已提交
147
    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.
A
annie_wangli 已提交
148

A
Annie_wang 已提交
149 150
   ```c++
   static int HdfCameraHostDriverBind(struct HdfDeviceObject *deviceObject)
A
annie_wangli 已提交
151
   {
A
Annie_wang 已提交
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
       HDF_LOGI("HdfCameraHostDriverBind enter");
    
       auto *hdfCameraHostHost = new (std::nothrow) HdfCameraHostHost;
       if (hdfCameraHostHost == nullptr) {
           HDF_LOGE("%{public}s: failed to create HdfCameraHostHost object", __func__);
           return HDF_FAILURE;
       }
    
       hdfCameraHostHost->ioService.Dispatch = CameraHostDriverDispatch; // Provide a method to remotely call a CameraHost method.
       hdfCameraHostHost->ioService.Open = NULL;
       hdfCameraHostHost->ioService.Release = NULL;
    
       auto serviceImpl = ICameraHost::Get(true);
       if (serviceImpl == nullptr) {
           HDF_LOGE("%{public}s: failed to get of implement service", __func__);
           delete hdfCameraHostHost;
A
annie_wangli 已提交
168 169
           return HDF_FAILURE;
       }
A
Annie_wang 已提交
170 171 172 173 174 175
    
       hdfCameraHostHost->stub = OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl,
           ICameraHost::GetDescriptor()); // Initialize the camera.
       if (hdfCameraHostHost->stub == nullptr) {
           HDF_LOGE("%{public}s: failed to get stub object", __func__);
           delete hdfCameraHostHost;
A
annie_wangli 已提交
176 177
           return HDF_FAILURE;
       }
A
Annie_wang 已提交
178 179
    
       deviceObject->service = &hdfCameraHostHost->ioService;
A
annie_wangli 已提交
180 181 182 183 184 185
       return HDF_SUCCESS;
   }
   ```

   The following functions are the implementation of the methods of the **CameraHost**:

A
Annie_wang 已提交
186
   ```c++
A
annie_wangli 已提交
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
   int32_t CameraHostStub::CameraHostServiceStubOnRemoteRequest(int cmdId, MessageParcel &data,
       MessageParcel &reply, MessageOption &option)
   {
       switch(cmdId) {
           case CMD_CAMERA_HOST_SET_CALLBACK: {
               return CameraHostStubSetCallback(data, reply, option);
           }
           case CMD_CAMERA_HOST_GET_CAMERAID: {
               return CameraHostStubGetCameraIds(data, reply, option);
           }
           case CMD_CAMERA_HOST_GET_CAMERA_ABILITY: {
               return CameraHostStubGetCameraAbility(data, reply, option);
           }
           case CMD_CAMERA_HOST_OPEN_CAMERA: {
               return CameraHostStubOpenCamera(data, reply, option);
           }
           case CMD_CAMERA_HOST_SET_FLASH_LIGHT: {
               return CameraHostStubSetFlashlight(data, reply, option);
           }
           default: {
               HDF_LOGE("%s: not support cmd %d", __func__, cmdId);
               return HDF_ERR_INVALID_PARAM;
           }
       }
       return HDF_SUCCESS;
   }
   ```

   **CameraHostStubInstance()** finally calls **CameraHostImpl::Init()** to obtain the physical camera and initialize the DeviceManager and PipelineCore modules.

A
Annie_wang 已提交
217
3. Obtain the **CameraHost** service.
A
annie_wangli 已提交
218

A
Annie_wang 已提交
219
   Use **Get()** to obtain the **CameraHost** from the **CameraService**. The **Get()** method is as follows:
A
annie_wangli 已提交
220

A
Annie_wang 已提交
221
   ```c++
A
annie_wangli 已提交
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
   sptr<ICameraHost> ICameraHost::Get(const char *serviceName)
   {
       do {
           using namespace OHOS::HDI::ServiceManager::V1_0;
           auto servMgr = IServiceManager::Get();
           if (servMgr == nullptr) {
               HDF_LOGE("%s: IServiceManager failed!", __func__);
               break;
           }
           auto remote = servMgr->GetService(serviceName);  // Obtain the CameraHost based on serviceName.
           if (remote != nullptr) {
               sptr<CameraHostProxy> hostSptr = iface_cast<CameraHostProxy>(remote); // Return the CameraHostProxy object that contains interfaces such as OpenCamera() to the caller.
               return hostSptr;
           }
           HDF_LOGE("%s: GetService failed! serviceName = %s", __func__, serviceName);
       } while(false);
       HDF_LOGE("%s: get %s failed!", __func__, serviceName);
       return nullptr;
   }
   ```
Z
zengyawen 已提交
242

A
Annie_wang 已提交
243
4. Open a camera device.
Z
zengyawen 已提交
244

A
Annie_wang 已提交
245
   The **CameraHostProxy** class provides **SetCallback()**, **GetCameraIds()**, **GetCameraAbility()**, **OpenCamera()**, and **SetFlashlight()**.
A
annie_wangli 已提交
246

A
Annie_wang 已提交
247 248 249 250 251
   Use **OpenCamera()** to call the remote **CameraHostStubOpenCamera()** through the **CMD_CAMERA_HOST_OPEN_CAMERA** to obtain an **ICameraDevice** object.

   ```c++
   int32_t CameraHostProxy::OpenCamera(const std::string& cameraId, const sptr<ICameraDeviceCallback>& callbackObj,
       sptr<ICameraDevice>& device)
A
annie_wangli 已提交
252
   {
A
Annie_wang 已提交
253 254 255 256 257 258 259
       MessageParcel cameraHostData;
       MessageParcel cameraHostReply;
       MessageOption cameraHostOption(MessageOption::TF_SYNC);
    
       if (!cameraHostData.WriteInterfaceToken(ICameraHost::GetDescriptor())) {
           HDF_LOGE("%{public}s: failed to write interface descriptor!", __func__);
           return HDF_ERR_INVALID_PARAM;
A
annie_wangli 已提交
260
       }
A
Annie_wang 已提交
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
    
       if (!cameraHostData.WriteCString(cameraId.c_str())) {
           HDF_LOGE("%{public}s: write cameraId failed!", __func__);
           return HDF_ERR_INVALID_PARAM;
       }
    
       if (!cameraHostData.WriteRemoteObject(OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(callbackObj, 
           ICameraDeviceCallback::GetDescriptor()))) {
           HDF_LOGE("%{public}s: write callbackObj failed!", __func__);
           return HDF_ERR_INVALID_PARAM;
       }
    
       int32_t cameraHostRet = Remote()->SendRequest(CMD_CAMERA_HOST_OPEN_CAMERA, cameraHostData, cameraHostReply, cameraHostOption);
       if (cameraHostRet != HDF_SUCCESS) {
           HDF_LOGE("%{public}s failed, error code is %{public}d", __func__, cameraHostRet);
           return cameraHostRet;
A
annie_wangli 已提交
277
       }
A
Annie_wang 已提交
278 279 280 281
    
       device = hdi_facecast<ICameraDevice>(cameraHostReply.ReadRemoteObject());
    
       return cameraHostRet;
A
annie_wangli 已提交
282 283 284
   }
   ```

A
Annie_wang 已提交
285
   **Remote()->SendRequest** calls **CameraHostServiceStubOnRemoteRequest()**, locates **CameraHostStubOpenCamera()** based on **cmdId**, and finally calls **CameraHostImpl::OpenCamera()** to obtain a **CameraDevice** and power on the camera hardware.
A
annie_wangli 已提交
286

A
Annie_wang 已提交
287 288 289
   ```c++
   int32_t CameraHostImpl::OpenCamera(const std::string& cameraId, const sptr<ICameraDeviceCallback>& callbackObj,
       sptr<ICameraDevice>& device)
A
annie_wangli 已提交
290
   {
A
Annie_wang 已提交
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305
       CAMERA_LOGD("OpenCamera entry");
       DFX_LOCAL_HITRACE_BEGIN;
       if (CameraIdInvalid(cameraId) != RC_OK || callbackObj == nullptr) {
           CAMERA_LOGW("open camera id is empty or callback is null.");
           return INVALID_ARGUMENT;
       }
    
       auto itr = cameraDeviceMap_.find(cameraId);
       if (itr == cameraDeviceMap_.end()) {
           CAMERA_LOGE("camera device not found.");
           return INSUFFICIENT_RESOURCES;
       }
       CAMERA_LOGD("OpenCamera cameraId find success.");
    
       std::shared_ptr<CameraDeviceImpl> cameraDevice = itr->second;
A
annie_wangli 已提交
306 307 308 309
       if (cameraDevice == nullptr) {
           CAMERA_LOGE("camera device is null.");
           return INSUFFICIENT_RESOURCES;
       }
A
Annie_wang 已提交
310 311 312 313
    
       CamRetCode ret = cameraDevice->SetCallback(callbackObj);
       CHECK_IF_NOT_EQUAL_RETURN_VALUE(ret, HDI::Camera::V1_0::NO_ERROR, ret);
    
A
annie_wangli 已提交
314
       CameraHostConfig *config = CameraHostConfig::GetInstance();
A
Annie_wang 已提交
315 316
       CHECK_IF_PTR_NULL_RETURN_VALUE(config, INVALID_ARGUMENT);
    
A
annie_wangli 已提交
317 318 319 320 321 322 323 324 325 326 327
       std::vector<std::string> phyCameraIds;
       RetCode rc = config->GetPhysicCameraIds(cameraId, phyCameraIds);
       if (rc != RC_OK) {
           CAMERA_LOGE("get physic cameraId failed.");
           return DEVICE_ERROR;
       }
       if (CameraPowerUp(cameraId, phyCameraIds) != RC_OK) { // Power on the camera hardware.
           CAMERA_LOGE("camera powerup failed.");
           CameraPowerDown(phyCameraIds);
           return DEVICE_ERROR;
       }
A
Annie_wang 已提交
328
    
A
annie_wangli 已提交
329 330
       auto sptrDevice = deviceBackup_.find(cameraId);
       if (sptrDevice == deviceBackup_.end()) {
A
Annie_wang 已提交
331 332 333
   #ifdef CAMERA_BUILT_ON_OHOS_LITE
           deviceBackup_[cameraId] = cameraDevice;
   #else
A
annie_wangli 已提交
334
           deviceBackup_[cameraId] = cameraDevice.get();
A
Annie_wang 已提交
335
   #endif
A
annie_wangli 已提交
336 337 338
       }
       device = deviceBackup_[cameraId];
       cameraDevice->SetStatus(true);
A
Annie_wang 已提交
339 340 341
       CAMERA_LOGD("open camera success.");
       DFX_LOCAL_HITRACE_END;
       return HDI::Camera::V1_0::NO_ERROR;
A
annie_wangli 已提交
342 343
   }
   ```
Z
zengyawen 已提交
344

A
Annie_wang 已提交
345
5. Obtain streams.
Z
zengyawen 已提交
346

A
Annie_wang 已提交
347
   **CameraDeviceImpl** defines **GetStreamOperator()**, **UpdateSettings()**, **SetResultMode()**, and **GetEnabledResult()**. Use **GetStreamOperator()** to obtain steams.
A
annie_wangli 已提交
348

A
Annie_wang 已提交
349 350 351
   ```c++
   int32_t CameraDeviceImpl::GetStreamOperator(const sptr<IStreamOperatorCallback>& callbackObj,
       sptr<IStreamOperator>& streamOperator)
A
annie_wangli 已提交
352
   {
A
Annie_wang 已提交
353 354 355
       HDI_DEVICE_PLACE_A_WATCHDOG;
       DFX_LOCAL_HITRACE_BEGIN;
       if (callbackObj == nullptr) {
A
annie_wangli 已提交
356 357 358
           CAMERA_LOGW("input callback is null.");
           return INVALID_ARGUMENT;
       }
A
Annie_wang 已提交
359 360
    
       spCameraDeciceCallback_ = callbackObj;
A
annie_wangli 已提交
361
       if (spStreamOperator_ == nullptr) {
A
Annie_wang 已提交
362 363 364 365 366 367
   #ifdef CAMERA_BUILT_ON_OHOS_LITE
           // Create a spStreamOperator_ object and pass it to the caller for subsequent stream operations.
           spStreamOperator_ = std::make_shared<StreamOperator>(spCameraDeciceCallback_, shared_from_this());
   #else
           spStreamOperator_ = new(std::nothrow) StreamOperator(spCameraDeciceCallback_, shared_from_this());
   #endif
A
annie_wangli 已提交
368 369 370 371
           if (spStreamOperator_ == nullptr) {
               CAMERA_LOGW("create stream operator failed.");
               return DEVICE_ERROR;
           }
A
Annie_wang 已提交
372
           spStreamOperator_->Init();
A
annie_wangli 已提交
373 374 375
           ismOperator_ = spStreamOperator_;
       }
       streamOperator = ismOperator_;
A
Annie_wang 已提交
376 377 378 379 380
   #ifndef CAMERA_BUILT_ON_OHOS_LITE
       CAMERA_LOGI("CameraDeviceImpl %{public}s: line: %{public}d", __FUNCTION__, __LINE__);
       pipelineCore_->GetStreamPipelineCore()->SetCallback(
           [this](const std::shared_ptr<CameraMetadata> &metadata) {
           OnMetadataChanged(metadata);
A
annie_wangli 已提交
381
       });
A
Annie_wang 已提交
382 383 384
   #endif
       DFX_LOCAL_HITRACE_END;
       return HDI::Camera::V1_0::NO_ERROR;
A
annie_wangli 已提交
385 386
   }
   ```
Z
zengyawen 已提交
387

A
Annie_wang 已提交
388
6. Create streams.
Z
zengyawen 已提交
389

A
Annie_wang 已提交
390
   Fill in the **StreamInfo** structure before creating streams by calling **CreateStreams()**.
A
annie_wangli 已提交
391

A
Annie_wang 已提交
392
   ```c++
A
annie_wangli 已提交
393 394
   using StreamInfo = struct _StreamInfo {
       int streamId_; 
A
Annie_wang 已提交
395 396 397
       int width_;                             // Stream width
       int height_;                            // Stream height
       int format_;                            // Stream format, for example, PIXEL_FMT_YCRCB_420_SP
A
annie_wangli 已提交
398
       int dataSpace_; 
A
Annie_wang 已提交
399
       StreamIntent intent_;                   // StreamIntent, for example, PREVIEW
A
annie_wangli 已提交
400
       bool tunneledMode_;
A
Annie_wang 已提交
401
       ufferProducerSequenceable bufferQueue_; // Use streamCustomer->CreateProducer() to create a buffer queue for streams.
A
annie_wangli 已提交
402 403 404 405 406
       int minFrameDuration_;
       EncodeType encodeType_;
   };
   ```

A
Annie_wang 已提交
407
   **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.
A
annie_wangli 已提交
408

A
Annie_wang 已提交
409 410
   ```c++
   int32_t StreamOperator::CreateStreams(const std::vector<StreamInfo>& streamInfos)
A
annie_wangli 已提交
411
   {
A
Annie_wang 已提交
412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
       PLACE_A_NOKILL_WATCHDOG(requestTimeoutCB_);
       DFX_LOCAL_HITRACE_BEGIN;
       for (const auto& it : streamInfos) {
           CHECK_IF_NOT_EQUAL_RETURN_VALUE(CheckStreamInfo(it), true, INVALID_ARGUMENT);
           CAMERA_LOGI("streamId:%{public}d and format:%{public}d and width:%{public}d and height:%{public}d",
               it.streamId_, it.format_, it.width_, it.height_);
           if (streamMap_.count(it.streamId_) > 0) {
               CAMERA_LOGE("stream [id = %{public}d] has already been created.", it.streamId_);
               return INVALID_ARGUMENT;
           }
           std::shared_ptr<IStream> stream = StreamFactory::Instance().CreateShared( // Create a stream instance.
               IStream::g_availableStreamType[it.intent_], it.streamId_, it.intent_, pipelineCore_, messenger_);
           if (stream == nullptr) {
               CAMERA_LOGE("create stream [id = %{public}d] failed.", it.streamId_);
               return INSUFFICIENT_RESOURCES;
           }
           StreamConfiguration scg;
           StreamInfoToStreamConfiguration(scg, it);
           RetCode rc = stream->ConfigStream(scg);
           if (rc != RC_OK) {
               CAMERA_LOGE("configure stream %{public}d failed", it.streamId_);
               return INVALID_ARGUMENT;
           }
           if (!scg.tunnelMode && (it.bufferQueue_)->producer_ != nullptr) {
               CAMERA_LOGE("stream [id:%{public}d] is not tunnel mode, can't bind a buffer producer", it.streamId_);
               return INVALID_ARGUMENT;
           }
           if ((it.bufferQueue_)->producer_ != nullptr) {
               auto tunnel = std::make_shared<StreamTunnel>();
               CHECK_IF_PTR_NULL_RETURN_VALUE(tunnel, INSUFFICIENT_RESOURCES);
               rc = tunnel->AttachBufferQueue((it.bufferQueue_)->producer_);
               CHECK_IF_NOT_EQUAL_RETURN_VALUE(rc, RC_OK, INVALID_ARGUMENT);
               if (stream->AttachStreamTunnel(tunnel) != RC_OK) {
                   CAMERA_LOGE("attach buffer queue to stream [id = %{public}d] failed", it.streamId_);
                   return INVALID_ARGUMENT;
               }
           }
           {
               std::lock_guard<std::mutex> l(streamLock_);
               streamMap_[stream->GetStreamId()] = stream;
           }
           CAMERA_LOGI("create stream success [id:%{public}d] [type:%{public}s]", stream->GetStreamId(),
                       IStream::g_availableStreamType[it.intent_].c_str());
A
annie_wangli 已提交
455
       }
A
Annie_wang 已提交
456 457 458
       DFX_LOCAL_HITRACE_END;
       return HDI::Camera::V1_0::NO_ERROR;
    }
A
annie_wangli 已提交
459 460
   ```

A
Annie_wang 已提交
461
7. Configure streams.
A
annie_wangli 已提交
462

A
Annie_wang 已提交
463
   Use **CommitStreams()** to configure streams, including initializing and creating **PipelineCore**. **CommitStreams()** must be called after streams are created.
A
annie_wangli 已提交
464

A
Annie_wang 已提交
465 466
   ```c++
   int32_t StreamOperator::CommitStreams(OperationMode mode, const std::vector<uint8_t>& modeSetting)
A
annie_wangli 已提交
467
   {
A
Annie_wang 已提交
468 469 470 471 472 473
       CAMERA_LOGV("enter");
       CHECK_IF_PTR_NULL_RETURN_VALUE(streamPipeline_, DEVICE_ERROR);
       PLACE_A_NOKILL_WATCHDOG(requestTimeoutCB_);
       if (modeSetting.empty()) {
           CAMERA_LOGE("input vector is empty");
           return INVALID_ARGUMENT;
A
annie_wangli 已提交
474
       }
A
Annie_wang 已提交
475
       DFX_LOCAL_HITRACE_BEGIN;
A
annie_wangli 已提交
476
   
A
Annie_wang 已提交
477 478 479 480 481
       std::vector<StreamConfiguration> configs = {};
       {
           std::lock_guard<std::mutex> l(streamLock_);
           std::transform(streamMap_.begin(), streamMap_.end(), std::back_inserter(configs),
               [](auto &iter) { return iter.second->GetStreamAttribute(); });
A
annie_wangli 已提交
482
       }
A
Annie_wang 已提交
483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505
    
       std::shared_ptr<CameraMetadata> setting;
       MetadataUtils::ConvertVecToMetadata(modeSetting, setting);
       DynamicStreamSwitchMode method = streamPipeline_->CheckStreamsSupported(mode, setting, configs);
       if (method == DYNAMIC_STREAM_SWITCH_NOT_SUPPORT) {
           return INVALID_ARGUMENT;
       }
       if (method == DYNAMIC_STREAM_SWITCH_NEED_INNER_RESTART) {
           std::lock_guard<std::mutex> l(streamLock_);
           for (auto it : streamMap_) {
               it.second->StopStream();
           }
       }
       {
           std::lock_guard<std::mutex> l(streamLock_);
           for (auto it : streamMap_) {
               if (it.second->CommitStream() != RC_OK) {
                   CAMERA_LOGE("commit stream [id = %{public}d] failed.", it.first);
                   return DEVICE_ERROR;
               }
           }
       }
       RetCode rc = streamPipeline_->PreConfig(setting); // Configure the device stream.
A
annie_wangli 已提交
506
       if (rc != RC_OK) {
A
Annie_wang 已提交
507
           CAMERA_LOGE("prepare mode settings failed");
A
annie_wangli 已提交
508 509
           return DEVICE_ERROR;
       }
A
Annie_wang 已提交
510
       rc = streamPipeline_->CreatePipeline(mode); // Create a pipeline.
A
annie_wangli 已提交
511
       if (rc != RC_OK) {
A
Annie_wang 已提交
512
           CAMERA_LOGE("create pipeline failed.");
A
annie_wangli 已提交
513 514
           return INVALID_ARGUMENT;
       }
A
Annie_wang 已提交
515 516 517
    
       DFX_LOCAL_HITRACE_END;
       return HDI::Camera::V1_0::NO_ERROR;
A
annie_wangli 已提交
518 519 520 521 522
   }
   ```

8. Capture images.

A
Annie_wang 已提交
523
   Fill in the **CaptureInfo** structure before calling **Capture()**.
A
annie_wangli 已提交
524

A
Annie_wang 已提交
525
   ```c++
A
annie_wangli 已提交
526
   using CaptureInfo = struct _CaptureInfo {
A
Annie_wang 已提交
527 528 529
       int[] streamIds_;                 // IDs of the streams to capture.
       unsigned char[]  captureSetting_; // Use the camera ability obtained by GetCameraAbility() of CameraHost to fill in the settings.
       bool enableShutterCallback_;
A
annie_wangli 已提交
530 531 532
   };
   ```

A
Annie_wang 已提交
533
   Use the **Capture()** method in **StreamOperator** to capture data streams.
A
annie_wangli 已提交
534

A
Annie_wang 已提交
535 536
   ```c++
   int32_t StreamOperator::Capture(int32_t captureId, const CaptureInfo& info, bool isStreaming)
A
annie_wangli 已提交
537
   {
A
Annie_wang 已提交
538 539 540 541 542 543 544 545 546 547
       CHECK_IF_EQUAL_RETURN_VALUE(captureId < 0, true, INVALID_ARGUMENT);
       PLACE_A_NOKILL_WATCHDOG(requestTimeoutCB_);
       DFX_LOCAL_HITRACE_BEGIN;
    
       for (auto id : info.streamIds_) {
           std::lock_guard<std::mutex> l(streamLock_);
           auto it = streamMap_.find(id);
           if (it == streamMap_.end()) {
               return INVALID_ARGUMENT;
           }
A
annie_wangli 已提交
548
       }
A
Annie_wang 已提交
549
    
A
annie_wangli 已提交
550
       {
A
Annie_wang 已提交
551 552 553 554 555
           std::lock_guard<std::mutex> l(requestLock_);
           auto itr = requestMap_.find(captureId);
           if (itr != requestMap_.end()) {
               return INVALID_ARGUMENT;
           }
A
annie_wangli 已提交
556
       }
A
Annie_wang 已提交
557 558 559 560 561 562 563 564 565 566 567 568
    
       std::shared_ptr<CameraMetadata> captureSetting;
       MetadataUtils::ConvertVecToMetadata(info.captureSetting_, captureSetting);
       CaptureSetting setting = captureSetting;
       auto request =
           std::make_shared<CaptureRequest>(captureId, info.streamIds_.size(), setting,
                                             info.enableShutterCallback_, isStreaming);
       for (auto id : info.streamIds_) {
           RetCode rc = streamMap_[id]->AddRequest(request);
           if (rc != RC_OK) {
               return DEVICE_ERROR;
           }
A
annie_wangli 已提交
569
       }
A
Annie_wang 已提交
570 571 572 573 574 575
    
       {
           std::lock_guard<std::mutex> l(requestLock_);
           requestMap_[captureId] = request;
       }
       return HDI::Camera::V1_0::NO_ERROR;
A
annie_wangli 已提交
576 577 578 579 580
   }  
   ```

9. Cancel the capture and release the offline stream.

A
Annie_wang 已提交
581
   Use **CancelCapture()** in the **StreamOperatorImpl** class to cancel the stream capture based on **captureId**.
A
annie_wangli 已提交
582

A
Annie_wang 已提交
583 584
   ```c++
   int32_t StreamOperator::CancelCapture(int32_t captureId)
A
annie_wangli 已提交
585
   {
A
Annie_wang 已提交
586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604
       CHECK_IF_EQUAL_RETURN_VALUE(captureId < 0, true, INVALID_ARGUMENT);
       PLACE_A_NOKILL_WATCHDOG(requestTimeoutCB_);
       DFX_LOCAL_HITRACE_BEGIN;
    
       std::lock_guard<std::mutex> l(requestLock_);
       auto itr = requestMap_.find(captureId); // Search for the CameraCapture object in the Map based on the captureId.
       if (itr == requestMap_.end()) {
           CAMERA_LOGE("can't cancel capture [id = %{public}d], this capture doesn't exist", captureId);
           return INVALID_ARGUMENT;
       }
    
       RetCode rc = itr->second->Cancel();    // Call Cancel() in CameraCapture to cancel the stream capture.
       if (rc != RC_OK) {
           return DEVICE_ERROR;
       }
       requestMap_.erase(itr);                // Erase the CameraCapture object.
    
       DFX_LOCAL_HITRACE_END;
       return HDI::Camera::V1_0::NO_ERROR;
A
annie_wangli 已提交
605 606 607
   }
   ```

A
Annie_wang 已提交
608
   Use **ReleaseStreams()** in the **StreamOperatorImpl** class to release the streams created by using **CreateStream()** and **CommitStreams()** and destroy the pipeline.
A
annie_wangli 已提交
609

A
Annie_wang 已提交
610 611
   ```c++
   int32_t StreamOperator::ReleaseStreams(const std::vector<int32_t>& streamIds)
A
annie_wangli 已提交
612
   {
A
Annie_wang 已提交
613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633
       PLACE_A_NOKILL_WATCHDOG(requestTimeoutCB_);
       DFX_LOCAL_HITRACE_BEGIN;
       for (auto id : streamIds) {
           std::lock_guard<std::mutex> l(streamLock_);
           auto it = streamMap_.find(id);
           if (it == streamMap_.end()) {
               continue;
           }
           if (it->second->IsRunning()) {
               it->second->StopStream();
           }
           it->second->DumpStatsInfo();
           streamMap_.erase(it);
       }
    
       for (auto id : streamIds) {
           CHECK_IF_EQUAL_RETURN_VALUE(id < 0, true, INVALID_ARGUMENT);
       }
    
       DFX_LOCAL_HITRACE_END;
       return HDI::Camera::V1_0::NO_ERROR;
A
annie_wangli 已提交
634 635
   }
   ```
Z
zengyawen 已提交
636

W
wusongqing 已提交
637
10. Close the camera device.
A
annie_wangli 已提交
638

A
Annie_wang 已提交
639
    Use **Close()** in the **CameraDeviceImpl** class to close the camera device. The **PowerDown()** in **DeviceManager** is called to power off the device.    
A
annie_wangli 已提交
640

A
Annie_wang 已提交
641
### Example
A
annie_wangli 已提交
642

643
There is a [ohos_camera_demo](https://gitee.com/openharmony/drivers_peripheral/tree/master/camera/hal/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. 
A
annie_wangli 已提交
644

A
Annie_wang 已提交
645 646 647 648 649
The following uses the demo to describe how to use the HDI to implement **PreviewOn()** and **CaptureON()**.

1. 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**.

   ```c++
A
annie_wangli 已提交
650 651 652 653
   int main(int argc, char** argv)
   {
       RetCode rc = RC_OK;
       auto mainDemo = std::make_shared<CameraDemo>();
A
Annie_wang 已提交
654
       rc = mainDemo->InitSensors();      // Initialize the CameraHost.
A
annie_wangli 已提交
655 656 657 658 659 660 661 662 663 664 665
       if (rc == RC_ERROR) {
           CAMERA_LOGE("main test: mainDemo->InitSensors() error\n");
           return -1;
       }
   
       rc = mainDemo->InitCameraDevice(); // Initialize the CameraDevice.
       if (rc == RC_ERROR) {
           CAMERA_LOGE("main test: mainDemo->InitCameraDevice() error\n");
           return -1;
       }
   
A
Annie_wang 已提交
666
       rc = PreviewOn(0, mainDemo);       // Configure and enable streams.
A
annie_wangli 已提交
667 668 669 670 671
       if (rc != RC_OK) {
           CAMERA_LOGE("main test: PreviewOn() error demo exit");
           return -1;
       }
   
A
Annie_wang 已提交
672
       ManuList(mainDemo, argc, argv);    // Print the menu to the console.
A
annie_wangli 已提交
673 674 675 676 677 678 679
   
       return RC_OK;
   }
   ```

   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:

A
Annie_wang 已提交
680 681
   ```c++
   RetCode OhosCameraDemo::InitSensors()
A
annie_wangli 已提交
682
   {
A
Annie_wang 已提交
683 684 685 686 687 688 689 690 691 692 693 694 695
       int rc = 0;
   
       CAMERA_LOGD("demo test: InitSensors enter");
    
       if (demoCameraHost_ != nullptr) {
           return RC_OK;
       }
   #ifdef CAMERA_BUILT_ON_OHOS_LITE
       demoCameraHost_ = OHOS::Camera::CameraHost::CreateCameraHost();
   #else
       constexpr const char *DEMO_SERVICE_NAME = "camera_service";
       demoCameraHost_ = ICameraHost::Get(DEMO_SERVICE_NAME, false);
   #endif
A
annie_wangli 已提交
696 697 698 699
       if (demoCameraHost_ == nullptr) {
           CAMERA_LOGE("demo test: ICameraHost::Get error");
           return RC_ERROR;
       }
A
Annie_wang 已提交
700 701 702 703 704 705
    
   #ifdef CAMERA_BUILT_ON_OHOS_LITE
       hostCallback_ = std::make_shared<DemoCameraHostCallback>();
   #else
       hostCallback_ = new DemoCameraHostCallback();
   #endif
A
annie_wangli 已提交
706
       rc = demoCameraHost_->SetCallback(hostCallback_);
A
Annie_wang 已提交
707 708 709 710 711 712 713
       if (rc != HDI::Camera::V1_0::NO_ERROR) {
           CAMERA_LOGE("demo test: demoCameraHost_->SetCallback(hostCallback_) error");
           return RC_ERROR;
       }
    
       CAMERA_LOGD("demo test: InitSensors exit");
    
A
annie_wangli 已提交
714 715 716 717
       return RC_OK;
   }
   ```

A
Annie_wang 已提交
718
   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**.
A
annie_wangli 已提交
719

A
Annie_wang 已提交
720 721
   ```c++
   RetCode OhosCameraDemo::InitCameraDevice()
A
annie_wangli 已提交
722
   {
A
Annie_wang 已提交
723 724 725 726 727 728 729 730 731
       int rc = 0;
    
       CAMERA_LOGD("demo test: InitCameraDevice enter");
    
       if (demoCameraHost_ == nullptr) {
           CAMERA_LOGE("demo test: InitCameraDevice demoCameraHost_ == nullptr");
           return RC_ERROR;
       }
    
A
annie_wangli 已提交
732
       (void)demoCameraHost_->GetCameraIds(cameraIds_);
A
Annie_wang 已提交
733 734 735
       if (cameraIds_.empty()) {
           return RC_ERROR;
       }
A
annie_wangli 已提交
736
       const std::string cameraId = cameraIds_.front();
A
Annie_wang 已提交
737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761
       demoCameraHost_->GetCameraAbility(cameraId, cameraAbility_);
    
       MetadataUtils::ConvertVecToMetadata(cameraAbility_, ability_);
    
       GetFaceDetectMode(ability_);
       GetFocalLength(ability_);
       GetAvailableFocusModes(ability_);
       GetAvailableExposureModes(ability_);
       GetExposureCompensationRange(ability_);
       GetExposureCompensationSteps(ability_);
       GetAvailableMeterModes(ability_);
       GetAvailableFlashModes(ability_);
       GetMirrorSupported(ability_);
       GetStreamBasicConfigurations(ability_);
       GetFpsRange(ability_);
       GetCameraPosition(ability_);
       GetCameraType(ability_);
       GetCameraConnectionType(ability_);
       GetFaceDetectMaxNum(ability_);
    
   #ifdef CAMERA_BUILT_ON_OHOS_LITE
       std::shared_ptr<CameraDeviceCallback> callback = std::make_shared<CameraDeviceCallback>();
   #else
       sptr<DemoCameraDeviceCallback> callback = new DemoCameraDeviceCallback();
   #endif
A
annie_wangli 已提交
762
       rc = demoCameraHost_->OpenCamera(cameraIds_.front(), callback, demoCameraDevice_);
A
Annie_wang 已提交
763 764 765 766 767 768 769
       if (rc != HDI::Camera::V1_0::NO_ERROR || demoCameraDevice_ == nullptr) {
           CAMERA_LOGE("demo test: InitCameraDevice OpenCamera failed");
           return RC_ERROR;
       }
    
       CAMERA_LOGD("demo test: InitCameraDevice exit");
    
A
annie_wangli 已提交
770 771 772 773
       return RC_OK;
   }   
   ```

A
Annie_wang 已提交
774
2. Implement **PreviewOn()** to configure streams, enable preview streams, and start stream capture. 
A
annie_wangli 已提交
775

A
Annie_wang 已提交
776
   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.
A
annie_wangli 已提交
777

A
Annie_wang 已提交
778 779
   ```c++
   static RetCode PreviewOn(int mode, const std::shared_ptr<OhosCameraDemo>& mainDemo)
A
annie_wangli 已提交
780 781
   {
       RetCode rc = RC_OK;
A
Annie_wang 已提交
782 783 784 785 786 787
       CAMERA_LOGD("main test: PreviewOn enter");
    
       rc = mainDemo->StartPreviewStream();     // Configure the preview stream.
       if (rc != RC_OK) {
           CAMERA_LOGE("main test: PreviewOn StartPreviewStream error");
           return RC_ERROR;
A
annie_wangli 已提交
788
       }
A
Annie_wang 已提交
789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810
    
       if (mode == 0) {
           rc = mainDemo->StartCaptureStream(); // Configure the capture stream.
           if (rc != RC_OK) {
               CAMERA_LOGE("main test: PreviewOn StartCaptureStream error");
               return RC_ERROR;
           }
       } else {
           rc = mainDemo->StartVideoStream();   // Configure the video stream.
           if (rc != RC_OK) {
               CAMERA_LOGE("main test: PreviewOn StartVideoStream error");
               return RC_ERROR;
           }
       }
    
       rc = mainDemo->CaptureON(STREAM_ID_PREVIEW, CAPTURE_ID_PREVIEW, CAPTURE_PREVIEW);
       if (rc != RC_OK) {
           CAMERA_LOGE("main test: PreviewOn mainDemo->CaptureON() preview error");
           return RC_ERROR;
       }
    
       CAMERA_LOGD("main test: PreviewOn exit");
A
annie_wangli 已提交
811
       return RC_OK;
A
Annie_wang 已提交
812
   }           
A
annie_wangli 已提交
813 814
   ```

A
Annie_wang 已提交
815
   The **StartCaptureStream()**, **StartVideoStream()**, and **StartPreviewStream()** methods call **CreateStream()** with different input parameters.
A
annie_wangli 已提交
816

A
Annie_wang 已提交
817 818 819 820 821
   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.

   ```c++
   RetCode OhosCameraDemo::CreateStream(const int streamId, std::shared_ptr<StreamCustomer> &streamCustomer,
       StreamIntent intent)
A
annie_wangli 已提交
822
   {
A
Annie_wang 已提交
823 824 825
       int rc = 0;
       CAMERA_LOGD("demo test: CreateStream enter");
    
A
annie_wangli 已提交
826
       GetStreamOpt(); // Obtain a StreamOperator object.
A
Annie_wang 已提交
827 828
       if (streamOperator_ == nullptr) {
           CAMERA_LOGE("demo test: CreateStream GetStreamOpt() is nullptr\n");
A
annie_wangli 已提交
829 830
           return RC_ERROR;
       }
A
Annie_wang 已提交
831 832 833 834 835 836
    
       StreamInfo streamInfo = {0};
    
       SetStreamInfo(streamInfo, streamCustomer, streamId, intent); // Fills in the StreamInfo stream.
       if (streamInfo.bufferQueue_->producer_ == nullptr) {
           CAMERA_LOGE("demo test: CreateStream CreateProducer(); is nullptr\n");
A
annie_wangli 已提交
837 838
           return RC_ERROR;
       }
A
Annie_wang 已提交
839 840 841 842
    
       std::vector<StreamInfo> streamInfos;
       streamInfos.push_back(streamInfo);
    
A
annie_wangli 已提交
843
       rc = streamOperator_->CreateStreams(streamInfos); // Create a stream.
A
Annie_wang 已提交
844
       if (rc != HDI::Camera::V1_0::NO_ERROR) {
A
annie_wangli 已提交
845 846 847 848
           CAMERA_LOGE("demo test: CreateStream CreateStreams error\n");
           return RC_ERROR;
       }
   
A
Annie_wang 已提交
849 850
       rc = streamOperator_->CommitStreams(NORMAL, cameraAbility_);
       if (rc != HDI::Camera::V1_0::NO_ERROR) {
A
annie_wangli 已提交
851
           CAMERA_LOGE("demo test: CreateStream CommitStreams error\n");
A
Annie_wang 已提交
852 853
           std::vector<int> streamIds;
           streamIds.push_back(streamId);
A
annie_wangli 已提交
854 855 856
           streamOperator_->ReleaseStreams(streamIds);
           return RC_ERROR;
       }
A
Annie_wang 已提交
857 858 859
   
       CAMERA_LOGD("demo test: CreateStream exit");
    
A
annie_wangli 已提交
860 861 862 863
       return RC_OK;
   }
   ```

A
Annie_wang 已提交
864
   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.
A
annie_wangli 已提交
865

A
Annie_wang 已提交
866 867 868
   ```c++
   RetCode OhosCameraDemo::CaptureON(const int streamId,
       const int captureId, CaptureMode mode)
A
annie_wangli 已提交
869
   {
A
Annie_wang 已提交
870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911
       CAMERA_LOGI("demo test: CaptureON enter streamId == %{public}d and captureId == %{public}d and mode == %{public}d",
           streamId, captureId, mode);
       std::lock_guard<std::mutex> l(metaDatalock_);
       if (mode == CAPTURE_SNAPSHOT) {
           constexpr double latitude = 27.987500; // dummy data: Qomolangma latitde
           constexpr double longitude = 86.927500; // dummy data: Qomolangma longituude
           constexpr double altitude = 8848.86; // dummy data: Qomolangma altitude
           constexpr size_t entryCapacity = 100;
           constexpr size_t dataCapacity = 2000;
           captureSetting_ = std::make_shared<CameraSetting>(entryCapacity, dataCapacity);
           captureQuality_ = OHOS_CAMERA_JPEG_LEVEL_HIGH;
           captureOrientation_ = OHOS_CAMERA_JPEG_ROTATION_270;
           mirrorSwitch_ = OHOS_CAMERA_MIRROR_ON;
           gps_.push_back(latitude);
           gps_.push_back(longitude);
           gps_.push_back(altitude);
           captureSetting_->addEntry(OHOS_JPEG_QUALITY, static_cast<void*>(&captureQuality_),
               sizeof(captureQuality_));
           captureSetting_->addEntry(OHOS_JPEG_ORIENTATION, static_cast<void*>(&captureOrientation_),
               sizeof(captureOrientation_));
           captureSetting_->addEntry(OHOS_CONTROL_CAPTURE_MIRROR, static_cast<void*>(&mirrorSwitch_),
               sizeof(mirrorSwitch_));
           captureSetting_->addEntry(OHOS_JPEG_GPS_COORDINATES, gps_.data(), gps_.size());
       }
    
       std::vector<uint8_t> setting;
       MetadataUtils::ConvertMetadataToVec(captureSetting_, setting);
       captureInfo_.streamIds_ = {streamId};
       if (mode == CAPTURE_SNAPSHOT) {
           captureInfo_.captureSetting_ = setting;
       } else {
           captureInfo_.captureSetting_ = cameraAbility_;
       }
       captureInfo_.enableShutterCallback_ = false;
    
       int rc = streamOperator_->Capture(captureId, captureInfo_, true); // The capture starts, and buffer starts to flip.
       if (rc != HDI::Camera::V1_0::NO_ERROR) {
           CAMERA_LOGE("demo test: CaptureStart Capture error\n");
           streamOperator_->ReleaseStreams(captureInfo_.streamIds_);
           return RC_ERROR;
       }
    
A
annie_wangli 已提交
912
       if (mode == CAPTURE_PREVIEW) {
A
Annie_wang 已提交
913
           streamCustomerPreview_->ReceiveFrameOn(nullptr); // Create a preview thread to receive the passed buffer.
A
annie_wangli 已提交
914
       } else if (mode == CAPTURE_SNAPSHOT) {
A
Annie_wang 已提交
915
           streamCustomerCapture_->ReceiveFrameOn([this](void* addr, const uint32_t size) { // Create a capture thread to receive the passed buffer through the StoreImage callback.
A
annie_wangli 已提交
916 917 918 919
               StoreImage(addr, size);
           });
       } else if (mode == CAPTURE_VIDEO) {
           OpenVideoFile();
A
Annie_wang 已提交
920 921
    
           streamCustomerVideo_->ReceiveFrameOn([this](void* addr, const uint32_t size) { // Create a video thread to receive the passed buffer through the StoreImage callback.
A
annie_wangli 已提交
922 923 924
               StoreVideo(addr, size);
           });
       }
A
Annie_wang 已提交
925 926
       CAMERA_LOGD("demo test: CaptureON exit");
    
A
annie_wangli 已提交
927 928 929 930
       return RC_OK;
   }
   ```

A
Annie_wang 已提交
931
3. 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.
A
annie_wangli 已提交
932

A
Annie_wang 已提交
933 934
   ```c++
   static void ManuList(const std::shared_ptr<OhosCameraDemo>& mainDemo,
A
annie_wangli 已提交
935 936 937
       const int argc, char** argv)
   {
       int idx, c;
A
Annie_wang 已提交
938 939 940 941
       bool isAwb = true;
       const char *shortOptions = "h:cwvaeqof:";
       c = getopt_long(argc, argv, shortOptions, LONG_OPTIONS, &idx);
       while (1) {
A
annie_wangli 已提交
942 943
           switch (c) {
               case 'h':
A
Annie_wang 已提交
944
                   c = PutMenuAndGetChr();   // Print the menu.
A
annie_wangli 已提交
945
                   break;
A
Annie_wang 已提交
946 947
               case 'f':
                   FlashLightTest(mainDemo); // Verify the flashlight capability.
A
annie_wangli 已提交
948 949 950
                   c = PutMenuAndGetChr();
                   break;
               case 'o':
A
Annie_wang 已提交
951
                   OfflineTest(mainDemo);    // Verify the offline capability.
A
annie_wangli 已提交
952 953 954
                   c = PutMenuAndGetChr();
                   break;
               case 'c':
A
Annie_wang 已提交
955
                   CaptureTest(mainDemo);    // Verify the capture capability.
A
annie_wangli 已提交
956 957
                   c = PutMenuAndGetChr();
                   break;
A
Annie_wang 已提交
958 959
               case 'w':                     // Verify the AWB capability.
                   if (isAwb) {
A
annie_wangli 已提交
960 961 962 963
                       mainDemo->SetAwbMode(OHOS_CAMERA_AWB_MODE_INCANDESCENT);
                   } else {
                       mainDemo->SetAwbMode(OHOS_CAMERA_AWB_MODE_OFF);
                   }
A
Annie_wang 已提交
964
                   isAwb = !isAwb;
A
annie_wangli 已提交
965 966
                   c = PutMenuAndGetChr();
                   break;
A
Annie_wang 已提交
967
               case 'a':                    // Verify the AE capability.
A
annie_wangli 已提交
968 969 970
                   mainDemo->SetAeExpo();
                   c = PutMenuAndGetChr();
                   break;
A
Annie_wang 已提交
971 972 973 974 975
               case'e':                     // Verify the metadata operations.
                   mainDemo->SetMetadata();
                   c = PutMenuAndGetChr();
                   break;
               case'v':                     // Verify the video function.
A
annie_wangli 已提交
976 977 978
                   VideoTest(mainDemo);
                   c = PutMenuAndGetChr();
                   break;
A
Annie_wang 已提交
979
               case 'q':                    // Exit the demo.
A
annie_wangli 已提交
980 981
                   PreviewOff(mainDemo);
                   mainDemo->QuitDemo();
A
Annie_wang 已提交
982
                   return;
A
annie_wangli 已提交
983 984 985 986 987 988 989 990 991
               default:
                   CAMERA_LOGE("main test: command error please retry input command");
                   c = PutMenuAndGetChr();
                   break;
           }
       }
   }
   ```

A
Annie_wang 已提交
992
   Use **PutMenuAndGetChr()** to print the menu of the demo and call **fgets()** to wait for commands from the console.
A
annie_wangli 已提交
993

A
Annie_wang 已提交
994
   ```c++
A
annie_wangli 已提交
995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015
   static int PutMenuAndGetChr(void)
   {
       constexpr uint32_t inputCount = 50;
       int c = 0;
       char strs[inputCount];
       Usage(stdout);
       CAMERA_LOGD("pls input command(input -q exit this app)\n");
       fgets(strs, inputCount, stdin);
   
       for (int i = 0; i < inputCount; i++) {
           if (strs[i] != '-') {
               c = strs[i];
               break;
           }
       }
       return c;
   }
   ```

   The console outputs the menu details as follows:

A
Annie_wang 已提交
1016
   ```c++
A
annie_wangli 已提交
1017 1018 1019 1020 1021
   "Options:\n"
   "-h | --help          Print this message\n"
   "-o | --offline       stream offline test\n"
   "-c | --capture       capture one picture\n"
   "-w | --set WB        Set white balance Cloudy\n"
A
Annie_wang 已提交
1022
   "-v | --video         capture Video of 10s\n"
A
annie_wangli 已提交
1023
   "-a | --Set AE        Set Auto exposure\n"
A
Annie_wang 已提交
1024
   "-e | --Set Metadeta  Set Metadata\n"
A
annie_wangli 已提交
1025 1026 1027 1028
   "-f | --Set Flashlight        Set flashlight ON 5s OFF\n"
   "-q | --quit          stop preview and quit this app\n");
   ```

A
Annie_wang 已提交
1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048
4. Compile and build the **ohos_camera_demo**.        

   Add **init:ohos_camera_demo** to **deps** in the **drivers/peripheral/camera/hal/BUILD.gn** file. 

   The sample code is as follows:

   ```
   deps = [
       "buffer_manager:camera_buffer_manager",
       "device_manager:camera_device_manager",
       "hdi_impl:camera_host_service_1.0",
       "pipeline_core:camera_pipeline_core",
       "utils:camera_utils",
       "init:ohos_camera_demo",
       ]
   ```

   The following uses RK3568 development board as an example.       
   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/**.       
   2. Import the executable file **ohos_camera_demo** to the development board, modify the permission, and run the file.