Camera pipeline 剪裁实现

85a1467a7ed8467f332d743d9bcc6684.gif

和你一起终身学习,这里是程序员Android

经典好文推荐,通过阅读本文,您将收获以下知识点:

一、基础介绍
1.ChiUsecase数据结构用来概括一个usecase的信息
2.ChiPipelineTargetCreateDescriptor数据结构用来描述一个完整的pipeline
3.ChiPipelineCreateDescriptor数据结构描述一个pipeline的构成
4.ChiTargetPortDescriptorInfo数据结构描述一个pipeline的sink/source缓存信息
二、裁剪变量
1.裁剪变量的定义
2.usecase描述中的裁剪参数
三、usecase裁剪的代码实现
四、裁剪ZSLSnapshotJpeg 举例
1.ZSLSnapshotJpeg pipeline
2.裁剪node
3.裁剪link
4.裁剪sourceTarget

一、基础介绍

usecase裁剪是指根据pruneSettings将一个usecase描述中部分内容剪修的处理过程。

接下来会以ZSLSnapshotJpeg 这条pipeline的裁剪为例子,了解是如何裁剪的。

在开始裁剪一条pipeline前,先看下usecas描述中的几个数据结构,了解可裁剪的内容有哪些(node, target, link)。

1.ChiUsecase数据结构用来概括一个usecase的信息
struct ChiUsecase
{
    const CHAR* pUsecaseName;
    UINT streamConfigMode;
    UINT numTargets;
    ChiTarget** ppChiTargets;
    UINT numPipelines;
    ChiPipelineTargetCreateDescriptor* pPipelineTargetCreateDesc;
    const PruneSettings* pTargetPruneSettings;
    BOOL isOriginalDescriptor;
}

一个usecase的基本信息包括:

  • usecase名字

  • streamConfigMode, 表明该usecase用于什么相机操作模式

  • chiTargets, 该usecase所拥有的target,包括sinkTarget和sourceTarget.

  • chiPipelineTargetCreateDescriptor, 该usecase所拥有的pipeline的描述

  • pruneSettings, 该usecase的裁剪配置

2.ChiPipelineTargetCreateDescriptor数据结构用来描述一个完整的pipeline
struct ChiPipelineTargetCreateDescriptor
{
    const CHAR* pPipelineName;
    ChiPipelineCreateDescriptor pipelineCreateDesc;
    ChiTargetPortDescriptorInfo sinkTarget;
    ChiTargetPortDescriptorInfo sourceTarget;
};

一个Pipeline的完整描述有四个内容:

  • pipeline名,区分pipeline的不同;

  • pipeline的构建描述,描述这条pipeline是什么样的构成

  • sinkTarget下游目标,描述pipeline的输出是什么样的;

  • sourceTarget上游目标,描述pipeline的输入是什么样的。

3.ChiPipelineCreateDescriptor数据结构描述一个pipeline的构成
typedef struct ChiPipelineCreateDescriptor
{
    UINT32 size;
    INT32 numNode;
    CHINODE* pNodes;      
    INT32 nulLinks;
    CHINODELINK* pLinks;
    UINT32 isRealTime;
    UINT numBatchedFrames;
    UINT maxFPSValue;
    UINT32 cameraId;
    CHIMETAHANDLE hPipelineMetadata;
    BOOL HALOutputBufferCombined;
    UINT32 logicalCameraId;
}

pipeline的构成有两个基本构件:

  • CHINODE,说明这条pipeline由哪些节点租出

  • CHINODELINK, 说明够成这条pipeline的节点是如何连接的
    对于realtime pipeline是sensor作为开始节点,通过isRealTime和cameraId区分。

3.1用CHINODE数据结构描述一个节点
typedef struct ChiNode
{
    CHINODEPROPERTY* pNodeProperties;
    UINT32 nodeId;
    UINT32 nodeInstanceId;
    CHINODEPORTS nodeAllPorts;
    UINT32 numProperties;
    PruneSettings pruneProperties;
}CHINODE;
3.2用CHINODELINK数据结构描述两个端口的连接
typedef struct ChiNodeLink
{
    CHILINKNODESCRIPTOR srcNode;
    UINT32 numDestNodes;
    CHILINKNODESCRIPTOR pDestNodes;
    CHILINKBUFFERPROPERTIES bufferProperties;
    CHILINKPROPERTIES linkProperties;
}CHINODELINK;
4.ChiTargetPortDescriptorInfo数据结构描述一个pipeline的sink/source缓存信息
struct ChiTargetPortDescriptorInfo
{
    UINT numTargets;
    ChiTargetPortDescriptor* pTargetPortDesc;
}

