Hass Multimedia (MPP) Development (8) - VI of YUV data acquisition

Preface:

    Hass multimedia processing platform (MPP) is divided into: a video input (VI), a video processing (VPSS), a video encoder (VENC), a video decoder (VDEC), video output (VO), Video Detection Analysis (VDA), the audio input (AI), an audio output (AO), the audio encoder (AENC), an audio decoder (ADEC), area management (the rEGION) modules. presented here video input module acquires data directly YUV (VI) in.

Introduction:

    In normal use the video output and video coding, we are bound to the VI channel to the other modules, an image data stream into other modules. If an application needs to obtain the original camera YUV data when the data is not to be obtained from or VENC VO module, the use of such promising scenario Hass reservation interface directly from the raw data acquired image VI. Which is mainly used to these two interfaces: HI_MPI_VI_SetFrameDepth and HI_MPI_VI_GetFrame

HI_MPI_VI_GetFrame:

    Set VI acquired image maximum depth.

    HI_S32 HI_MPI_VI_SetFrameDepth(VI_CHN ViChn, HI_U32 u32Depth);

This interface is used to set a certain channel VI buffered video frames. When the user sets the multi-frame buffer video images, the user can obtain a certain number of consecutive image data.

Precautions:

(1) If the specified u32Depth is 0, indicating that the system does not require channel VI cached images, so the user can not acquire image data of the VI channel. VI default channel is not cached images, i.e. u32Depth defaults to 0.

(2) If the specified u32Depth> 0, the buffer system VI for u32Depth image channel, the user can obtain the image data through an interface channel VI HI_MPI_VI_GetFrame. Specifically divided into the following situations:

  • User has not acquired image.

The system will automatically update the oldest image data, to ensure that users get once you start, you can get to the nearest latest u32Depth consecutive images.

  • Users get u32Depth times in a row and has not released.

VB because the system can not automatically stop acquiring new VI image caching, users can not get the new VI image. It is suggested that the user interface to ensure the acquisition and release paired.

  • User Gets / release rate is slower than the speed of image generation channel VI.

The system will automatically update the oldest image data is not acquired by the user to ensure that the cached image queue for the recent new VI image. Since the user does not guarantee acquisition speed, resulting in a continuous image may not be obtained.

(3) system for each channel cache u32Depth a VI VI of image data, the cache block occupies the interior of the MPP (abbreviated VB). Therefore, the user should be provided with sufficient VB via the interface HI_MPI_VB_SetConf, it may take up too much because the system image buffer VB, VI thus affecting the normal image pickup, resulting in not obtaining the user image data VI. Support for dynamic adjustment u32Depth. Such as when a user is not required to obtain the VI channel data, it may be set to 0 u32Depth, VI to reduce the number of channels occupied by the internal VB; acquired when needed, and then u32Depth set to an appropriate value, to acquire the set time after continuous VI image.

 

HI_MPI_VI_GetFrame

Acquiring an image captured VI.

HI_S32 HI_MPI_VI_GetFrame(VI_CHN ViChn, VIDEO_FRAME_INFO_S *pstFrameInfom,HI_S32 s32MilliSec);    

Precautions

  1. This interface may acquire the video image information VI specified channel. The image information includes: width, height, pixel format, a time stamp and a physical address of each component of the YUV image.
  2. This interface should be effective only after the channel is enabled.
  3. Support multiple acquisitions and then released, but it is recommended to acquire and release an interface paired.
  4. Acquired physical address information from VideoBuffer MPP internal use, so after use, must call HI_MPI_VI_ReleaseFrame interface release its memory.
  5. pstFrameInfo -> stVFrame .u32PhyAddr [0] and pstFrameInfo -> stVFrame .u32PhyAddr [1] point to the physical address of the luminance and chrominance components of the image.

Examples of introduction:

 (A) channel initialization VI

VI module which acquires from the video data, first AD peripheral needs to be initialized, and initializes the channel VI.

