jl3276

jl3276

1个粉丝

8

问答

0

专栏

0

资料

jl3276  发布于  2016-09-11 16:01:36
采纳率 0%
8个问答
8180

hi3520D的VO部分我的理解

 

[i=s] 本帖最后由 jl3276 于 2017-3-22 16:27 编辑 [/i]

先声明一下,以下内容是接续我《hi3520D的VPSS部分我的理解》 写的,如有需要可以点击链接查看http://www.ebaina.com/bbs/thread-12618-1-1.html

前面我们分析了4部分,分别是

/** step 1: init variable **/ /** step 2: mpp system init. **/ /** step 3: start vi dev & chn **/ /** step 4: start vpss and vi bind vpss **/

由于我用到的是VGA设备,所以略过以下部分的代码分析 /** step 5: start vo SD1(CVBS) **/

/** step 7: start vo SD0 (CVBS) (WBC target) **/ 我们来看 /** step 6: start vo HD0 (HDMI+VGA), multi-screen, you can switch mode **/ 这一部分的代码~先把这一部分的代码贴到2楼:

hi3520D的VI部分我的理解: http://ebaina.com/bbs/thread-12613-1-1.html hi3520D的VPSS部分我的理解: http://ebaina.com/bbs/thread-12618-1-1.html hi3520D的VO部分我的理解: http://www.ebaina.com/bbs/thread-12619-1-1.html 如有问题欢迎加群讨论: 学习交流群:375323762

我来回答
回答18个
时间排序
认可量排序

jl3276

1个粉丝

8

问答

0

专栏

0

资料

jl3276 2016-09-11 16:08:10
认可0
[code]
/******************************************
         step 6: start vo HD0 (HDMI+VGA), multi-screen, you can switch mode
        ******************************************/
        printf("start vo HD0.\n");
        VoDev = SAMPLE_VO_DEV_DHD0;
        u32WndNum = 4;
        enVoMode = VO_MODE_4MUX;
       
        if(VIDEO_ENCODING_MODE_PAL == gs_enNorm)
        {
                stVoPubAttr.enIntfSync = VO_OUTPUT_1024x768_60;
        }
        else
        {
                stVoPubAttr.enIntfSync = VO_OUTPUT_1024x768_60;
        }
#ifdef HI_FPGA
        stVoPubAttr.enIntfType = VO_INTF_HDMI|VO_INTF_VGA|VO_INTF_BT1120;
#else
        stVoPubAttr.enIntfType = VO_INTF_HDMI|VO_INTF_VGA;
