- 系统软件版本: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叠加不混乱的能力,保证不丢帧,麻烦请专家详细介绍一下底层原理以及解决方案,万分感谢.