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