#endif

        stVoPubAttr.u32BgColor = 0;
        stVoPubAttr.bDoubleFrame = HI_TRUE;
       
        s32Ret = SAMPLE_COMM_VO_StartDevLayer(VoDev, &stVoPubAttr, gs_u32ViFrmRate);
        if (HI_SUCCESS != s32Ret)
        {
                SAMPLE_PRT("Start SAMPLE_COMM_VO_StartDevLayer failed!\n");
                goto END_8D1_4;
        }
       
        s32Ret = SAMPLE_COMM_VO_StartChn(VoDev, &stVoPubAttr, enVoMode);
        if (HI_SUCCESS != s32Ret)
        {
                SAMPLE_PRT("Start SAMPLE_COMM_VO_StartChn failed!\n");
                goto END_8D1_5;
        }

        /* if it's displayed on HDMI, we should start HDMI */
        if (stVoPubAttr.enIntfType & VO_INTF_HDMI)
        {
                if (HI_SUCCESS != SAMPLE_COMM_VO_HdmiStart(stVoPubAttr.enIntfSync))
                {
                        SAMPLE_PRT("Start SAMPLE_COMM_VO_HdmiStart failed!\n");
                        goto END_8D1_5;
                }
        }
       
        for(i=0;i         {
                VoChn = i;
                VpssGrp = i;
               
                s32Ret = SAMPLE_COMM_VO_BindVpss(VoDev,VoChn,VpssGrp,VpssChn_VoHD0);
                if (HI_SUCCESS != s32Ret)
                {
                        SAMPLE_PRT("Start VO failed!\n");
                        goto END_8D1_5;
                }
        }[/code]

jl3276

1个粉丝

8

问答

0

专栏

0

资料

jl3276 2016-09-11 16:26:50
认可0
本帖最后由 jl3276 于 2016-9-11 17:57 编辑

#if HICHIP == HI3520D_V100 || HICHIP == HI3521_V100 || HICHIP == HI3520A_V100
#define SAMPLE_VO_DEV_DHD0 0
#define SAMPLE_VO_DEV_DSD0 1
#define SAMPLE_VO_DEV_DSD1 2
#elif HICHIP == HI3531_V100 || HICHIP == HI3532_V100
#define SAMPLE_VO_DEV_DHD0 0
#define SAMPLE_VO_DEV_DHD1 1
#define SAMPLE_VO_DEV_DSD0 2
#define SAMPLE_VO_DEV_DSD1 3
#define SAMPLE_VO_DEV_DSD2 4
#define SAMPLE_VO_DEV_DSD3 5
#define SAMPLE_VO_DEV_DSD4 6
#define SAMPLE_VO_DEV_DSD5 7
#else
/*
#error HICHIP define may be error
*/
#endif
首先SAMPLE_VO_DEV_DHD0的宏定义见上面,在sample_comm.h里面,但是HICHIP这个宏在哪里定义的我没找到。。。。。。那位仁兄可以告知下,谢了
先把相关结构体类型的定义贴出来
------------------------------------------------------------------------------------------
typedef enum sample_vo_mode_e
{
    VO_MODE_1MUX  = 0,
    VO_MODE_4MUX = 1,
    VO_MODE_9MUX = 2,
    VO_MODE_16MUX = 3,
    VO_MODE_BUTT
}SAMPLE_VO_MODE_E;


VO_PUB_ATTR_S
【说明】
定义视频输出公共属性结构体。
【定义】
typedef struct hiVO_PUB_ATTR_S
{
HI_U32 u32BgColor; /* 设备背景色 RGB表示 */
VO_INTF_TYPE_E enIntfType; /* Vo 接口类型 */
VO_INTF_SYNC_E enIntfSync; /* Vo接口时序类型 */
VO_SYNC_INFO_S stSyncInfo; /* Vo接口时序信息 */
HI_BOOL bDoubleFrame; /* 是否需要倍帧 */
} VO_PUB_ATTR_S;

****************************************
enIntfType 接口类型典型配置,原型定义:
Typedef HI_S32 VO_INTF_TYPE_E;
#define VO_INTF_CVBS (0x01L<<0)
#define VO_INTF_YPBPR (0x01L<<1)
#define VO_INTF_VGA (0x01L<<2)
#define VO_INTF_BT656 (0x01L<<3)
#define VO_INTF_BT1120 (0x01L<<4)
#define VO_INTF_HDMI (0x01L<<5)
#define VO_INTF_LCD (0x01L<<6)
#define VO_INTF_BT656_H (0x01L<<7)
#define VO_INTF_BT656_L (0x01L<<8)
****************************************************************
enIntfSync 接口时序典型配置,原型定义:
typedef enum hiVO_INTF_SYNC_E
{
VO_OUTPUT_PAL = 0,
VO_OUTPUT_NTSC,
VO_OUTPUT_1080P24,
VO_OUTPUT_1080P25,
VO_OUTPUT_1080P30,
VO_OUTPUT_720P50,
VO_OUTPUT_720P60,
VO_OUTPUT_1080I50,
VO_OUTPUT_1080I60,
VO_OUTPUT_1080P50,
VO_OUTPUT_1080P60,
VO_OUTPUT_576P50,
VO_OUTPUT_480P60,
VO_OUTPUT_800x600_60,
VO_OUTPUT_1024x768_60,
VO_OUTPUT_1280x1024_60,
VO_OUTPUT_1366x768_60,
VO_OUTPUT_1440x900_60,
VO_OUTPUT_1280x800_60,
VO_OUTPUT_USER,
VO_OUTPUT_BUTT
} VO_INTF_SYNC_E;
**************************************************************
stSyncInfo 接口时序结构体,原型定义:
typedef struct tagVO_SYNC_INFO_S
{
HI_BOOL bSynm;
HI_BOOL bIop;
HI_U8 u8Intfb;
HI_U16 u16Vact ;
HI_U16 u16Vbb;
HI_U16 u16Vfb;
HI_U16 u16Hact;
HI_U16 u16Hbb;
HI_U16 u16Hfb;
HI_U16 u16Hmid; HI_U16 u16Bvact;
HI_U16 u16Bvbb;
HI_U16 u16Bvfb;
HI_U16 u16Hpw;
HI_U16 u16Vpw;
HI_BOOL bIdv;
HI_BOOL bIhs;
HI_BOOL bIvs;
} VO_SYNC_INFO_S;
**************************************************************
Hi3520D/Hi3515A 支持 VO_INTF_CVBS、 VO_INTF_VGA、 VO_INTF_HDMI 时序
**************************************************************
当接口时序配置为 VO_OUTPUT_USER 时, stSyncInfo 定义的时序结构才会生
效,表示用户自定义的时序结构。
---------------------------------------------------------------------------------------------------------------
stVoPubAttr.enIntfType = VO_INTF_HDMI|VO_INTF_VGA;表示同时使用HDMI和VGA接口
然后在27行调用了s32Ret = SAMPLE_COMM_VO_StartDevLayer(VoDev, &stVoPubAttr, gs_u32ViFrmRate);函数我们把这个函数的定义贴在下面

jl3276

1个粉丝

8

问答

0

专栏

0

资料

jl3276 2016-09-11 16:28:06
认可0
本帖最后由 jl3276 于 2016-9-11 16:50 编辑

先把函数的参数贴出来,VoDev = SAMPLE_VO_DEV_DHD0;    stVoPubAttr就是前面定义的视频输出公共属性结构体变量。gs_u32ViFrmRate=25;
[code]HI_S32 SAMPLE_COMM_VO_StartDevLayer(VO_DEV VoDev, VO_PUB_ATTR_S *pstPubAttr, HI_U32 u32SrcFrmRate)
{
    HI_S32 s32Ret = HI_SUCCESS;
    HI_U32 u32Width = 0;
    HI_U32 u32Height = 0;
    HI_U32 u32Frm = 0;
    VO_VIDEO_LAYER_ATTR_S stLayerAttr;

    if ( 0 == u32SrcFrmRate )
    {
        SAMPLE_PRT("vo u32SrcFrmRate invaild! %d!\n", u32SrcFrmRate);
        return HI_FAILURE;
    }
    //printf("-----------------dev:%d\n", VoDev);
    s32Ret = HI_MPI_VO_SetPubAttr(VoDev, pstPubAttr);
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("failed with %#x!\n", s32Ret);
        return HI_FAILURE;
    }

    s32Ret = HI_MPI_VO_Enable(VoDev);
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("failed with %#x!\n", s32Ret);
        return HI_FAILURE;
    }

    s32Ret = SAMPLE_COMM_VO_GetWH(pstPubAttr->enIntfSync, &u32Width, &u32Height, &u32Frm);
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("failed with %#x!\n", s32Ret);
        return HI_FAILURE;
    }

    stLayerAttr.enPixFormat = SAMPLE_PIXEL_FORMAT;
    stLayerAttr.u32DispFrmRt = u32SrcFrmRate;

    stLayerAttr.stDispRect.s32X       = 0;
    stLayerAttr.stDispRect.s32Y       = 0;
    stLayerAttr.stDispRect.u32Width   = u32Width;
    stLayerAttr.stDispRect.u32Height  = u32Height;
    stLayerAttr.stImageSize.u32Width  = u32Width;
    stLayerAttr.stImageSize.u32Height = u32Height;
   
    s32Ret = HI_MPI_VO_SetVideoLayerAttr(VoDev, &stLayerAttr);
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("failed with %#x!\n", s32Ret);
        return HI_FAILURE;
    }

    s32Ret = HI_MPI_VO_EnableVideoLayer(VoDev);
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("failed with %#x!\n", s32Ret);
        return HI_FAILURE;
    }
   
    return s32Ret;
}
[/code]
首先把相关的结构体类型贴出来
------------------------------------------------------------------------------------------------------
VO_VIDEO_LAYER_ATTR_S
【说明】
定义视频层属性。
在视频层属性中存在三个概念,即设备分辨率、显示分辨率和图像分辨率。
图像分辨率指放置各个通道图像的画布大小。
显示分辨率是把图像分辨率中描述的画布经过 VO 放大后的显示区域。
设备分辨率与设备时序一致,即如果时序为 1920 x 1080,那设备分辨率就为 1920 x1080。
typedef struct hiVO_VIDEO_LAYER_ATTR_S
{
RECT_S stDispRect; /* 显示分辨率大小 */
SIZE_S stImageSize; /* 视频层画布大小 */
HI_U32 u32DispFrmRt; /* 显示帧率 */
PIXEL_FORMAT_E enPixFormat; /* 视频层使用的像素格式 */
} VO_VIDEO_LAYER_ATTR_S;
--------------------------------------------------------------------------------------------------------
首先调用s32Ret = HI_MPI_VO_SetPubAttr(VoDev, pstPubAttr);配置视频输出设备的公共属性。
然后调用s32Ret = HI_MPI_VO_Enable(VoDev);启用视频输出设备。
然后调用了 s32Ret = SAMPLE_COMM_VO_GetWH(pstPubAttr->enIntfSync, &u32Width, &u32Height, &u32Frm);
这个函数,该函数定义在sample_comm_vo.c里面,把该函数的代码贴出来
[code]HI_S32 SAMPLE_COMM_VO_GetWH(VO_INTF_SYNC_E enIntfSync, HI_U32 *pu32W,HI_U32 *pu32H, HI_U32 *pu32Frm)
{
    switch (enIntfSync)
    {
        case VO_OUTPUT_PAL       :  *pu32W = 720;  *pu32H = 576; *pu32Frm = 25; break;
        case VO_OUTPUT_NTSC      :  *pu32W = 720;  *pu32H = 480; *pu32Frm = 30; break;
        case VO_OUTPUT_800x600_60:  *pu32W = 800;  *pu32H = 600;  *pu32Frm = 60; break;
        case VO_OUTPUT_720P50    :  *pu32W = 1280; *pu32H = 720;  *pu32Frm = 50; break;
        case VO_OUTPUT_1080P24  : *pu32W = 1920; *pu32H = 1080;  *pu32Frm = 24; break;
        case VO_OUTPUT_720P60    : *pu32W = 1280; *pu32H = 720;  *pu32Frm = 60; break;
        case VO_OUTPUT_1080P30   :  *pu32W = 1920; *pu32H = 1080; *pu32Frm = 30; break;
        case VO_OUTPUT_1080P25   :  *pu32W = 1920; *pu32H = 1080; *pu32Frm = 25; break;
        case VO_OUTPUT_1080P50   :  *pu32W = 1920; *pu32H = 1080; *pu32Frm = 50; break;
        case VO_OUTPUT_1080P60   :  *pu32W = 1920; *pu32H = 1080; *pu32Frm = 60; break;
        case VO_OUTPUT_1024x768_60:  *pu32W = 1024; *pu32H = 768;  *pu32Frm = 60; break;
        case VO_OUTPUT_1280x1024_60:  *pu32W = 1280; *pu32H = 1024;  *pu32Frm = 60; break;
        case VO_OUTPUT_1366x768_60:   *pu32W = 1366; *pu32H = 768;  *pu32Frm = 60; break;
        case VO_OUTPUT_1440x900_60: *pu32W = 1440; *pu32H = 900;  *pu32Frm = 60; break;
        case VO_OUTPUT_1280x800_60: *pu32W = 1280; *pu32H = 800;  *pu32Frm = 60; break;
        default:
            SAMPLE_PRT("vo enIntfSync not support!\n");
            return HI_FAILURE;
    }
    return HI_SUCCESS;
}[/code]