/******************************************************** 
Function:    BIAO_Get_VI_Frame
Description: 初始化VI  ,然后直接获取YUV数据
Input:  none
OutPut: none
Return: 0: success,none 0:error
Others: 
Author: Caibiao Lee
Date:   2020-02-02
*********************************************************/
int BIAO_Get_VI_Frame(void)
{
    SAMPLE_VI_MODE_E enViMode = SAMPLE_VI_MODE_2_720P;
    VIDEO_NORM_E enNorm = VIDEO_ENCODING_MODE_PAL;

    HI_U32 u32ViChnCnt = 4;
    HI_S32 s32VpssGrpCnt = 4;
    
    VB_CONF_S stVbConf;   

    HI_S32 i;
    HI_S32 s32Ret = HI_SUCCESS;
    HI_U32 u32BlkSize;
    HI_CHAR ch;
    SIZE_S stSize;
    HI_U32 u32WndNum;

    /******************************************
     step  1: init variable 
    ******************************************/ 
    memset(&stVbConf,0,sizeof(VB_CONF_S));
    u32BlkSize = SAMPLE_COMM_SYS_CalcPicVbBlkSize(enNorm,\
                PIC_HD720, SAMPLE_PIXEL_FORMAT, SAMPLE_SYS_ALIGN_WIDTH,COMPRESS_MODE_SEG);
    stVbConf.u32MaxPoolCnt = 128;

    /* video buffer*/
    //todo: vb=15
    stVbConf.astCommPool[0].u32BlkSize = u32BlkSize;
    stVbConf.astCommPool[0].u32BlkCnt = u32ViChnCnt * 8;

    /******************************************
     step 2: mpp system init. 
    ******************************************/
    s32Ret = SAMPLE_COMM_SYS_Init(&stVbConf);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("system init failed with %d!\n", s32Ret);
        goto ERROR_0;
    }

    /******************************************
     step 3: start vi dev & chn
    ******************************************/
    s32Ret = SAMPLE_COMM_VI_Start(enViMode, enNorm);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("start vi failed!\n");
        goto ERROR_1;
    }

    BIAO_MPP_GET_VI_Frame(0);

ERROR_1: 
    SAMPLE_COMM_VI_Stop(enViMode);
    
ERROR_0:    
    SAMPLE_COMM_SYS_Exit();

}

(B) the acquisition YUV data

Use mpp YUV data acquisition system interface, and then save them to a file:

