x3 关于OSD的问题讨论

  • 系统软件版本:x3_ubuntu_v1.1.3
  • 问题涉及的技术领域: 硬件、软件
  • 问题描述:

首先是测试了多路编解码的性能,测试结果为:最大支持5路1080P 25FPS H264视频的编解码能力,第6路的时候会出现下面的提示信息

[ERROR]["multimedia"][src/vdi/linux/vdi_osal.c:174] [ERROR][242623.19205][28800:28948][VDI] fail to vdi_allocate_dma_memory size=20553868
[ERROR]["multimedia"][src/vdi/linux/vdi_osal.c:174] [ERROR][242623.19219][28800:28948][VideoDecoder] RegisterFrameBuffers:154 Failed to VPU_DecRegisterFrameBufferEx(17)
[ERROR]["multimedia"][src/vdi/linux/vdi_osal.c:174] [ERROR][242623.19225][28800:28948][COMPONENT] Component wave_decoder will be terminated.

推测是硬件dma内存不够了导致的-
接着又输出了下面的错误信息:

[ERROR]["LOG"][src/utils/mem_log.c:108] [ERROR][242623.37583][28800:28952][ION_ALLOCATOR] <mem_ion_alloc_internal:236> Fail to do ION_IOC_ALLOC(ret=Cannot allocate memory)!
[ERROR]["LOG"][src/utils/mem_log.c:108] [ERROR][242623.37620][28800:28952][ION_ALLOCATOR] <mem_alloc_handle_and_buf:293> Fail to allocate ion memory(ret=-12).
[ERROR]["LOG"][src/utils/mem_log.c:108] [ERROR][242623.37628][28800:28952][ION_ALLOCATOR] <mem_osal_alloc_com_buf:425> Fail to allocate handle and buf(ret=-16777211).
[ERROR]["LOG"][src/utils/mem_log.c:108] [ERROR][242623.37639][28800:28952][MEM_ALLOCATOR] <mem_try_alloc_com_buf_locked:125> Fail to allocate memory(Insufficient memory).
[ERROR]["LOG"][src/utils/mem_log.c:108] [ERROR][242623.37642][28800:28952][MEM_ALLOCATOR] <hb_mem_alloc_com_buf_with_lable:259> Fail to allocate common buffer(ret=-16777211).
[ERROR]["LOG"][src/utils/mem_log.c:108] [ERROR][242623.37644][28800:28952][HBMEM] <hbmem_alloc:125> Fail to allocate buffer(ret=-16777211).
[ERROR]["multimedia"][src/vdi/linux/vdi_osal.c:174] [ERROR][242623.37647][28800:28952][MIANHELPER] hbmem_alloc failed
[ERROR]["multimedia"][src/vdi/linux/vdi_osal.c:174] [ERROR][242623.37650][28800:28952][VideoReader] PrepareReader:217 Fail to allocate bitstream buffer
HB_VDEC_GetFrame pop. max_size:3.
[ERROR]["LOG"][src/utils/mem_log.c:108] [ERROR][242623.39226][28800:28954][ION_ALLOCATOR] <mem_ion_alloc_internal:236> Fail to do ION_IOC_ALLOC(ret=Cannot allocate memory)!
[ERROR]["LOG"][src/utils/mem_log.c:108] [ERROR][242623.39236][28800:28954][ION_ALLOCATOR] <mem_alloc_handle_and_buf:293> Fail to allocate ion memory(ret=-12).
[ERROR]["LOG"][src/utils/mem_log.c:108] [ERROR][242623.39238][28800:28954][ION_ALLOCATOR] <mem_osal_alloc_com_buf:425> Fail to allocate handle and buf(ret=-16777211).
[ERROR]["LOG"][src/utils/mem_log.c:108] [ERROR][242623.39240][28800:28954][MEM_ALLOCATOR] <mem_try_alloc_com_buf_locked:125> Fail to allocate memory(Insufficient memory).
[ERROR]["LOG"][src/utils/mem_log.c:108] [ERROR][242623.39242][28800:28954][MEM_ALLOCATOR] <hb_mem_alloc_com_buf_with_lable:259> Fail to allocate common buffer(ret=-16777211).
[ERROR]["LOG"][src/utils/mem_log.c:108] [ERROR][242623.39243][28800:28954][HBMEM] <hbmem_alloc:125> Fail to allocate buffer(ret=-16777211).
[ERROR]["vio_bufmgr"][utils/hb_vio_buffer_mgr.c:364] [242623.392453]ion_alloc_phy_type[364]: hbmem_alloc failed

