海思3531DV100视频输入模块

海思3531DV100视频输入模块(VI)

VI 可以对接收到的原始视频图像数据进行裁剪(Crop)、水平垂直缩小(Down Scaling)和水平垂直翻转(Mirror、Flip)等处理,并实现一路或多路原始视频图像输入,输出一路或多路视频图像功能。

视频输入设备支持标准 BT.656、标准 BT.1120、自定义时序等若干种时序输入,负责对时序进行解析。

Hi3531DV100 芯片有 5 个 BT.1120 接口,除第 5 个 BT.1120 接口外,每个 BT.1120 接口依次对应两个 VI 设备,即第 1 个 BT.1120 口对应 VI 的 Dev0 和 Dev1,第 2 个BT.1120 口对应 VI 的 Dev2 和 Dev3,第 3 个 BT.1120 口对应 VI 的 Dev4 和 Dev5,第 4个 BT.1120 口对应 VI 的 Dev6 和 Dev7。第 5 个 BT.1120 口是专用于级联的,对应DEV8,共8+1个输入设备。

前 8 个 VI 设备均支持 1/2/4 路 D1(D1:480i:720×480,几乎相当于我们所说的4CIF(720×576);)、960H 复合模式输入(BT.656 协议),以及 2 路720P 复合模式。当前 8 个设备配置为支持 720P/1080P 高清输入(BT.1120 协议),此时,同一个 BT1120 接口的另一个 Dev 不可用,即 DEV0、DEV1 中只能一个可用;DEV2、DEV3 中只能用一个,依此类推。DEV 的选择与 VI 的时钟必须一致,以DEV0 和 DEV1 为例,如果时钟选择为 VI0_CLK,则 DEV 选择为 DEV0,如果时钟选择为 VI1_CLK,则 DEV 选择为 DEV1,其他 DEV 依次类推。

绑定关系

Hi3531DV100 VI 有 9 个设备和 33 个物理通道,除级联设备外每个设备默认与对应的 4个通道绑定,其钟一个设备绑定关系如图 所示
在这里插入图片描述
级联设备绑定关系
在这里插入图片描述
通过cat /proc/umap/vi可以查看vi状态,如下图。
图中显示了配置的vi设备及通道,板子使用了24通道,为vi设备6的通道0,同时显示了接受的数据帧数。
在这里插入图片描述
下图说明了具体的vi设备配置属性,使用的接口及复用情况等。
在这里插入图片描述
下图说明了具体的vi绑定关系,中断次数,获取 VideoBuffer 失败次数,丢失中断次数,图像帧场标志:frm:逐行图像,intl:隔行图像,图片一行跨度。
在这里插入图片描述
通过cat /proc/umap/sys可以查看整个系统绑定状态,如下图。
这幅图说明了我绑定的资源为vi设备6绑定了vpss的group6的1号通道,vpss再绑定vo(视频输出)。
在这里插入图片描述

下面的代码块配置说明为了简洁,已经把if安全判断删除

次代码为配置视频输入的主要代码,为打开vi(视频输入)设备,vpss(视频处理)设备,将vi的数据绑定vpss,绑定后,vi采集的数据将自动传输给绑定的vpss
{
s32Ret = SAMPLE_COMM_VI_Start(enViMode, enNorm);

/******************************************
 step 4: start vpss and vi bind vpss(视频处理)
******************************************/
s32Ret = SAMPLE_COMM_SYS_GetPicSize(enNorm, PIC_HD1080, &stSize);
memset(&stGrpAttr,0,sizeof(VPSS_GRP_ATTR_S));
stGrpAttr.u32MaxW = stSize.u32Width;
stGrpAttr.u32MaxH = stSize.u32Height;
stGrpAttr.bNrEn = HI_TRUE;
stGrpAttr.enDieMode = VPSS_DIE_MODE_NODIE;
stGrpAttr.enPixFmt = SAMPLE_PIXEL_FORMAT;
s32Ret = SAMPLE_COMM_VPSS_Start(s32VpssGrpCnt, &stSize, VPSS_MAX_CHN_NUM, &stGrpAttr);

s32Ret = SAMPLE_COMM_VI_BindVpss(enViMode);

}

