海思3518E MPP初始化详解及blocksize的计算

海思3518E MPP初始化详解及blocksize的计算 Lixiaofeng 2024-02-12 16:37:00 90

为了兼容性的问题,海思为多个版本的3518e编写了sample

我们分析这一路

变量定义

这里有几个关键性的变量
playload数组中有3个成员,对应3个通道。编码尺寸也对应3个通道

typedef struct hiVB_CONF_S
{
    HI_U32 u32MaxPoolCnt;     /* max count of pools, (0,VB_MAX_POOLS]  */    
    struct hiVB_CPOOL_S
    {
        HI_U32 u32BlkSize;
        HI_U32 u32BlkCnt;
        HI_CHAR acMmzName[MAX_MMZ_NAME_LEN];
    }astCommPool[VB_MAX_COMM_POOLS];
} VB_CONF_S;

VB_CONF_S stVbConf;
这个结构体是视频缓冲池的相关属性
包括缓冲池的最大值、块的数量和大小等

step 1: init sys variable
/******************************************
     step  1: init sys variable 
    ******************************************/
    memset(&stVbConf,0,sizeof(VB_CONF_S));

    SAMPLE_COMM_VI_GetSizeBySensor(&enSize[0]);
    if (PIC_HD1080 == enSize[0])
    {
        enSize[1] = PIC_VGA;
        s32ChnNum = 2;
    }
    else if (PIC_HD720 == enSize[0])
    {
        enSize[1] = PIC_VGA;            
        enSize[2] = PIC_QVGA;
        s32ChnNum = 3;
    }
    else
    {
        printf("not support this sensor\n");
        return HI_FAILURE;
    }
#ifdef hi3518ev201
    s32ChnNum = 1;
#endif
    printf("s32ChnNum = %d\n",s32ChnNum);

    stVbConf.u32MaxPoolCnt = 128;//最大视频缓存池数量,根据内存大小给出的经验值

    /*video buffer*/
    if(s32ChnNum >= 1)//根据通道数量计算mpp结构体参数,填充视频缓存池结构体
    {
        //u32BlkSize为一帧图像所需要的大小,也就是块大小
        u32BlkSize = SAMPLE_COMM_SYS_CalcPicVbBlkSize(gs_enNorm,\//第一个参数为扫描方式
                    enSize[0], SAMPLE_PIXEL_FORMAT, SAMPLE_SYS_ALIGN_WIDTH);//计算块大小,//传入分辨率格式,像素格式,对齐排布,用于像素取整//关键是把enSize[0]传进去,
        stVbConf.astCommPool[0].u32BlkSize = u32BlkSize;//设置块大小  //从上面的得到enSize[0]为PIC_HD1080
        stVbConf.astCommPool[0].u32BlkCnt = g_u32BlkCnt;//设置块数量
    }
    if(s32ChnNum >= 2)
    {
        u32BlkSize = SAMPLE_COMM_SYS_CalcPicVbBlkSize(gs_enNorm,\
                    enSize[1], SAMPLE_PIXEL_FORMAT, SAMPLE_SYS_ALIGN_WIDTH);
        stVbConf.astCommPool[1].u32BlkSize = u32BlkSize;
        stVbConf.astCommPool[1].u32BlkCnt =g_u32BlkCnt;
    }
    if(s32ChnNum >= 3)//3个通道对应三个视频缓存池,因为不同通道也就是不同分辨率,他们对应的码流不同
    {
        u32BlkSize = SAMPLE_COMM_SYS_CalcPicVbBlkSize(gs_enNorm,\
                enSize[2], SAMPLE_PIXEL_FORMAT, SAMPLE_SYS_ALIGN_WIDTH);
        stVbConf.astCommPool[2].u32BlkSize = u32BlkSize;
        stVbConf.astCommPool[2].u32BlkCnt = g_u32BlkCnt;
    }

首先初始化视频缓存池
接着调用SAMPLE_COMM_VI_GetSizeBySensor,通过配置makefile传入的sensor类型进行图像尺寸及通道数的判断

