Hi3559 MPP学习记录(3)

文章介绍了VGS(VideoGraphicsSub-System)模块的功能,包括画线、覆盖(COVER)以及OSD(On-ScreenDisplay)的叠加位图操作。VGS用于处理视频帧,支持缩放、格式转换、压缩/解压等。在示例代码中,展示了如何使用VGS进行画线和添加覆盖位图,并通过区域管理实现OSD的叠加。文章最后提到,相比VGS,使用区域管理来打OSD更加简便。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文章目录

  • VGS
  • REGION 模块
  • 一、画线、打COVER(VGS实现)
  • 二、打OSD(区域管理实现叠加位图)
  • 总结


VGS

VGS 是视频图形子系统,全称为 Video Graphics Sub-System。支持对一幅输入图像进 行处理,如进行缩放、像素格式转换、视频存储格式转换、压缩/解压、打 COVER、 打 OSD、画线、旋转、动态范围转换等处理

REGION 模块

用户一般都需要在视频中叠加 OSD 用于显示一些特定的信息(如:通道号、时间戳 等),必要时还会填充色块。这些叠加在视频上的 OSD 和遮挡在视频上的色块统称为 区域。REGION 模块,用于统一管理这些区域资源


一、画线、打COVER(VGS实现)

代码实例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/prctl.h>
#include <fcntl.h>
#include <sys/ioctl.h>

#include "sample_comm.h"
#include "loadbmp.h"

pthread_t VgsThreadId;
HI_BOOL bVgsThreadExit = HI_FALSE;
HI_CHAR* PICTURE_NAME = "keys.bmp";

/******************************************************************************
* function : show usage
******************************************************************************/
HI_VOID SAMPLE_VGS_VoInterface_Usage(HI_VOID)
{
    printf("intf:\n");
    printf("\t 0) vo HDMI output, default.\n");
    printf("\t 1) vo BT1120 output.\n");
}

void SAMPLE_VGS_Usage(char* sPrgNm)
{
    printf("Usage : %s <index> <intf>\n", sPrgNm);
    printf("index:\n");
    printf("\t 0) SDR10 COMPRESS, VI - VGS - VO - HDMI. \n");

    printf("intf:\n");
    printf("\t 0) vo HDMI output, default.\n");
    printf("\t 1) vo BT1120 output.\n");
    return;
}

/******************************************************************************
* function : to process abnormal case
******************************************************************************/
void SAMPLE_VGS_HandleSig(HI_S32 signo)
{
    if (SIGINT == signo || SIGTERM == signo)
    {
        SAMPLE_COMM_All_ISP_Stop();
        SAMPLE_COMM_SYS_Exit();
        printf("\033[0;31mprogram termination abnormally!\033[0;39m\n");
    }
    exit(-1);
}