按照视频输入场景,依次初始化VI设备
HI_S32 SAMPLE_COMM_VI_Start(SAMPLE_VI_MODE_E enViMode, VIDEO_NORM_E enNorm)
{
VI_DEV ViDev;
VI_CHN ViChn;
HI_S32 i;
HI_S32 s32Ret;
SAMPLE_VI_PARAM_S stViParam;
SIZE_S stTargetSize;
RECT_S stCapRect;
VI_CHN_BIND_ATTR_S stChnBindAttr;

/*** 通过视频输入场景,获得输入设备参数 ***/
s32Ret = SAMPLE_COMM_VI_Mode2Param(enViMode, &stViParam);

//手动设置输入的视频宽高
s32Ret = SAMPLE_COMM_VI_Mode2Size(enViMode, enNorm, &stCapRect, &stTargetSize);

for(i=0; i<stViParam.s32ViDevCnt; i++)
{
    ViDev = i * stViParam.s32ViDevInterval;
    s32Ret = SAMPLE_COMM_VI_StartDev(ViDev, enViMode);//根据视频输入场景,初始化输入设备
}

/*** Start VI Chn ***/
for(i=0; i<stViParam.s32ViChnCnt; i++)
{
    ViChn = i * stViParam.s32ViChnInterval;

    if (SAMPLE_VI_MODE_16_1080P == enViMode|| SAMPLE_VI_MODE_16_720P == enViMode)
    {
        /* When in the 16x1080p mode, bind chn 2,6,10,14 to way1 is needed */
        if (ViChn%4 != 0)
        {
            s32Ret = HI_MPI_VI_GetChnBind(ViChn, &stChnBindAttr);//获取 VI 通道绑定关系
            if (HI_ERR_VI_FAILED_NOTBIND == s32Ret)
            {
                stChnBindAttr.ViDev = ViChn/4;
                stChnBindAttr.ViWay = 1;
                s32Ret = HI_MPI_VI_BindChn(ViChn, &stChnBindAttr);
            } 
        }
    }
    s32Ret = SAMPLE_COMM_VI_StartChn(ViChn, &stCapRect, &stTargetSize, enViMode, VI_CHN_SET_NORMAL);
}

return HI_SUCCESS;

}

HI_S32 SAMPLE_COMM_VI_Mode2Param(SAMPLE_VI_MODE_E enViMode, SAMPLE_VI_PARAM_S pstViParam)
{
switch (enViMode)
{
case SAMPLE_VI_MODE_32_D1:
case SAMPLE_VI_MODE_32_960H:
case SAMPLE_VI_MODE_32_1280H:
case SAMPLE_VI_MODE_32_HALF720P:
/
use chn 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16*/
pstViParam->s32ViDevCnt = 4;
pstViParam->s32ViDevInterval = 1;//设备号间隔
pstViParam->s32ViChnCnt = 16;
pstViParam->s32ViChnInterval = 1;//通道号间隔
break;
case SAMPLE_VI_MODE_16_720P:
case SAMPLE_VI_MODE_16_1080P:
/* use chn 0,2,4,6,8,10,12,14,16,18,20,22,24,28,30,32 /
pstViParam->s32ViDevCnt = 8;
pstViParam->s32ViDevInterval = 1;
pstViParam->s32ViChnCnt = 16;
pstViParam->s32ViChnInterval = 2;
break;
case SAMPLE_VI_MODE_8_720P:
case SAMPLE_VI_MODE_8_1080P:
/
use chn 0,4,8,12,16,20,24,28 */
pstViParam->s32ViDevCnt = 8;
pstViParam->s32ViDevInterval = 1;
pstViParam->s32ViChnCnt = 8;
pstViParam->s32ViChnInterval = 4;
break;
default:
SAMPLE_PRT(“ViMode invaild!\n”);
return HI_FAILURE;
}
return HI_SUCCESS;
}