按照数据的流入/流出方向,端口缓存分为两种:流入端口的缓存称为sinkTarget,从端口流出的缓存sourceTarget。

一个端口的缓存包括两个内容:

  • numTargets缓存的个数,表明该端口缓存有几份组成

  • chiTargetPortDescriptor缓存的端口描述,说明一份缓存是和哪些端口交互、这份缓存的地址是什么

4.1用ChiTargetPortDescriptor数据结构描述一个端口的一个缓存
struct ChiTargetPortDescriptor
{
    const CHAR* pTargetName;
    ChiTarget* pTarget;
    UINT numNodePorts;
    ChiLinkNodeDescriptor* pNodePort;
}

一份端口缓存包含三个内容:

  • target名字,

  • 指向chiTarget的指针。

  • 和这个target连接的ports信息

struct ChiTarget
{
    ChiStreamType direction;          //target的方向:input/output/bidirectional
    BufferDimension dimension;        //缓存尺寸
    UINT numFormats;                  //该target支持的缓存格式的个数
    ChiBufferFormat* pBufferFormats;  //缓存格式
    ChiStream* pChiStream;            //指向该target使用的chiStream的指针
}

ChiLinkNodeDescriptor数据结构用于描述link中关于node的用于定义两个node间连接的信息:

typedef struct ChiLinkNodeDescriptor
{
    UINT32 nodeId;
    UINT32 nodeInstanceId;
    UINT32 nodePortId;
    UINT32 portSourceTypeId;
    PruneSettings pruneProperties;
}CHILINKNODESCRIPTOR;

从以上数据结构的定义发现具有裁剪属性的有:

  • ChiUsecase,即usecase的描述

  • ChiLinkNodeDescriptor, target中的link描述

  • ChiNode, 节点

二、裁剪变量

1.裁剪变量的定义
struct PruneSettings {
    UINT numSettings;
    const PruneVariant* pVariants;
}
2.usecase描述中的裁剪参数

在描述usecase的xml中node的裁剪参数如下,

c508bc468f2dc984996a745b08ed1699.jpeg

link port的裁剪参数:

1af4aeb70793f0003f452efdc7268130.jpeg

三、usecase裁剪的代码实现

CDKResult UsecaseSelector::PruneUsecaseDescriptor(const ChiUsecase* const pUsecase,
                                         const UINT numPruneVariants,
                                         const PruneVariant* const pPruneVariants,
                                         ChiUsecase** ppPrunedUsecase)
{
    //1.为目的usecase描述分配空间
    ChiUsecase *pPrunedUsecase = 
              static_cast<ChiUsecase*>(CHX_CALLOC(1*sizeof(ChiUsecase)));
    ChiPipelineTargetCreateDescriptor* pPrunedTargetCreateDesc =
        static_cast<ChiPipelineTargetCreateDescriptor*>(
        CHX_CALLOC(pUsecase->numPipelines * sizeof(ChiPipelineTargetCreateDescriptor)));
    ChiTarget** ppPrunedChiTargets = static_cast<ChiTarget**>(
        CHX_CALLOC(pUsecase->numTargets * sizeof(ChiTarget*)));
    
    pPrunedUsecase->pPipelineTargetCreateDesc = pPrunedTargetCreateDesc;
    pPrunedUsecase->ppChiTargets = ppPrunedChiTargets;
    
    *ppPrunedUsecase = pPrunedUsecase;
    //2.填充目的usecase
    pPrunedUsecase->pUsecaseName = pUsecase->pUsecaseName;
    pPrunedUsecase->streamConfigMode = pUsecase->streamConfigMode;
    pPrunedUsecase->numPipelines = pUsecase->numPipelines;
    //3.组成usecase的pipeline的描述
    for (UINT j = 0; j < pUsecase->numPipelines; j++)
    {
        ChiPipelineTargetCreateDescriptor& rTargetPrunedDesc = 
                                pPrunedUsecase->pPipelineTargetCreateDesc[j];
        ChiPipelineCreateDescriptor& rPrunedDesc = rTargetPrunedDesc.pipelineCreateDesc;
        rTargetPrunedDesc.pPipelineName = rTargetCreateDesc.pPipelineName;
        rTargetPrunedDesc.sinkTarget.pTargetPortDesc = static_cast<ChiTargetPortDescriptor*>(
            CHX_CALLOC(rTargetCreateDesc.sinkTarget.numTargets *
                       sizeof(ChiTargetPortDescriptor)));
        rTargetPrunedDesc.sourceTarget.pTargetPortDesc = static_cast<ChiTargetPortDescriptor*>(
            CHX_CALLOC(rTargetCreateDesc.sourceTarget.numTargets *
                       sizeof(ChiTargetPortDescriptor)));
        rPrunedDesc.isRealTime = rCreateDesc.isRealTime;
        
        rPrunedDesc.pNodes = static_cast<CHINODE*>(
            CHX_CALLOC(rCreateDesc.numNodes * size(CHINODE)));
        rPrunedDesc.pLinks = static_cast<CHINODELINK*>(
            CHX_CALLOC(rCreateDesc.numLinks * sizeof(CHINODELINK)));
        
        const ChiPipelineCreateDescriptor& rCreateDesc = 
            rTargetCreateDesc.pipelineCreateDesc;
        //3.1裁剪node
        //3.2裁剪link
        //3.3裁剪sourceTarget
    }
}

