概述
OpenHarmony相机驱动框架模型对上实现相机HDI(Hardware Device Interface)接口,对下实现相机Pipeline模型,管理相机各个硬件设备。
该驱动框架模型内部分为三层,依次为HDI实现层、框架层和设备适配层,各层基本概念如下:
- HDI实现层:实现OHOS(OpenHarmony Operation System)相机标准南向接口。
- 框架层:对接HDI实现层的控制、流的转发,实现数据通路的搭建,管理相机各个硬件设备等功能。
- 设备适配层:屏蔽底层芯片和OS(Operation System)差异,支持多平台适配。
图 1 Camera驱动模块架构图

目录
- Camera模块目录表如下:
/drivers/peripheral/camera
├── hal # camera模块的hal层代码
│ ├── adapter # camera hal平台适配层的实现
│ ├── buffer_manager # camera hal统一的Buffer管理
│ ├── device_manager # 提供camera hal层设备管理能力,包括设备枚举、设备能力查询等
│ ├── hdi_impl # camera hal HDI的具体实现
│ ├── include # camera hal层内部的头文件
│ ├── init # camera hal层HDI接口使用样例实现
│ ├── pipeline_core # camera hal层pipeline核心代码
│ ├── test # camera hal层测试代码实现
│ └── utils # camera hal层工具类代码,目前提供的是watchdog
├── hal_c # 提供C实现的HAL接口
│ ├── hdi_cif # C实现的HDI接口适配代码
│ └── include # C形式的HDI接口
└── interfaces # camera hal对上层服务提供的驱动能力接口
├── hdi_ipc # IPC模式的HDI实现
├── hdi_passthrough # 直通模式的HDI实现
└── include # camera hal对外提供的HDI定义
接口说明
- icamera_device.h
功能描述 |
接口名称 |
---|---|
获取流控制器 |
CamRetCode GetStreamOperator( |
更新设备控制参数 |
CamRetCode UpdateSettings(const std::shared_ptr &settings) |
设置Result回调模式和回调函数 |
CamRetCode SetResultMode(const ResultCallbackMode &mode) |
获取使能的ResultMeta |
CamRetCode GetEnabledResults(std::vector &results) |
使能具体的ResultMeta |
CamRetCode EnableResult(const std::vector &results) |
禁止具体的ResultMeta |
CamRetCode DisableResult(const std::vector &results) |
关闭Camera设备 |
void Close() |
- icamera_device_callback.h
功能描述 |
接口名称 |
---|---|
设备发生错误时调用,由调用者实现,用于返回错误信息给调用者 |
void OnError(ErrorType type, int32_t errorCode) |
上报camera设备相关的metadata的回调 |
void OnResult(uint64_t timestamp, const std::shared_ptr &result) |
- icamera_host.h
功能描述 |
接口名称 |
---|---|
设置ICameraHost回调接口 |
CamRetCode SetCallback(const OHOS::sptr &callback) |
获取当前可用的Camera设备ID列表 |
CamRetCode GetCameraIds(std::vector<:string> &cameraIds) |
获取Camera设备能力集合 |
CamRetCode GetCameraAbility(const std::string &cameraId, |
打开Camera设备 |
CamRetCode OpenCamera(const std::string &cameraId, |
打开或关闭闪光灯 |
CamRetCode SetFlashlight(const std::string &cameraId, bool &isEnable) |
- icamera_host_callback.h
功能描述 |
接口名称 |
---|---|
Camera设备状态变化上报 |
void OnCameraStatus(const std::string &cameraId, CameraStatus status) |
闪光灯状态变化回调 |
void OnFlashlightStatus(const std::string &cameraId, FlashlightStatus status) |
- ioffline_stream_operator.h
功能描述 |
接口名称 |
---|---|
取消捕获请求 |
CamRetCode CancelCapture(int captureId) |
释放流 |
CamRetCode ReleaseStreams(const std::vector &streamIds) |
释放所有离线流 |
CamRetCode Release() |
- istream_operator.h
功能描述 |
接口名称 |
---|---|
查询是否支持添加参数对应的流 |
CamRetCode IsStreamsSupported( |
创建流 |
CamRetCode CreateStreams(const std::vector<:shared_ptr>> &streamInfos) |
释放流 |
CamRetCode ReleaseStreams(const std::vector &streamIds) |
配置流 |
CamRetCode CommitStreams(OperationMode mode, |
获取流的属性 |
CamRetCode GetStreamAttributes( |
绑定生产者句柄和指定流 |
CamRetCode AttachBufferQueue(int streamId, const OHOS::sptr<:ibufferproducer> &producer) |
解除生产者句柄和指定流的绑定关系 |
CamRetCode DetachBufferQueue(int streamId) |
捕获图像 |
CamRetCode Capture(int captureId, |
取消捕获 |
CamRetCode CancelCapture(int captureId) |
将指定流转换成离线流 |
CamRetCode ChangeToOfflineStream(const std::vector &streamIds, |
- istream_operator_callback.h
功能描述 |
接口名称 |
---|---|
捕获开始回调,在捕获开始时调用 |
void OnCaptureStarted(int32_t captureId, const std::vector &streamIds) |
捕获结束回调,在捕获结束时调用 |
void OnCaptureEnded(int32_t captureId, |
捕获错误回调,在捕获过程中发生错误时调用 |
void OnCaptureError(int32_t captureId, |
帧捕获回调 |
void OnFrameShutter(int32_t captureId, |
使用方法
在/drivers/peripheral/camera/hal/init目录下有一个关于Camera的demo,该demo可以完成Camera的预览,拍照等基础功能。下面我们就以此demo为例讲述怎样用HDI接口去编写预览PreviewOn()和拍照CaptureOn()的用例 。
- 在main函数中构造一个CameraDemo 对象,该对象中有对Camera初始化、启停流、释放等控制的方法。下面mainDemo->InitSensors()函数为初始化CameraHost,mainDemo->InitCameraDevice()函数为初始化CameraDevice。
int main(int argc, char** argv)
{
RetCode rc = RC_OK;
auto mainDemo = std::make_shared();
rc = mainDemo->InitSensors(); // 初始化CameraHost
if (rc == RC_ERROR) {
CAMERA_LOGE("main test: mainDemo->InitSensors() errorn");
return RC_ERROR;
}
rc = mainDemo->InitCameraDevice(); // 初始化CameraDevice
if (rc == RC_ERROR) {
CAMERA_LOGE("main test: mainDemo->InitCameraDevice() errorn");
return RC_ERROR;
}
rc = PreviewOn(0, mainDemo); // 配流和启流
if (rc != RC_OK) {
CAMERA_LOGE("main test: PreviewOn() error demo exit");
return RC_ERROR;
}
ManuList(mainDemo, argc, argv); // 打印菜单到控制台
return RC_OK;
}
初始化CameraHost函数实现如下,这里调用了HDI接口ICameraHost::Get()去获取demoCameraHost,并对其设置回调函数。
RetCode CameraDemo::InitSensors()
{
demoCameraHost_ = ICameraHost::Get(DEMO_SERVICE_NAME);
if (demoCameraHost_ == nullptr) {
CAMERA_LOGE("demo test: ICameraHost::Get error");
return RC_ERROR;
}
hostCallback_ = new CameraHostCallback();
rc = demoCameraHost_->SetCallback(hostCallback_);
return RC_OK;
}
初始化CameraDevice函数实现如下,这里调用了GetCameraIds(cameraIds),GetCameraAbility(cameraId, ability),OpenCamera(cameraIds.front(), callback, demoCameraDevice_)等接口实现了demoCameraHost的获取。
RetCode CameraDemo::InitCameraDevice()
{
(void)demoCameraHost_->GetCameraIds(cameraIds_);
const std::string cameraId = cameraIds_.front();
demoCameraHost_->GetCameraAbility(cameraId, ability_);
sptr callback = new CameraDeviceCallback();
rc = demoCameraHost_->OpenCamera(cameraIds_.front(), callback, demoCameraDevice_);
return RC_OK;
}
- PreviewOn()接口包含配置流、开启预览流和启动Capture动作。该接口执行完成后Camera预览通路已经开始运转并开启了两路流,一路流是preview,另外一路流是capture或者video,两路流中仅对preview流进行capture动作。
static RetCode PreviewOn(int mode, const std::shared_ptr &mainDemo)
{
rc = mainDemo->StartPreviewStream(); // 配置preview流
if (mode == 0) {
rc = mainDemo->StartCaptureStream(); // 配置capture流
} else {
rc = mainDemo->StartVideoStream(); // 配置video流
}
rc = mainDemo->CaptureOn(STREAM_ID_PREVIEW, CAPTURE_ID_PREVIEW, CAPTURE_PREVIEW); // 将preview流capture
return RC_OK;
}
StartCaptureStream()、StartVideoStream()和StartPreviewStream()接口都会调用CreateStream()接口,只是传入的参数不同。
RetCode CameraDemo::StartVideoStream()
{
RetCode rc = RC_OK;
if (!isVideoOn_) {
isVideoOn_ = true;
rc = CreateStream(STREAM_ID_VIDEO, streamCustomerVideo_, VIDEO); // 如需启preview或者capture流更改该接口参数即可。
}
return RC_OK;
}
CreateStream()方法调用HDI接口去配置和创建流,首先调用HDI接口去获取StreamOperation对象,然后创建一个StreamInfo。调用CreateStreams()和CommitStreams()实际创建流并配置流。
RetCode CameraDemo::CreateStreams()
{
std::vector<:shared_ptr>> streamInfos;
GetStreamOpt(); // 获取StreamOperator对象
rc = streamOperator_->CreateStreams(streamInfos); // 创建流
rc = streamOperator_->CommitStreams(Camera::NORMAL, ability_);
return RC_OK;
}
CaptureOn()接口调用streamOperator的Capture()方法获取Camera数据并轮转buffer,拉起一个线程接收相应类型的数据。
RetCode CameraDemo::CaptureOn(const int streamId, const int captureId, CaptureMode mode)
{
std::shared_ptr<:captureinfo> captureInfo = std::make_shared<:captureinfo>(); // 创建并填充CaptureInfo
captureInfo->streamIds_ = {streamId};
captureInfo->captureSetting_ = ability_;
captureInfo->enableShutterCallback_ = false;
int rc = streamOperator_->Capture(captureId, captureInfo, true); // 实际capture开始,buffer轮转开始
if (mode == CAPTURE_PREVIEW) {
streamCustomerPreview_->ReceiveFrameOn(nullptr); // 创建预览线程接收递上来的buffer
} else if (mode == CAPTURE_SNAPSHOT) {
streamCustomerCapture_->ReceiveFrameOn([this](void* addr, const uint32_t size) { // 创建capture线程通过StoreImage回调接收递上来的buffer
StoreImage(addr, size);
});
} else if (mode == CAPTURE_VIDEO) {
OpenVideoFile();
streamCustomerVideo_->ReceiveFrameOn([this](void* addr, const uint32_t size) {// 创建Video线程通过StoreVideo回调接收递上来的buffer
StoreVideo(addr, size);
});
}
return RC_OK;
}
- ManuList()函数从控制台通过fgets()接口获取字符,不同字符所对应demo支持的功能不同,并打印出该demo所支持功能的菜单。
static void ManuList(const std::shared_ptr &mainDemo,
const int argc, char** argv)
{
int idx, c;
int awb = 1;
constexpr char shortOptions[] = "h:cwvaqof:";
c = getopt_long(argc, argv, shortOptions, longOptions, &idx);
while(1) {
switch (c) {
case 'h':
c = PutMenuAndGetChr(); // 打印菜单
break;
case 'f':
FlashLightTest(mainDemo); // 手电筒功能测试
c = PutMenuAndGetChr();
break;
case 'o':
OfflineTest(mainDemo); // Offline功能测试
c = PutMenuAndGetChr();
break;
case 'c':
CaptureTest(mainDemo); // Capture功能测试
c = PutMenuAndGetChr();
break;
case 'w': // AWB功能测试
if (awb) {
mainDemo->SetAwbMode(OHOS_CAMERA_AWB_MODE_INCANDESCENT);
} else {
mainDemo->SetAwbMode(OHOS_CAMERA_AWB_MODE_OFF);
}
awb = !awb;
c = PutMenuAndGetChr();
break;
case 'a': // AE功能测试
mainDemo->SetAeExpo();
c = PutMenuAndGetChr();
break;
case 'v': // Video功能测试
VideoTest(mainDemo);
c = PutMenuAndGetChr();
break;
case 'q': // 退出demo
PreviewOff(mainDemo);
mainDemo->QuitDemo();
exit(EXIT_SUCCESS);
default:
CAMERA_LOGE("main test: command error please retry input command");
c = PutMenuAndGetChr();
break;
}
}
}
PutMenuAndGetChr()接口打印了demo程序的菜单,并调用fgets()等待从控制台输入命令,内容如下:
static int PutMenuAndGetChr(void)
{
constexpr uint32_t inputCount = 50;
int c = 0;
char strs[inputCount];
Usage(stdout);
CAMERA_LOGD("pls input command(input -q exit this app)n");
fgets(strs, inputCount, stdin);
for (int i = 0; i < inputCount; i++) {
if (strs[i] != '-') {
c = strs[i];
break;
}
}
return c;
}
控制台输出菜单详情如下:
"Options:n"
"-h | --help Print this messagen"
"-o | --offline stream offline testn"
"-c | --capture capture one picturen"
"-w | --set WB Set white balance Cloudyn"
"-v | --video capture Video of 10sn"
"-a | --Set AE Set Auto exposuren"
"-f | --Set Flashlight Set flashlight ON 5s OFFn"
"-q | --quit stop preview and quit this appn");
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.1024c.cn/archives/21595,转载请注明出处。
评论0