/******************************************************** 
Function:    BIAO_MPP_GET_VI_Frame
Description: 循环获取YUV数据
Input:  s32ViChn 通道号
OutPut: none
Return: 0: success,none 0:error
Others: 
Author: Caibiao Lee
Date:   2020-02-02
*********************************************************/
void BIAO_MPP_GET_VI_Frame(int s32ViChn)
{

    int s32Ret=-1;
    unsigned int u32Depth;
    unsigned int i = 10;
    unsigned int j = 0;
    unsigned int u32Size = 0;
    VIDEO_FRAME_INFO_S stFrameInfom;
    HI_S32 s32MilliSec;
    FILE * l_Fp = NULL;
    unsigned char *l_pUserAddr;

    s32Ret=HI_MPI_VI_GetFrameDepth(s32ViChn, &u32Depth);

    if(s32Ret!=0)
    {
        printf("%s %d HI_MPI_VI_GetFrameDepth(%d) err=%#x\n",__FUNCTION__,__LINE__,
            s32ViChn, s32Ret);
        return -1;
    }

    if(u32Depth==0)
    {
        s32Ret=HI_MPI_VI_SetFrameDepth(s32ViChn, 1);
        if(s32Ret!=0)
        {
            printf("%s %d HI_MPI_VI_SetFrameDepth(%d) err=%#x\n",
                __FUNCTION__,__LINE__, s32ViChn, s32Ret);
            return -2;
        }
    }

    i=10;
    while(i--)
    {
        s32Ret=HI_MPI_VI_GetFrame(s32ViChn, &stFrameInfom, s32MilliSec);
        if(s32Ret!=0)
        {
            printf("%s %d HI_MPI_VI_GetFrame(%d) err=%#x\n",__FUNCTION__,__LINE__,
                s32ViChn, s32Ret);
             usleep(100000);
            //return -3;
            continue;
        }

        if(i!=1)
        {
            sleep(1);
            continue;
        }
        
        printf("u32Width        = 0x%x \n",stFrameInfom.stVFrame.u32Width);
        printf("u32Height       = 0x%x \n",stFrameInfom.stVFrame.u32Height);
        printf("u32Field        = 0x%x \n",stFrameInfom.stVFrame.u32Field);
        printf("enPixelFormat   = 0x%x \n",stFrameInfom.stVFrame.enPixelFormat);
        printf("enVideoFormat   = 0x%x \n\n",stFrameInfom.stVFrame.enVideoFormat);

        for(j=0;j<3;j++)
        {
            printf("j = %d u32PhyAddr    = 0x%x \n",j,stFrameInfom.stVFrame.u32PhyAddr[j]);
            printf("j = %d pVirAddr        = 0x%x \n",j,stFrameInfom.stVFrame.pVirAddr[j]);
            printf("j = %d u32Stride       = 0x%x \n",j,stFrameInfom.stVFrame.u32Stride[j]);
            printf("j = %d u32HeaderPhyAddr= 0x%x \n",j,stFrameInfom.stVFrame.u32HeaderPhyAddr[j]);
            printf("j = %d pHeaderVirAddr  = 0x%x \n",j,stFrameInfom.stVFrame.pHeaderVirAddr[j]);
            printf("j = %d u32HeaderStride = 0x%x\n\n",j,stFrameInfom.stVFrame.u32HeaderStride[j]); 
        }

        printf("s16OffsetBottom = 0x%x \n",stFrameInfom.stVFrame.s16OffsetBottom);
        printf("s16OffsetLeft   = 0x%x \n",stFrameInfom.stVFrame.s16OffsetLeft);
        printf("s16OffsetRight  = 0x%x \n",stFrameInfom.stVFrame.s16OffsetRight);
        printf("u64pts          = 0x%x \n",stFrameInfom.stVFrame.u64pts);
        printf("u32TimeRef      = 0x%x \n",stFrameInfom.stVFrame.u32TimeRef);
        printf("u32PrivateData  = 0x%x \n",stFrameInfom.stVFrame.u32PrivateData); 
        printf("enFlashType     = 0x%x\n\n",stFrameInfom.stVFrame.stSupplement.enFlashType);

        
#if 0
        l_Fp = fopen("yuv420.yuv","w+");
        if(NULL==l_Fp)
        {
            printf("%s %d file open error \n",__FUNCTION__,__LINE__);
            break;
        }

        /**Y 分量**/
        u32Size = stFrameInfom.stVFrame.u32Stride[0]*stFrameInfom.stVFrame.u32Height;
        s32Ret = fwrite(stFrameInfom.stVFrame.u32PhyAddr[0],1,u32Size,l_Fp);
        if(s32Ret!=u32Size)
        {
            fclose(l_Fp);
            printf("%s %d fwrite file error %d \n",__FUNCTION__,__LINE__,s32Ret);
            break;
        }else
        {
            printf("%s %d write file len = %d \n",__FUNCTION__,__LINE__,s32Ret);
        }


        /**UV 分量**/
        u32Size = stFrameInfom.stVFrame.u32Stride[1]*stFrameInfom.stVFrame.u32Height;
        s32Ret = fwrite(stFrameInfom.stVFrame.u32PhyAddr[1],1,u32Size,l_Fp);
        if(s32Ret!=u32Size)
        {
            fclose(l_Fp);
            printf("%s %d fwrite file error %d \n",__FUNCTION__,__LINE__,s32Ret);
            break;
        }else
        {
            printf("%s %d write file len = %d \n",__FUNCTION__,__LINE__,s32Ret);
        }

        fclose(l_Fp);
#endif
   
       u32Size = stFrameInfom.stVFrame.u32Stride[0]*stFrameInfom.stVFrame.u32Height*3/2; 
       l_pUserAddr =(unsigned char *)HI_MPI_SYS_Mmap(stFrameInfom.stVFrame.u32PhyAddr[0], u32Size);
       if(NULL!=l_pUserAddr)
       {
            
           l_Fp = fopen("yuv420.yuv","w+");
           if(NULL==l_Fp)
           {
               printf("%s %d file open error \n",__FUNCTION__,__LINE__);
               break;
           }
                      
           s32Ret = fwrite(l_pUserAddr,1,u32Size,l_Fp);
           if(s32Ret!=u32Size)
           {
               fclose(l_Fp);
               printf("%s %d fwrite file error %d \n",__FUNCTION__,__LINE__,s32Ret);
               break;
           }else
           {
               printf("%s %d write file len = %d \n",__FUNCTION__,__LINE__,s32Ret);
           }

           HI_MPI_SYS_Munmap(l_pUserAddr, u32Size);
           fclose(l_Fp);
       }
 
        HI_MPI_VI_ReleaseFrame(s32ViChn, &stFrameInfom);

        break;
        
        //usleep(100000);

    }

    return 0;

}