其作用就是根据enIntfSync这个变量,拆分出宽,高,帧率
进入的是这个分支case VO_OUTPUT_1024x768_60:  *pu32W = 1024; *pu32H = 768;  *pu32Frm = 60; break;
后面会根据分拆出来的宽,高,帧率来填充VO_VIDEO_LAYER_ATTR_S类型的结构体变量
#define SAMPLE_PIXEL_FORMAT         PIXEL_FORMAT_YUV_SEMIPLANAR_420
视频层属性结构体变量填充完成后,调用HI_MPI_VO_SetVideoLayerAttr来设置视频层属性。
然后调用HI_MPI_VO_EnableVideoLayer来使能视频层。到此为止SAMPLE_COMM_VO_StartDevLayer函数返回了

jl3276

1个粉丝

8

问答

0

专栏

0

资料

jl3276 2016-09-11 18:05:08
认可0
本帖最后由 jl3276 于 2016-9-11 18:30 编辑

接下来回到sample_vio.c
调用了s32Ret = SAMPLE_COMM_VO_StartChn(VoDev, &stVoPubAttr, enVoMode);这个函数,其中函数参数        enVoMode = VO_MODE_4MUX;
该函数定义在sample_comm_vo.c中,将该函数的定义代码贴出来看看:
[code]HI_S32 SAMPLE_COMM_VO_StartChn(VO_DEV VoDev,VO_PUB_ATTR_S *pstPubAttr,SAMPLE_VO_MODE_E enMode)
{
    HI_S32 i;
    HI_S32 s32Ret = HI_SUCCESS;
    HI_U32 u32WndNum = 0;
    HI_U32 u32Square = 0;
    HI_U32 u32Width = 0;
    HI_U32 u32Height = 0;
    HI_U32 u32Frm = 0;
    VO_CHN_ATTR_S stChnAttr;
   
    switch (enMode)
    {
        case VO_MODE_1MUX:
            u32WndNum = 1;
            u32Square = 1;
            break;
        case VO_MODE_4MUX:
            u32WndNum = 4;
            u32Square = 2;
            break;
        case VO_MODE_9MUX:
            u32WndNum = 9;
            u32Square = 3;
            break;
        case VO_MODE_16MUX:
            u32WndNum = 16;
            u32Square = 4;
            break;
        default:
            SAMPLE_PRT("failed with %#x!\n", s32Ret);
            return HI_FAILURE;
    }

    s32Ret = SAMPLE_COMM_VO_GetWH(pstPubAttr->enIntfSync, &u32Width,&u32Height,&u32Frm);
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("failed with %#x!\n", s32Ret);
        return HI_FAILURE;
    }
    printf("u32Width:%d, u32Square:%d\n", u32Width, u32Square);
    for (i=0; i     {
        stChnAttr.stRect.s32X       = ALIGN_BACK((u32Width/u32Square) * (i%u32Square), 2);
        stChnAttr.stRect.s32Y       = ALIGN_BACK((u32Height/u32Square) * (i/u32Square), 2);
        stChnAttr.stRect.u32Width   = ALIGN_BACK(u32Width/u32Square, 2);
        stChnAttr.stRect.u32Height  = ALIGN_BACK(u32Height/u32Square, 2);
        stChnAttr.u32Priority       = 0;
        stChnAttr.bDeflicker        = HI_FALSE;

        s32Ret = HI_MPI_VO_SetChnAttr(VoDev, i, &stChnAttr);
        if (s32Ret != HI_SUCCESS)
        {
            printf("%s(%d):failed with %#x!\n",\
                   __FUNCTION__,__LINE__,  s32Ret);
            return HI_FAILURE;
        }

        s32Ret = HI_MPI_VO_EnableChn(VoDev, i);
        if (s32Ret != HI_SUCCESS)
        {
            SAMPLE_PRT("failed with %#x!\n", s32Ret);
            return HI_FAILURE;
        }
    }

    return HI_SUCCESS;
}[/code]