HI_VOID SAMPLE_VGS_GetYUVBufferCfg(SAMPLE_VB_BASE_INFO_S* pstBaseInfo, SAMPLE_VB_CAL_CONFIG_S* pstCalConfig)
{
    HI_U32 u32Width       = 0;
    HI_U32 u32Height      = 0;
    HI_U32 u32TailInBytes = 0;
    HI_U32 u32BitWidth    = 0;
    HI_U32 u32HeadStride  = 0;
    HI_U32 u32VBSize      = 0;
    HI_U32 u32HeadSize    = 0;
    HI_U32 u32AlignHeight = 0;
    HI_U32 u32MainStride  = 0;
    HI_U32 u32MainSize    = 0;
    HI_U32 u32ExtStride   = 0;
    HI_U32 u32ExtSize     = 0;
    HI_U32 u32ExtYSize    = 0;
    HI_U32 u32HeadYSize   = 0;
    HI_U32 u32YSize       = 0;
    HI_U32 u32Align       = 0;

    u32Align = pstBaseInfo->u32Align;

    if(0 == u32Align)
    {
        u32Align = DEFAULT_ALIGN;
    }
    else if(u32Align > MAX_ALIGN)
    {
        u32Align = MAX_ALIGN;
    }
    else
    {
        u32Align = (ALIGN_UP(u32Align, DEFAULT_ALIGN));
    }

    u32Width  = pstBaseInfo->u32Width;
    u32Height = pstBaseInfo->u32Height;

    u32AlignHeight = ALIGN_UP(u32Height, 2);

    if (DYNAMIC_RANGE_SDR8 == pstBaseInfo->enDynamicRange)
    {
        u32BitWidth = 8;
    }
    else
    {
        if(VIDEO_FORMAT_LINEAR_DISCRETE == pstBaseInfo->enVideoFormat)
        {
            u32BitWidth = 16;
        }
        else
        {
            u32BitWidth = 10;
        }
    }

    if (COMPRESS_MODE_NONE == pstBaseInfo->enCompressMode)
    {
        u32MainStride = ALIGN_UP((u32Width * u32BitWidth + 7) >> 3, u32Align);
        u32YSize = u32MainStride * u32AlignHeight;

        if(PIXEL_FORMAT_YVU_SEMIPLANAR_420 == pstBaseInfo->enPixelFormat)
        {
            u32MainSize = (u32MainStride * u32AlignHeight)*3 >> 1;
        }
        else if (PIXEL_FORMAT_YVU_SEMIPLANAR_422 == pstBaseInfo->enPixelFormat)
        {
            u32MainSize = u32MainStride * u32AlignHeight * 2;
        }
        else if (PIXEL_FORMAT_YUV_400 == pstBaseInfo->enPixelFormat)
        {
            u32MainSize = u32MainStride * u32AlignHeight;
        }
        else
        {
            u32MainSize = u32MainStride * u32AlignHeight * 3;
        }

        u32VBSize   = u32MainSize;
    }
    else
    {
        if (u32Width <= 4096)
        {
            u32HeadStride = 16;
        }
        else if (u32Width <= 8192)
        {
            u32HeadStride = 32;
        }
        else
        {
            u32HeadStride = 64;
        }
        u32HeadStride = (u32Align == DEFAULT_ALIGN) ? u32HeadStride : (ALIGN_UP(u32HeadStride, u32Align));

        if (u32BitWidth == 8)
        {
            u32MainStride  = ALIGN_UP(u32Width, u32Align);
            u32HeadYSize   = u32HeadStride * u32AlignHeight;
            u32YSize       = u32MainStride * u32AlignHeight;

            if(PIXEL_FORMAT_YVU_SEMIPLANAR_420 == pstBaseInfo->enPixelFormat)
            {
                u32HeadSize = (u32HeadStride * u32AlignHeight * 3) >> 1;
                u32MainSize = (u32MainStride * u32AlignHeight * 3) >> 1;
            }
            else if (PIXEL_FORMAT_YVU_SEMIPLANAR_422 == pstBaseInfo->enPixelFormat)
            {
                u32HeadSize = u32HeadStride * u32AlignHeight * 2;
                u32MainSize = u32MainStride * u32AlignHeight * 2;
            }
            else if (PIXEL_FORMAT_YUV_400 == pstBaseInfo->enPixelFormat)
            {
                u32HeadSize = u32HeadStride * u32AlignHeight;
                u32MainSize = u32MainStride * u32AlignHeight;
            }
            else
            {
                u32HeadSize = u32HeadStride * u32AlignHeight * 3;
                u32MainSize = u32MainStride * u32AlignHeight * 3;
            }
        }
        else if (u32BitWidth == 10)
        {
            u32TailInBytes = DIV_UP(u32Width%SEG_CMP_LENGTH*u32BitWidth, 8);
            u32MainStride  = ALIGN_DOWN(u32Width, SEG_CMP_LENGTH) + ((u32TailInBytes > SEG_CMP_LENGTH) ? SEG_CMP_LENGTH : u32TailInBytes);
            u32MainStride  = ALIGN_UP(u32MainStride, u32Align);
            u32ExtStride   = (u32TailInBytes > SEG_CMP_LENGTH) ? (ALIGN_UP(DIV_UP(u32Width,4), u32Align)) :\
                             ALIGN_UP((ALIGN_DOWN(u32Width, SEG_CMP_LENGTH)/4), u32Align);

            u32HeadYSize  = u32HeadStride * u32AlignHeight;
            u32YSize      = u32MainStride * u32AlignHeight;
            u32ExtYSize   = u32ExtStride * u32AlignHeight;

            if(PIXEL_FORMAT_YVU_SEMIPLANAR_420 == pstBaseInfo->enPixelFormat)
            {
                u32HeadSize = (u32HeadStride * u32AlignHeight * 3) >> 1;
                u32MainSize = (u32MainStride * u32AlignHeight * 3) >> 1;
                u32ExtSize  = (u32ExtStride * u32AlignHeight * 3) >> 1;
            }
            else if (PIXEL_FORMAT_YVU_SEMIPLANAR_422 == pstBaseInfo->enPixelFormat)
            {
                u32HeadSize = u32HeadStride * u32AlignHeight * 2;
                u32MainSize = u32MainStride * u32AlignHeight * 2;
                u32ExtSize  = u32ExtStride * u32AlignHeight * 2;
            }
            else if (PIXEL_FORMAT_YUV_400 == pstBaseInfo->enPixelFormat)
            {
                u32HeadSize = u32HeadStride * u32AlignHeight;
                u32MainSize = u32MainStride * u32AlignHeight;
                u32ExtSize  = u32ExtStride * u32AlignHeight;
            }
            else
            {
                u32HeadSize = u32HeadStride * u32AlignHeight * 3;
                u32MainSize = u32MainStride * u32AlignHeight * 3;
                u32ExtSize  = u32ExtStride * u32AlignHeight * 3;
            }

        }
        else
        {
            u32VBSize     = 0;
            u32HeadYSize  = 0;
            u32HeadSize   = 0;
            u32HeadStride = 0;
            u32MainStride = 0;
            u32YSize      = 0;
            u32MainSize   = 0;
            u32ExtStride  = 0;
            u32ExtYSize   = 0;
        }

        u32VBSize = u32HeadSize + u32MainSize + u32ExtSize;
    }

    pstCalConfig->u32VBSize     = u32VBSize;
    pstCalConfig->u32HeadYSize  = u32HeadYSize;
    pstCalConfig->u32HeadSize   = u32HeadSize;
    pstCalConfig->u32HeadStride = u32HeadStride;
    pstCalConfig->u32MainStride = u32MainStride;
    pstCalConfig->u32MainYSize  = u32YSize;
    pstCalConfig->u32MainSize   = u32MainSize;
    pstCalConfig->u32ExtStride  = u32ExtStride;
    pstCalConfig->u32ExtYSize   = u32ExtYSize;

    return;
}


typedef struct hiSAMPLE_VGS_MOD_INFO_S
{
    VI_PIPE               ViPipe;
    VI_CHN                ViChn;
    VO_DEV                VoDev;
    VO_CHN                VoChn;
}SAMPLE_VGS_MOD_INFO_S;