由于我们使用的是AR0130,于是走的是else。即三通道码流

一路主码流(原始的没有裁剪的,全功能版本),另外两路(在主码流的基础上经过裁剪缩放等操作简化而来,阉 割版本)为子码流,客户用手机看的话就用子码流看就行了,没必要看主码流,还可以省点网络带宽,还比较流畅。

裸流:开发过程中的半成品,把文件头一解析就知道这个文件的分辨率, mp4、rtsp等都可以查一下文件头来看。
裸流(h264)是没有这个文件头的。

怎么看sensor支持的图像大小?

720p 1280x720=92万像素至少要留点余量,100万像素以上
1080p 1920x1080 = 207万像素 至少sensor也要210万像素以上

为什么不同的码流要对应不同的pool呢?
因为不同的码流分辨率不一样,对应的blocksize的大小也就不一样

计算blocksize
最后根据不同通道不同分辨率,计算blocksize
调用了SAMPLE_COMM_SYS_CalcPicVbBlkSize,传入

  • 视频输入制式类型(图像的扫描方式,早期CRT显示用到,现在意义只有向前兼容)
  • 编码尺寸
  • 像素格式
  • 像素对齐(根据像素排布进行向上取整对齐)
/******************************************************************************
* function : calculate VB Block size of picture.
******************************************************************************/
HI_U32 SAMPLE_COMM_SYS_CalcPicVbBlkSize(VIDEO_NORM_E enNorm, PIC_SIZE_E enPicSize, PIXEL_FORMAT_E enPixFmt, HI_U32 u32AlignWidth)
{
    HI_S32 s32Ret = HI_FAILURE;
    SIZE_S stSize;
    HI_U32 u32VbSize;
    HI_U32 u32HeaderSize;

    s32Ret = SAMPLE_COMM_SYS_GetPicSize(enNorm, enPicSize, &stSize);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("get picture size[%d] failed!\n", enPicSize);
            return HI_FAILURE;
    }

    if (PIXEL_FORMAT_YUV_SEMIPLANAR_422 != enPixFmt && PIXEL_FORMAT_YUV_SEMIPLANAR_420 != enPixFmt)
    {
        SAMPLE_PRT("pixel format[%d] input failed!\n", enPixFmt);
            return HI_FAILURE;
    }

    if (16!=u32AlignWidth && 32!=u32AlignWidth && 64!=u32AlignWidth)
    {
        SAMPLE_PRT("system align width[%d] input failed!\n",\
               u32AlignWidth);
            return HI_FAILURE;
    }
    //SAMPLE_PRT("w:%d, u32AlignWidth:%d\n", CEILING_2_POWER(stSize.u32Width,u32AlignWidth), u32AlignWidth);
    u32VbSize = (CEILING_2_POWER(stSize.u32Width, u32AlignWidth) * \
            CEILING_2_POWER(stSize.u32Height,u32AlignWidth) * \
           ((PIXEL_FORMAT_YUV_SEMIPLANAR_422 == enPixFmt)?2:1.5));

    VB_PIC_HEADER_SIZE(stSize.u32Width, stSize.u32Height, enPixFmt, u32HeaderSize);
    u32VbSize += u32HeaderSize;

    return u32VbSize;
}

SAMPLE_COMM_SYS_CalcPicVbBlkSize中又调用了SAMPLE_COMM_SYS_GetPicSize,用于计算图像大小

可以看到,在早期电视显示标准中,需要考虑制式,现在的数字显示就不需要。考虑兼容问题,于是这个sample就这样写了

接下来判断像素格式,这个sample只支持422和420

再考虑对齐,此sample只考虑16bit、32bit和64bit对齐,我们选用的是64字节对齐

最后就是计算blocksize的大小,宽x高x字节数,用了一个宏来计算宽和高CEILING_2_POWER

