更多信息请访问:与华为共建的鸿蒙技术社区正式https://harmonyos.51cto.com1.简单回顾下面简单回顾一下前两章的要点,总结一下。CameraHDI框架与HDF框架绑定,在系统启动时初始化CameraHost实例。应用层通过获取CameraHost实例获取设备支持的相机能力属性,并打开对应的设备。应用层通过IPC通信调用HDI接口。补充说明:当CameraHostImpl::Init()创建CameraDevice实例对象时,会实例化PipelineCore的各个子模块,包括HostStreamMgr和StreamPipelineCore。相应的功能将在后续文章中一一讲解。本章开始省略与IPC通信相关的代码(包括流程图)。读者可以参考第1章中的SetCallback过程自行整理代码。2.回到代码应用层,完成CameraDevice的初始化,然后开始创建流。相关的上层调用代码比较简单,这里简单放一张图,大家可以整理一下代码。我们从CreatStrem开始,继续往下看。先抛出本章代码相关的流程图2.1Hos3516Demo::GetStreamOpt()首先创建流操作接口的上层回调,然后通过IPC调用CameraDeviceImpl的GetStreamOperator接口获取流的实例手术。//drivers\peripheral\camera\hal\init\3516_demo.cppvoidHos3516Demo::GetStreamOpt(){intrc=0;如果(streamOperator_==nullptr){constsptrstreamOperatorCallback=newStreamOperatorCallback();rc=demo_Camera->GetStreamOperator(streamOperatorCallback,streamOperator_);if(rc!=Camera::NO_ERROR){CAMERA_LOGE("演示测试:GetStreamOptGetStreamOperator失败\n");streamOperator_=nullptr;}}}CameraDeviceImpl负责实例化StreamOperator对象,调用StreamOperator::Init()完成初始化。//drivers\peripheral\camera\hal\hdi_impl\src\camera_device\camera_device_impl.cppCamRetCodeCameraDeviceImpl::GetStreamOperator(constOHOS::sptr&callback,OHOS::sptr&streamOperator){...spCamera_Decall=;如果(spStreamOperator_==nullptr){spStreamOperator_=new(std::nothrow)StreamOperator(spCameraDeciceCallback_,shared_from_this());if(spStreamOperator_==nullptr){CAMERA_LOGW("创建流运算符失败。");返回设备}_ERRspStreamOperator_->Init();ismOperator_=spStreamOperator_;}streamOperator=ismOperator_;...}StreamOperator::Init()会从之前实例化的CameraDevice对象中取出实例化的StreamPipelineCore对象并调用相应的Init初始化,同时创建一个进程来接收具体的消息。//drivers\peripheral\camera\hal\hdi_impl\src\stream_operator\stream_operator.cppRetCodeStreamOperator::Init(){...pipelineCore_=dev->GetPipelineCore();...streamPipeline_=pipelineCore_->GetStreamPipelineCore();...RetCoderc=streamPipeline_->Init();...autocb=[this](MessageGroup&m){HandleCallbackMessage(m);};messenger_=std::make_shared(cb);CHECK_IF_PTR_NULL_RETURN_VALUE(messenger_,RC_ERROR);messenger_->StartProcess();returnRC_OK;}StreamPipelineCore::Init()继续实例化StreamPipelineStrategy、StreamPipelineBuilder和StreamPipelineDispatcher这三个类。它们负责pipeNode的创建和控制,现在我们只需要记住代码已经实例化了它们并将它们放在了StreamPipelineCore中。RetCodeStreamPipelineCore::Init(){strategy_=StreamPipelineStrategy::Create(context_->streamMgr_);builder_=StreamPipelineBuilder::Create(context_->streamMgr_);dispatcher_=StreamPipelineDispatcher::Create();returnRC_OK;}gohereStremOperator(下图红框部分)被创建,然后通过IPC传回给上层应用。整个StremOperator的创建涉及到的关系对应的类比较多,可以看下面的类图(个人理解,非官方)2.2Hos3516Demo::SetStreamInfo()创建一个流信息StreamInfo这里的代码比较简单,设置分辨率这个码流速率,编码方式,流ID等。这里要注意的是bufferQueue_成员。下面就简单说一下,也算是挖坑了。然后tunneledMode=5感觉是个bug因为在后面的HDI代码部分其实是bool类型。voidHos3516Demo::SetStreamInfo(std::shared_ptr&streamInfo,conststd::shared_ptr&streamCustomer,constintstreamId,constStreamIntentintent){constexpruint32_tdatasapce=8;constexpruint32_t隧道模式=5;if(intent==PREVIEW){constexpruint32_twidth=640;constexpruint32_t高度=480;streamInfo->width_=宽度;streamInfo->height_=height;}elseif(intent==STILL_CAPTURE){constexpruint32_twidth=1280;constexpruint32_t高度=960;streamInfo->width_=宽度;streamInfo->height_=height;streamInfo->encodeType_=ENCODE_TYPE_JPEG;}else{constexpruint32_twidth=1280;constexpruint32_t高度=960;streamInfo->width_=宽度;streamInfo->height_=height;streamInfo->encodeType_=ENCODE_TYPE_H265;}streamInfo->streamId_=streamId;streamInfo->format_=PIXEL_FMT_YCRCB_420_SP;streamInfo->datasapce_=datasapce;streamInfo->intent_=意图;streamInfo->tunneledMode_=tunneledMode;streamInfo->bufferQueue_=streamCustomer->CreateProducer();streamInfo->bufferQueue_->SetQueueSize(8);//8:setbufferQueuesize}StreamCustomer::CreateProducer()这里的OHOS::Surface涉及到Graphic子系统中的SurfaceSurface,它是图形缓冲区管理接口,负责管理图形缓冲区和高效方便的Rotate缓冲区。详细说明请参考源码中Readme路径:foundation/graphic/standard/README_zh.md。这里根据我个人的理解简单介绍一下:Surface分为“生产者”和“消费者”。应用端作为“消费者”,从Surface模块中申请一个Surface。当对应的“生产者”生产数据时,会通知“消费者”对数据进行处理。StreamCustomer::CreateProducer()做了两件事来为上层应用程序获取“消费者”表面。从获取的surface中取出对应的“producer”对象放到StremInfo信息中丢给StreamOperator//drivers\peripheral\camera\hal\init\stream_customer.cppsptrStreamCustomer::CreateProducer(){consumer_=OHOS::Surface::CreateSurfaceAsConsumer();//Buffer的消费者使用这个函数创建一个Surfaceif(consumer_==nullptr){returnnullptr;}sptrlistener=newTestBuffersConsumerListener();consumer_->RegisterConsumerListener(listener);//注册一个消费者监听器,监听Buffer的Flush事件autoproducer=consumer_->GetProducer();//在Surface内部获取一个IBufferProducer对象if(producer==nullptr){returnnullptr;}CAMERA_LOGI("demo测试,创建缓冲队列生产者%{public}p",producer.GetRefPtr());returnproducer;}3.代码总结至此,上层应用已经获取到了HDI层的StreamOperator对象实例。同时为图像数据准备了一个Surface!还挖了两个小坑,下面留下代码进一步解释StreamPipelineStrategy、StreamPipelineBuilder、StreamPipelineDispatcher是如何工作的?Surface的“生产者”在哪里?想了解更多内容请访问:与华为官方共建的Harmonyos技术社区https://harmonyos.51cto.com