Hi3519DV500 上如何在 VPSS Grp0 的多个 Chn 同时创建 Mosaic:排坑指南

Hi3519DV500 上如何在 VPSS Grp0 的多个 Chn 同时创建 Mosaic:排坑指南 % 2024-12-24 14:38:39 63

Hi3519DV500 上如何在 VPSS Grp0 的多个 Chn 同时创建 Mosaic:排坑指南

关键词:海思、Hi3519DV500、VPSS、RGN、Mosaic、参数超出合法范围(0xa0038007)

一、背景与需求

在视频监控、智慧安防等场景中,我们常常需要在主码流(高分辨率)和子码流(较低分辨率)上对指定区域进行马赛克处理(又称“打码”)。马赛克处理在海思平台上通常是通过 RGN(Region) 模块实现的——也就是创建一个 Mosaic 类型的 RGN,然后将其叠加到对应的通道上。

常见的应用场景包括:

人脸打码:出于隐私保护,在公共视频中将人物面部进行马赛克。
敏感区域打码:在监控画面中遮挡一些不适宜的区域。
可配置场景打码:动态给用户指定的区域进行马赛克处理等。
然而,在实际开发时,我们很容易遇到一个典型问题:在 VPSS Grp0 下,如果要在 Chn0、Chn1 上分别叠加 Mosaic,ss_mpi_rgn_attach_to_chn 可能会返回 0xa0038007(参数超出合法范围),主码流可以成功显示马赛克,但给子码流或其他通道绑定时却失败。本文就针对这个问题做一次系统的排查和解决思路分享。

二、问题重现

  1. 环境描述
    平台:Hi3519DV500(海思)
    工程配置:
    VI pipe0 chn0 -> VPSS grp0 chn0(主码流)
    VI pipe0 chn0 -> VPSS grp0 chn1(子码流)
    VI pipe0 chn0 -> VPSS grp0 chn2(JPEG)
  2. 需求描述
    希望在 主子码流(VPSS Grp0 的 Chn0 和 Chn1)甚至 Chn2(JPEG)上都呈现相同或相似的 Mosaic 效果。根据海思文档,Mosaic 类型的 RGN 只支持在 VPSS 上叠加,所以我们就为同一个 VPSS grp0 下的三个 Chn,都各自创建并 attach 一个 Mosaic 的 region。

  3. 代码片段示例
    (简化示意)

    int           ret;
     int           maxWidth, maxHeight;
     int           px, py, pw, ph;
     ot_rgn_handle rgnHd;
     mpp_rgn_t     *rgn;
     gsf_vmask_t   *vmask = (gsf_vmask_t *) param;
    
     // rgn mosaic do not support venc, but support vpss
     // vi pipe0 chn0 -> vpss grp0 chn0 for main stream
     // vi pipe0 chn0 -> vpss grp0 chn1 for sub stream
     // vi pipe0 chn0 -> vpss grp0 chn2 for jpeg
     for (int c = 0; c < VPSS_CHN_NUM; c++)
     {
         rgnHd = RGN_VMASK_START_INDEX + c * MAX_IPC_VMASK_NUM + vmask->idx;
         rgn   = &s_context.vmask[c][vmask->idx];
         rgn->hd = rgnHd;
    
         maxWidth  = s_context.vpss_cfg.chn_attr[c].width;
         maxHeight = s_context.vpss_cfg.chn_attr[c].height;
    
         rgn->stRegion.type                      = OT_RGN_MOSAIC;
    
         ret = ss_mpi_rgn_create(rgn->hd, &rgn->stRegion);
         if (ret != TD_SUCCESS)
         {
             sample_print("ss_mpi_rgn_create(%d) failed %#x\n", rgn->hd, ret);
             return ret;
         }
    
         rgn->stChn.mod_id = OT_ID_VPSS;
         rgn->stChn.dev_id = 0;
         rgn->stChn.chn_id = c;
    
         pw = vmask->rect[2] * maxWidth;
         ph = vmask->rect[3] * maxHeight;
         pw = pw >= maxWidth ? maxWidth : pw;
         ph = ph >= maxHeight ? maxHeight : ph;
         pw = ALIGN_UP(pw, 4);
         ph = ALIGN_UP(ph, 2);
    
         px = vmask->rect[0] * maxWidth;
         py = vmask->rect[1] * maxHeight;
         px = px + pw >= maxWidth ? maxWidth - pw - 5 : px;
         py = py + ph >= maxHeight ? maxHeight - ph - 5 : py;
         px = px < 0 ? 5 : px;
         py = py < 0 ? 5 : py;
         px = ALIGN_UP(px, 4);
         py = ALIGN_UP(py, 2);
    
         rgn->stChnAttr.is_show                      = vmask->enable;
         rgn->stChnAttr.type                         = OT_RGN_MOSAIC;
         rgn->stChnAttr.attr.mosaic_chn.rect.x       = px;
         rgn->stChnAttr.attr.mosaic_chn.rect.y       = py;
         rgn->stChnAttr.attr.mosaic_chn.rect.width   = pw;
         rgn->stChnAttr.attr.mosaic_chn.rect.height  = ph;
         rgn->stChnAttr.attr.mosaic_chn.blk_size     = OT_MOSAIC_BLK_SIZE_64;
         rgn->stChnAttr.attr.mosaic_chn.layer        = 0;
    
         // -1610383348 = a0038007 = 参数超出合法范围
         ret = ss_mpi_rgn_attach_to_chn(rgn->hd, &rgn->stChn, &rgn->stChnAttr);
         if (ret != TD_SUCCESS)
         {
             sample_print("ss_mpi_rgn_attach_to_chn(%d) failed with %#x\n", rgn->hd, ret);
             return ret;
         }
    
         ret = ss_mpi_rgn_set_chn_display_attr(rgn->hd, &rgn->stChn, &rgn->stChnAttr);
         if (ret != TD_SUCCESS)
         {
             sample_print("ss_mpi_rgn_set_chn_display_attr failed with %#x\n", ret);
             return ret;
         }
     }
     return ret;
    

    当我们先在 c=0(主码流)时,一切都能成功执行,但到 c=1(子码流)时,ss_mpi_rgn_attach_to_chn 却报错 0xa0038007。