//设置输入视频宽高
HI_S32 SAMPLE_COMM_VI_Mode2Size(SAMPLE_VI_MODE_E enViMode, VIDEO_NORM_E enNorm, RECT_S *pstCapRect, SIZE_S *pstDestSize)
{
pstCapRect->s32X = 0;
pstCapRect->s32Y = 0;
switch (enViMode)
{
case SAMPLE_VI_MODE_32_D1:
pstDestSize->u32Width = 720; //图像目标宽度(由捕获图像缩放得到)
pstDestSize->u32Height = (VIDEO_ENCODING_MODE_PALenNorm)?576:480;
pstCapRect->u32Width = 576; //捕获视频输入区域起始位置
pstCapRect->u32Height = (VIDEO_ENCODING_MODE_PAL
enNorm)?576:480;
break;
case SAMPLE_VI_MODE_32_960H:
pstDestSize->u32Width = 960;
pstDestSize->u32Height = (VIDEO_ENCODING_MODE_PALenNorm)?576:480;
pstCapRect->u32Width = 960;
pstCapRect->u32Height = (VIDEO_ENCODING_MODE_PAL
enNorm)?576:480;
break;
case SAMPLE_VI_MODE_8_720P:
case SAMPLE_VI_MODE_16_720P:
pstDestSize->u32Width = 1280;
pstDestSize->u32Height = 720;
pstCapRect->u32Width = 1280;
pstCapRect->u32Height = 720;
break;

    case SAMPLE_VI_MODE_8_1080P:
    case SAMPLE_VI_MODE_16_1080P:
        pstDestSize->u32Width  = 1920;
        pstDestSize->u32Height = 1080;
        pstCapRect->u32Width  = 1920;
        pstCapRect->u32Height = 1080;
        break;           
    case SAMPLE_VI_MODE_4_4Kx2K:
        pstDestSize->u32Width  = 3840;
        pstDestSize->u32Height = 2160;
        pstCapRect->u32Width  = 3840;
        pstCapRect->u32Height = 2160;
        break;

    default:
        SAMPLE_PRT("vi mode invaild!\n");
        return HI_FAILURE;
}

return HI_SUCCESS;

}

//打开对应的视频输入设备
HI_S32 SAMPLE_COMM_VI_StartDev(VI_DEV ViDev, SAMPLE_VI_MODE_E enViMode)
{
HI_S32 s32Ret;
VI_DEV_ATTR_S stViDevAttr;
memset(&stViDevAttr,0,sizeof(stViDevAttr));

//主要设置视频输入 接口模式;1、2、4 路复合工作模式; 分量掩码配置;时钟边沿模式;入数据顺序 (仅支持 yuv 格式)。
switch (enViMode)
{
case SAMPLE_VI_MODE_32_D1:
memcpy(&stViDevAttr,&DEV_ATTR_BT656D1_4MUX,sizeof(stViDevAttr));
SAMPLE_COMM_VI_SetMask(ViDev,&stViDevAttr);
break;
case SAMPLE_VI_MODE_32_960H:
memcpy(&stViDevAttr,&DEV_ATTR_BT656D1_4MUX,sizeof(stViDevAttr));
SAMPLE_COMM_VI_SetMask(ViDev,&stViDevAttr);
break;
case SAMPLE_VI_MODE_8_720P:
case SAMPLE_VI_MODE_8_1080P:
memcpy(&stViDevAttr,&DEV_ATTR_TP2823_720P_1MUX_BASE,sizeof(stViDevAttr));
SAMPLE_COMM_VI_SetMask(ViDev,&stViDevAttr);
break;
case SAMPLE_VI_MODE_16_720P:
memcpy(&stViDevAttr,&DEV_ATTR_TP2823_720P_2MUX_BASE,sizeof(stViDevAttr));
SAMPLE_COMM_VI_SetMask(ViDev,&stViDevAttr);
break;
case SAMPLE_VI_MODE_16_1080P:
memcpy(&stViDevAttr,&DEV_ATTR_7441_BT1120_STANDARD_BASE,sizeof(stViDevAttr));
SAMPLE_COMM_VI_SetMask(ViDev,&stViDevAttr);
break;
default:
SAMPLE_PRT(“vi input type[%d] is invalid!\n”, enViMode);
return HI_FAILURE;
}

s32Ret = HI_MPI_VI_SetDevAttr(ViDev, &stViDevAttr);//设置 VI 设备属性

s32Ret = HI_MPI_VI_EnableDev(ViDev);//启用 VI 设备

return HI_SUCCESS;

}