ppPrunedUsecase是裁剪后的usecase,pUsecase是裁剪的初始,pPruneVariants是裁剪参数。

四、裁剪ZSLSnapshotJpeg

工程中对usecase的裁剪基于xml中描述的usecase,通过裁剪参数将clone的usecase裁剪成业务需要的usecase。根据configure_streams阶段用户设置的相机参数和使用的相机设备会生成一组裁剪参数。

这里使用的用户裁剪参数:EIS :Disabled 、Snapshot:JPEG、FDIN:Disabled

1.ZSLSnapshotJpeg pipeline

xml中对ZSLSnapshotJpeg pipeline的描述如下,

6d2c48ac5905c3913ff599e584b65c11.jpeg

2.裁剪node

ab7e7c25f7a4d6ee52dba495147bbd12.jpeg

检索Jpeg node的裁剪参数group=Snapshot,然后查找到用户设置的裁剪参数中有group=Snapshot,比较Jpeg node和用户设置是一致的Jpeg,则当前Jpeg node不需要被剪掉。JPEG Node的描述信息将添加到目的pipeline描述的节点列表中。

3.裁剪link

link根据连接的内容有三种情况:

  • sourceTarget-->dstNode

  • srcNode-->dstNode

  • srcNode-->sinkTarget sinkTarget又有两种情况(sink buffer和sink no buffer)

对一条link裁剪主要是三个步骤:

  • [更新link的start]对于srcNode--> 这种部分,首先需要更新srcNode的端口信息

  • [更新link的end]对于-->dstNode这部分,如果不被剪掉添加dstNode信息;对于-->sinkTarget这部分,如果不被剪掉更新sinkTarget

  • [更新link]对于srcNode bypass nextNode这种情况,需要根据srcNode的bypass属性更新link的dstPort(修改link.dstPort dstNode.inputPortA为dstNode.outputPortB,绕过dstNode)

裁剪发生在第二步,根据dstNode或者sinkTarget的裁剪信息确定是不是要被剪掉,不被剪掉的dstNode或者sinkTarget被加到目的usecase.pipeline中。

情况一:sourceTarget-->dstNode

93afeb84d6c5888fdaad2f90b842913b.jpeg

以BPS0[0].BPSOutputPortFull-->IFE0[0].IPEInputPortFull这条link为例子,

步骤1:因为BPS0 node没被剪掉,所以直接更新pipeline.node[BPS0].nodeAllPorts.pOutputPorts[1]的端口信息

步骤2:对于[1]BPSOutputPortFull-->[0]IPEInputPortFull这条link,dstNode是IPE0, 根据节点裁剪逻辑,IPE0是不被剪掉的,所以添加节点描述到目的pipeline.node[]

步骤3:对于[1]BPSOutputPortFull-->[0]IPEInputPortFull这条link,srcNode BPS0没有设置bypass属性,所以IPE0不需要绕过。

