海思3559万能平台搭建:OSD实时叠加的支持2区域RGN的配置

简介: OSD实时叠加的支持2区域RGN的配置

前言

 位图的生成只是我们字符叠加的基础,具体表现就要靠对区域RGN的配置了

调试记录

 现在距离移植成功osd也有一段时间了,所有所有的报错一时也想不起来太多,当时是在焦头烂额没有记录下全部,但是遇到错误一定要按照logmpp下的错误告警做出修改,再次感谢之前的转变

 这部分的代码是参考手册写的,直接搬来肯定肯定肯定是跑不起来的!

报错1

 HI_MPI_RGN_Create

 出师不利,生成区域就开始报错,这个还是比较直接的根据提示修改画布数量

FunG  irgn_check  base canvas num attr lline1474 LInfoJcanvas numl1E  lrvalic, not gelons 
O2100 Func  :rgnattach to chn [Line]:4294 [Info]:region(1) is unexist!  
region  Func  :rgn set bit ap lline:3403 (Infol:rgn(1) unexist  
3 rogion  FunG  :rgn_checkbaso_carvasnumattr[LineJ:1474[Info]:canvas num(127) invalid, not belong [1, 6]. 
retion. Func  :rgn_attach_to_chn [Line]:4294 [Info]:region(1) is unexist  
rogion  irgn set bit map lLine]:3403 (Info]:rgn(1) unexist! 
region  Func  :rgn_check_base_canvas_num_attr_[Line]:1474[Info]:canvas_num(127) invalid, not belong [1, 6]. 
region  :rgn attach to chn lLine]:4294 [Infol:region(1) is unexist! 
recion  PinC  irgn set bit map lLine]:3403 [Info]:rgn(1) unexist! 
:rgn_checkbasecanvasnumattr[Line]:1474[Info]:canvas_nu(127) invalid, not belong [1, 6].
rekion  Func  :rgnattach to chn lLine]:4294 (Infol:region(1) is unexist!  
egion Func  :rgn set bit map lLine]:3403 [Info]:rrn(1) unexist! 
:rgn_check_base_canas_num_attr[Line]:1474[Info]:canvas_num(127) invalid, not belong [1, 6].
Finc
98107 ren attach to chn lLinel:4294 lInfol:region(1) is unexist!  
2i6n  iren set bit map (Line]:3403 [Info]:rgn(1) unexist! 
Tegi0n  IFunc :rgn_checkbase_canvas_numattr[Line]:1474[Info]:canvas_num(127) invalid, not belong [1, 6].  
Fumc  :rgn attach to_chn [Line]:4294 [Info]:region(1) is unexist! 
region  Func  iren set bit map [Line]:3403 [Info]:ren(i) unexist! 
rogion  Func. :rgncheckbasecanvasnumattr[LineJ:1474 [Info]:canvas_num(127) invalid, not belong [1, 6].  
region! :rgnattach to chn [Line]:4294 [Info]:region(1) is unexist!  
rogion  tnc :rgn set_bit map [Line]:3403 [Info]:rgn(1) unexist! 
region  :rgn_check_base_canvas_numattr[ine]:1474[Info]:canvas_num(127) invalid, not belonHfL_9024 
3Drogion. Func:rgn attach to chnLine]:4294 [Infol:region(1) is unerist!
stRgnAttr.unAttr.stOverlay.u32CanvasNum = 1;

报错2

 HI_MPI_RGN_AttachToChn实际上,创建通道的时候并不会对参数检查,真正的参数检查在这个函数进行

 rgn_check_qp [Line]:1152 [Info]:protect_qp:127 err!

3>[region][Func]:rsn_check_op [Line]:1152 [Info]:protectap:127 enr! an
stChnAttr.unChnAttr.stOverlayChn.stQpInfo.bQpDisable = HI_FALSE;

 看样子关键字就是qp(我当时也不知道qp是啥)(Qp量化参数,反应压缩效果)那就解决qp的部分错误

报错3

stChnAttr.unChnAttr.stOverlayChn.enAttachDest =ATTACH_JPEG_MAIN;

 可写可不写。最开始忘记什么原因导致的HI_MPI_RGN_AttachToChn报了错,当时也是根据log的提示表示dest值不对,提示需要修改此处值。后来不知道为什么删了也没有影响,留作疑问

报错4

 空指针错误

cone of nisroot found in cmdline.# cat /dev/1ogmpp
<3>[region] [Func]:rgn_check_nu11 [Line]:64 [Info]:NULL pointer detectid-1024

这个错误就是没有在设置画布之前生成位图导致的

报错汇总5

 一切都好像设置对了之后还是没有区域叠加怎么办?

 检查编码通道是否正确?位图是否生成正确?宽高XY的值是否都设置正确了?

改进

 此外,关于w和h的值,必须是偶数。但是字库导出的位图不可能每次都刚好,也是在其他博主处看到的字体大小无法调节,调节后参数错误的,非常简单,检查一下手动部位偶数即可。更不能随意设置,有可能会遇到明明水印文件字体是常规,不是倾斜的,但在视频上显示倾斜,更不用说还显示不全。

if (stBitmap.u32Width % 2 != 0)
        {
        stBitmap.u32Width += 1;
        }
    if (stBitmap.u32Height % 2 != 0)
        {
        stBitmap.u32Height += 1;
        }
    printf ("stBitmap.u32Width is %d ,stBitmap.u32Height is %d\n",stBitmap.u32Width,stBitmap.u32Height);
    stRgnAttr.unAttr.stOverlay.stSize.u32Width  = stBitmap.u32Width;//240;        /**区域宽**/
stRgnAttr.unAttr.stOverlay.stSize.u32Height = stBitmap.u32Height;//192;        /**区域高**/

 同样XY的值是需要16的倍数,但是XY的值相对是比较灵活的,我们自己按照心情手动配置就好了

 透明度的解决办法暂时还没有思路,后续补充

代码框架如下

RGN_AddOsdToVenc();
// HI_MPI_VPSS_ReleaseChnFrame(pstPara->VpssGrp,pstPara->VpssChn,&stVideoFrame); while(1)
// sleep(1);
s32Ret=HI_MPI_VPSS_GetChnFrame(pstPara->VpssGrp,pstPara->VpssChn,&stVideoFrame,1000);
s32Ret=HI_MPI_VENC_SendFrame(pstPara->VpssChn, &stvideoFrame,1080);// RGN_AddOsdToVenc()
HI_MPI_VPSS_ReleaseChnFrame(pstPara->VpssGrp,pstPara->VpssChn,&stVideoFrame):
Hx--1024

 区域设置函数RGN_AddOsdToVenc

/* 
 *描述  :用于将视频文件添加时间水印
 *参数  :无
 *返回值:OverlayHandle
 *注意  :参数在HI_MPI_RGN_Create并不做检查,只有在HI_MPI_RGN_AttachToChn的时候才会报出相应的错
 */
HI_S32 RGN_AddOsdToVenc(HI_VOID)
{
    HI_S32 s32Ret;
    RGN_ATTR_S stRgnAttr;
    RGN_CHN_ATTR_S stChnAttr;
    MPP_CHN_S stChn;
    RGN_HANDLE OverlayHandle;
    // RGN_CANVAS_INFO_S stCanvasInfo;
    OverlayHandle =0;
    stChn.enModId  = HI_ID_VENC; /**模块号**///HI_ID_VPSS  HI_ID_VENC
    stChn.s32DevId = 0;          /**设备号**/
    stChn.s32ChnId = 1;          /**通道号**/
    /**创建区域**/
    sleep(2);//等待位图生成
    stRgnAttr.unAttr.stOverlay.u32CanvasNum = 2; 
    stRgnAttr.enType = OVERLAY_RGN;  /**区域类型:叠加**/
    stRgnAttr.unAttr.stOverlay.enPixelFmt       = PIXEL_FORMAT_ARGB_1555; /**像素格式**///PIXEL_FORMAT_BGR_565 PIXEL_FORMAT_ARGB_1555
    if (stBitmap.u32Width % 2 != 0)
        {
        stBitmap.u32Width += 1;
        }
    if (stBitmap.u32Height % 2 != 0)
        {
        stBitmap.u32Height += 1;
        }
    printf ("stBitmap.u32Width is %d ,stBitmap.u32Height is %d\n",stBitmap.u32Width,stBitmap.u32Height);
    stRgnAttr.unAttr.stOverlay.stSize.u32Width  = stBitmap.u32Width;//240;        /**区域宽**/
    stRgnAttr.unAttr.stOverlay.stSize.u32Height = stBitmap.u32Height;//192;        /**区域高**/
    stRgnAttr.unAttr.stOverlay.u32BgColor       = 0xffffff00;//0x00007c00; /**区域背景颜色**/
    s32Ret = HI_MPI_RGN_Create(OverlayHandle, &stRgnAttr);
    if(s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("RGN create failed: %#x\n", s32Ret);
    }
/**将区域叠加到通道**/
        /**设置叠加区域的通道显示属性**/
        stChnAttr.bShow  = HI_TRUE;
        stChnAttr.enType = OVERLAY_RGN;
        stChnAttr.unChnAttr.stOverlayChn.stPoint.s32X = 640;//240;
        stChnAttr.unChnAttr.stOverlayChn.stPoint.s32Y = 320;//192;
        stChnAttr.unChnAttr.stOverlayChn.u32BgAlpha   = 128;
        stChnAttr.unChnAttr.stOverlayChn.u32FgAlpha   = 80;
        stChnAttr.unChnAttr.stOverlayChn.u32Layer     = OverlayHandle;
        /**设置QP属性**/
        stChnAttr.unChnAttr.stOverlayChn.stQpInfo.bAbsQp = HI_FALSE;
        stChnAttr.unChnAttr.stOverlayChn.stQpInfo.s32Qp  = 0;
        stChnAttr.unChnAttr.stOverlayChn.stQpInfo.bQpDisable = HI_FALSE;
        /**定义 OSD 反色相关属性**/
        /**单元反色区域,反色处理的基本单元,[16, 64],需 16 对齐**/
        stChnAttr.unChnAttr.stOverlayChn.stInvertColor.stInvColArea.u32Height = 16;
        stChnAttr.unChnAttr.stOverlayChn.stInvertColor.stInvColArea.u32Width  = 16;
        /**亮度阈值,取值范围:[0, 255]**/
        stChnAttr.unChnAttr.stOverlayChn.stInvertColor.u32LumThresh = 128;//128
        /**OSD 反色触发模式**/
        stChnAttr.unChnAttr.stOverlayChn.stInvertColor.enChgMod     = LESSTHAN_LUM_THRESH;
        /**OSD 反色开关。overlay不支持反色**/
        stChnAttr.unChnAttr.stOverlayChn.stInvertColor.bInvColEn    = HI_FALSE;
        stChnAttr.unChnAttr.stOverlayChn.enAttachDest =ATTACH_JPEG_MAIN;
        OverlayHandle =0;
        s32Ret = HI_MPI_RGN_AttachToChn(OverlayHandle, &stChn, &stChnAttr);
        if(s32Ret != HI_SUCCESS)
        {
             SAMPLE_PRT("HI_MPI_RGN_AttachToChn: %#x\n", s32Ret);
        }       
        stBitmap.enPixelFormat = PIXEL_FORMAT_ARGB_1555;
        // stBitmap.u32Height = OVERLAY_H;
        // stBitmap.u32Width = OVERLAY_W;
        s32Ret = HI_MPI_RGN_SetBitMap(OverlayHandle,&stBitmap);
        if(s32Ret != HI_SUCCESS)
        {
            SAMPLE_PRT("HI_MPI_RGN_SetBitMap failed with %#x!\n", s32Ret);
        }
        memset(stBitmap.pData, 0, sizeof(BITMAP_S));
        // s32Ret = HI_MPI_RGN_GetCanvasInfo(OverlayHandle,&stCanvasInfo);
        // s32Ret = HI_MPI_RGN_DetachFromChn(OverlayHandle, &stChn);//最后用户可以将该区域从通道中撤出(非必须操作),再销毁区域。
        // if(s32Ret != HI_SUCCESS)
        // {
        //      SAMPLE_PRT("HI_MPI_RGN_DetachFromChn: %#x\n", s32Ret);
        // }  
        // s32Ret = HI_MPI_RGN_Destroy(OverlayHandle);
        // if(s32Ret != HI_SUCCESS)
        // {
        //     SAMPLE_PRT("RGN create failed: %#x\n", s32Ret);
        // }
    return 0;
}

实时更新

开个线程每秒更新画布


/* 
 *描述  :用于osd 字体bmp图像生成
 *参数  :NULL
 *返回值:无
 *注意  :需要加载字体ttf才能使用,否则会报段错误
 */
HI_VOID *bitmap_update(HI_VOID*arg)
{
    RGN_HANDLE OverlayHandle = 0;
    HI_S32 s32Ret;
    // time_t now;
    // struct tm *ptm;
    // char timestr[OSD_LENGTH] = {0};
    while(1)
    {
        sleep(1);
        HI_MPI_RGN_UpdateCanvas(0);
        s32Ret = HI_MPI_RGN_SetBitMap(OverlayHandle,&stBitmap);//s32Ret 为RGN_HANDLE OverlayHandle
        if(s32Ret != HI_SUCCESS)
        {
            SAMPLE_PRT("HI_MPI_RGN_SetBitMap failed with %#x!\n", s32Ret);
        }
       memset(stBitmap.pData, 0, sizeof(BITMAP_S));
    }
    return 0;
}

每秒生成新的位图

画布结构体BITMAP_S设置成全局的,方便更新


/* 
 *描述  :用于将想填写的内容生成位图 用于pthread osd_create_task
 *参数  :pu8Str u8指针,传字符串
 *返回值:成功返回0
 *注意  :无
 */
HI_S32 string_to_bmp(char *pu8Str)
{
    SDL_PixelFormat *fmt;
    TTF_Font *font;  
    SDL_Surface *text, *temp;  
    if (TTF_Init() < 0 ) 
    {  
        fprintf(stderr, "Couldn't initialize TTF: %s\n",SDL_GetError());  
        SDL_Quit();
    }  
    font = TTF_OpenFont(FONT_PATH, 45); 
    if ( font == NULL ) 
    {  
        fprintf(stderr, "Couldn't load %d pt font from %s: %s\n",18,"ptsize", SDL_GetError());  
    }  
    SDL_Color forecol = { 0xff, 0xff, 0xff, 0xff };  
    text = TTF_RenderUTF8_Solid(font, pu8Str, forecol);
    fmt = (SDL_PixelFormat*)malloc(sizeof(SDL_PixelFormat));
    memset(fmt,0,sizeof(SDL_PixelFormat));
    fmt->BitsPerPixel = 16;
    fmt->BytesPerPixel = 2;
    fmt->colorkey = 0xffffffff;
    fmt->alpha = 0xff;
    temp = SDL_ConvertSurface(text,fmt,0);
    // SDL_Surface *osd_test = SDL_ConvertSurface(text, fmt, 0);
    // printf ("w is %d ,h is %d\n",temp->w,temp->h);
    stBitmap.pData = malloc(2*(temp->w)*(temp->h));
    if(stBitmap.pData == NULL)
    {
    printf("stBitmap.pData faided\r\n");
    }
    memset(stBitmap.pData, 0, sizeof(BITMAP_S));
   memcpy(stBitmap.pData, temp->pixels, (2*(temp->w)*(temp->h)));
    stBitmap.u32Width = temp->w;
    stBitmap.u32Height = temp->h;
    char savename[20] = {0};
    snprintf(savename,20,"./osd/now_time.bmp");
    // printf("savename = %s\n",savename);
    SDL_SaveBMP(temp, savename); 
    free(fmt);
    //  memset(stBitmap.pData, 0, sizeof(BITMAP_S));
    SDL_FreeSurface(text);  
    SDL_FreeSurface(temp);
    TTF_CloseFont(font);  
    TTF_Quit();  
    return 0;
}
/* 
 *描述  :用于osd 字体bmp图像生成
 *参数  :NULL
 *返回值:无
 *注意  :需要加载字体ttf才能使用,否则会报段错误
 */
HI_VOID *osd_ttf_task(HI_VOID*arg)
{
    RGN_HANDLE OverlayHandle = 0;
    HI_S32 s32Ret;
    time_t now;
    struct tm *ptm;
    char timestr[OSD_LENGTH] = {0};
    while(1)
    {
        usleep(1000000);
        time(&now);
        ptm = localtime(&now);
        snprintf(timestr,100,"时间:%d-%02d-%02d %02d:%02d:%02d",ptm->tm_year+1900,ptm->tm_mon+1,ptm->tm_mday,ptm->tm_hour,ptm->tm_min,ptm->tm_sec); 
        string_to_bmp(timestr);
        HI_MPI_RGN_UpdateCanvas(OverlayHandle);
        s32Ret = HI_MPI_RGN_SetBitMap(OverlayHandle,&stBitmap);//s32Ret 为RGN_HANDLE OverlayHandle
        if(s32Ret != HI_SUCCESS)
        {
            SAMPLE_PRT("HI_MPI_RGN_SetBitMap failed with %#x!\n", s32Ret);
        }
          memset(stBitmap.pData, 0, sizeof(BITMAP_S));
        memset(timestr,0,OSD_LENGTH);
    }
    return 0;
}

结果

2860377ee4524faf9d82d49d3667da69.png



相关文章
|
传感器 机器学习/深度学习 算法
能抓取玻璃碎片、水下透明物,清华提出通用型透明物体抓取框架,成功率极高
能抓取玻璃碎片、水下透明物,清华提出通用型透明物体抓取框架,成功率极高
143 0
|
Android开发 开发者
Android平台GB28181设备接入模块之球机/云台控制探究
好多开发者在做GB28181设备接入的时候,问云台控制是否可以处理(亦或拉取外部RTSP摄像头,通过命令中转的方式,控制摄像头),实际上云台控制命令相对来说还是比较好处理的。协议规范有明确说明,云台控制命令不需要发送应答命令,实现相对简单,和我们之前做的远程启动命令(TeleBoot)类似。
158 0
|
前端开发 定位技术 Android开发
Android平台GB28181设备接入端如何实时更新经纬度实现国标平台侧电子地图位置标注
我们在做GB28181设备接入端的时候,其中有个功能,不难但非常重要:那就是GB28181实时位置的订阅(mobileposition subscribe)和上报(notify)。
170 0
|
存储 数据库
PACS系统源码,自主研发,3D重建、三维虚拟内窥镜、心脏动脉钙化分析
RIS/PACS系统源码是按照DICOM3.0和HL7标准,遵循IHE标准工作流程, 100%自主知识产权,以医疗影像的采集、传输、存储和诊断为核心,集流程质控、患者信息管理应用和患者关注服务于一体的,覆盖放射、超声、窥镜和病理等科室的CS架构的综合应用系统。集成三维影像后处理功能,包括三维多平面重建、三维容积重建、三维表面重建、三维虚拟内窥镜、最大/小密度投影、心脏动脉钙化分析等功能。系统功能强大,代码完整。
153 0
PACS系统源码,自主研发,3D重建、三维虚拟内窥镜、心脏动脉钙化分析
|
机器学习/深度学习 存储 固态存储
ARM-CPU150FPS | PicoDet助力移动端达到超实时检测(强烈建议工程人员学习)(一)
ARM-CPU150FPS | PicoDet助力移动端达到超实时检测(强烈建议工程人员学习)(一)
173 0
|
数据可视化
ARM-CPU150FPS | PicoDet助力移动端达到超实时检测(强烈建议工程人员学习)(二)
ARM-CPU150FPS | PicoDet助力移动端达到超实时检测(强烈建议工程人员学习)(二)
75 0