/初始化vpss,vpss支持4个通道,具体属性在下节说明/
HI_S32 SAMPLE_COMM_VPSS_Start(HI_S32 s32GrpCnt, SIZE_S *pstSize, HI_S32 s32ChnCnt,VPSS_GRP_ATTR_S *pstVpssGrpAttr)
{
VPSS_GRP VpssGrp;
VPSS_CHN VpssChn;
VPSS_GRP_ATTR_S stGrpAttr = {0};
VPSS_CHN_ATTR_S stChnAttr = {0};
VPSS_GRP_PARAM_S stVpssParam = {0};
HI_S32 s32Ret;
HI_S32 i, j;

/*** Set Vpss Grp Attr ***/

if(NULL == pstVpssGrpAttr)
{
    stGrpAttr.u32MaxW = pstSize->u32Width;
    stGrpAttr.u32MaxH = pstSize->u32Height;
    stGrpAttr.enPixFmt = SAMPLE_PIXEL_FORMAT;
    
    stGrpAttr.bIeEn = HI_FALSE;
    stGrpAttr.bNrEn = HI_TRUE;
    stGrpAttr.bDciEn = HI_FALSE;
    stGrpAttr.bHistEn = HI_FALSE;
    stGrpAttr.bEsEn = HI_FALSE;
    stGrpAttr.enDieMode = VPSS_DIE_MODE_NODIE;
}
else
{
    memcpy(&stGrpAttr,pstVpssGrpAttr,sizeof(VPSS_GRP_ATTR_S));
}


for(i=0; i<s32GrpCnt; i++)
{
    VpssGrp = i;
    /*** create vpss group ***/
    s32Ret = HI_MPI_VPSS_CreateGrp(VpssGrp, &stGrpAttr);

    /*** set vpss param ***/
    s32Ret = HI_MPI_VPSS_GetGrpParam(VpssGrp, &stVpssParam);
    
    stVpssParam.u32IeStrength = 0;
    s32Ret = HI_MPI_VPSS_SetGrpParam(VpssGrp, &stVpssParam);

    /*** enable vpss chn, with frame ***/
    for(j=0; j<s32ChnCnt; j++)
    {
        VpssChn = j;
        /* Set Vpss Chn attr */
        stChnAttr.bSpEn = HI_FALSE;
        stChnAttr.bUVInvert = HI_FALSE;
        stChnAttr.bBorderEn = HI_TRUE;
        stChnAttr.stBorder.u32Color = 0xffffff;
        stChnAttr.stBorder.u32LeftWidth = 2;
        stChnAttr.stBorder.u32RightWidth = 2;
        stChnAttr.stBorder.u32TopWidth = 2;
        stChnAttr.stBorder.u32BottomWidth = 2;
        
        s32Ret = HI_MPI_VPSS_SetChnAttr(VpssGrp, VpssChn, &stChnAttr);

        s32Ret = HI_MPI_VPSS_EnableChn(VpssGrp, VpssChn);
    }
    
    /*** start vpss group ***/
    s32Ret = HI_MPI_VPSS_StartGrp(VpssGrp);
}
return HI_SUCCESS;

}

//将vi的设备绑定对应vpss。至此,vi的通道数据就可以到达vpss。
HI_S32 SAMPLE_COMM_VI_BindVpss(SAMPLE_VI_MODE_E enViMode)
{
HI_S32 j, s32Ret;
VPSS_GRP VpssGrp;
MPP_CHN_S stSrcChn;
MPP_CHN_S stDestChn;
SAMPLE_VI_PARAM_S stViParam;
VI_CHN ViChn;

s32Ret = SAMPLE_COMM_VI_Mode2Param(enViMode, &stViParam);

VpssGrp = 0;
for (j=0; j<stViParam.s32ViChnCnt; j++)
{
    ViChn = j * stViParam.s32ViChnInterval;
    
    stSrcChn.enModId = HI_ID_VIU;
    stSrcChn.s32DevId = 0;
    stSrcChn.s32ChnId = ViChn;

    stDestChn.enModId = HI_ID_VPSS;
    stDestChn.s32DevId = VpssGrp;
    stDestChn.s32ChnId = 0;

    s32Ret = HI_MPI_SYS_Bind(&stSrcChn, &stDestChn);
    VpssGrp ++;
}
return HI_SUCCESS;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JKLTYU_0_0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值