static HI_VOID *SAMPLE_VGS_Get_Frame_Thread(HI_VOID *arg)
{
    SAMPLE_VGS_MOD_INFO_S *pstVgsModInfo = (SAMPLE_VGS_MOD_INFO_S *)arg;

    VI_PIPE                ViPipe = pstVgsModInfo->ViPipe;
    VI_CHN                 ViChn  = pstVgsModInfo->ViChn;
    VO_DEV                 VoDev  = pstVgsModInfo->VoDev;
    VO_CHN                 VoChn  = pstVgsModInfo->VoChn;

    VGS_HANDLE             hHandle;
    HI_U32                 u32OutWidth          = 1920;
    HI_U32                 u32OutHeight       = 1080;
    VGS_TASK_ATTR_S stTask;
    VGS_DRAW_LINE_S stVgsDrawLine;
    VGS_ADD_COVER_S stVgsAddCover;

    SAMPLE_VB_BASE_INFO_S  stVBBaseInfo;
    SAMPLE_VB_CAL_CONFIG_S stVBCalConfig;
    VB_BLK                 VbHandle = 0;

    HI_S32                 s32Ret = HI_FAILURE;

    HI_S32                 s32MilliSec        = -1;
    HI_U32                 u32OldDepth        = 2;
    HI_U32                 u32Depth           = 2;
    VI_CHN_ATTR_S          stChnAttr;
    HI_CHAR                acThreadName[15]   = {0};

    snprintf(acThreadName,sizeof(acThreadName),"VgsGetFrame");
    prctl(PR_SET_NAME,(unsigned long)acThreadName);

    SAMPLE_PRT("SAMPLE_VGS_Get_Frame_Thread working!\n");

    /************************************************
    Set depth
    *************************************************/
    s32Ret = HI_MPI_VI_GetChnAttr(ViPipe,ViChn,&stChnAttr);

    if(HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("HI_MPI_VI_GetChnAttr failed, s32Ret:0x%x\n",s32Ret);
        goto EXIT;
    }

    u32OldDepth         = stChnAttr.u32Depth;
    stChnAttr.u32Depth  = u32Depth;

    s32Ret = HI_MPI_VI_SetChnAttr(ViPipe,ViChn,&stChnAttr);

    if(HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("HI_MPI_VI_SetChnAttr failed, s32Ret:0x%x\n",s32Ret);
        goto EXIT;
    }

    while(HI_FALSE == bVgsThreadExit)
    {
        /************************************************
        Get VI chn frame
        *************************************************/
        s32Ret = HI_MPI_VI_GetChnFrame(ViPipe, ViChn, &stTask.stImgIn, s32MilliSec);

        if(HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("HI_MPI_VI_GetChnFrame failed, s32Ret:0x%x\n",s32Ret);
            goto EXIT;
        }

        /************************************************
        Create VGS job
        *************************************************/
        stVBBaseInfo.b3DNRBuffer    = HI_FALSE;
        stVBBaseInfo.u32Align        = 32;
        stVBBaseInfo.enCompressMode = COMPRESS_MODE_SEG;
        stVBBaseInfo.enDynamicRange = DYNAMIC_RANGE_SDR10;
        stVBBaseInfo.enPixelFormat  = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
        stVBBaseInfo.enVideoFormat  = VIDEO_FORMAT_LINEAR;
        stVBBaseInfo.u32Width       = u32OutWidth;
        stVBBaseInfo.u32Height      = u32OutHeight;

        SAMPLE_VGS_GetYUVBufferCfg(&stVBBaseInfo, &stVBCalConfig);

        VbHandle = HI_MPI_VB_GetBlock(VB_INVALID_POOLID, stVBCalConfig.u32VBSize, HI_NULL);

        if (VB_INVALID_HANDLE == VbHandle)
        {
            SAMPLE_PRT("HI_MPI_VB_GetBlock failed!\n");
            goto EXIT;
        }

        stTask.stImgOut.u32PoolId                     = HI_MPI_VB_Handle2PoolId(VbHandle);
        stTask.stImgOut.enModId                      = HI_ID_VGS;
        stTask.stImgOut.stVFrame.u32Width             = stVBBaseInfo.u32Width;
        stTask.stImgOut.stVFrame.u32Height             = stVBBaseInfo.u32Height;
        stTask.stImgOut.stVFrame.enDynamicRange      = stVBBaseInfo.enDynamicRange;
        stTask.stImgOut.stVFrame.enCompressMode      = stVBBaseInfo.enCompressMode;;
        stTask.stImgOut.stVFrame.enPixelFormat         = stVBBaseInfo.enPixelFormat;
        stTask.stImgOut.stVFrame.enVideoFormat         = stVBBaseInfo.enVideoFormat;
        stTask.stImgOut.stVFrame.enField             = VIDEO_FIELD_FRAME;
        stTask.stImgOut.stVFrame.enColorGamut         = COLOR_GAMUT_BT709;
        stTask.stImgOut.stVFrame.u32MaxLuminance     = 1200;
        stTask.stImgOut.stVFrame.u32MinLuminance     = 200;

        stTask.stImgOut.stVFrame.u64HeaderPhyAddr[0] = HI_MPI_VB_Handle2PhysAddr(VbHandle);
        stTask.stImgOut.stVFrame.u64HeaderPhyAddr[1] = stTask.stImgOut.stVFrame.u64HeaderPhyAddr[0] + stVBCalConfig.u32HeadYSize;
        stTask.stImgOut.stVFrame.u64HeaderPhyAddr[2] = stTask.stImgOut.stVFrame.u64HeaderPhyAddr[1];
        stTask.stImgOut.stVFrame.u64HeaderVirAddr[0] = (HI_U64)HI_MPI_SYS_Mmap(stTask.stImgOut.stVFrame.u64HeaderPhyAddr[0], stVBCalConfig.u32VBSize);
        stTask.stImgOut.stVFrame.u64HeaderVirAddr[1] = stTask.stImgOut.stVFrame.u64HeaderVirAddr[0] + stVBCalConfig.u32HeadYSize;
        stTask.stImgOut.stVFrame.u64HeaderVirAddr[2] = stTask.stImgOut.stVFrame.u64HeaderVirAddr[1];
        stTask.stImgOut.stVFrame.u32HeaderStride[0]  = stVBCalConfig.u32HeadStride;
        stTask.stImgOut.stVFrame.u32HeaderStride[1]  = stVBCalConfig.u32HeadStride;
        stTask.stImgOut.stVFrame.u32HeaderStride[2]  = stVBCalConfig.u32HeadStride;

        stTask.stImgOut.stVFrame.u64PhyAddr[0]         = stTask.stImgOut.stVFrame.u64HeaderPhyAddr[0] + stVBCalConfig.u32HeadSize;
        stTask.stImgOut.stVFrame.u64PhyAddr[1]         = stTask.stImgOut.stVFrame.u64PhyAddr[0] + stVBCalConfig.u32MainYSize;
        stTask.stImgOut.stVFrame.u64PhyAddr[2]         = stTask.stImgOut.stVFrame.u64PhyAddr[1];
        stTask.stImgOut.stVFrame.u64VirAddr[0]         = stTask.stImgOut.stVFrame.u64HeaderVirAddr[0] + stVBCalConfig.u32HeadSize;
        stTask.stImgOut.stVFrame.u64VirAddr[1]         = stTask.stImgOut.stVFrame.u64VirAddr[0] + stVBCalConfig.u32MainYSize;
        stTask.stImgOut.stVFrame.u64VirAddr[2]         = stTask.stImgOut.stVFrame.u64VirAddr[1];
        stTask.stImgOut.stVFrame.u32Stride[0]         = stVBCalConfig.u32MainStride;
        stTask.stImgOut.stVFrame.u32Stride[1]         = stVBCalConfig.u32MainStride;
        stTask.stImgOut.stVFrame.u32Stride[2]         = stVBCalConfig.u32MainStride;

        stTask.stImgOut.stVFrame.u64ExtPhyAddr[0]    = stTask.stImgOut.stVFrame.u64PhyAddr[0] + stVBCalConfig.u32MainSize;
        stTask.stImgOut.stVFrame.u64ExtPhyAddr[1]    = stTask.stImgOut.stVFrame.u64ExtPhyAddr[0] + stVBCalConfig.u32ExtYSize;
        stTask.stImgOut.stVFrame.u64ExtPhyAddr[2]    = stTask.stImgOut.stVFrame.u64ExtPhyAddr[1];
        stTask.stImgOut.stVFrame.u64ExtVirAddr[0]    = stTask.stImgOut.stVFrame.u64VirAddr[0] + stVBCalConfig.u32MainSize;
        stTask.stImgOut.stVFrame.u64ExtVirAddr[1]    = stTask.stImgOut.stVFrame.u64ExtVirAddr[0] + stVBCalConfig.u32ExtYSize;
        stTask.stImgOut.stVFrame.u64ExtVirAddr[2]    = stTask.stImgOut.stVFrame.u64ExtVirAddr[1];
        stTask.stImgOut.stVFrame.u32ExtStride[0]     = stVBCalConfig.u32ExtStride;
        stTask.stImgOut.stVFrame.u32ExtStride[1]     = stVBCalConfig.u32ExtStride;
        stTask.stImgOut.stVFrame.u32ExtStride[2]     = stVBCalConfig.u32ExtStride;

        stVgsDrawLine.stStartPoint.s32X = 2;
        stVgsDrawLine.stStartPoint.s32Y = 2;
        stVgsDrawLine.stEndPoint.s32X = 1024;
        stVgsDrawLine.stEndPoint.s32Y = 1024;
        stVgsDrawLine.u32Thick = 4;
        stVgsDrawLine.u32Color = 0xFFFFFF;

        stVgsAddCover.enCoverType = COVER_RECT;  //矩形COVER
        stVgsAddCover.stDstRect.s32X = 1024;
        stVgsAddCover.stDstRect.s32Y = 1024;
        stVgsAddCover.stDstRect.u32Width = 512;
        stVgsAddCover.stDstRect.u32Height = 512;
        stVgsAddCover.u32Color = 0xFFFFFF;

        /*****
         * 下面是很关键的一段代码
         * HI_MPI_VGS_AddDrawLineTask、
         * HI_MPI_VGS_AddCoverTask、
         * HI_MPI_VGS_AddOsdTask
         * 需要输入输出图像使用同一块buffer
        */
        memcpy(&stTask.stImgOut, &stTask.stImgIn, sizeof(VIDEO_FRAME_INFO_S));

        s32Ret = HI_MPI_VGS_BeginJob(&hHandle);
        if(HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("HI_MPI_VI_GetChnFrame failed, s32Ret:0x%x\n",s32Ret);
            goto EXIT2;
        }

        s32Ret = HI_MPI_VGS_AddDrawLineTask(hHandle, &stTask, &stVgsDrawLine);
        if(HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("HI_MPI_VGS_AddDrawLineTask failed, s32Ret:0x%x\n",s32Ret);
            goto EXIT2;
        }

        s32Ret = HI_MPI_VGS_AddCoverTask(hHandle, &stTask, &stVgsAddCover);
        if(HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("HI_MPI_VGS_AddCoverTask failed, s32Ret:0x%x\n",s32Ret);
            goto EXIT2;
        }

        s32Ret = HI_MPI_VGS_EndJob(hHandle);
        if(HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("HI_MPI_VGS_EndJob failed, s32Ret:0x%x\n",s32Ret);
            goto EXIT2;
        }
        /************************************************
        Send frame to VO
        *************************************************/
        s32Ret = HI_MPI_VO_SendFrame(VoDev, VoChn, &stTask.stImgOut, s32MilliSec);

        if(HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("HI_MPI_VO_SendFrame failed, s32Ret:0x%x\n",s32Ret);
            goto EXIT2;
        }

        usleep(30000);

        /************************************************
        Munmap
        *************************************************/
        s32Ret = HI_MPI_SYS_Munmap((HI_VOID*)stTask.stImgOut.stVFrame.u64HeaderVirAddr[0],stVBCalConfig.u32VBSize);

        if(HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("HI_MPI_SYS_Munmap failed, s32Ret:0x%x\n",s32Ret);
            goto EXIT1;
        }

        /************************************************
        Release frame
        *************************************************/
        s32Ret = HI_MPI_VI_ReleaseChnFrame(ViPipe,ViChn,&stTask.stImgIn);

        if(HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("HI_MPI_VI_ReleaseChnFrame failed, s32Ret:0x%x\n",s32Ret);
            goto EXIT1;
        }

        /************************************************
        Release VB
        *************************************************/
        s32Ret = HI_MPI_VB_ReleaseBlock(VbHandle);

        if(HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("HI_MPI_VB_ReleaseBlock failed, s32Ret:0x%x\n",s32Ret);
            goto EXIT;
        }
    }

    /************************************************
    Set depth
    *************************************************/
    stChnAttr.u32Depth = u32OldDepth;
    s32Ret = HI_MPI_VI_SetChnAttr(ViPipe,ViChn,&stChnAttr);
    if(HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("HI_MPI_VI_SetChnAttr failed, s32Ret:0x%x\n",s32Ret);
        return HI_NULL;
    }

EXIT2:
    HI_MPI_SYS_Munmap((HI_VOID*)stTask.stImgOut.stVFrame.u64HeaderVirAddr[0],stVBCalConfig.u32VBSize);
EXIT1:
    HI_MPI_VB_ReleaseBlock(VbHandle);
EXIT:
    return HI_NULL;
}