根据enVoMode = VO_MODE_4MUX;
进入的是这个分支
case VO_MODE_4MUX:
            u32WndNum = 4;
            u32Square = 2;
            break;
其用到的结构体类型写在下面:
--------------------------------------------------------------------------------
VO_CHN_ATTR_S
【说明】
定义视频输出通道属性。
【定义】
typedef struct hiVO_CHN_ATTR_S
{
HI_U32 u32Priority; /* 通道优先级 */视频通道叠加优先级,优先级高的在上层。高清设备取值范围: [0, 1]。标清设备取值范围: [0, VO_MAX_CHN_NUM-1]。动态属性。
RECT_S stRect;
/* 通道显示区域 */通道矩形显示区域。以屏幕的左上角为原点。其取值必须是 2 对齐,且该矩形区域必须在屏幕范围之内。 注意:当高清设备是隔行时序且 SPYCbCr420 显示时,高度必须 4 对齐。动态属性。
HI_BOOL bDeflicker; /* 是否开启抗闪烁 */是否开启抗闪烁。抗闪烁效果仅针对使用 TDE 缩放的设备的通道有效,即该参数仅对标清设备和虚拟设备有效。动态属性。
}VO_CHN_ATTR_S;
--------------------------------------------------------------------------------
在sample_comm.h中,定义了#define ALIGN_BACK(x, a)              ((a) * (((x) / (a))))这个宏
这个宏可能是用来对其窗口坐标和宽高的(分屏),没搞懂。。。。。。。
配置完VO_CHN_ATTR_S 类型的结构体变量stChnAttr后,调用s32Ret = HI_MPI_VO_SetChnAttr(VoDev, i, &stChnAttr);配置指定视频输出通道的属性。
然后调用HI_MPI_VO_EnableChn启用指定的视频输出通道。到此,SAMPLE_COMM_VO_StartChn这个函数就返回了。。。

jl3276

1个粉丝

8

问答

0

专栏

0

资料

jl3276 2016-09-11 18:33:22
认可0
由于我们没有连接HDMI(需要将stVoPubAttr.enIntfType = VO_INTF_HDMI|VO_INTF_VGA;修改为stVoPubAttr.enIntfType = VO_INTF_HDMI|VO_INTF_VGA;),所以if (stVoPubAttr.enIntfType & VO_INTF_HDMI)条件判断为假,不再分析HDMI部分。

