未验证 提交 4059bb05 编写于 作者: O openharmony_ci 提交者: Gitee

!10746 Camera Development Guide Optimization

Merge pull request !10746 from Zhangzi/master
...@@ -18,9 +18,9 @@ Camera模块主要包含服务、设备的初始化,数据通路的搭建, ...@@ -18,9 +18,9 @@ Camera模块主要包含服务、设备的初始化,数据通路的搭建,
        ![](figures/Camera模块驱动模型.png)         ![](figures/Camera模块驱动模型.png)
1. 系统启动时创建camera_host进程。进程创建后,首先枚举底层设备,创建(也可以通过配置表创建)管理设备树的DeviceManager类及其内部各个底层设备的对象,创建对应的CameraHost类实例并且将其注册到UHDF服务中,方便相机服务层通过UHDF服务获取底层CameraDeviceHost的服务,从而操作硬件设备。 1. 系统启动时创建camera_host进程。进程创建后,首先枚举底层设备,创建(也可以通过配置表创建)管理设备树的DeviceManager类及其内部各个底层设备的对象,创建对应的CameraHost类实例并且将其注册到UHDF(用户态HDF驱动框架)服务中,方便相机服务层通过UHDF服务获取底层CameraDeviceHost的服务,从而操作硬件设备。
2. Service通过CameraDeviceHost服务获取CameraHost实例,CameraHost可以获取底层的Camera能力,打开手电筒、调用Open接口打开Camera创建连接、创建DeviceManager(负责底层硬件模块上电)、创建CameraDevice(向上提供设备控制接口)。创建CameraDevice时会实例化PipelineCore的各个子模块,其中StreamPipelineCore负责创建Pipeline,MetaQueueManager负责上报metaData。 2. Service通过CameraDeviceHost服务获取CameraHost实例,CameraHost可以获取底层的Camera能力,开启闪光灯、调用Open接口打开Camera创建连接、创建DeviceManager(负责底层硬件模块上电)、创建CameraDevice(向上提供设备控制接口)。创建CameraDevice时会实例化PipelineCore的各个子模块,其中StreamPipelineCore负责创建Pipeline,MetaQueueManager负责上报metaData。
3. Service通过CameraDevice模块配置流、创建Stream类。StreamPipelineStrategy模块通过上层下发的模式和查询配置表创建对应流的Node连接方式,StreamPipelineBuilder模块创建Node实例并且连接返回该Pipeline给StreamPipelineDispatcher。StreamPipelineDispatcher提供统一的Pipeline调用管理。 3. Service通过CameraDevice模块配置流、创建Stream类。StreamPipelineStrategy模块通过上层下发的模式和查询配置表创建对应流的Node连接方式,StreamPipelineBuilder模块创建Node实例并且连接返回该Pipeline给StreamPipelineDispatcher。StreamPipelineDispatcher提供统一的Pipeline调用管理。
...@@ -43,86 +43,88 @@ Camera模块主要包含服务、设备的初始化,数据通路的搭建, ...@@ -43,86 +43,88 @@ Camera模块主要包含服务、设备的初始化,数据通路的搭建,
### 场景介绍<a name="5"></a> ### 场景介绍<a name="5"></a>
Camera模块主要用以相机预览、拍照、视频流等场景下对相机操作封装,使开发者更易操作相机硬件,提高开发效率。 Camera模块主要针对相机预览、拍照、视频流等场景,对这些场景下的相机操作进行封装,使开发者更易操作相机硬件,提高开发效率。
### 接口说明<a name="6"></a> ### 接口说明<a name="6"></a>
注:以下接口列举的为IDL接口描述生成的对应C++语言函数接口,接口声明见idl文件(/drivers/interface/camera/v1_0/)。
- icamera_device.h - icamera_device.h
| 功能描述 | 接口名称 | | 功能描述 | 接口名称 |
| ---------------------------- | ------------------------------------------------------------ | | ---------------------------- | ------------------------------------------------------------ |
| 获取流控制器 | CamRetCode GetStreamOperator(<br>const OHOS::sptr<IStreamOperatorCallback> &callback,<br>OHOS::sptr<IStreamOperator> &streamOperator) | | 获取流控制器 | int32_t GetStreamOperator(const sptr<IStreamOperatorCallback>& callbackObj,<br>sptr<IStreamOperator>& streamOperator) |
| 更新设备控制参数 | CamRetCode UpdateSettings(const std::shared_ptr<CameraSetting> &settings) | | 更新设备控制参数 | int32_t UpdateSettings(const std::vector<uint8_t>& settings) |
| 设置Result回调模式和回调函数 | CamRetCode SetResultMode(const ResultCallbackMode &mode) | | 设置Result回调模式和回调函数 | int32_t SetResultMode(ResultCallbackMode mode) |
| 获取使能的ResultMeta | CamRetCode GetEnabledResults(std::vector<MetaType> &results) | | 获取使能的ResultMeta | int32_t GetEnabledResults(std::vector<int32_t>& results) |
| 使能具体的ResultMeta | CamRetCode EnableResult(const std::vector<MetaType> &results) | | 使能具体的ResultMeta | int32_t EnableResult(const std::vector<int32_t>& results) |
| 禁止具体的ResultMeta | CamRetCode DisableResult(const std::vector<MetaType> &results) | | 禁止具体的ResultMeta | int32_t DisableResult(const std::vector<int32_t>& results) |
| 关闭Camera设备 | void Close() | | 关闭Camera设备 | int32_t Close() |
- icamera_device_callback.h - icamera_device_callback.h
| 功能描述 | 接口名称 | | 功能描述 | 接口名称 |
| ---------------------------------------------------------- | ------------------------------------------------------------ | | ---------------------------------------------------------- | ------------------------------------------------------------ |
| 设备发生错误时调用,由调用者实现,用于返回错误信息给调用者 | void OnError(ErrorType type, int32_t errorCode) | | 设备发生错误时调用,由调用者实现,用于返回错误信息给调用者 | int32_t OnError(ErrorType type, int32_t errorCode) |
| 上报camera设备相关的metadata的回调 | void OnResult(uint64_t timestamp, const std::shared_ptr<CameraMetadata> &result) | | 上报camera设备相关的metadata的回调 | int32_t OnResult(uint64_t timestamp, const std::vector<uint8_t>& result) |
- icamera_host.h - icamera_host.h
| 功能描述 | 接口名称 | | 功能描述 | 接口名称 |
| ------------------------------ | ------------------------------------------------------------ | | ------------------------------ | ------------------------------------------------------------ |
| 设置ICameraHost回调接口 | CamRetCode SetCallback(const OHOS::sptr<ICameraHostCallback> &callback) | | 设置ICameraHost回调接口 | int32_t SetCallback(const sptr<ICameraHostCallback>& callbackObj) |
| 获取当前可用的Camera设备ID列表 | CamRetCode GetCameraIds(std::vector\<std::string\> &cameraIds) | | 获取当前可用的Camera设备ID列表 | int32_t GetCameraIds(std::vector<std::string>& cameraIds) |
| 获取Camera设备能力集合 | CamRetCode GetCameraAbility(const std::string &cameraId, std::shared_ptr<CameraAbility> &ability) | | 获取Camera设备能力集合 | int32_t GetCameraAbility(const std::string& cameraId, std::vector<uint8_t>& cameraAbility) |
| 打开Camera设备 | CamRetCode OpenCamera(const std::string &cameraId,<br>const OHOS::sptr<ICameraDeviceCallback> &callback,<br>OHOS::sptr<ICameraDevice> &device) | | 打开Camera设备 | int32_t OpenCamera(const std::string& cameraId, const sptr<ICameraDeviceCallback>& callbackObj,<br>sptr<ICameraDevice>& device) |
| 打开或关闭闪光灯 | CamRetCode SetFlashlight(const std::string &cameraId, bool &isEnable) | | 打开或关闭闪光灯 | int32_t SetFlashlight(const std::string& cameraId, bool isEnable) |
- icamera_host_callback.h - icamera_host_callback.h
| 功能描述 | 接口名称 | | 功能描述 | 接口名称 |
| ---------------------- | ------------------------------------------------------------ | | ---------------------- | ------------------------------------------------------------ |
| Camera设备状态变化上报 | void OnCameraStatus(const std::string &cameraId, CameraStatus status) | | Camera设备状态变化上报 | int32_t OnCameraStatus(const std::string& cameraId, CameraStatus status) |
| 闪光灯状态变化回调 | void OnFlashlightStatus(const std::string &cameraId, FlashlightStatus status) | | 闪光灯状态变化回调 | int32_t OnFlashlightStatus(const std::string& cameraId, FlashlightStatus status) |
| Camera事件回调 | int32_t OnCameraEvent(const std::string& cameraId, CameraEvent event) |
- ioffline_stream_operator.h - ioffline_stream_operator.h
| 功能描述 | 接口名称 | | 功能描述 | 接口名称 |
| -------------- | ------------------------------------------------------------ | | -------------- | ------------------------------------------------------------ |
| 取消捕获请求 | CamRetCode CancelCapture(int captureId) | | 取消捕获请求 | int32_t CancelCapture(int32_t captureId) |
| 释放流 | CamRetCode ReleaseStreams(const std::vector<int> &streamIds) | | 释放流 | int32_t ReleaseStreams(const std::vector<int32_t>& streamIds) |
| 释放所有离线流 | CamRetCode Release() | | 释放所有离线流 | int32_t Release() |
- istream_operator.h - istream_operator.h
| 功能描述 | 接口名称 | | 功能描述 | 接口名称 |
| -------------------------------- | ------------------------------------------------------------ | | -------------------------------- | ------------------------------------------------------------ |
| 查询是否支持添加参数对应的流 | CamRetCode IsStreamsSupported(<br>OperationMode mode,<br>const std::shared_ptr\<Camera::CameraMetadata\> &modeSetting,<br>const std::vector&ltstd::shared_ptr&ltStreamInfo&gt> &info,<br>StreamSupportType &type) | | 查询是否支持添加参数对应的流 | int32_t IsStreamsSupported(<br>OperationMode mode,<br>const std::vector<uint8_t>& modeSetting,<br>const std::vector<StreamInfo>& infos,<br> StreamSupportType& type) |
| 创建流 | CamRetCode CreateStreams(const std::vector<std::shared_ptr<StreamInfo>> &streamInfos) | | 创建流 | int32_t CreateStreams(const std::vector<StreamInfo>& streamInfos) |
| 释放流 | CamRetCode ReleaseStreams(const std::vector<int> &streamIds) | | 释放流 | int32_t ReleaseStreams(const std::vector<int32_t>& streamIds) |
| 配置流 | CamRetCode CommitStreams(OperationMode mode, const std::shared_ptr<CameraMetadata> &modeSetting) | | 配置流 | int32_t CommitStreams(OperationMode mode, const std::vector<uint8_t>& modeSetting) |
| 获取流的属性 | CamRetCode GetStreamAttributes(std::vector<std::shared_ptr<StreamAttribute>> &attributes) | | 获取流的属性 | int32_t GetStreamAttributes(std::vector<StreamAttribute>& attributes) |
| 绑定生产者句柄和指定流 | CamRetCode AttachBufferQueue(int streamId, const OHOS::sptr\<OHOS::IBufferProducer\> &producer) | | 绑定生产者句柄和指定流 | int32_t AttachBufferQueue(int32_t streamId, const sptr<BufferProducerSequenceable>& bufferProducer) |
| 解除生产者句柄和指定流的绑定关系 | CamRetCode DetachBufferQueue(int streamId) | | 解除生产者句柄和指定流的绑定关系 | int32_t DetachBufferQueue(int32_t streamId) |
| 捕获图像 | CamRetCode Capture(int captureId, const std::shared_ptr<CaptureInfo> &info, bool isStreaming) | | 捕获图像 | int32_t Capture(int32_t captureId, const CaptureInfo& info, bool isStreaming) |
| 取消捕获 | CamRetCode CancelCapture(int captureId) | | 取消捕获 | int32_t CancelCapture(int32_t captureId) |
| 将指定流转换成离线流 | CamRetCode ChangeToOfflineStream(const std::vector<int> &streamIds,<br>OHOS::sptr<IStreamOperatorCallback> &callback,<br>OHOS::sptr<IOfflineStreamOperator> &offlineOperator) | | 将指定流转换成离线流 | int32_t ChangeToOfflineStream(const std::vector<int32_t>& streamIds,<br>const sptr<IStreamOperatorCallback>& callbackObj,<br>sptr<IOfflineStreamOperator>& offlineOperator) |
- istream_operator_callback.h - istream_operator_callback.h
| 功能描述 | 接口名称 | | 功能描述 | 接口名称 |
| ---------------------------------------- | ------------------------------------------------------------ | | ---------------------------------------- | ------------------------------------------------------------ |
| 捕获开始回调,在捕获开始时调用 | void OnCaptureStarted(int32_t captureId, const std::vector<int32_t> &streamIds) | | 捕获开始回调,在捕获开始时调用 | int32_t OnCaptureStarted(int32_t captureId, const std::vector<int32_t>& streamIds) |
| 捕获结束回调,在捕获结束时调用 | void OnCaptureEnded(int32_t captureId, const std::vector<std::shared_ptr<CaptureEndedInfo>> &infos) | | 捕获结束回调,在捕获结束时调用 | int32_t OnCaptureEnded(int32_t captureId, const std::vector<CaptureEndedInfo>& infos) |
| 捕获错误回调,在捕获过程中发生错误时调用 | void OnCaptureError(int32_t captureId, const std::vector<std::shared_ptr<CaptureErrorInfo>> &infos) | | 捕获错误回调,在捕获过程中发生错误时调用 | int32_t OnCaptureError(int32_t captureId, const std::vector<CaptureErrorInfo>& infos) |
| 帧捕获回调 | void OnFrameShutter(int32_t captureId,<br>const std::vector<int32_t> &streamIds, uint64_t timestamp) | | 帧捕获回调 | int32_t OnFrameShutter(int32_t captureId, const std::vector<int32_t>& streamIds, uint64_t timestamp) |
### 开发步骤<a name="7"></a> ### 开发步骤<a name="7"></a>
Camera驱动的开发过程主要包含以下步骤: Camera驱动的开发过程主要包含以下步骤:
1. 注册CameraHost 1. 注册CameraHost
定义Camera的HdfDriverEntry结构体,该结构体中定义了CameraHost初始化的方法。 定义Camera的HdfDriverEntry结构体,该结构体中定义了CameraHost初始化的方法(代码目录drivers/peripheral/camera/interfaces/hdi_ipc/camera_host_driver.cpp)
``` ```c++
struct HdfDriverEntry g_cameraHostDriverEntry = { struct HdfDriverEntry g_cameraHostDriverEntry = {
.moduleVersion = 1, .moduleVersion = 1,
.moduleName = "camera_service", .moduleName = "camera_service",
...@@ -135,33 +137,46 @@ Camera驱动的开发过程主要包含以下步骤: ...@@ -135,33 +137,46 @@ Camera驱动的开发过程主要包含以下步骤:
2. 初始化Host服务 2. 初始化Host服务
步骤1中提到的HdfCameraHostDriverBind接口提供了CameraServiceDispatch和CameraHostStubInstance的注册。这两个接口一个是远端调用CameraHost的方法,如OpenCamera(),SetFlashlight()等,另外一个是Camera设备的初始化,在开机时被调用。 步骤1中提到的HdfCameraHostDriverBind接口提供了CameraServiceDispatch和CameraHostStubInstance的注册。CameraServiceDispatch接口是远端调用CameraHost的方法,如OpenCamera(),SetFlashlight()等,CameraHostStubInstance接口是Camera设备的初始化,在开机时被调用。
``` ```c++
int HdfCameraHostDriverBind(HdfDeviceObject *deviceObject) static int HdfCameraHostDriverBind(struct HdfDeviceObject *deviceObject)
{ {
HDF_LOGI("HdfCameraHostDriverBind enter!"); HDF_LOGI("HdfCameraHostDriverBind enter");
if (deviceObject == nullptr) {
HDF_LOGE("HdfCameraHostDriverBind: HdfDeviceObject is NULL!"); auto *hdfCameraHostHost = new (std::nothrow) HdfCameraHostHost;
if (hdfCameraHostHost == nullptr) {
HDF_LOGE("%{public}s: failed to create HdfCameraHostHost object", __func__);
return HDF_FAILURE; return HDF_FAILURE;
} }
HdfCameraService *hdfCameraService = reinterpret_cast<HdfCameraService *>(OsalMemAlloc(sizeof(HdfCameraService)));
if (hdfCameraService == nullptr) { hdfCameraHostHost->ioService.Dispatch = CameraHostDriverDispatch; // 提供远端CameraHost调用方法
HDF_LOGE("HdfCameraHostDriverBind OsalMemAlloc HdfCameraService failed!"); 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;
return HDF_FAILURE;
}
hdfCameraHostHost->stub = OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl,
ICameraHost::GetDescriptor()); // 初始化Camera设备
if (hdfCameraHostHost->stub == nullptr) {
HDF_LOGE("%{public}s: failed to get stub object", __func__);
delete hdfCameraHostHost;
return HDF_FAILURE; return HDF_FAILURE;
} }
hdfCameraService->ioservice.Dispatch = CameraServiceDispatch; // 提供远端CameraHost调用方法
hdfCameraService->ioservice.Open = nullptr; deviceObject->service = &hdfCameraHostHost->ioService;
hdfCameraService->ioservice.Release = nullptr;
hdfCameraService->instance = CameraHostStubInstance(); // 初始化Camera设备
deviceObject->service = &hdfCameraService->ioservice;
return HDF_SUCCESS; return HDF_SUCCESS;
} }
``` ```
下面的函数是远端CameraHost调用的方法: 下面的函数是远端CameraHost调用的方法:
``` ```c++
int32_t CameraHostStub::CameraHostServiceStubOnRemoteRequest(int cmdId, MessageParcel &data, int32_t CameraHostStub::CameraHostServiceStubOnRemoteRequest(int cmdId, MessageParcel &data,
MessageParcel &reply, MessageOption &option) MessageParcel &reply, MessageOption &option)
{ {
...@@ -196,7 +211,7 @@ Camera驱动的开发过程主要包含以下步骤: ...@@ -196,7 +211,7 @@ Camera驱动的开发过程主要包含以下步骤:
调用Get()接口从远端CameraService中获取CameraHost对象。get()方法如下: 调用Get()接口从远端CameraService中获取CameraHost对象。get()方法如下:
``` ```c++
sptr<ICameraHost> ICameraHost::Get(const char *serviceName) sptr<ICameraHost> ICameraHost::Get(const char *serviceName)
{ {
do { do {
...@@ -223,46 +238,74 @@ Camera驱动的开发过程主要包含以下步骤: ...@@ -223,46 +238,74 @@ Camera驱动的开发过程主要包含以下步骤:
CameraHostProxy对象中有五个方法,分别是SetCallback、GetCameraIds、GetCameraAbility、OpenCamera和SetFlashlight。下面着重描述OpenCamera接口。 CameraHostProxy对象中有五个方法,分别是SetCallback、GetCameraIds、GetCameraAbility、OpenCamera和SetFlashlight。下面着重描述OpenCamera接口。
CameraHostProxy的OpenCamera()接口通过CMD_CAMERA_HOST_OPEN_CAMERA调用远端CameraHostStubOpenCamera()接口并获取ICameraDevice对象。 CameraHostProxy的OpenCamera()接口通过CMD_CAMERA_HOST_OPEN_CAMERA调用远端CameraHostStubOpenCamera()接口并获取ICameraDevice对象。
``` ```c++
CamRetCode CameraHostProxy::OpenCamera(const std::string &cameraId, const OHOS::sptr<ICameraDeviceCallback> &callback, OHOS::sptr<ICameraDevice> &pDevice) int32_t CameraHostProxy::OpenCamera(const std::string& cameraId, const sptr<ICameraDeviceCallback>& callbackObj,
sptr<ICameraDevice>& device)
{ {
int32_t ret = Remote()->SendRequest(CMD_CAMERA_HOST_REMOTE_OPEN_CAMERA, data, reply, option); MessageParcel cameraHostData;
if (ret != HDF_SUCCESS) { MessageParcel cameraHostReply;
HDF_LOGE("%{public}s: SendRequest failed, error code is %{public}d", __func__, ret); MessageOption cameraHostOption(MessageOption::TF_SYNC);
return INVALID_ARGUMENT;
if (!cameraHostData.WriteInterfaceToken(ICameraHost::GetDescriptor())) {
HDF_LOGE("%{public}s: failed to write interface descriptor!", __func__);
return HDF_ERR_INVALID_PARAM;
} }
CamRetCode retCode = static_cast<CamRetCode>(reply.ReadInt32());
bool flag = reply.ReadBool(); if (!cameraHostData.WriteCString(cameraId.c_str())) {
if (flag) { HDF_LOGE("%{public}s: write cameraId failed!", __func__);
sptr<IRemoteObject> remoteCameraDevice = reply.ReadRemoteObject(); return HDF_ERR_INVALID_PARAM;
if (remoteCameraDevice == nullptr) { }
HDF_LOGE("%{public}s: CameraHostProxy remoteCameraDevice is null", __func__);
} if (!cameraHostData.WriteRemoteObject(OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(callbackObj,
pDevice = OHOS::iface_cast<ICameraDevice>(remoteCameraDevice); 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;
} }
return retCode;
device = hdi_facecast<ICameraDevice>(cameraHostReply.ReadRemoteObject());
return cameraHostRet;
} }
``` ```
Remote()->SendRequest调用上文提到的CameraHostServiceStubOnRemoteRequest(),根据cmdId进入CameraHostStubOpenCamera()接口,最终调用CameraHostImpl::OpenCamera(),该接口获取了CameraDevice并对硬件进行上电等操作。 Remote()->SendRequest调用上文提到的CameraHostServiceStubOnRemoteRequest(),根据cmdId进入CameraHostStubOpenCamera()接口,最终调用CameraHostImpl::OpenCamera(),该接口获取了CameraDevice并对硬件进行上电等操作。
``` ```c++
CamRetCode CameraHostImpl::OpenCamera(const std::string &cameraId, const OHOS::sptr<ICameraDeviceCallback> &callback, OHOS::sptr<ICameraDevice> &device) int32_t CameraHostImpl::OpenCamera(const std::string& cameraId, const sptr<ICameraDeviceCallback>& callbackObj,
sptr<ICameraDevice>& device)
{ {
std::shared_ptr<CameraDeviceImpl> cameraDevice = std::static_pointer_cast<CameraDeviceImpl>(itr->second); 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;
if (cameraDevice == nullptr) { if (cameraDevice == nullptr) {
CAMERA_LOGE("camera device is null."); CAMERA_LOGE("camera device is null.");
return INSUFFICIENT_RESOURCES; return INSUFFICIENT_RESOURCES;
} }
CamRetCode ret = cameraDevice->SetCallback(callback);
if (ret != NO_ERROR) { CamRetCode ret = cameraDevice->SetCallback(callbackObj);
CAMERA_LOGW("set camera device callback failed."); CHECK_IF_NOT_EQUAL_RETURN_VALUE(ret, HDI::Camera::V1_0::NO_ERROR, ret);
return ret;
}
CameraHostConfig *config = CameraHostConfig::GetInstance(); CameraHostConfig *config = CameraHostConfig::GetInstance();
if (config == nullptr) { CHECK_IF_PTR_NULL_RETURN_VALUE(config, INVALID_ARGUMENT);
return INVALID_ARGUMENT;
}
std::vector<std::string> phyCameraIds; std::vector<std::string> phyCameraIds;
RetCode rc = config->GetPhysicCameraIds(cameraId, phyCameraIds); RetCode rc = config->GetPhysicCameraIds(cameraId, phyCameraIds);
if (rc != RC_OK) { if (rc != RC_OK) {
...@@ -274,14 +317,20 @@ Camera驱动的开发过程主要包含以下步骤: ...@@ -274,14 +317,20 @@ Camera驱动的开发过程主要包含以下步骤:
CameraPowerDown(phyCameraIds); CameraPowerDown(phyCameraIds);
return DEVICE_ERROR; return DEVICE_ERROR;
} }
auto sptrDevice = deviceBackup_.find(cameraId); auto sptrDevice = deviceBackup_.find(cameraId);
if (sptrDevice == deviceBackup_.end()) { if (sptrDevice == deviceBackup_.end()) {
#ifdef CAMERA_BUILT_ON_OHOS_LITE
deviceBackup_[cameraId] = cameraDevice;
#else
deviceBackup_[cameraId] = cameraDevice.get(); deviceBackup_[cameraId] = cameraDevice.get();
#endif
} }
device = deviceBackup_[cameraId]; device = deviceBackup_[cameraId];
cameraDevice->SetStatus(true); cameraDevice->SetStatus(true);
return NO_ERROR; CAMERA_LOGD("open camera success.");
DFX_LOCAL_HITRACE_END;
return HDI::Camera::V1_0::NO_ERROR;
} }
``` ```
...@@ -289,29 +338,42 @@ Camera驱动的开发过程主要包含以下步骤: ...@@ -289,29 +338,42 @@ Camera驱动的开发过程主要包含以下步骤:
CameraDeviceImpl定义了GetStreamOperator、UpdateSettings、SetResultMode和GetEnabledResult等方法,获取流操作方法如下: CameraDeviceImpl定义了GetStreamOperator、UpdateSettings、SetResultMode和GetEnabledResult等方法,获取流操作方法如下:
``` ```c++
CamRetCode CameraDeviceImpl::GetStreamOperator(const OHOS::sptr<IStreamOperatorCallback> &callback, int32_t CameraDeviceImpl::GetStreamOperator(const sptr<IStreamOperatorCallback>& callbackObj,
OHOS::sptr<IStreamOperator> &streamOperator) sptr<IStreamOperator>& streamOperator)
{ {
if (callback == nullptr) { HDI_DEVICE_PLACE_A_WATCHDOG;
DFX_LOCAL_HITRACE_BEGIN;
if (callbackObj == nullptr) {
CAMERA_LOGW("input callback is null."); CAMERA_LOGW("input callback is null.");
return INVALID_ARGUMENT; return INVALID_ARGUMENT;
} }
spCameraDeviceCallback_ = callback;
spCameraDeciceCallback_ = callbackObj;
if (spStreamOperator_ == nullptr) { if (spStreamOperator_ == nullptr) {
// 这里新建一个spStreamOperator对象传递给调用者,以便对stream进行各种操作。 #ifdef CAMERA_BUILT_ON_OHOS_LITE
spStreamOperator_ = new(std::nothrow) StreamOperatorImpl(spCameraDeviceCallback_, shared_from_this()); // 这里创建一个spStreamOperator_ 对象传递给调用者,以便对stream进行各种操作
spStreamOperator_ = std::make_shared<StreamOperator>(spCameraDeciceCallback_, shared_from_this());
#else
spStreamOperator_ = new(std::nothrow) StreamOperator(spCameraDeciceCallback_, shared_from_this());
#endif
if (spStreamOperator_ == nullptr) { if (spStreamOperator_ == nullptr) {
CAMERA_LOGW("create stream operator failed."); CAMERA_LOGW("create stream operator failed.");
return DEVICE_ERROR; return DEVICE_ERROR;
} }
spStreamOperator_->Init();
ismOperator_ = spStreamOperator_; ismOperator_ = spStreamOperator_;
} }
streamOperator = ismOperator_; streamOperator = ismOperator_;
#ifndef CAMERA_BUILT_ON_OHOS_LITE
spStreamOperator_->SetRequestCallback([this](){ CAMERA_LOGI("CameraDeviceImpl %{public}s: line: %{public}d", __FUNCTION__, __LINE__);
spCameraDeviceCallback_->OnError(REQUEST_TIMEOUT, 0); pipelineCore_->GetStreamPipelineCore()->SetCallback(
[this](const std::shared_ptr<CameraMetadata> &metadata) {
OnMetadataChanged(metadata);
}); });
#endif
DFX_LOCAL_HITRACE_END;
return HDI::Camera::V1_0::NO_ERROR;
} }
``` ```
...@@ -319,7 +381,7 @@ Camera驱动的开发过程主要包含以下步骤: ...@@ -319,7 +381,7 @@ Camera驱动的开发过程主要包含以下步骤:
调用CreateStreams创建流前需要填充StreamInfo结构体,具体内容如下: 调用CreateStreams创建流前需要填充StreamInfo结构体,具体内容如下:
``` ```c++
using StreamInfo = struct _StreamInfo { using StreamInfo = struct _StreamInfo {
int streamId_; int streamId_;
int width_; // 数据流宽 int width_; // 数据流宽
...@@ -328,141 +390,239 @@ Camera驱动的开发过程主要包含以下步骤: ...@@ -328,141 +390,239 @@ Camera驱动的开发过程主要包含以下步骤:
int dataSpace_; int dataSpace_;
StreamIntent intent_; // StreamIntent 如PREVIEW StreamIntent intent_; // StreamIntent 如PREVIEW
bool tunneledMode_; bool tunneledMode_;
OHOS::sptr<OHOS::IBufferProducer> bufferQueue_; // 数据流bufferQueue可用streamCustomer->CreateProducer()接口创建 BufferProducerSequenceable bufferQueue_; // 数据流bufferQueue可用streamCustomer->CreateProducer()接口创建
int minFrameDuration_; int minFrameDuration_;
EncodeType encodeType_; EncodeType encodeType_;
}; };
``` ```
CreateStreams()接口是StreamOperatorImpl类中的方法,该接口的主要作用是创建一个StreamBase对象,通过StreamBase的Init方法初始化CreateBufferPool等操作。 CreateStreams()接口是StreamOperator(StreamOperatorImpl类是StreamOperator的基类)类中的方法,该接口的主要作用是创建一个StreamBase对象,通过StreamBase的Init方法初始化CreateBufferPool等操作。
``` ```c++
RetCode StreamOperatorImpl::CreateStream(const std::shared_ptr<StreamInfo>& streamInfo) int32_t StreamOperator::CreateStreams(const std::vector<StreamInfo>& streamInfos)
{ {
static std::map<StreamIntent, std::string> typeMap = { PLACE_A_NOKILL_WATCHDOG(requestTimeoutCB_);
{PREVIEW, "PREVIEW"}, DFX_LOCAL_HITRACE_BEGIN;
{VIDEO, "VIDEO"}, for (const auto& it : streamInfos) {
{STILL_CAPTURE, "STILL_CAPTURE"}, CHECK_IF_NOT_EQUAL_RETURN_VALUE(CheckStreamInfo(it), true, INVALID_ARGUMENT);
{POST_VIEW, "POST_VIEW"}, {ANALYZE, "ANALYZE"}, CAMERA_LOGI("streamId:%{public}d and format:%{public}d and width:%{public}d and height:%{public}d",
{CUSTOM, "CUSTOM"} 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_);
auto itr = typeMap.find(streamInfo->intent_); return INVALID_ARGUMENT;
if (itr == typeMap.end()) { }
CAMERA_LOGE("do not support stream type. [type = %{public}d]", streamInfo->intent_); std::shared_ptr<IStream> stream = StreamFactory::Instance().CreateShared( // 创建Stream实例
return RC_ERROR; 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());
} }
std::shared_ptr<StreamBase> stream = StreamFactory::Instance().CreateShared(itr->second); // 创建StreamBase实例 DFX_LOCAL_HITRACE_END;
RetCode rc = stream->Init(streamInfo); return HDI::Camera::V1_0::NO_ERROR;
return RC_OK; }
}
``` ```
7. **配置流** 7. 配置流
CommitStreams()是配置流的接口,必须在创建流之后调用,其主要作用是初始化Pipeline和创建Pipeline。 CommitStreams()是配置流的接口,必须在创建流之后调用,其主要作用是初始化Pipeline和创建Pipeline。
``` ```c++
CamRetCode StreamOperatorImpl::CommitStreams(OperationMode mode, const std::shared_ptr<Camera::CameraMetadata>& modeSetting) int32_t StreamOperator::CommitStreams(OperationMode mode, const std::vector<uint8_t>& modeSetting)
{ {
auto cameraDevice = cameraDevice_.lock(); CAMERA_LOGV("enter");
if (cameraDevice == nullptr) { CHECK_IF_PTR_NULL_RETURN_VALUE(streamPipeline_, DEVICE_ERROR);
CAMERA_LOGE("camera device closed."); PLACE_A_NOKILL_WATCHDOG(requestTimeoutCB_);
return CAMERA_CLOSED; if (modeSetting.empty()) {
} CAMERA_LOGE("input vector is empty");
std::shared_ptr<IPipelineCore> PipelineCore = return INVALID_ARGUMENT;
std::static_pointer_cast<CameraDeviceImpl>(cameraDevice)->GetPipelineCore();
if (PipelineCore == nullptr) {
CAMERA_LOGE("get pipeline core failed.");
return CAMERA_CLOSED;
} }
DFX_LOCAL_HITRACE_BEGIN;
streamPipeCore_ = PipelineCore->GetStreamPipelineCore(); std::vector<StreamConfiguration> configs = {};
if (streamPipeCore_ == nullptr) { {
CAMERA_LOGE("get stream pipeline core failed."); std::lock_guard<std::mutex> l(streamLock_);
return DEVICE_ERROR; std::transform(streamMap_.begin(), streamMap_.end(), std::back_inserter(configs),
[](auto &iter) { return iter.second->GetStreamAttribute(); });
} }
RetCode rc = streamPipeCore_->Init(); // 对pipelinecore的初始化 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); // 设备流配置
if (rc != RC_OK) { if (rc != RC_OK) {
CAMERA_LOGE("stream pipeline core init failed."); CAMERA_LOGE("prepare mode settings failed");
return DEVICE_ERROR; return DEVICE_ERROR;
} }
rc = streamPipeCore_->CreatePipeline(mode); // 创建一个pipeline rc = streamPipeline_->CreatePipeline(mode); // 创建一个pipeline
if (rc != RC_OK) { if (rc != RC_OK) {
CAMERA_LOGE("create pipeline failed."); CAMERA_LOGE("create pipeline failed.");
return INVALID_ARGUMENT; return INVALID_ARGUMENT;
} }
return NO_ERROR;
DFX_LOCAL_HITRACE_END;
return HDI::Camera::V1_0::NO_ERROR;
} }
``` ```
8. **捕获图像** 8. 捕获图像
在调用Capture()接口前需要先填充CaptureInfo结构体,具体内容如下: 在调用Capture()接口前需要先填充CaptureInfo结构体,具体内容如下:
``` ```c++
using CaptureInfo = struct _CaptureInfo { using CaptureInfo = struct _CaptureInfo {
std::vector<int> streamIds_; //需要Capture的streamIds int[] streamIds_; // 需要Capture的streamIds
std::shared_ptr<Camera::CameraMetadata> captureSetting_; // 这里填充camera ability 可通过CameraHost 的GetCameraAbility()接口获取 unsigned char[] captureSetting_; // 这里填充camera ability 可通过CameraHost 的GetCameraAbility()接口获取
bool enableShutterCallback_; bool enableShutterCallback_;
}; };
``` ```
StreamOperatorImpl中的Capture方法主要调用CreateCapture()接口去捕获数据流: StreamOperator中的Capture方法主要是捕获数据流:
``` ```c++
CamRetCode StreamOperatorImpl::Capture(int captureId, const std::shared_ptr<CaptureInfo>& captureInfo, bool isStreaming) int32_t StreamOperator::Capture(int32_t captureId, const CaptureInfo& info, bool isStreaming)
{ {
if (!ValidCaptureInfo(captureId, captureInfo)) { CHECK_IF_EQUAL_RETURN_VALUE(captureId < 0, true, INVALID_ARGUMENT);
CAMERA_LOGE("capture streamIds is empty. [captureId = %d]", captureId); PLACE_A_NOKILL_WATCHDOG(requestTimeoutCB_);
return INVALID_ARGUMENT; DFX_LOCAL_HITRACE_BEGIN;
}
std::shared_ptr<CameraCapture> cameraCapture = nullptr; for (auto id : info.streamIds_) {
RetCode rc = CreateCapture(captureId, captureInfo, isStreaming, cameraCapture); std::lock_guard<std::mutex> l(streamLock_);
if (rc != RC_OK) { auto it = streamMap_.find(id);
CAMERA_LOGE("create capture is failed."); if (it == streamMap_.end()) {
return DEVICE_ERROR; return INVALID_ARGUMENT;
}
} }
{ {
std::unique_lock<std::mutex> lock(captureMutex_); std::lock_guard<std::mutex> l(requestLock_);
camerCaptureMap_.insert(std::make_pair(captureId, cameraCapture)); auto itr = requestMap_.find(captureId);
if (itr != requestMap_.end()) {
return INVALID_ARGUMENT;
}
} }
rc = StartThread(); std::shared_ptr<CameraMetadata> captureSetting;
if (rc != RC_OK) { MetadataUtils::ConvertVecToMetadata(info.captureSetting_, captureSetting);
CAMERA_LOGE("preview start failed."); CaptureSetting setting = captureSetting;
return DEVICE_ERROR; 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;
}
}
{
std::lock_guard<std::mutex> l(requestLock_);
requestMap_[captureId] = request;
} }
return NO_ERROR; return HDI::Camera::V1_0::NO_ERROR;
} }
``` ```
9. 取消捕获和释放离线流 9. 取消捕获和释放离线流
StreamOperatorImpl类中的CancelCapture()接口的主要作用是根据captureId取消数据流的捕获。 StreamOperator类中的CancelCapture()接口的主要作用是根据captureId取消数据流的捕获。
``` ```c++
CamRetCode StreamOperatorImpl::CancelCapture(int captureId) int32_t StreamOperator::CancelCapture(int32_t captureId)
{ {
auto itr = camerCaptureMap_.find(captureId); // 根据captureId 在Map中查找对应的CameraCapture对象 CHECK_IF_EQUAL_RETURN_VALUE(captureId < 0, true, INVALID_ARGUMENT);
RetCode rc = itr->second->Cancel(); // 调用CameraCapture中Cancel方法结束数据捕获 PLACE_A_NOKILL_WATCHDOG(requestTimeoutCB_);
std::unique_lock<std::mutex> lock(captureMutex_); DFX_LOCAL_HITRACE_BEGIN;
camerCaptureMap_.erase(itr); // 擦除该CameraCapture对象
return NO_ERROR; std::lock_guard<std::mutex> l(requestLock_);
auto itr = requestMap_.find(captureId); // 根据captureId 在Map中查找对应的CameraCapture对象
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(); // 调用CameraCapture中Cancel方法结束数据捕获
if (rc != RC_OK) {
return DEVICE_ERROR;
}
requestMap_.erase(itr); // 擦除该CameraCapture对象
DFX_LOCAL_HITRACE_END;
return HDI::Camera::V1_0::NO_ERROR;
} }
``` ```
StreamOperatorImpl类中的ReleaseStreams接口的主要作用是释放之前通过CreateStream()和CommitStreams()接口创建的流,并销毁Pipeline。 StreamOperator类中的ReleaseStreams接口的主要作用是释放之前通过CreateStream()和CommitStreams()接口创建的流,并销毁Pipeline。
``` ```c++
CamRetCode StreamOperatorImpl::ReleaseStreams(const std::vector<int>& streamIds) int32_t StreamOperator::ReleaseStreams(const std::vector<int32_t>& streamIds)
{ {
RetCode rc = DestroyStreamPipeline(streamIds); // 销毁该streamIds 的pipeline PLACE_A_NOKILL_WATCHDOG(requestTimeoutCB_);
rc = DestroyHostStreamMgr(streamIds); DFX_LOCAL_HITRACE_BEGIN;
rc = DestroyStreams(streamIds); // 销毁该streamIds 的 Stream for (auto id : streamIds) {
return NO_ERROR; 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;
} }
``` ```
...@@ -472,11 +632,11 @@ Camera驱动的开发过程主要包含以下步骤: ...@@ -472,11 +632,11 @@ Camera驱动的开发过程主要包含以下步骤:
### 开发实例<a name = "8"></a> ### 开发实例<a name = "8"></a>
在/drivers/peripheral/camera/hal/init目录下有一个关于Camera的demo,开机后会在/vendor/bin下生成可执行文件ohos_camera_demo,该demo可以完成amera的预览,拍照等基础功能。下面我们就以此demo为例讲述怎样用HDI接口去编写预览PreviewOn()和拍照CaptureON()的用例,可参考[ohos_camera_demo](https://gitee.com/openharmony/drivers_peripheral/tree/master/camera/hal/init)。 在/drivers/peripheral/camera/hal/init目录下有一个关于Camera的demo,开机后会在/vendor/bin下生成可执行文件ohos_camera_demo,该demo可以完成Camera的预览,拍照等基础功能。下面我们就以此demo为例讲述怎样用HDI接口去编写预览PreviewOn()和拍照CaptureON()的用例,可参考[ohos_camera_demo](https://gitee.com/openharmony/drivers_peripheral/tree/master/camera/hal/init)。
1. 在main函数中构造一个CameraDemo 对象,该对象中有对Camera初始化、启停流、释放等控制的方法。下面mainDemo->InitSensors()函数为初始化CameraHost,mainDemo->InitCameraDevice()函数为初始化CameraDevice。 1. 在main函数中构造一个CameraDemo 对象,该对象中有对Camera初始化、启停流、释放等控制的方法。下面mainDemo->InitSensors()函数为初始化CameraHost,mainDemo->InitCameraDevice()函数为初始化CameraDevice。
``` ```c++
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
RetCode rc = RC_OK; RetCode rc = RC_OK;
...@@ -507,157 +667,271 @@ Camera驱动的开发过程主要包含以下步骤: ...@@ -507,157 +667,271 @@ Camera驱动的开发过程主要包含以下步骤:
初始化CameraHost函数实现如下,这里调用了HDI接口ICameraHost::Get()去获取demoCameraHost,并对其设置回调函数。 初始化CameraHost函数实现如下,这里调用了HDI接口ICameraHost::Get()去获取demoCameraHost,并对其设置回调函数。
``` ```c++
RetCode CameraDemo::InitSensors() RetCode OhosCameraDemo::InitSensors()
{ {
demoCameraHost_ = ICameraHost::Get(DEMO_SERVICE_NAME); 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
if (demoCameraHost_ == nullptr) { if (demoCameraHost_ == nullptr) {
CAMERA_LOGE("demo test: ICameraHost::Get error"); CAMERA_LOGE("demo test: ICameraHost::Get error");
return RC_ERROR; return RC_ERROR;
} }
hostCallback_ = new CameraHostCallback(); #ifdef CAMERA_BUILT_ON_OHOS_LITE
hostCallback_ = std::make_shared<DemoCameraHostCallback>();
#else
hostCallback_ = new DemoCameraHostCallback();
#endif
rc = demoCameraHost_->SetCallback(hostCallback_); rc = demoCameraHost_->SetCallback(hostCallback_);
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");
return RC_OK; return RC_OK;
} }
``` ```
初始化CameraDevice函数实现如下,这里调用了GetCameraIds(cameraIds_),GetCameraAbility(cameraId, ability_),OpenCamera(cameraIds_.front(), callback, demoCameraDevice_)等接口实现了demoCameraHost的获取。 初始化CameraDevice函数实现如下,这里调用了GetCameraIds(cameraIds_),GetCameraAbility(cameraId, ability_),OpenCamera(cameraIds_.front(), callback, demoCameraDevice_)等接口实现了demoCameraHost的获取。
``` ```c++
RetCode CameraDemo::InitCameraDevice() RetCode OhosCameraDemo::InitCameraDevice()
{ {
int rc = 0;
CAMERA_LOGD("demo test: InitCameraDevice enter");
if (demoCameraHost_ == nullptr) {
CAMERA_LOGE("demo test: InitCameraDevice demoCameraHost_ == nullptr");
return RC_ERROR;
}
(void)demoCameraHost_->GetCameraIds(cameraIds_); (void)demoCameraHost_->GetCameraIds(cameraIds_);
if (cameraIds_.empty()) {
return RC_ERROR;
}
const std::string cameraId = cameraIds_.front(); const std::string cameraId = cameraIds_.front();
demoCameraHost_->GetCameraAbility(cameraId, ability_); demoCameraHost_->GetCameraAbility(cameraId, cameraAbility_);
sptr<CameraDeviceCallback> callback = new CameraDeviceCallback(); 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
rc = demoCameraHost_->OpenCamera(cameraIds_.front(), callback, demoCameraDevice_); rc = demoCameraHost_->OpenCamera(cameraIds_.front(), callback, demoCameraDevice_);
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");
return RC_OK; return RC_OK;
} }
``` ```
2. PreviewOn()接口包含配置流、开启预览流和启动Capture动作。该接口执行完成后Camera预览通路已经开始运转并开启了两路流,一路流是preview,另外一路流是capture或者video,两路流中仅对preview流进行capture动作。 2. PreviewOn()接口包含配置流、开启预览流和启动Capture动作。该接口执行完成后Camera预览通路已经开始运转并开启了两路流,一路流是preview,另外一路流是capture或者video,两路流中仅对preview流进行capture动作。
``` ```c++
static RetCode PreviewOn(int mode, const std::shared_ptr<CameraDemo>& mainDemo) static RetCode PreviewOn(int mode, const std::shared_ptr<OhosCameraDemo>& mainDemo)
{ {
rc = mainDemo->StartPreviewStream(); // 配置preview流 RetCode rc = RC_OK;
if (mode == 0) { CAMERA_LOGD("main test: PreviewOn enter");
rc = mainDemo->StartPreviewStream(); // 配置preview流
if (rc != RC_OK) {
CAMERA_LOGE("main test: PreviewOn StartPreviewStream error");
return RC_ERROR;
}
if (mode == 0) {
rc = mainDemo->StartCaptureStream(); // 配置capture流 rc = mainDemo->StartCaptureStream(); // 配置capture流
} else { if (rc != RC_OK) {
CAMERA_LOGE("main test: PreviewOn StartCaptureStream error");
return RC_ERROR;
}
} else {
rc = mainDemo->StartVideoStream(); // 配置video流 rc = mainDemo->StartVideoStream(); // 配置video流
} if (rc != RC_OK) {
CAMERA_LOGE("main test: PreviewOn StartVideoStream error");
rc = mainDemo->CaptureON(STREAM_ID_PREVIEW, CAPTURE_ID_PREVIEW, CAPTURE_PREVIEW); // 将preview流capture 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");
return RC_OK; return RC_OK;
} }
``` ```
StartCaptureStream()、StartVideoStream()和StartPreviewStream()接口都会调用CreateStream()接口,只是传入的参数不同。 StartCaptureStream()、StartVideoStream()和StartPreviewStream()接口都会调用CreateStream()接口,只是传入的参数不同。
```
RetCode CameraDemo::StartVideoStream()
{
RetCode rc = RC_OK;
if (isVideoOn_ == 0) {
isVideoOn_ = 1;
rc = CreateStream(STREAM_ID_VIDEO, streamCustomerVideo_, VIDEO); // 如需启preview或者capture流更改该接口参数即可。
}
return RC_OK;
}
```
CreateStream()方法调用HDI接口去配置和创建流,首先调用HDI接口去获取StreamOperation对象,然后创建一个StreamInfo。调用CreateStreams()和CommitStreams()实际创建流并配置流。 CreateStream()方法调用HDI接口去配置和创建流,首先调用HDI接口去获取StreamOperation对象,然后创建一个StreamInfo。调用CreateStreams()和CommitStreams()实际创建流并配置流。
``` ```c++
RetCode CameraDemo::CreateStreams(const int streamIdSecond, StreamIntent intent) RetCode OhosCameraDemo::CreateStream(const int streamId, std::shared_ptr<StreamCustomer> &streamCustomer,
StreamIntent intent)
{ {
std::vector<std::shared_ptr<StreamInfo>> streamInfos; int rc = 0;
std::vector<std::shared_ptr<StreamInfo>>().swap(streamInfos); CAMERA_LOGD("demo test: CreateStream enter");
GetStreamOpt(); // 获取StreamOperator对象 GetStreamOpt(); // 获取StreamOperator对象
std::shared_ptr<StreamInfo> previewStreamInfo = std::make_shared<StreamInfo>(); if (streamOperator_ == nullptr) {
SetStreamInfo(previewStreamInfo, streamCustomerPreview_, STREAM_ID_PREVIEW, PREVIEW); // 填充StreamInfo CAMERA_LOGE("demo test: CreateStream GetStreamOpt() is nullptr\n");
if (previewStreamInfo->bufferQueue_ == nullptr) {
CAMERA_LOGE("demo test: CreateStream CreateProducer(); is nullptr\n");
return RC_ERROR; return RC_ERROR;
} }
streamInfos.push_back(previewStreamInfo);
StreamInfo streamInfo = {0};
std::shared_ptr<StreamInfo> secondStreamInfo = std::make_shared<StreamInfo>();
if (streamIdSecond == STREAM_ID_CAPTURE) { SetStreamInfo(streamInfo, streamCustomer, streamId, intent); // 填充StreamInfo流
SetStreamInfo(secondStreamInfo, streamCustomerCapture_, STREAM_ID_CAPTURE, intent); if (streamInfo.bufferQueue_->producer_ == nullptr) {
} else { CAMERA_LOGE("demo test: CreateStream CreateProducer(); is nullptr\n");
SetStreamInfo(secondStreamInfo, streamCustomerVideo_, STREAM_ID_VIDEO, intent);
}
if (secondStreamInfo->bufferQueue_ == nullptr) {
CAMERA_LOGE("demo test: CreateStreams CreateProducer() secondStreamInfo is nullptr\n");
return RC_ERROR; return RC_ERROR;
} }
streamInfos.push_back(secondStreamInfo);
std::vector<StreamInfo> streamInfos;
streamInfos.push_back(streamInfo);
rc = streamOperator_->CreateStreams(streamInfos); // 创建流 rc = streamOperator_->CreateStreams(streamInfos); // 创建流
if (rc != Camera::NO_ERROR) { if (rc != HDI::Camera::V1_0::NO_ERROR) {
CAMERA_LOGE("demo test: CreateStream CreateStreams error\n"); CAMERA_LOGE("demo test: CreateStream CreateStreams error\n");
return RC_ERROR; return RC_ERROR;
} }
rc = streamOperator_->CommitStreams(Camera::NORMAL, ability_); rc = streamOperator_->CommitStreams(NORMAL, cameraAbility_);
if (rc != Camera::NO_ERROR) { if (rc != HDI::Camera::V1_0::NO_ERROR) {
CAMERA_LOGE("demo test: CreateStream CommitStreams error\n"); CAMERA_LOGE("demo test: CreateStream CommitStreams error\n");
std::vector<int> streamIds = {STREAM_ID_PREVIEW, streamIdSecond}; std::vector<int> streamIds;
streamIds.push_back(streamId);
streamOperator_->ReleaseStreams(streamIds); streamOperator_->ReleaseStreams(streamIds);
return RC_ERROR; return RC_ERROR;
} }
CAMERA_LOGD("demo test: CreateStream exit");
return RC_OK; return RC_OK;
} }
``` ```
CaptureON()接口调用streamOperator的Capture()方法获取Camera数据并轮转buffer,拉起一个线程接收相应类型的数据。 CaptureON()接口调用streamOperator的Capture()方法获取Camera数据并轮转buffer,拉起一个线程接收相应类型的数据。
``` ```c++
RetCode CameraDemo::CaptureON(const int streamId, const int captureId, CaptureMode mode) RetCode OhosCameraDemo::CaptureON(const int streamId,
const int captureId, CaptureMode mode)
{ {
std::shared_ptr<Camera::CaptureInfo> captureInfo = std::make_shared<Camera::CaptureInfo>(); // 创建并填充CaptureInfo CAMERA_LOGI("demo test: CaptureON enter streamId == %{public}d and captureId == %{public}d and mode == %{public}d",
captureInfo->streamIds_ = {streamId}; streamId, captureId, mode);
captureInfo->captureSetting_ = ability_; std::lock_guard<std::mutex> l(metaDatalock_);
captureInfo->enableShutterCallback_ = false; if (mode == CAPTURE_SNAPSHOT) {
constexpr double latitude = 27.987500; // dummy data: Qomolangma latitde
int rc = streamOperator_->Capture(captureId, captureInfo, true); // 实际capture开始,buffer轮转开始 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); // 实际capture开始,buffer轮转开始
if (rc != HDI::Camera::V1_0::NO_ERROR) {
CAMERA_LOGE("demo test: CaptureStart Capture error\n");
streamOperator_->ReleaseStreams(captureInfo_.streamIds_);
return RC_ERROR;
}
if (mode == CAPTURE_PREVIEW) { if (mode == CAPTURE_PREVIEW) {
streamCustomerPreview_->ReceiveFrameOn(nullptr); // 创建预览线程接收递上来的buffer streamCustomerPreview_->ReceiveFrameOn(nullptr); // 创建预览线程接收递上来的buffer
} else if (mode == CAPTURE_SNAPSHOT) { } else if (mode == CAPTURE_SNAPSHOT) {
streamCustomerCapture_->ReceiveFrameOn([this](void* addr, const uint32_t size) { // 创建capture线程通过StoreImage回调接收递上来的buffer streamCustomerCapture_->ReceiveFrameOn([this](void* addr, const uint32_t size) { // 创建capture线程通过StoreImage回调接收递上来的buffer
StoreImage(addr, size); StoreImage(addr, size);
}); });
} else if (mode == CAPTURE_VIDEO) { } else if (mode == CAPTURE_VIDEO) {
OpenVideoFile(); OpenVideoFile();
streamCustomerVideo_->ReceiveFrameOn([this](void* addr, const uint32_t size) {// 创建Video线程通过StoreVideo回调接收递上来的buffer
streamCustomerVideo_->ReceiveFrameOn([this](void* addr, const uint32_t size) { // 创建video线程通过StoreImage回调接收传递上来的buffer
StoreVideo(addr, size); StoreVideo(addr, size);
}); });
} }
CAMERA_LOGD("demo test: CaptureON exit");
return RC_OK; return RC_OK;
} }
``` ```
3. ManuList()函数从控制台通过fgets()接口获取字符,不同字符所对应demo支持的功能不同,并打印出该demo所支持功能的菜单。 3. ManuList()函数从控制台通过fgets()接口获取字符,不同字符所对应demo支持的功能不同,并打印出该demo所支持功能的菜单。
``` ```c++
static void ManuList(const std::shared_ptr<CameraDemo>& mainDemo, static void ManuList(const std::shared_ptr<OhosCameraDemo>& mainDemo,
const int argc, char** argv) const int argc, char** argv)
{ {
int idx, c; int idx, c;
int awb = 1; bool isAwb = true;
constexpr char shortOptions[] = "h:cwvaqof:"; const char *shortOptions = "h:cwvaeqof:";
c = getopt_long(argc, argv, shortOptions, longOptions, &idx); c = getopt_long(argc, argv, shortOptions, LONG_OPTIONS, &idx);
while(1) { while (1) {
switch (c) { switch (c) {
case 'h': case 'h':
c = PutMenuAndGetChr(); // 打印菜单 c = PutMenuAndGetChr(); // 打印菜单
break; break;
case 'f':
case 'f':
FlashLightTest(mainDemo); // 手电筒功能测试 FlashLightTest(mainDemo); // 手电筒功能测试
c = PutMenuAndGetChr(); c = PutMenuAndGetChr();
break; break;
...@@ -670,27 +944,30 @@ Camera驱动的开发过程主要包含以下步骤: ...@@ -670,27 +944,30 @@ Camera驱动的开发过程主要包含以下步骤:
c = PutMenuAndGetChr(); c = PutMenuAndGetChr();
break; break;
case 'w': // AWB功能测试 case 'w': // AWB功能测试
if (awb) { if (isAwb) {
mainDemo->SetAwbMode(OHOS_CAMERA_AWB_MODE_INCANDESCENT); mainDemo->SetAwbMode(OHOS_CAMERA_AWB_MODE_INCANDESCENT);
} else { } else {
mainDemo->SetAwbMode(OHOS_CAMERA_AWB_MODE_OFF); mainDemo->SetAwbMode(OHOS_CAMERA_AWB_MODE_OFF);
} }
awb = !awb; isAwb = !isAwb;
c = PutMenuAndGetChr(); c = PutMenuAndGetChr();
break; break;
case 'a': // AE功能测试 case 'a': // AE功能测试
mainDemo->SetAeExpo(); mainDemo->SetAeExpo();
c = PutMenuAndGetChr(); c = PutMenuAndGetChr();
break; break;
case 'v': // Video功能测试 case 'e': // Metadata测试
mainDemo->SetMetadata();
c = PutMenuAndGetChr();
break;
case 'v': // VIDEO功能测试
VideoTest(mainDemo); VideoTest(mainDemo);
c = PutMenuAndGetChr(); c = PutMenuAndGetChr();
break; break;
case 'q': // 退出demo case 'q': // 退出demo
PreviewOff(mainDemo); PreviewOff(mainDemo);
mainDemo->QuitDemo(); mainDemo->QuitDemo();
exit(EXIT_SUCCESS); return;
default: default:
CAMERA_LOGE("main test: command error please retry input command"); CAMERA_LOGE("main test: command error please retry input command");
c = PutMenuAndGetChr(); c = PutMenuAndGetChr();
...@@ -702,7 +979,7 @@ Camera驱动的开发过程主要包含以下步骤: ...@@ -702,7 +979,7 @@ Camera驱动的开发过程主要包含以下步骤:
PutMenuAndGetChr()接口打印了demo程序的菜单,并调用fgets()等待从控制台输入命令,内容如下: PutMenuAndGetChr()接口打印了demo程序的菜单,并调用fgets()等待从控制台输入命令,内容如下:
``` ```c++
static int PutMenuAndGetChr(void) static int PutMenuAndGetChr(void)
{ {
constexpr uint32_t inputCount = 50; constexpr uint32_t inputCount = 50;
...@@ -724,7 +1001,7 @@ Camera驱动的开发过程主要包含以下步骤: ...@@ -724,7 +1001,7 @@ Camera驱动的开发过程主要包含以下步骤:
控制台输出菜单详情如下: 控制台输出菜单详情如下:
``` ```c++
"Options:\n" "Options:\n"
"-h | --help Print this message\n" "-h | --help Print this message\n"
"-o | --offline stream offline test\n" "-o | --offline stream offline test\n"
...@@ -732,8 +1009,24 @@ Camera驱动的开发过程主要包含以下步骤: ...@@ -732,8 +1009,24 @@ Camera驱动的开发过程主要包含以下步骤:
"-w | --set WB Set white balance Cloudy\n" "-w | --set WB Set white balance Cloudy\n"
"-v | --video capture Video of 10s\n" "-v | --video capture Video of 10s\n"
"-a | --Set AE Set Auto exposure\n" "-a | --Set AE Set Auto exposure\n"
"-e | --Set Metadeta Set Metadata\n"
"-f | --Set Flashlight Set flashlight ON 5s OFF\n" "-f | --Set Flashlight Set flashlight ON 5s OFF\n"
"-q | --quit stop preview and quit this app\n"); "-q | --quit stop preview and quit this app\n");
``` ```
4. 编译用例
在drivers/peripheral/camera/hal/BUILD.gn文件中的deps中添加“init:ohos_camera_demo”,示例代码如下:
```
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",
]
```
以RK3568为例:
1. 执行全量编译命令./build.sh --product-name rk3568 --ccache,生成可执行二进制文件ohos_camera_demo,路径为:out/rk3568/packages/phone/vendor/bin/。
2. 将可执行文件ohos_camera_demo导入开发板,修改权限直接运行即可。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册