还是申请内存的时候出现错误。-
但是将1080P 的视频改成720P的话,8路同时25FPS编解码没的问题,cpu占用也才到338%,所以推测不同分辨率下硬件资源占用不一样导致,但是我们是希望能同时8路1080P视频的编解码的,不知道是不是我的程序上还有优化的空间,还希望指导一下。万分感谢

迫于无奈,只能降低视频处理路数,同时加上OSD叠加的功能,但是又发现OSD分为软件叠加、硬件叠加,时间上大概有一倍的区别,下面会详细讨论,先附上一张图-

现在的需求是想实现4路1080P 25FPS的编解码并且每路OSD叠加文字操作,基于这个前提,我们先测试了不同 VpsGrp 和 VpsChn 之间的潜在关系。部分示例接口代码如下:

  • 创建group

    VPS_GRP_ATTR_S grp_attr;
    memset(&grp_attr, 0, sizeof(VPS_GRP_ATTR_S));
    grp_attr.maxW = 1920;
    grp_attr.maxH = 1080;
    grp_attr.frameDepth = 8;
    ret = HB_VPS_CreateGrp(VpsGrp, &grp_attr);
    ret = HB_SYS_SetVINVPSMode(VpsGrp, VIN_OFFLINE_VPS_OFFINE);
    
  • 开启通道

    VPS_CHN_ATTR_S chn_attr;
    memset(&chn_attr, 0, sizeof(VPS_CHN_ATTR_S));
    chn_attr.enScale = 1;
    chn_attr.width = 1920;
    chn_attr.height = 1080;
    chn_attr.frameDepth = 8;
    HB_VPS_SetChnAttr(VpsGrp, VpsChn, &chn_attr);
    HB_VPS_EnableChn(VpsGrp, VpsChn);
    HB_VPS_StartGrp(VpsGrp);
    
  • 区域创建,并且附加到通道

    RGN_ATTR_S pstRegion;
    pstRegion.enType = OVERLAY_RGN;
    pstRegion.stOverlayAttr.stSize.u32Width = 1920;
    pstRegion.stOverlayAttr.stSize.u32Height = 1080;
    pstRegion.stOverlayAttr.enPixelFmt = PIXEL_FORMAT_VGA_4;
    pstRegion.stOverlayAttr.enBgColor  = FONT_KEY_COLOR;
    ret = HB_RGN_Create(VpsChn+1, &pstRegion);
    
    RGN_CHN_S chn;
    chn.s32PipelineId = VpsGrp;
    // 画图时的通道必须是VPS通道号+1
    chn.enChnId = VpsChn+1;
    
    RGN_CHN_ATTR_S chn_attr;
    chn_attr.bShow = true;
    chn_attr.bInvertEn = false;
    chn_attr.unChnAttr.stOverlayChn.stPoint.u32X = 0;
    chn_attr.unChnAttr.stOverlayChn.stPoint.u32Y = 0;
    
    ret = HB_RGN_AttachToChn(VpsChn+1, &chn, &chn_attr);
    
  • 附加信息

    typedef enum HB_RGN_CHN_ID_ATTR_E      /*ipu channel region attached to*/
    {
        CHN_US,
        CHN_DS0,
        CHN_DS1,
        CHN_DS2,
        CHN_DS3,
        CHN_DS4,
        CHN_GRP,
        CHANNEL_MAX_NUM
    }RGN_CHN_ID_E;
    

单路测试结果:

  • (OSD叠加了6个矩形框,6个文本框)

  • 单路测试时,VpsGrp固定为0, (多次测试结果发现单路测试时,OSD性能与VpsGrp的值无关)

  • 表中不支持项表示程序运行时会提示如下信息,猜测意思是此通道最大支持处理1280 wiidth的图片

    [ERROR]["vps"][vps/hb_vps_api.c:640] [245724.703130]HB_VPS_SetChnAttr[640]: chn 1920 width beyond safe size 1280
    

分辨率

VpsChn

OSD叠加时间(ms)(50次平均值)

720P

CHN_US

6

720P

CHN_DS0

6

720P

CHN_DS1

13

720P

CHN_DS2

13

720P

CHN_DS3

13

720P

CHN_DS4

6

1080P

CHN_US

