当前位置: 首页 > news >正文

Hi3518E官方录像例程源码流程分析(四)

文章目录

  • Vpss的一些基本概念(来自资料里的官方文档)
    • GROUP
    • CHANNEL
    • FRC
  • 第四阶段 启动视频处理子系统vpss,并且绑定vi到vpss
    • SAMPLE_COMM_SYS_GetPicSize
    • if(s32ChnNum >= 1)
      • SAMPLE_COMM_VPSS_StartGroup
        • HI_MPI_VPSS_CreateGrp
        • HI_MPI_VPSS_GetNRParam
        • HI_MPI_VPSS_SetNRParam
        • HI_MPI_VPSS_StartGrp
      • SAMPLE_COMM_VI_BindVpss(),将当前组绑定到上一级VI的通道
        • SAMPLE_COMM_VI_Mode2Param()
        • 回到SAMPLE_COMM_VI_BindVpss

源码地址 + 文档资料 – 提取码: chmr

本专栏分析的是mpp\venc\sample\sample_venc.c

Vpss的一些基本概念(来自资料里的官方文档)

在这里插入图片描述
VPSS(Video Process Sub-System) 模块接收 VI 和解码模块发送过来的图像,支持对一幅输入图像进行统一预处理,如去噪、去隔行等,然后再对各通道分别进行缩放、锐化等处理,最后输出多种不同分辨率的图像。

GROUP

VPSS 对用户提供组(GROUP)的概念。最大可用数为 VPSS_MAX_GRP_NUM个,各芯片的最大组数目有所不同,各 GROUP 分时复用 VPSS 硬件。每个 VPSS GROUP 包含多个通道,通道数目视方案实现有所不同,具体描述请参见CHANNEL。

CHANNEL

VPSS 组的通道。通道分为 2 种:物理通道和扩展通道。VPSS 硬件提供多个物理通道,每个通道具有缩放、裁剪等功能。扩展通道具备缩放功能,它通过绑定物理通道,将物理通道输出作为自己的输入,把图像缩放成用户设置的目标分辨率输出。

FRC

  • Group 帧率控制:用于控制各 group 对输入图像的接收,只应用在 VI—VPSS的离线方案中。
  • Chn 帧率控制:用于控制各个物理通道图像的处理,应用在离线和在线方案中。

在这里插入图片描述
通过调用 SYS 模块的绑定接口,可与 VI 和 VO/VENC/IVE 等模块进行绑定,其中前者为 VPSS 的输入源,后者为 VPSS 的接收者。用户可通过提供的 MPI 接口对 GROUP进行管理。每个 GROUP 仅可与一个输入源绑定。

GROUP 的物理通道有两种工作模式:AUTO 和 USER,两种模式间可动态切换。默认的工作模式为 AUTO,此模式下各通道仅可与一个接收者绑定。若想使用 USER 模式,则需调用 MPI 接口进行设置,同时指定所需图像的大小和格式,此模式下各通道可与多个接收者绑定。需要特别注意的是,USER 模式主要用于对同一通道图像进行多路编码的场景,此模式下播放控制不生效,因此预览和回放场景下不建议使用 USER 模式。

第四阶段 启动视频处理子系统vpss,并且绑定vi到vpss

第四阶段看似很长,其实设置通道的三部分都是重复的步骤