三、常见原因分析

海思 SDK 中,如果出现 0xa0038007,其含义通常是参数超出合法范围。结合 Mosaic 这一类型,最常见的原因包括:

坐标或尺寸越界

在子码流中,如果我们直接使用与主码流相同的相对位置和大小,可能会导致 px + pw 或 py + ph 超出子码流的分辨率范围。
此时,内部检查到坐标越界,就会抛出参数不合法的错误。
对齐(Alignment)不符合要求

不同的海思版本,对 Mosaic 类型的 rect.x / rect.y / rect.width / rect.height 有不同的对齐要求。
当使用 OT_MOSAIC_BLK_SIZE_64 时,通常要求 X/Y/Width/Height 要按照 16 或 64 对齐(视官方文档及 SDK 要求而定)。简单的对 4 或 2 进行对齐,可能不够。
如果马赛克区域未满足必须的对齐边界,也会出现参数非法报错。
blk_size 设置不匹配

OT_MOSAIC_BLK_SIZE_64 代表单个马赛克小块是 64×64 像素。
如果你的子码流分辨率很小,或需要高精度打码,就要根据实际需求将 blk_size 调整为 16 或 32 等更合适的大小,否则很可能因为宽高太小不符合最小块要求,导致 attach 失败。
重复创建 RGN 或 Handle 重复使用

如果在子码流上使用了与主码流相同的 RGN handle(没有重新申请),则也会出现冲突。
在示例代码中,你已经按照不同 c 值(通道号)去计算 RGN_VMASK_START_INDEX + c * MAX_IPC_VMASK_NUM + vmask->idx,所以该问题大概率已经规避了。但依旧要确保 handle 不重复被复用。

