加入收藏 | 设为首页 | 会员中心 | 我要投稿 云计算网_泰州站长网 (http://www.0523zz.com/)- 视觉智能、AI应用、CDN、行业物联网、智能数字人!
当前位置: 首页 > 服务器 > 系统 > 正文

OH-v3.0-LTS Camera相机驱动框架 L2 分析3_创建流的准备

发布时间:2022-02-16 20:54:40 所属栏目:系统 来源:互联网
导读:简单回顾 先简单回顾总结下前面两章的内容要点 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的“生产者”在哪里?

(编辑:云计算网_泰州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读