jl3276

1个粉丝

8

问答

0

专栏

0

资料

jl3276 2016-09-11 18:40:23
认可0
本帖最后由 jl3276 于 2016-9-11 18:55 编辑

最后运行一个for循环,循环4次VoChn = i;VpssGrp = i;(i=0~3),调用s32Ret = SAMPLE_COMM_VO_BindVpss(VoDev,VoChn,VpssGrp,VpssChn_VoHD0);这个函数;其中,函数参数有VPSS_CHN VpssChn_VoHD0 = VPSS_PRE0_CHN;
-----------------------------------------------------------------------------
VPSS_PRE0_CHN
【说明】
定义预览通道 0 的 ID 号。
【定义】
#define VPSS_PRE0_CHN 2
------------------------------------------------------------------------------------
该函数的定义贴在下面
[code]HI_S32 SAMPLE_COMM_VO_BindVpss(VO_DEV VoDev,VO_CHN VoChn,VPSS_GRP VpssGrp,VPSS_CHN VpssChn)
{
    HI_S32 s32Ret = HI_SUCCESS;
    MPP_CHN_S stSrcChn;
    MPP_CHN_S stDestChn;

    stSrcChn.enModId = HI_ID_VPSS;
    stSrcChn.s32DevId = VpssGrp;
    stSrcChn.s32ChnId = VpssChn;

    stDestChn.enModId = HI_ID_VOU;
    stDestChn.s32DevId = VoDev;
    stDestChn.s32ChnId = VoChn;

    s32Ret = HI_MPI_SYS_Bind(&stSrcChn, &stDestChn);
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("failed with %#x!\n", s32Ret);
        return HI_FAILURE;
    }

    return s32Ret;
}[/code]

其中,
--------------------------------------------------------------------------------
MPP_CHN_S
【说明】
定义模块设备通道结构体。
【定义】
typedef struct hiMPP_CHN_S
{
MOD_ID_E enModId//模块号
HI_S32 s32DevId;//设备号
HI_S32 s32ChnId;//通道号
} MPP_CHN_S;


*************************************************
typedef enum hiMOD_ID_E
{
HI_ID_CMPI = 0,
HI_ID_VB = 1,
HI_ID_SYS = 2,
HI_ID_VALG = 3,
HI_ID_CHNL = 4,
HI_ID_GROUP = 5,
HI_ID_VENC = 6,
HI_ID_VPSS = 7,
HI_ID_VDA = 8,
HI_ID_H264E = 9,
HI_ID_JPEGE = 10,
HI_ID_MPEG4E = 11,
HI_ID_VDEC = 12,
HI_ID_H264D = 13,
HI_ID_JPEGD = 14,
HI_ID_VOU = 15,
HI_ID_VIU = 16,
HI_ID_DSU = 17,
HI_ID_RGN = 18,
HI_ID_RC = 19,
HI_ID_SIO = 20,
HI_ID_AI = 21,
HI_ID_AO = 22,
HI_ID_AENC = 23,
HI_ID_ADEC = 24,
HI_ID_AVENC = 25,
HI_ID_PCIV = 26,
HI_ID_PCIVFMW = 27,
/* there is a hole */
HI_ID_DCCM = 31,
HI_ID_DCCS = 32,
HI_ID_PROC = 33,
HI_ID_LOG = 34,
HI_ID_MST_LOG = 35,
HI_ID_VD = 36,
/* there is a hole */
HI_ID_VCMP = 38,
HI_ID_FB = 39,
HI_ID_USR = 40,
HI_ID_BUTT,
} MOD_ID_E;
--------------------------------------------------------------------------------------
然后调用HI_MPI_SYS_Bind,将数据源到数据接收者绑定接口。到此为止SAMPLE_COMM_VO_BindVpss函数返回了。
step 5: start vo HD0(HDMI) 也就到此结束了~

jl3276

1个粉丝

8

问答

0

专栏

0

资料