HI_S32 SAMPLE_VGS_SDR10_COMPRESS(VO_INTF_TYPE_E enVoIntfType)
{
    SAMPLE_VGS_MOD_INFO_S stVgsModInfo;

    HI_S32                s32WorkSnsId         = 0;
    combo_dev_t           ComboDev;
    SAMPLE_VI_CONFIG_S       stViConfig;

    SAMPLE_VO_CONFIG_S       stVoConfig;

    PIC_SIZE_E               enPicSize            = PIC_3840x2160;
    SIZE_S                stSize;
    HI_U32                u32BlkSize;
    VB_CONFIG_S              stVbConf;

    HI_S32                  s32Ret;

    VI_DEV                   ViDev = 0;
    VI_PIPE                  ViPipe;
    VI_CHN                   ViChn;

    stVgsModInfo.ViPipe = 0;
    stVgsModInfo.ViChn  = 0;
    stVgsModInfo.VoDev  = SAMPLE_VO_DEV_DHD0;
    stVgsModInfo.VoChn  = 0;

    ViPipe = stVgsModInfo.ViPipe;
    ViChn  = stVgsModInfo.ViChn;

    /************************************************
    step1:  Get all sensors information
    *************************************************/
    SAMPLE_COMM_VI_GetSensorInfo(&stViConfig);
    ComboDev = SAMPLE_COMM_VI_GetComboDevBySensor(stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType, s32WorkSnsId);

    stViConfig.s32WorkingViNum    = 1;
    stViConfig.as32WorkingViId[0] = 0;

    stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.MipiDev         = ComboDev;
    stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.s32BusId        = 0;

    stViConfig.astViInfo[s32WorkSnsId].stDevInfo.ViDev           = ViDev;
    stViConfig.astViInfo[s32WorkSnsId].stDevInfo.enWDRMode       = WDR_MODE_NONE;

    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.enMastPipeMode = VI_OFFLINE_VPSS_OFFLINE;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[0]       = ViPipe;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[1]       = -1;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[2]       = -1;
    stViConfig.astViInfo[s32WorkSnsId].stPipeInfo.aPipe[3]       = -1;

    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.ViChn           = ViChn;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enPixFormat     = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enDynamicRange  = DYNAMIC_RANGE_SDR10;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enVideoFormat   = VIDEO_FORMAT_LINEAR;
    stViConfig.astViInfo[s32WorkSnsId].stChnInfo.enCompressMode  = COMPRESS_MODE_SEG;

    /************************************************
    step2:  Get input size
    *************************************************/
    s32Ret = SAMPLE_COMM_VI_GetSizeBySensor(stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType, &enPicSize);

    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("SAMPLE_COMM_VI_GetSizeBySensor failed, s32Ret:0x%x\n",s32Ret);
        goto EXIT;
    }

    s32Ret = SAMPLE_COMM_SYS_GetPicSize(enPicSize, &stSize);

    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("SAMPLE_COMM_SYS_GetPicSize failed, s32Ret:0x%x\n",s32Ret);
        goto EXIT;
    }

    /************************************************
    step3:  Init SYS and common VB
    *************************************************/
    memset(&stVbConf, 0, sizeof(VB_CONFIG_S));
    stVbConf.u32MaxPoolCnt              = 2;

    u32BlkSize = COMMON_GetPicBufferSize(stSize.u32Width, stSize.u32Height, SAMPLE_PIXEL_FORMAT, DATA_BITWIDTH_10, COMPRESS_MODE_LINE, DEFAULT_ALIGN);
    stVbConf.astCommPool[0].u64BlkSize  = u32BlkSize;
    stVbConf.astCommPool[0].u32BlkCnt   = 10;

    u32BlkSize = VI_GetRawBufferSize(stSize.u32Width, stSize.u32Height, PIXEL_FORMAT_RGB_BAYER_16BPP, COMPRESS_MODE_NONE, DEFAULT_ALIGN);
    stVbConf.astCommPool[1].u64BlkSize  = u32BlkSize;
    stVbConf.astCommPool[1].u32BlkCnt   = 10;

    s32Ret = SAMPLE_COMM_SYS_Init(&stVbConf);

    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("SAMPLE_COMM_SYS_Init failed, s32Ret:0x%x\n",s32Ret);
        goto EXIT;
    }

    s32Ret = SAMPLE_COMM_VI_SetParam(&stViConfig);

    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("SAMPLE_COMM_VI_SetParam failed, s32Ret:0x%x\n",s32Ret);
        goto EXIT;
    }

     /************************************************
    step 4: start VI
    *************************************************/
    s32Ret = SAMPLE_COMM_VI_StartVi(&stViConfig);

    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("SAMPLE_COMM_VI_StartVi failed, s32Ret:0x%x\n", s32Ret);
        goto EXIT;
    }

    /************************************************
    step4:  Start VO
    *************************************************/
    SAMPLE_COMM_VO_GetDefConfig(&stVoConfig);

    stVoConfig.enDstDynamicRange = DYNAMIC_RANGE_SDR10;

    s32Ret = SAMPLE_COMM_VO_StartVO(&stVoConfig);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("SAMPLE_COMM_VO_StartVO failed, s32Ret:0x%x\n", s32Ret);
        goto EXIT1;
    }

    /************************************************
    step6:  Start VGS process
    *************************************************/
    bVgsThreadExit = HI_FALSE;

    pthread_create(&VgsThreadId, HI_NULL, SAMPLE_VGS_Get_Frame_Thread, &stVgsModInfo);

    PAUSE();

    bVgsThreadExit = HI_TRUE;

    pthread_join(VgsThreadId, HI_NULL);

    /************************************************
    step7:  Exit
    *************************************************/

    SAMPLE_COMM_VO_StopVO(&stVoConfig);