不支持

1080P

CHN_DS0

16

1080P

CHN_DS1

35

1080P

CHN_DS2

35

1080P

CHN_DS3

不支持

1080P

CHN_DS4

35

基于上述表格结果分析:VpsGrp固定下,只有 CHN_DS0 能支持1080P的硬件OSD,因此下面尝试多线程1080P的硬件OSD。-
开4线程,每个线程同时1080P 25FPS编解码的同时,进行独立OSD操作,观察每路时间消耗如下表

线程编号

分辨率

VpsGrp

VpsChn

OSD叠加时间(ms)(50次平均值)

0

1080P

0

CHN_DS0

34

1

1080P

1

CHN_DS0

36

2

1080P

2

CHN_DS0

35

3

1080P

3

CHN_DS0

34

测试只开2线程,观察每路时间消耗如下表

线程编号

分辨率

VpsGrp

VpsChn

OSD叠加时间(ms)(50次平均值)

0

1080P

0

CHN_DS0

11

1

1080P

1

CHN_DS0

12

测试只开单线程,观察每路时间消耗如下表

线程编号

分辨率

VpsGrp

VpsChn

OSD叠加时间(ms)(50次平均值)

0

1080P

0

CHN_DS0

10

测试只开4线程,使用不同VpsChn,观察每路时间消耗如下表

  • 测试时每个线程是差了2s启动的,随着线程1,2,3慢慢起来的时候,线程0的OSD时间是在慢慢增加的

  • 此种组合不会造成OSD混乱的问题

    线程编号

    分辨率

    VpsGrp

    VpsChn

    OSD叠加时间(ms)(50次平均值)

    0

    1080P

    0

    CHN_DS0

    44

    1

    1080P

    1

    CHN_DS1

    72

    2

    1080P

    2

    CHN_DS2

    76

    3

    1080P

    3

    CHN_DS4

    79

基于上述4、2、1、4线程结果进行分析:

  • 测试时出现了意外情况:当VpsChn取值相同时,不同VpsGrp下,OSD叠加后数据时混乱的,比如线程0上本来叠加的是 字符串0 ,实际上却可能叠加上字符串1,2,3,同理线程3上叠加的字符串也会出现0,1,2。线程越多时混乱程度越高。而不同VpsGrp与VpsChn时,OSD数据没有出现混乱问题。分析可能原因:当多路视频OSD时,VpsChn相同导致每路的bitmap在相同VpsChn下被覆盖,导致多路视频拿到了相同的bitmap在自己的yuv数据上进行叠加造成。
  • 根据文档说明,OSD硬件叠加是分时复用的,在内部应该存在一把锁,当4路同时OSD时,等待时间较长,但是也不合理,这里请详细解释一下底层实现原理,便于我们二次开发。
  • 但是当单线程、2线程时每路OSD的时间变化却不大,这里也有疑问,请详细解释一下,万分感谢。
  • 4线程时,每路OSD时间太长,导致必须丢帧,实际编码帧率达不到25FPS
  • 单线程对比OSD硬件通道和软件通道,硬件通道会快很多,但是CPU占用率也高了8%左右

前提:

  • 开线程后的OSD操作都是在各自的线程内初始化后,对每帧进行OSD操作
  • 开线程编解码处理的视频都是拉取海康相机的rtsp流,编码后使用avformat,avcodec推流的
  • OSD绘制的内容为固定坐标的6个不同位置的矩形框,和6个相机的id,如下图:-
    -
  • 如上图,当VpsChn取值相同时,不同VpsGrp下,两张图中图像内容没有变化,但是OSD内容却有变化,两张图都是线程3065的产生的,但是却有3068,很奇怪,当VpsChn取值不同时,不同VpsGrp下时,就没有这个问题,所以应该不是我测试代码的bug。请对此现象作出解释 ,安分感谢

现在最大的问题时如何实现4路1080P 25FPS的编解码+OSD叠加不混乱的能力,保证不丢帧,麻烦请专家详细介绍一下底层原理以及解决方案,万分感谢.

您好,可以参考手册修改ION大小,解决内存占用问题 修改BPU保留内存大小 | RDK X3用户手册 (horizon.cc)

您好,那么多路1080P OSD叠加时间效率问题呢,有解决方案吗,目前2路1080P 25FPS 的OSD叠加都会掉帧

您好,贵公司是? 需要和对应的fae做一下沟通