四、排查和解决思路

  1. 检查子码流的分辨率和马赛克区域大小
    打印调试信息:输出 px, py, pw, ph 在子码流时的实际数值,确认它们没有超出 [0, width/height] 的范围。
    对齐策略:如果 SDK 要求 Mosaic 的 width 和 height 必须是 16 或 64 的倍数,那么你的对齐操作需要从 ALIGN_UP(… , 4) 改成 ALIGN_UP(… , 16) 或者 ALIGN_UP(… , 64)。
    边界处理:如果做完对齐后发现又超出分辨率,需要重新缩放或减小区域,避免越界。
  2. 自行计算缩放后的打码区域
    如果你希望“主码流和子码流打码区域在视觉上是同一位置”,而不是同一像素坐标,就需要根据主码流与子码流的分辨率比做比例缩放。
    举个例子:主码流是 1920×1080,子码流是 640×360。若主码流的打码区域是 (x=100, y=50, w=200, h=100),要保持相对画面位置相同,那么子码流就应该在 (x=100(640/1920), y=50(360/1080), …) 做相应缩放。
  3. 测试不同的 OT_MOSAIC_BLK_SIZE_X 值
    试着将 OT_MOSAIC_BLK_SIZE_64 调成 OT_MOSAIC_BLK_SIZE_16 或 OT_MOSAIC_BLK_SIZE_32,看看能否通过 attach。
    一些情况下,如果你的子码流特别小,blk_size 太大时就会导致越界或无法满足 SDK 要求的最小块数目、对齐规则等。
  4. 只 attach 子码流看是否正常
    可以先注释掉主码流部分的创建和 attach,只给子码流 attach Mosaic,看是否仍然报错。
    如果单独给子码流 attach 成功,说明 handle 重复或者区域坐标之间有冲突。
    如果单独子码流依旧失败,则更能确定问题在于它本身的坐标/对齐/blk_size 等细节。

    五、示例代码优化与小技巧

    假设我们要让主码流(1920×1080)和子码流(640×360)都打相似位置的马赛克,使用 blk_size=16。伪代码示例如下:

    for (int c = 0; c < 2; c++) // 只演示主码流和子码流
    {
     int ch_width  = (c == 0) ? 1920 : 640; 
     int ch_height = (c == 0) ? 1080 : 360;
    
     // 创建 RGN handle
     ot_rgn_handle rgn_handle = RGN_VMASK_START_INDEX + c * MAX_IPC_VMASK_NUM + vmask->idx;
     // Mosaic 区域参数
     int px = (int)(vmask->rect[0] * ch_width);
     int py = (int)(vmask->rect[1] * ch_height);
     int pw = (int)(vmask->rect[2] * ch_width);
     int ph = (int)(vmask->rect[3] * ch_height);
    
     // 保证对齐
     px = ALIGN_UP(px, 16);
     py = ALIGN_UP(py, 16);
     pw = ALIGN_UP(pw, 16);
     ph = ALIGN_UP(ph, 16);
    
     // 边界处理:如果越界就缩小
     if (px + pw > ch_width)  pw = ALIGN_DOWN(ch_width - px, 16);
     if (py + ph > ch_height) ph = ALIGN_DOWN(ch_height - py, 16);
    
     // 后面就是 ss_mpi_rgn_create, attach, set_display 等
     // ...
    }
    

    这样就可以避免因对齐、越界而导致的报错。当然,具体对齐要求要根据海思官方手册或 SDK 提示来做最终确认。

六、总结

在 Hi3519DV500 平台上,为 VPSS Grp0 下的多个通道(chn0、chn1、chn2)同时创建 Mosaic RGN 并不复杂,但也隐藏了一些细节坑点。最常见的问题就是参数越界和对齐不符合要求。只要我们在计算 Mosaic 区域时,认真对待子码流和主码流之间的分辨率差异、马赛克块大小的对齐要求,并做好越界保护,就能顺利实现多通道 Mosaic 功能。

排查思路:先单独测试单通道,确认区域参数,使用恰当的对齐方式;
打码缩放:若要多通道保持“相同视觉区域”,需根据分辨率比进行缩放;
blk_size 调整:根据画面大小和马赛克颗粒度需求,选合适的块大小;
精细调试:多打印调试信息,查看实际算出来的 px、py、pw、ph,对齐和边界是否符合硬件限制。
希望本文的分享能帮助你快速排查 Mosaic 创建和 attach 到子码流(chn1、chn2)失败的问题,让你的海思方案更稳定地支持多路马赛克叠加。祝开发顺利!

如果你在实际开发中碰到了更复杂的情况,例如多路 VI 输入、多级 VPSS 转发、或是需要对接 AI 分析模块,请根据海思 SDK 文档和你自己的应用需求,灵活扩展思路。

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

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

举报反馈

举报类型

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

详细说明

审核成功

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

审核失败

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

小包子的红包

恭喜发财,大吉大利

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

    易百纳技术社区