EXIT1:
    SAMPLE_COMM_VI_StopVi(&stViConfig);
EXIT:
    SAMPLE_COMM_SYS_Exit();

    return HI_SUCCESS;

}


/******************************************************************************
* function    : main()
* Description : main
******************************************************************************/
int main(int argc, char* argv[])
{
    HI_S32 s32Ret = HI_FAILURE;
    HI_S32 s32Index;
    VO_INTF_TYPE_E enVoIntfType = VO_INTF_HDMI;

    if (argc < 2)
    {
        SAMPLE_VGS_Usage(argv[0]);
        return HI_FAILURE;
    }

    signal(SIGINT, SAMPLE_VGS_HandleSig);
    signal(SIGTERM, SAMPLE_VGS_HandleSig);

    if ((argc > 2) && (1 == atoi(argv[2])))
    {
        enVoIntfType = VO_INTF_BT1120;
    }

    s32Index = atoi(argv[1]);
    switch (s32Index)
    {
        case 0:
            s32Ret = SAMPLE_VGS_SDR10_COMPRESS(enVoIntfType);
            break;

        default:
            SAMPLE_PRT("the index %d is invaild!\n",s32Index);
            SAMPLE_VGS_Usage(argv[0]);
            return HI_FAILURE;
    }

    if (HI_SUCCESS == s32Ret)
    {
        SAMPLE_PRT("program exit normally!\n");
    }
    else
    {
        SAMPLE_PRT("program exit abnormally!\n");
    }
    return(s32Ret);
}