jl3276 2016-09-11 18:59:44
认可0
然后我们来分析一下分支模式选择的代码
[code]    /******************************************
         step 9: HD0 switch mode
    ******************************************/
    VoDev = SAMPLE_VO_DEV_DHD0;
    enVoMode = VO_MODE_9MUX;
    while(1)
    {
                  enPreVoMode = enVoMode;
        printf("please choose preview mode, press 'q' to exit this sample.\n");
        printf("\t0) 1 preview\n");
        printf("\t1) 4 preview\n");
        printf("\t2) 9 preview\n");      
        printf("\tq) quit\n");

        ch = getchar();
        getchar();
        if ('0' == ch)
        {
            u32WndNum = 1;
            enVoMode = VO_MODE_1MUX;
        }
        else if ('1' == ch)
        {
            u32WndNum = 4;
            enVoMode = VO_MODE_4MUX;
        }
        else if ('2' == ch)
        {
            u32WndNum = 8;
            enVoMode = VO_MODE_9MUX;
        }      
        else if ('q' == ch)
        {
            break;
        }
        else
        {
            SAMPLE_PRT("preview mode invaild! please try again.\n");
            continue;
        }
                /* VI Chn size should change from D1/2cif to D1 */
                if((VO_MODE_1MUX== enVoMode) || (VO_MODE_4MUX== enVoMode))
                {
                         stSizeTmp.u32Width = 720;
                        stSizeTmp.u32Height = ((VIDEO_ENCODING_MODE_PAL==gs_enNorm)?576:480);
            if(VO_MODE_1MUX == enVoMode)
                {
                                s32Ret = SAMPLE_COMM_VI_ChangeMixCap(0,HI_FALSE,gs_u32ViFrmRate);
                                if (HI_SUCCESS != s32Ret)
                                {
                                        SAMPLE_PRT("SAMPLE_COMM_VI_ChangeCapSize VO failed!\n");
                                        goto END_8_MixCap_4;
                                }

                                s32Ret = SAMPLE_COMM_DisableVpssPreScale(0,stSizeTmp);
                                if (HI_SUCCESS != s32Ret)
                                {
                                        SAMPLE_PRT("SAMPLE_COMM_DisableVpssPreScale VO failed!\n");
                                        goto END_8_MixCap_4;
                                }
                }
                        else
                        {
                                for(i=0;i                                  {
                                        s32Ret = SAMPLE_COMM_VI_ChangeMixCap(i,HI_FALSE,gs_u32ViFrmRate);
                                        if (HI_SUCCESS != s32Ret)
                                        {
                                                SAMPLE_PRT("SAMPLE_COMM_VI_ChangeCapSize VO failed!\n");
                                                goto END_8_MixCap_4;
                                        }

                                        s32Ret = SAMPLE_COMM_DisableVpssPreScale(i,stSizeTmp);
                                        if (HI_SUCCESS != s32Ret)
                                        {
                                                SAMPLE_PRT("SAMPLE_COMM_DisableVpssPreScale VO failed!\n");
                                                goto END_8_MixCap_4;
                                        }
                                 }
                        }
                }
                /* VI Chn size should change from  D1 to D1/2cif */
        else if((VO_MODE_9MUX== enVoMode) || (VO_MODE_16MUX== enVoMode))
        {
                stSizeTmp.u32Width= D1_WIDTH / 2;
                        stSizeTmp.u32Height = ((VIDEO_ENCODING_MODE_PAL==gs_enNorm)?576:480);
                if(VO_MODE_9MUX == enVoMode)
                {
                        for(i=0;i                                  {
                                        s32Ret = SAMPLE_COMM_VI_ChangeMixCap(i,HI_TRUE,6);
                                        if (HI_SUCCESS != s32Ret)
                                        {
                                                SAMPLE_PRT("SAMPLE_COMM_VI_ChangeCapSize VO failed!\n");
                                                goto END_8_MixCap_4;
                                        }

                                        s32Ret = SAMPLE_COMM_EnableVpssPreScale(i,stSizeTmp);
                                        if (HI_SUCCESS != s32Ret)
                                        {
                                                SAMPLE_PRT("SAMPLE_COMM_DisableVpssPreScale VO failed!\n");
                                                goto END_8_MixCap_4;
                                        }
                        }
                }
                        else
                        {
                                for(i=0;i                                  {
                                        s32Ret = SAMPLE_COMM_VI_ChangeMixCap(i,HI_TRUE,6);
                                        if (HI_SUCCESS != s32Ret)
                                        {
                                                SAMPLE_PRT("SAMPLE_COMM_VI_ChangeCapSize VO failed!\n");
                                                goto END_8_MixCap_4;
                                        }

                                        s32Ret = SAMPLE_COMM_EnableVpssPreScale(i,stSizeTmp);
                                        if (HI_SUCCESS != s32Ret)
                                        {
                                                SAMPLE_PRT("SAMPLE_COMM_DisableVpssPreScale VO failed!\n");
                                                goto END_8_MixCap_4;
                                        }
                                 }
                        }
        }
                else if (enVoMode== enPreVoMode)
                {
                        continue;
                }
               
        SAMPLE_PRT("vo(%d) switch to %d mode\n", VoDev, u32WndNum);

        s32Ret= HI_MPI_VO_SetAttrBegin(VoDev);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("Start VO failed!\n");
            goto END_8_MixCap_4;
        }
        
        s32Ret = SAMPLE_COMM_VO_StopChn(VoDev, enPreVoMode);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("Start VO failed!\n");
            goto END_8_MixCap_4;
        }

        s32Ret = SAMPLE_COMM_VO_StartChn(VoDev, &stVoPubAttr, enVoMode);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("Start VO failed!\n");
            goto END_8_MixCap_4;
        }
        s32Ret= HI_MPI_VO_SetAttrEnd(VoDev);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("Start VO failed!\n");
            goto END_8_MixCap_4;
        }
    }[/code]

jl3276

1个粉丝

8

问答

0

专栏

0

资料

jl3276 2016-09-11 19:07:57
认可0
本帖最后由 jl3276 于 2016-9-11 19:22 编辑