#define CEILING_2_POWER(x,a) ( ((x) + ((a) - 1) ) & ( ~((a) - 1) ) )
若输入15和2,即15和2对齐,输出16
若输入15和64,即15和64对齐,输出64
实际中,比如720p,代码中规定向64取整,即1280向上增加到64的倍数,即1280
如果是一个其他的数,如WVGA是854,和64向上取整,即896

每一个像素占多少字节,

  • yuv422
    四个像素占8个字节,每个像素占2字节

  • yuv420
    四个像素占6个字节,每个像素占1.5个字节
    宽x高x字节数就是blocksize

然后要留一些余量给后续操作做准备

为文件头留出余量后就计算完毕

以上,第一步计算mpp所需要的参数就计算好了
这些参数是根据应用需求进行核算的

但是此时系统还没有启动
于是进入第二步,进行初始化

step 2: mpp system init

第二步所有操作包在了一个函数里

/******************************************************************************
* function : vb init & MPI system init
******************************************************************************/
HI_S32 SAMPLE_COMM_SYS_Init(VB_CONF_S *pstVbConf)
{
    MPP_SYS_CONF_S stSysConf = {0};
    HI_S32 s32Ret = HI_FAILURE;

    HI_MPI_SYS_Exit();
    HI_MPI_VB_Exit();

    if (NULL == pstVbConf)
    {
        SAMPLE_PRT("input parameter is null, it is invaild!\n");
        return HI_FAILURE;
    }

    s32Ret = HI_MPI_VB_SetConf(pstVbConf);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("HI_MPI_VB_SetConf failed!\n");
        return HI_FAILURE;
    }

    s32Ret = HI_MPI_VB_Init();
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("HI_MPI_VB_Init failed!\n");
        return HI_FAILURE;
    }

    stSysConf.u32AlignWidth = SAMPLE_SYS_ALIGN_WIDTH;
    s32Ret = HI_MPI_SYS_SetConf(&stSysConf);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("HI_MPI_SYS_SetConf failed\n");
        return HI_FAILURE;
    }

    s32Ret = HI_MPI_SYS_Init();
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("HI_MPI_SYS_Init failed!\n");
        return HI_FAILURE;
    }

    return HI_SUCCESS;
}

HI_MPI_SYS_Exit()HI_MPI_VB_Exit()这两个是怕你之前的VB和SYS没处理干净,保险起见,打扫卫生的。需要注意,释放的时候是SYS在前,VB在后的(文档规定)

HI_MPI_VB_SetConfHI_MPI_VB_Init是SDK中的函数
在定义好视频缓冲池后将结构体交给SDK进行处理,分配内存

只要把VB(缓冲池搞好了),SYS里面都是自动化的,海思封装的特别好,我们要操心的是VB的参数pstVbconf

声明:本文内容由易百纳平台入驻作者撰写,文章观点仅代表作者本人,不代表易百纳立场。如有内容侵权或者其他问题,请联系本站进行删除。
红包 点赞 收藏 评论 打赏
评论
0个
内容存在敏感词
手气红包
    易百纳技术社区暂无数据
相关专栏
置顶时间设置
结束时间
删除原因
  • 广告/SPAM
  • 恶意灌水
  • 违规内容
  • 文不对题
  • 重复发帖
打赏作者
易百纳技术社区
Lixiaofeng
您的支持将鼓励我继续创作!
打赏金额:
¥1易百纳技术社区
¥5易百纳技术社区
¥10易百纳技术社区
¥50易百纳技术社区
¥100易百纳技术社区
支付方式:
微信支付
支付宝支付
易百纳技术社区微信支付
易百纳技术社区
打赏成功!

感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~

举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

审核成功

发布时间设置
发布时间:
是否关联周任务-专栏模块

审核失败

失败原因
备注
拼手气红包 红包规则
祝福语
恭喜发财,大吉大利!
红包金额
红包最小金额不能低于5元
红包数量
红包数量范围10~50个
余额支付
当前余额:
可前往问答、专栏板块获取收益 去获取
取 消 确 定

小包子的红包

恭喜发财,大吉大利

已领取20/40,共1.6元 红包规则

    易百纳技术社区