情况二:target-->dstNode

ca193c4713681d6fdd5915bd90ee5432.jpeg

对于ZSLSnapshotJpeg pipeline的输入TARGET_BUFFER_RAW-->[0]BPSInputPort1这条link,裁剪过程:

步骤1:因为是sourceTarget输入,所以不存在port要更新

步骤2:是-->dstNode这种情况,dstNode是BPS, 根据BSP的裁剪参数,BPS0 Node不需要剪掉,所以添加节点到目的pipeline.node[]

步骤3:因为是sourceTarget输入,无bypass逻辑。

情况三:srcNode-->target

ca73f3116aa3aaf91144de2fb75f1aeb.jpeg

对于[1]JPEGAggregatorOutputPort0-->TARGET_BUFFER_BLOB这条link,裁剪过程:

步骤1:srcNode是JPEGAggregator,更新目的pipeline.node[JPEGAggregator0].nodeAllPorts.pOutputPorts[1]的端口信息

步骤2:是-->sinkTarget这种情况,TARGET_BUFFER_BLOB是sink buffer,根据target裁剪逻辑需要被剪掉(轻颜相机没有配置heic拍照)

步骤3:srcNode是JPEGAggregator,没有设置bypass,所以不存在bypass处理。

如果[1]JPEGAggregatorOutputPort0-->TARGET_BUFFER_BLOB JPEGAggregator有设置bypass属性处理逻辑是什么样的?这就不得不说下srcNode bypass处理,有两种情况:

srcNode-->dstNode, 这时更新srcNode link到对应的dstNode.outputPort

srcNode-->sinkTarget(也就是当前假设这种情况),这时由于sinkTarget不是dstNode所以不存在port这个概念,也就不存在bypass概念。

4.裁剪sourceTarget

1fc4412dfca50a1fbc84251fec94b530.jpeg

TARGET_BUFFER_RAW这个sourceTarget不需要剪掉通过两个条件判断:

  • TARGET_BUFFER_RAW有接收

  • TARGET_BUFFER_RAW有接收,且接收不被剪掉。

所以裁剪sourceTarget可以分为两步:裁剪接收sourceTarget的node和裁剪sourceTarget和dstNode的连接。

原文链接:https://blog.csdn.net/hongyeying/article/details/128318445

参考文献:

【腾讯文档】Camera学习知识库
https://docs.qq.com/doc/DSWZ6dUlNemtUWndv

至此,本篇已结束。转载网络的文章,小编觉得很优秀,欢迎点击阅读原文,支持原创作者,如有侵权,恳请联系小编删除,欢迎您的建议与指正。同时期待您的关注,感谢您的阅读,谢谢!

448bceaf20a2b556510a96b0644a3b6a.jpeg

点击阅读原文,为大佬点赞!

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
高通8250是一款高性能的芯片,它采用了先进的相机通道(camera pipeline)技术。 相机通道是指从图像传感器到最终呈现图像的一系列技术和算法,包括图像处理、图像传输、图像存储等过程。高通8250芯片具有强大的处理能力,可以支持高分辨率和高帧率的图像采集、处理和呈现。 高通8250的相机通道技术主要有以下几个特点: 1. 高速数据传输:高通8250芯片采用了先进的接口技术,可以实现高速的数据传输,可以快速将图像数据从传感器传输到处理器,从而提高图像采集的效率。 2. 强大的图像处理能力:高通8250芯片内置了先进的图像处理引擎,可以对图像进行实时的处理和优化,包括色彩校正、去噪、锐化等操作,从而提高图像的质量和细节。 3. 多功能支持:高通8250芯片支持多种图像采集模式,包括连续拍摄、慢速视频拍摄、高动态范围(HDR)图像拍摄等,满足不同场景下的需求。同时,它还支持多种图像格式的编码和解码,可以兼容各种图像处理算法和应用。 4. 低功耗设计:高通8250芯片采用了低功耗设计,可以在功耗较低的情况下实现高性能的图像处理,延长设备的电池续航时间。 综上所述,高通8250芯片的相机通道技术具有高速数据传输、强大的图像处理能力、多功能支持和低功耗设计等特点,可以为用户提供高质量、高性能的图像采集和处理体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员Android

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值