在这里插入图片描述

二、打OSD(区域管理实现叠加位图)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>

#include "sample_comm.h"
#include "loadbmp.h"

/******************************************************************************
* function : to process abnormal case
******************************************************************************/
void SAMPLE_VIO_HandleSig(HI_S32 signo)
{
    //当捕获到异常信号后触发的自定义函数如下,主要是对信号的重新定义以及系统退出资源的释放
    if (SIGINT == signo || SIGTERM == signo)
    {
        SAMPLE_COMM_All_ISP_Stop();
        SAMPLE_COMM_SYS_Exit();
        printf("\033[0;31mprogram termination abnormally!\033[0;39m\n");
    }
    exit(-1);
}

HI_S32 Sample_Load_Bmp(const char *filename, BITMAP_S *pstBitmap)
{
    OSD_SURFACE_S Surface;
    OSD_BITMAPFILEHEADER bmpFileHeader;
    OSD_BITMAPINFO bmpInfo;
 
    if(GetBmpInfo(filename,&bmpFileHeader,&bmpInfo) < 0)
    {
        printf("GetBmpInfo err!\n");
        return HI_FAILURE;
    }
    else
    {
        printf("GetBmpInfo OK!\n");
    }
 
    Surface.enColorFmt = OSD_COLOR_FMT_RGB1555;
 
    pstBitmap->pData = malloc(2*(bmpInfo.bmiHeader.biWidth)*(bmpInfo.bmiHeader.biHeight));
 
    if(NULL == pstBitmap->pData)
    {
        printf("malloc osd memroy err!\n");
        return HI_FAILURE;
    }
    else
    {
        printf("malloc osd memroy OK!\n");
    }
    CreateSurfaceByBitMap(filename,&Surface,(HI_U8*)(pstBitmap->pData));
 
    pstBitmap->u32Width = Surface.u16Width;
    pstBitmap->u32Height = Surface.u16Height;
    pstBitmap->enPixelFormat = PIXEL_FORMAT_ARGB_1555;
 
    return HI_SUCCESS;
}

