OH-v3.0-LTS Camera相机驱动框架 L2 分析3_创建流的准备
发布时间:2022-02-18 15:41:34 所属栏目:系统 来源:互联网
导读:简单回顾 先简单回顾总结下前面两章的内容要点 Camera HDI框架是通过绑定到HDF框架后在系统启动的时候完成初始化 Camera Host 实例。 应用层通过获取Camera Host 实例来得到设备支持的Camera的能力属性,并Open相应的设备。 应用层通过IPC通讯来调用HDI接口
简单回顾 先简单回顾总结下前面两章的内容要点 Camera HDI框架是通过绑定到HDF框架后在系统启动的时候完成初始化 Camera Host 实例。 应用层通过获取Camera Host 实例来得到设备支持的Camera的能力属性,并Open相应的设备。 应用层通过IPC通讯来调用HDI接口 补充说明 在前面CameraHostImpl::Init()创建CameraDevice实例对象的时候会实例化PipelineCore的各个子模块包括HostStreamMgr、StreamPipelineCore对应的功能会在下面的文章逐一说明。 本章开始略去IPC通讯相关的代码(包括流程图),读者可以参考第一章中SetCallback流程自行梳理代码。 2. 回到代码 应用层完成CameraDevice初始化后 开始创建流 相关的上层调用代码相对简单,这里简单画个图,大家可以对着代码梳理下。我们从CreatStrem开始继续往下看。 2.1 Hos3516Demo::GetStreamOpt() 先为 流操作 接口创建一个上层回调,然后通过IPC调用到CameraDeviceImpl的GetStreamOperator接口获取流操作的实例。 复制 //driversperipheralcamerahalinit3516_demo.cpp void Hos3516Demo::GetStreamOpt() { int rc = 0; if (streamOperator_ == nullptr) { const sptr<IStreamOperatorCallback> streamOperatorCallback = new StreamOperatorCallback(); rc = demoCameraDevice_->GetStreamOperator(streamOperatorCallback, streamOperator_); if (rc != Camera::NO_ERROR) { CAMERA_LOGE("demo test: GetStreamOpt GetStreamOperator failn"); streamOperator_ = nullptr; } } } CameraDeviceImpl负责实例化StreamOperator对象,并调用StreamOperator::Init() 完成初始化。 复制 //driversperipheralcamerahalhdi_implsrccamera_devicecamera_device_impl.cpp CamRetCode CameraDeviceImpl::GetStreamOperator( const OHOS::sptr<IStreamOperatorCallback> &callback, OHOS::sptr<IStreamOperator> &streamOperator) { ... spCameraDeciceCallback_ = callback; if (spStreamOperator_ == nullptr) { spStreamOperator_ = new(std::nothrow) StreamOperator(spCameraDeciceCallback_, shared_from_this()); if (spStreamOperator_ == nullptr) { CAMERA_LOGW("create stream operator failed."); return DEVICE_ERROR; } spStreamOperator_->Init(); ismOperator_ = spStreamOperator_; } streamOperator = ismOperator_; ... } StreamOperator::Init() 会从前面实例化的CameraDevice对象中取出已经实例化好的StreamPipelineCore对象调用对应的Init初始化,同时创建一个进程接收特定的消息。 复制 //driversperipheralcamerahalhdi_implsrcstream_operatorstream_operator.cpp RetCode StreamOperator::Init() { ... pipelineCore_ = dev->GetPipelineCore(); ... streamPipeline_ = pipelineCore_->GetStreamPipelineCore(); ... RetCode rc = streamPipeline_->Init(); ... auto cb = [this](MessageGroup& m) { HandleCallbackMessage(m); }; messenger_ = std::make_shared<CaptureMessageOperator>(cb); CHECK_IF_PTR_NULL_RETURN_VALUE(messenger_, RC_ERROR); messenger_->StartProcess(); return RC_OK; } StreamPipelineCore::Init()继续实例化StreamPipelineStrategy、StreamPipelineBuilder、StreamPipelineDispatcher 这3个类。它们是负责pipeNode的创建和控制的,现在我们只要记得代码已经把它们实例化完成并放在了StreamPipelineCore里。 复制 RetCode StreamPipelineCore::Init() { strategy_ = StreamPipelineStrategy::Create(context_->streamMgr_); builder_ = StreamPipelineBuilder::Create(context_->streamMgr_); dispatcher_ = StreamPipelineDispatcher::Create(); return RC_OK; } 到这里StremOperator(下面红框的部分)就创建好了,然后通过IPC回传给上层应用。 整个的StremOperator创建涉及到比较多的类 对应的关系可以看下下面的类图(个人理解,非官方) 2.2 Hos3516Demo::SetStreamInfo() 创建一个流信息 StreamInfo 这里的代码相对简单,设置这个流的分辨率、编码模式、流ID等等。 这里要注意的是bufferQueue_ 这个成员。下面会先简单讲一下,算是挖个坑。 然后tunneledMode = 5这个地方感觉是个BUG 因为在后续的HDI代码部分 实际是个bool类型。 复制 void Hos3516Demo::SetStreamInfo(std::shared_ptr<StreamInfo>& streamInfo, const std::shared_ptr<StreamCustomer>& streamCustomer, const int streamId, const StreamIntent intent) { constexpr uint32_t datasapce = 8; constexpr uint32_t tunneledMode = 5; if (intent == PREVIEW) { constexpr uint32_t width = 640; constexpr uint32_t height = 480; streamInfo->width_ = width; streamInfo->height_ = height; } else if (intent == STILL_CAPTURE) { constexpr uint32_t width = 1280; constexpr uint32_t height = 960; streamInfo->width_ = width; streamInfo->height_ = height; streamInfo->encodeType_ = ENCODE_TYPE_JPEG; } else { constexpr uint32_t width = 1280; constexpr uint32_t height = 960; streamInfo->width_ = width; streamInfo->height_ = height; streamInfo->encodeType_ = ENCODE_TYPE_H265; } streamInfo->streamId_ = streamId; streamInfo->format_ = PIXEL_FMT_YCRCB_420_SP; streamInfo->datasapce_ = datasapce; streamInfo->intent_ = intent; streamInfo->tunneledMode_ = tunneledMode; streamInfo->bufferQueue_ = streamCustomer->CreateProducer(); streamInfo->bufferQueue_->SetQueueSize(8); // 8:set bufferQueue size } StreamCustomer::CreateProducer() 这里的OHOS::Surface 涉及到了Graphic子系统中的Surface。Surface 是图形缓冲区管理接口,负责管理图形缓冲区和高效便捷的轮转缓冲区。 详细的说明可以看下源码中的Readme路径在:foundation/graphic/standard/README_zh.md。 是这里按照我个人的理解先简单的说一下: Surface分成了一个“生产者” 一个 “消费者”。应用端作为“消费者”向Surface模块申请一个Surface。当对应的“生产者”产生了数据就会通知“消费者” 对数据进行处理。 StreamCustomer::CreateProducer()做了两件事情 为上层应用获取了一个“消费型”surface 从获取到的surface中取出对应的“生产者”对象放在了StremInfo的信息里 丢给StreamOperator 复制 //driversperipheralcamerahalinitstream_customer.cpp sptr<OHOS::IBufferProducer> StreamCustomer::CreateProducer() { consumer_ = OHOS::Surface::CreateSurfaceAsConsumer(); //Buffer的消费者来使用该函数创建一个Surface if (consumer_ == nullptr) { return nullptr; } sptr<IBufferConsumerListener> listener = new TestBuffersConsumerListener(); consumer_->RegisterConsumerListener(listener); //注册一个消费监听器,监听Buffer的Flush事件 auto producer = consumer_->GetProducer(); //获得一个Surface内部的IBufferProducer对象 if (producer == nullptr) { return nullptr; } CAMERA_LOGI("demo test, create a buffer queue producer %{public}p", producer.GetRefPtr()); return producer; } 3. 小结 代码到这边 上层应用已经获取到了HDI层的StreamOperator对象实例。同时为图像数据准备了一个Surface! 同样挖了两个小坑,留待后面的代码进一步讲解 StreamPipelineStrategy、StreamPipelineBuilder、StreamPipelineDispatcher 这些类是怎么工作的? Surface的“生产者”在哪里? (编辑:晋中站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
站长推荐
热点阅读