我们只分析4路的部分
[code]                for(i=0;i                                  {
                                        s32Ret = SAMPLE_COMM_VI_ChangeMixCap(i,HI_FALSE,gs_u32ViFrmRate);
                                        if (HI_SUCCESS != s32Ret)
                                        {
                                                SAMPLE_PRT("SAMPLE_COMM_VI_ChangeCapSize VO failed!\n");
                                                goto END_8_MixCap_4;
                                        }

                                        s32Ret = SAMPLE_COMM_DisableVpssPreScale(i,stSizeTmp);
                                        if (HI_SUCCESS != s32Ret)
                                        {
                                                SAMPLE_PRT("SAMPLE_COMM_DisableVpssPreScale VO failed!\n");
                                                goto END_8_MixCap_4;
                                        }
                                 }[/code]       
我们贴出来SAMPLE_COMM_VI_ChangeMixCap这个函数的源代码
[code]HI_S32 SAMPLE_COMM_VI_ChangeMixCap(VI_CHN ViChn,HI_BOOL bMixCap,HI_U32 FrameRate)
{
    VI_CHN_ATTR_S stChnAttr,stChnMinorAttr;
        HI_S32 S32Ret = HI_SUCCESS;
        S32Ret = HI_MPI_VI_GetChnAttr(ViChn, &stChnAttr);
        if(HI_SUCCESS!= S32Ret)
        {
            SAMPLE_PRT( "HI_MPI_VI_GetChnAttr failed");
        }
       
        if(HI_TRUE == bMixCap)
        {
                memcpy(&stChnMinorAttr, &stChnAttr, sizeof(VI_CHN_ATTR_S));
            stChnMinorAttr.stDestSize.u32Width = D1_WIDTH / 2;
               
                stChnAttr.s32FrameRate = FrameRate;
               
                S32Ret = HI_MPI_VI_SetChnAttr(ViChn, &stChnAttr);
        if (HI_SUCCESS != S32Ret)
        {
            SAMPLE_PRT("call HI_MPI_VI_SetChnAttr failed with %#x\n", S32Ret);
            return HI_FAILURE;
        }
                S32Ret = HI_MPI_VI_SetChnMinorAttr(ViChn, &stChnMinorAttr);
                if (HI_SUCCESS != S32Ret)
                {
                        SAMPLE_PRT("call HI_MPI_VI_SetChnMinorAttr failed with %#x\n", S32Ret);
                        return HI_FAILURE;
                }
        }
        else
        {
                stChnAttr.s32FrameRate = stChnAttr.s32SrcFrameRate;
                S32Ret = HI_MPI_VI_SetChnAttr(ViChn, &stChnAttr);
        if (HI_SUCCESS != S32Ret)
        {
            SAMPLE_PRT("call HI_MPI_VI_SetChnAttr failed with %#x\n", S32Ret);
            return HI_FAILURE;
        }
        }
        return HI_SUCCESS;
}[/code]
由于我们设置的第二个参数是HI_FALSE,所以这个函数基本上没做什么事,就是重新设置了一下帧率,而且还是以前的值
随后调用了s32Ret = SAMPLE_COMM_DisableVpssPreScale(i,stSizeTmp);将其源代码贴出来
[code]HI_S32 SAMPLE_COMM_DisableVpssPreScale(VPSS_GRP VpssGrp,SIZE_S stSize)
{
    HI_S32 s32Ret;
    VPSS_PRESCALE_INFO_S stPreScaleInfo;
        
    stPreScaleInfo.bPreScale = HI_FALSE;
    stPreScaleInfo.enCapSel = VPSS_CAPSEL_BOTH;
    stPreScaleInfo.stDestSize.u32Width = stSize.u32Width;
    stPreScaleInfo.stDestSize.u32Height = stSize.u32Height;
    s32Ret = HI_MPI_VPSS_SetPreScale(VpssGrp, &stPreScaleInfo);
    if (s32Ret != HI_SUCCESS)
        {
            SAMPLE_PRT("HI_MPI_VPSS_SetPreScale failed with %#x!\n", s32Ret);
            return HI_FAILURE;
        }

    return s32Ret;
}[/code]
涉及到这样一个结构体,贴在下面
--------------------------------------------------------------------------------------------------
VPSS_PRESCALE_INFO_S
【说明】
定义 VPSS 预缩放属性。
【定义】
typedef struct
{
HI_BOOL bPreScale;//预缩放开关。
VPSS_CAPSEL_E enCapSel;// 抽场选择。
SIZE_S stDestSize;//目标图像大小,特别注意此大小不得超过GROUP 的最大处理能力。
}VPSS_PRESCALE_INFO_S;

--------------------------------------------------------------------------------------------------
主要是通过调用HI_MPI_VPSS_SetPreScale设置 VPSS 预缩放属性。
注意事项:
GROUP 号必须合法, [0, VPSS_MAX_GRP_NUM)。
GROUP 必须已创建。
预缩放只针对 VI 采集图像有效。
Bypass 通道不支持此功能。
pstPreScaleInfo 各成员的限制参见 VPSS_PRESCALE_INFO_S 结构说明。
Hi3520D/Hi3515A 只支持水平 2 倍的预缩放,并且对于宽度大于 960 的图像,禁止使用预缩放。
HI_MPI_VO_SetAttrBegin:设置属性开始。

SAMPLE_COMM_VO_StopChn
SAMPLE_COMM_VO_StartChn

z HI_MPI_VO_SetAttrEnd:设置属性结束。

jl3276

1个粉丝

8

问答

0

专栏

0

资料

jl3276 2016-09-11 19:21:58
认可0
本帖最后由 jl3276 于 2016-9-11 19:25 编辑

[code]HI_S32 SAMPLE_COMM_VO_StopChn(VO_DEV VoDev,SAMPLE_VO_MODE_E enMode)
{
    HI_S32 i;
    HI_S32 s32Ret = HI_SUCCESS;
    HI_U32 u32WndNum = 0;

    switch (enMode)
    {
        case VO_MODE_1MUX:
        {
            u32WndNum = 1;
            break;
        }

        case VO_MODE_4MUX:
        {
            u32WndNum = 4;
            break;
        }

        case VO_MODE_9MUX:
        {
            u32WndNum = 9;
            break;
        }

        case VO_MODE_16MUX:
        {
            u32WndNum = 16;
            break;
        }
        
        default:
            SAMPLE_PRT("failed with %#x!\n", s32Ret);
            return HI_FAILURE;
    }


    for (i=0; i     {
        s32Ret = HI_MPI_VO_DisableChn(VoDev, i);
        if (s32Ret != HI_SUCCESS)
        {
            SAMPLE_PRT("failed with %#x!\n", s32Ret);
            return HI_FAILURE;
        }
    }
   
    return s32Ret;
}[/code]
主要是调用HI_MPI_VO_DisableChn禁用指定的视频输出通道。
文档中有这样一句话:
当高清设备的通道绑定 VPSS 时,建议先调用本接口停止通道后,再解绑定 VO通道与 VPSS 通道的绑定关系,否则,可能出现 HI_ERR_VO_BUSY 的超时返回错误。

jl3276

1个粉丝

8

问答

0

专栏

0

资料

jl3276 2016-09-11 19:25:44
认可0
本帖最后由 jl3276 于 2016-9-11 19:27 编辑

[code]HI_S32 SAMPLE_COMM_VO_StartChn(VO_DEV VoDev,VO_PUB_ATTR_S *pstPubAttr,SAMPLE_VO_MODE_E enMode)
{
    HI_S32 i;
    HI_S32 s32Ret = HI_SUCCESS;
    HI_U32 u32WndNum = 0;
    HI_U32 u32Square = 0;
    HI_U32 u32Width = 0;
    HI_U32 u32Height = 0;
    HI_U32 u32Frm = 0;
    VO_CHN_ATTR_S stChnAttr;
   
    switch (enMode)
    {
        case VO_MODE_1MUX:
            u32WndNum = 1;
            u32Square = 1;
            break;
        case VO_MODE_4MUX:
            u32WndNum = 4;
            u32Square = 2;
            break;
        case VO_MODE_9MUX:
            u32WndNum = 9;
            u32Square = 3;
            break;
        case VO_MODE_16MUX:
            u32WndNum = 16;
            u32Square = 4;
            break;
        default:
            SAMPLE_PRT("failed with %#x!\n", s32Ret);
            return HI_FAILURE;
    }

    s32Ret = SAMPLE_COMM_VO_GetWH(pstPubAttr->enIntfSync, &u32Width,&u32Height,&u32Frm);
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("failed with %#x!\n", s32Ret);
        return HI_FAILURE;
    }
    printf("u32Width:%d, u32Square:%d\n", u32Width, u32Square);
    for (i=0; i     {
        stChnAttr.stRect.s32X       = ALIGN_BACK((u32Width/u32Square) * (i%u32Square), 2);
        stChnAttr.stRect.s32Y       = ALIGN_BACK((u32Height/u32Square) * (i/u32Square), 2);
        stChnAttr.stRect.u32Width   = ALIGN_BACK(u32Width/u32Square, 2);
        stChnAttr.stRect.u32Height  = ALIGN_BACK(u32Height/u32Square, 2);
        stChnAttr.u32Priority       = 0;
        stChnAttr.bDeflicker        = HI_FALSE;

        s32Ret = HI_MPI_VO_SetChnAttr(VoDev, i, &stChnAttr);
        if (s32Ret != HI_SUCCESS)
        {
            printf("%s(%d):failed with %#x!\n",\
                   __FUNCTION__,__LINE__,  s32Ret);
            return HI_FAILURE;
        }

        s32Ret = HI_MPI_VO_EnableChn(VoDev, i);
        if (s32Ret != HI_SUCCESS)
        {
            SAMPLE_PRT("failed with %#x!\n", s32Ret);
            return HI_FAILURE;
        }
    }

    return HI_SUCCESS;
}[/code]
就是重新将VO配置并使能一下

maxsee9999

0个粉丝

3

问答

0

专栏

0

资料

maxsee9999 2016-12-29 22:31:45
认可0
就是重新将VO配置并使能一下

whlss

0个粉丝

3

问答

0

专栏

2

资料

whlss 2017-01-04 14:34:50
认可0
LZ你这个成功了吗??

whlss

0个粉丝

3

问答

0

专栏

2

资料

whlss 2017-01-04 14:35:51
认可0
我的sample 没有成功 在HI_MPI_VO_SetPubAttr()这个函数出现错误
不知道LZ遇到这个问题没有

GilbertLiang

0个粉丝

0

问答

0

专栏

0

资料

GilbertLiang 2017-01-05 13:12:26
认可0
说的很好。先收藏,免得一楼一楼地看哈

桃花岛主

0个粉丝

0

问答

0

专栏

0

资料

桃花岛主 2017-08-18 10:01:51
认可0
得细细阅读。谢谢楼主

testforvc

0个粉丝

1

问答

0

专栏

0

资料

testforvc 2017-09-27 16:18:27
认可0
谢谢楼主细致的分析 对我这种初学者很有帮助

feiyashan

0个粉丝

11

问答

0

专栏

0

资料

feiyashan 2016-12-28 08:53:15
认可0
谢谢楼主!!!

hero

0个粉丝

1

问答

0

专栏

0

资料

hero 2017-08-18 08:55:05
认可0
:):):):):):):):):):):)
或将文件直接拖到这里
悬赏:
E币
网盘
* 网盘链接:
* 提取码:
悬赏:
E币

Markdown 语法

  • 加粗**内容**
  • 斜体*内容*
  • 删除线~~内容~~
  • 引用> 引用内容
  • 代码`代码`
  • 代码块```编程语言↵代码```
  • 链接[链接标题](url)
  • 无序列表- 内容
  • 有序列表1. 内容
  • 缩进内容
  • 图片![alt](url)
+ 添加网盘链接/附件

Markdown 语法

  • 加粗**内容**
  • 斜体*内容*
  • 删除线~~内容~~
  • 引用> 引用内容
  • 代码`代码`
  • 代码块```编程语言↵代码```
  • 链接[链接标题](url)
  • 无序列表- 内容
  • 有序列表1. 内容
  • 缩进内容
  • 图片![alt](url)
相关问答
无更多相似问答 去提问
举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

易百纳技术社区