Here are a few very important points:

(1) If the buffer depth image VI is 0, the required depth value set according to demand.

(2) HI_MPI_VI_GetFrame to acquire image data of the address is a physical address, but we need to address the application's virtual address, so it is necessary to convert the physical address of the virtual address before you can use, or not read the data. HI_MPI_SYS_Mmap need to use the interface to map virtual addresses and HI_MPI_SYS_Munmap unmapped.

(3) stFrameInfom.stVFrame.u32PhyAddr [0] is stored in the luminance component image, stFrameInfom.stVFrame.u32PhyAddr [1] is stored in the read color components. They address the two components are physically separate analysis, but their physical address is continuously distributed, it can be a memory-mapped together with the two components.

When (4) device has just started, it is possible VI there are no data for the first time to obtain data 0xa010800e may return an error code indicating that there is no data.

(5) has just started acquiring equipment, it may get to the empty image, an image that is all black screen, start from the back a few frames to normal.

Result of the above code is run as follows:

BIAO_MPP_GET_VI_Frame 352 HI_MPI_VI_GetFrame(0) err=0xa010800e
u32Width        = 0x500 
u32Height       = 0x2d0 
u32Field        = 0x4 
enPixelFormat   = 0x17 
enVideoFormat   = 0x0 

j = 0 u32PhyAddr    = 0x92243c00 
j = 0 pVirAddr        = 0x0 
j = 0 u32Stride       = 0x500 
j = 0 u32HeaderPhyAddr= 0x0 
j = 0 pHeaderVirAddr  = 0x0 
j = 0 u32HeaderStride = 0x0

j = 1 u32PhyAddr    = 0x92324c00 
j = 1 pVirAddr        = 0x0 
j = 1 u32Stride       = 0x500 
j = 1 u32HeaderPhyAddr= 0x0 
j = 1 pHeaderVirAddr  = 0x0 
j = 1 u32HeaderStride = 0x0

j = 2 u32PhyAddr    = 0x0 
j = 2 pVirAddr        = 0x0 
j = 2 u32Stride       = 0x0 
j = 2 u32HeaderPhyAddr= 0x0 
j = 2 pHeaderVirAddr  = 0x0 
j = 2 u32HeaderStride = 0x0

s16OffsetBottom = 0x0 
s16OffsetLeft   = 0x0 
s16OffsetRight  = 0x0 
u64pts          = 0x1 
u32TimeRef      = 0x164 
u32PrivateData  = 0x0 
enFlashType     = 0x0

BIAO_MPP_GET_VI_Frame 448 write file len = 1382400 
program exit normally!

As can be seen from the above results:

(1) VI is the input image resolution 1280 * 720; (0x500 * 0x2d0)

(2) corresponding to a pixel format of 0x17 Hass PIXEL_FORMAT_E in PIXEL_FORMAT_YUV_SEMIPLANAR_420

(3) Image span u32Stride = 0x500, to be noted here, the span may have a different image width, an image representing the span width plus the additional image data, in the absence of the attachment data, the pattern width as his of.

Because the image is YUV420 format, the size of the Y component is equal to the size of the image, the image component YU component is 1/2. YUV420 image data distribution is as follows:

According to the parameters described above, using pYUV tool to view files generated yuv420.yuv our program, shown below:

 

 

This chapter from the frequency measurement engineering "catalog preface" to get the address provided

 

The first article in this column "catalog preface," lists the complete directory column, read by directory order to help your understanding.

 

 

 

 

Published 175 original articles · won praise 262 · views 700 000 +

Guess you like

Origin blog.csdn.net/li_wen01/article/details/105140581