HI_S32 SAMPLE_VIO_StartViVo(SAMPLE_VI_CONFIG_S* pstViConfig, SAMPLE_VO_CONFIG_S* pstVoConfig)
{
    HI_S32  s32Ret;

    s32Ret = SAMPLE_COMM_VI_StartVi(pstViConfig);

    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vi failed!\n");
        return s32Ret;
    }

    s32Ret = SAMPLE_COMM_VO_StartVO(pstVoConfig);

    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("SAMPLE_VIO start VO failed with %#x!\n", s32Ret);
        goto EXIT;
    }

    return s32Ret;

EXIT:
    //VO失败了需要把VI一同停止
    SAMPLE_COMM_VI_StopVi(pstViConfig);

    return s32Ret;
}

HI_S32 SAMPLE_VIO_StopViVo(SAMPLE_VI_CONFIG_S* pstViConfig, SAMPLE_VO_CONFIG_S* pstVoConfig)
{
    SAMPLE_COMM_VO_StopVO(pstVoConfig);

    SAMPLE_COMM_VI_StopVi(pstViConfig);

    return HI_SUCCESS;
}

HI_S32 SAMPLE_OSD_RGN(BITMAP_S *pstBitmap, MPP_CHN_S *pstChn, RGN_CHN_ATTR_S *pstChnAttr)
{
    RGN_HANDLE Handle;
    RGN_ATTR_S stRgnAttr;
    HI_S32 s32Ret = HI_SUCCESS;

    Handle = 0;
    stRgnAttr.enType = OVERLAYEX_RGN; 
    stRgnAttr.unAttr.stOverlayEx.enPixelFmt = PIXEL_FORMAT_ARGB_1555; 
    stRgnAttr.unAttr.stOverlayEx.stSize.u32Width = 48;
    stRgnAttr.unAttr.stOverlayEx.stSize.u32Height = 48;
    stRgnAttr.unAttr.stOverlayEx.u32BgColor = 0x0000ffff;

    s32Ret = HI_MPI_RGN_Create(Handle,&stRgnAttr);
    if(s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("HI_MPI_RGN_Create failed with %x!\n", s32Ret);
        return s32Ret;
    }

    s32Ret = HI_MPI_RGN_SetBitMap(Handle, pstBitmap);
    if(s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("HI_MPI_RGN_SetBitMap failed with %x!\n", s32Ret);
        HI_MPI_RGN_Destroy(Handle);
        return s32Ret;
    }

    s32Ret = HI_MPI_RGN_AttachToChn(Handle, pstChn,pstChnAttr);
    if(s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("HI_MPI_RGN_AttachToChn failed with %x!\n", s32Ret);
        HI_MPI_RGN_Destroy(Handle);
        return s32Ret;
    }

    return HI_SUCCESS;
}