if(s32ChnNum >= 1){....}
if(s32ChnNum >= 2){....}
if(s32ChnNum >= 3){....}
    s32Ret = SAMPLE_COMM_SYS_GetPicSize(gs_enNorm, enSize[0], &stSize);if (HI_SUCCESS != s32Ret){SAMPLE_PRT("SAMPLE_COMM_SYS_GetPicSize failed!\n");goto END_VENC_1080P_CLASSIC_1;}if(s32ChnNum >= 1){VpssGrp = 0;//Grp number//Maximum sizestVpssGrpAttr.u32MaxW = stSize.u32Width;stVpssGrpAttr.u32MaxH = stSize.u32Height;//Some functions in the groupstVpssGrpAttr.bIeEn = HI_FALSE;stVpssGrpAttr.bNrEn = HI_TRUE;stVpssGrpAttr.bHistEn = HI_FALSE;stVpssGrpAttr.bDciEn = HI_FALSE;stVpssGrpAttr.enDieMode = VPSS_DIE_MODE_NODIE;//set convert from RAW_RGB to YUV420stVpssGrpAttr.enPixFmt = PIXEL_FORMAT_YUV_SEMIPLANAR_420;s32Ret = SAMPLE_COMM_VPSS_StartGroup(VpssGrp, &stVpssGrpAttr);if (HI_SUCCESS != s32Ret){SAMPLE_PRT("Start Vpss failed!\n");goto END_VENC_1080P_CLASSIC_2;}//Bind the current Group to the Channal of the previous level VIs32Ret = SAMPLE_COMM_VI_BindVpss(stViConfig.enViMode);if (HI_SUCCESS != s32Ret){SAMPLE_PRT("Vi bind Vpss failed!\n");goto END_VENC_1080P_CLASSIC_3;}//So far, the data in vi has arrived at Vpss.VpssChn = 0;//3518E can only work in MODE mode、mode:vpss channel's work modestVpssChnMode.enChnMode      = VPSS_CHN_MODE_USER;stVpssChnMode.bDouble        = HI_FALSE;stVpssChnMode.enPixelFormat  = PIXEL_FORMAT_YUV_SEMIPLANAR_420;stVpssChnMode.u32Width       = stSize.u32Width;stVpssChnMode.u32Height      = stSize.u32Height;//Processing modules in large bytesstVpssChnMode.enCompressMode = COMPRESS_MODE_SEG;memset(&stVpssChnAttr, 0, sizeof(stVpssChnAttr));//Does not control frame ratestVpssChnAttr.s32SrcFrameRate = -1;stVpssChnAttr.s32DstFrameRate = -1;s32Ret = SAMPLE_COMM_VPSS_EnableChn(VpssGrp, VpssChn, &stVpssChnAttr, &stVpssChnMode, HI_NULL);if (HI_SUCCESS != s32Ret){SAMPLE_PRT("Enable vpss chn failed!\n");goto END_VENC_1080P_CLASSIC_4;}}//There are three chn, but they all belong to the same grp.if(s32ChnNum >= 2){//Reset the obtained image sizes32Ret = SAMPLE_COMM_SYS_GetPicSize(gs_enNorm, enSize[1], &stSize);if (HI_SUCCESS != s32Ret){SAMPLE_PRT("SAMPLE_COMM_SYS_GetPicSize failed!\n");goto END_VENC_1080P_CLASSIC_4;}VpssChn = 1;stVpssChnMode.enChnMode       = VPSS_CHN_MODE_USER;stVpssChnMode.bDouble         = HI_FALSE;stVpssChnMode.enPixelFormat   = PIXEL_FORMAT_YUV_SEMIPLANAR_420;stVpssChnMode.u32Width        = stSize.u32Width;stVpssChnMode.u32Height       = stSize.u32Height;stVpssChnMode.enCompressMode  = COMPRESS_MODE_SEG;stVpssChnAttr.s32SrcFrameRate = -1;stVpssChnAttr.s32DstFrameRate = -1;s32Ret = SAMPLE_COMM_VPSS_EnableChn(VpssGrp, VpssChn, &stVpssChnAttr, &stVpssChnMode, HI_NULL);if (HI_SUCCESS != s32Ret){SAMPLE_PRT("Enable vpss chn failed!\n");goto END_VENC_1080P_CLASSIC_4;}}if(s32ChnNum >= 3){	s32Ret = SAMPLE_COMM_SYS_GetPicSize(gs_enNorm, enSize[2], &stSize);if (HI_SUCCESS != s32Ret){SAMPLE_PRT("SAMPLE_COMM_SYS_GetPicSize failed!\n");goto END_VENC_1080P_CLASSIC_4;}VpssChn = 2;stVpssChnMode.enChnMode 	= VPSS_CHN_MODE_USER;stVpssChnMode.bDouble		= HI_FALSE;stVpssChnMode.enPixelFormat = PIXEL_FORMAT_YUV_SEMIPLANAR_420;stVpssChnMode.u32Width		= stSize.u32Width;stVpssChnMode.u32Height 	= stSize.u32Height;stVpssChnMode.enCompressMode = COMPRESS_MODE_NONE;stVpssChnAttr.s32SrcFrameRate = -1;stVpssChnAttr.s32DstFrameRate = -1;s32Ret = SAMPLE_COMM_VPSS_EnableChn(VpssGrp, VpssChn, &stVpssChnAttr, &stVpssChnMode, HI_NULL);if (HI_SUCCESS != s32Ret){SAMPLE_PRT("Enable vpss chn failed!\n");goto END_VENC_1080P_CLASSIC_4;}}

SAMPLE_COMM_SYS_GetPicSize

这个函数提到过很多次了,更新图像的像素大小

case PIC_HD720:   /* 1280 * 720 */pstSize->u32Width  = 1280;pstSize->u32Height = 720;

if(s32ChnNum >= 1)

stVpssGrpAttr.bIeEn = HI_FALSE;
stVpssGrpAttr.bNrEn = HI_TRUE;
stVpssGrpAttr.bHistEn = HI_FALSE;
stVpssGrpAttr.bDciEn = HI_FALSE;
stVpssGrpAttr.enDieMode = VPSS_DIE_MODE_NODIE;

首先进来是Vpss的一些参数

stVpssGrpAttr.bIeEn //图像增强
stVpssGrpAttr.bNrEn //去噪声
stVpssGrpAttr.bDciEn // 动态对比度调节
stVpssGrpAttr.enDieMode //隔行扫描
stVpssGrpAttr.enPixFmt //Raw_RGB -> YUV…

SAMPLE_COMM_VPSS_StartGroup

前面那些条件判断就不理他了

HI_MPI_VPSS_CreateGrp

创建一个 VPSS GROUP

HI_MPI_VPSS_GetNRParam

获取 vpss 3DNR 参数

HI_MPI_VPSS_SetNRParam

设置 vpss 3DNR 参数,将s32Ret更改为自定义降噪部分等

HI_MPI_VPSS_StartGrp

启用 VPSS GROUP

SAMPLE_COMM_VI_BindVpss(),将当前组绑定到上一级VI的通道

这里又涉及到Vpss的另一个概念
在线模式

在这里插入图片描述

由手册也可以看到3518E的每个通道地区在线模式和离线模式可能会有不一样的功能
在这里插入图片描述

在这里插入图片描述
我们这里是直接把VI绑定到Vpss,所以都是在线模式

SAMPLE_COMM_VI_Mode2Param()

设置设备和通道的数量以及每个设备id之间和通道id之间的差值间隔

pstViParam->s32ViDevCnt      = 1;//There are currently several dev's.
pstViParam->s32ViDevInterval = 1;
pstViParam->s32ViChnCnt      = 1;//There are several channals currently
pstViParam->s32ViChnInterval = 1;
回到SAMPLE_COMM_VI_BindVpss

上面设置了stViParam.s32ViChnCnt = 1,所以这个只会执行1次

    VpssGrp = 0;for (j=0; j<stViParam.s32ViChnCnt; j++){				//Interval between each channal numberViChn = j * stViParam.s32ViChnInterval;//Source: chn0 of dev0 in unit vistSrcChn.enModId  = HI_ID_VIU;//Internal unit number of ChipstSrcChn.s32DevId = 0;stSrcChn.s32ChnId = ViChn;//Purpose: chn0 of Grp0 in the vpss unitstDestChn.enModId  = HI_ID_VPSS;stDestChn.s32DevId = VpssGrp;stDestChn.s32ChnId = 0;//online mode:Bind vi and vpsss32Ret = HI_MPI_SYS_Bind(&stSrcChn, &stDestChn);if (s32Ret != HI_SUCCESS){SAMPLE_PRT("failed with %#x!\n", s32Ret);return HI_FAILURE;}VpssGrp ++;}

先是这一句:ViChn = j * stViParam.s32ViChnInterval;
前面不是设置了通道id之间的差值吗,这里通过 j 乘 这个差值就能找到具体的通道

然后把vi的channel和Vpss Group里的channel绑定起来

		//Source: chn0 of dev0 in unit vistSrcChn.enModId  = HI_ID_VIU;//Internal unit number of ChipstSrcChn.s32DevId = 0;stSrcChn.s32ChnId = ViChn;//Purpose: chn0 of Grp0 in the vpss unitstDestChn.enModId  = HI_ID_VPSS;stDestChn.s32DevId = VpssGrp;stDestChn.s32ChnId = 0;

HI_MPI_SYS_Bind()

到此为止,Vi模块里的数据就到达了Vpss模块

相关文章:

  • 【NLP 62、实践 ⑮、基于RAG + 智谱语言模型的Dota2英雄故事与技能介绍系统】
  • 13【生命周期·进阶】省略规则与静态生命周期 (`‘static`)
  • 08【工具赋能】深入 Cargo:依赖管理、构建配置与工作空间 (Workspace)
  • C++类继承关键点总结
  • MySQL数据库(基础篇)
  • 量子计算与经典计算融合:开启计算新时代
  • 读一篇AI论文并理解——通过幻觉诱导优化缓解大型视觉语言模型中的幻觉
  • UE5 UI 教程系列全集
  • llama factory
  • 7、sentinel
  • 微信小程序通过mqtt控制esp32
  • 手写call,bind,apply
  • Jetson Orin Nano GPIO 实战,用 devmem 玩转 Pinmux 引脚复用配置
  • 【数据可视化-19】智能手机用户行为可视化分析
  • AI与思维模型【71】——断裂点理论
  • 第五章 SQLite数据库:5、SQLite 进阶用法:ALTER 命令、TRUNCATE 操作、视图创建、事务控制和子查询的操作
  • 【Java面试系列】Spring Cloud微服务架构中的分布式事务解决方案与Seata实现原理详解 - 3-5年Java开发必备知识
  • 每日算法-250420
  • qwen 32B 模型配置文件参数解释;48 个堆叠的解码器层是什么意思; `max_window_layers`的作用; 定义 `device_map`
  • 文件上传漏洞:Pass-01
  • 服务业扩大开放,金融、医疗等多领域明确155项试点任务
  • 深一度|上海半马,展示“体育+”无限可能的路跑狂欢
  • 白宫慌了!将设工作组紧急处理对中国加征关税危机
  • 关于沪泰创新合作,泰州市委书记姜冬冬谈到了三个“合”
  • 陕西省药监局:未检出巨子生物“可复美”存在“表皮生长因子”
  • 奥园集团:截至3月底逾期债务约438.33亿元