HI_S32 MY_SAMPLE_VIO(VO_INTF_TYPE_E enVoIntfType)
{
    // Embeded isp.
    HI_S32             s32Ret;     //返回值
    VI_DEV             ViDev               = 0;
    VI_PIPE            ViPipe              = 0;
    VI_CHN             ViChn               = 0;
    HI_S32             s32WorkSnsId        = 0;
    VO_DEV             VoDev               = SAMPLE_VO_DEV_DHD0;
    VO_CHN             VoChn               = 0;
    SIZE_S             stSize;     //结构体,宽、高
    VB_CONFIG_S        stVbConf;   //视频缓存池属性结构体,
    PIC_SIZE_E         enPicSize           = PIC_3840x2160; //图片分辨率,也就是定义的视频的每一帧的分辨率
    HI_U32             u32BlkSize;
    SAMPLE_VI_CONFIG_S stViConfig  = {0};  //设置VI模块属性的结构体
    SAMPLE_VO_CONFIG_S stVoConfig  = {0};  //设置VO模块属性的结构体
    combo_dev_t          ComboDev;

    DYNAMIC_RANGE_E    enDynamicRange = DYNAMIC_RANGE_SDR8;  //动态范围
    PIXEL_FORMAT_E     enPixFormat    = PIXEL_FORMAT_YVU_SEMIPLANAR_420;  //像素格式类型
    VIDEO_FORMAT_E     enVideoFormat  = VIDEO_FORMAT_LINEAR;  //视频格式类型
    COMPRESS_MODE_E    enCompressMode = COMPRESS_MODE_NONE;   //视频压缩数据格式
    VI_VPSS_MODE_E     enMastPipeMode = VI_ONLINE_VPSS_OFFLINE; //VI PIPE 和 VPSS 组的工作模式

    /************************************************
    Get all sensors information
    *************************************************/
    SAMPLE_COMM_VI_GetSensorInfo(&stViConfig);
    ComboDev = SAMPLE_COMM_VI_GetComboDevBySensor(stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType, s32WorkSnsId);

    stViConfig.s32WorkingViNum                           = 1;

    stViConfig.as32WorkingViId[0]                        = 0;
    stViConfig.astViInfo[0].stSnsInfo.MipiDev            = ComboDev;
    stViConfig.astViInfo[0].stSnsInfo.s32BusId           = 0;

    stViConfig.astViInfo[0].stDevInfo.ViDev              = ViDev;
    stViConfig.astViInfo[0].stDevInfo.enWDRMode          = WDR_MODE_NONE;

    stViConfig.astViInfo[0].stPipeInfo.enMastPipeMode    = enMastPipeMode;
    stViConfig.astViInfo[0].stPipeInfo.aPipe[0]          = ViPipe;
    stViConfig.astViInfo[0].stPipeInfo.aPipe[1]          = -1;
    stViConfig.astViInfo[0].stPipeInfo.aPipe[2]          = -1;
    stViConfig.astViInfo[0].stPipeInfo.aPipe[3]          = -1;

    stViConfig.astViInfo[0].stChnInfo.ViChn              = ViChn;
    stViConfig.astViInfo[0].stChnInfo.enPixFormat        = enPixFormat;
    stViConfig.astViInfo[0].stChnInfo.enDynamicRange     = enDynamicRange;
    stViConfig.astViInfo[0].stChnInfo.enVideoFormat      = enVideoFormat;
    stViConfig.astViInfo[0].stChnInfo.enCompressMode     = enCompressMode;

    /************************************************
    Get  input size
    *************************************************/
    s32Ret = SAMPLE_COMM_VI_GetSizeBySensor(stViConfig.astViInfo[s32WorkSnsId].stSnsInfo.enSnsType, &enPicSize);

    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("SAMPLE_COMM_VI_GetSizeBySensor failed!\n");
        return s32Ret;
    }

    s32Ret = SAMPLE_COMM_SYS_GetPicSize(enPicSize, &stSize);

    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("SAMPLE_COMM_SYS_GetPicSize failed!\n");
        return s32Ret;
    }

    /************************************************
    Init SYS and common VB(视频缓存池处理模块)
    *************************************************/
    hi_memset(&stVbConf, sizeof(VB_CONFIG_S), 0, sizeof(VB_CONFIG_S));
    stVbConf.u32MaxPoolCnt              = 2;

    u32BlkSize = COMMON_GetPicBufferSize(stSize.u32Width, stSize.u32Height, SAMPLE_PIXEL_FORMAT, DATA_BITWIDTH_10, COMPRESS_MODE_SEG, DEFAULT_ALIGN);
    stVbConf.astCommPool[0].u64BlkSize  = u32BlkSize;
    stVbConf.astCommPool[0].u32BlkCnt   = 10;

    u32BlkSize = VI_GetRawBufferSize(stSize.u32Width, stSize.u32Height, PIXEL_FORMAT_RGB_BAYER_16BPP, COMPRESS_MODE_NONE, 32);
    stVbConf.astCommPool[1].u64BlkSize  = u32BlkSize;
    stVbConf.astCommPool[1].u32BlkCnt   = 4;

    s32Ret = SAMPLE_COMM_SYS_Init(&stVbConf); 

    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("system init failed with %d!\n", s32Ret);
        SAMPLE_COMM_SYS_Exit();
        return s32Ret;
    }

    s32Ret = SAMPLE_COMM_VI_SetParam(&stViConfig);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_COMM_SYS_Exit();
        return s32Ret;
    }

    /************************************************
    Init VI and VO
    *************************************************/
    SAMPLE_COMM_VO_GetDefConfig(&stVoConfig);
    s32Ret = SAMPLE_VIO_StartViVo(&stViConfig, &stVoConfig);

    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("SAMPLE_VIO_StartViVo failed witfh %d\n", s32Ret);
        goto EXIT;
    }

    /***********************************************
    通过区域管理打OSD,
    Hi3559叠加位图到VI的chn需要选择OVERLAYEX_RGN模式 
    ************************************************/
    BITMAP_S stBitmap;
    s32Ret = Sample_Load_Bmp("keys.bmp", &stBitmap);
    if(HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("Sample_Load_Bmp failed, s32Ret:0x%x\n",s32Ret);
        return s32Ret;
    }

    MPP_CHN_S stChn;
    stChn.enModId = HI_ID_VI;
    stChn.s32DevId = ViDev;
    stChn.s32ChnId = ViChn;

    RGN_CHN_ATTR_S stChnAttr;
    stChnAttr.bShow = HI_TRUE;
    stChnAttr.enType = OVERLAYEX_RGN;
    stChnAttr.unChnAttr.stOverlayExChn.stPoint.s32X = 1024;
    stChnAttr.unChnAttr.stOverlayExChn.stPoint.s32Y = 1024;
    stChnAttr.unChnAttr.stOverlayExChn.u32FgAlpha = 255;
    stChnAttr.unChnAttr.stOverlayExChn.u32BgAlpha = 255;
    stChnAttr.unChnAttr.stOverlayExChn.u32Layer = 2;

    s32Ret = SAMPLE_OSD_RGN(&stBitmap, &stChn, &stChnAttr);
    if(HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("SAMPLE_OSD_RGN failed, s32Ret:0x%x\n",s32Ret);
        return s32Ret;
    }

    /************************************************
    Bind VI and VO
    *************************************************/
    s32Ret = SAMPLE_COMM_VI_Bind_VO(ViPipe, ViChn, VoDev, VoChn);

    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("SAMPLE_COMM_VI_Bind_VO failed with %#x!\n", s32Ret);
        goto EXIT1;
    }

    PAUSE();

    SAMPLE_COMM_VI_UnBind_VO(ViPipe, ViChn, VoDev, VoChn);   //解除bind

    EXIT1:
    SAMPLE_VIO_StopViVo(&stViConfig, &stVoConfig);

    EXIT:
    SAMPLE_COMM_SYS_Exit();

    return s32Ret;
}

/******************************************************************************
* function    : main()
* Description : main
******************************************************************************/

int main(int argc, char* argv[])
{
    HI_S32 s32Ret = HI_FAILURE;
    VO_INTF_TYPE_E enVoIntfType = VO_INTF_HDMI; //输出格式


    signal(SIGINT, SAMPLE_VIO_HandleSig);
    signal(SIGTERM, SAMPLE_VIO_HandleSig);

    s32Ret = MY_SAMPLE_VIO(enVoIntfType);

    if (HI_SUCCESS == s32Ret)
    {
        SAMPLE_PRT("my_osd exit success!\n");
    }
    else
    {
        SAMPLE_PRT("my_osd exit abnormally!\n");
    }
    return s32Ret;
}

运行结果

在这里插入图片描述


总结

个人感觉打OSD用区域管理要方便许多,HI_MPI_VGS_AddOsdTask函数有些用不明白。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值