海思3536编码H264接口HI_MPI_VENC_SendFrame不能连续调用的问题

最近在做一个音视频对接的功能,需要将摄像头取到的YUV数据编码为H264的,由于摄像头采到的YUV为YUYV,而H264需要用到420进行编码,因此需要将YUYV转为YUV420格式。

在将YUYV转为YUV420之后,打算使用HI3536的编码接口HI_MPI_VENC_SendFrame将YUV编码为H264,但是在使用之后发现一个问题:只有在第一次调用该接口的时候才会成功,后面都会返回错误码:0xA0088003(参数超出合法范围),原本以为是填写的YUV转换出错导致的,后面将其保存为文件进行播放发现没问题。

经过多次测试,发现是有个参数未进行设置:u32TimeRef(图像帧序列号),如果该参数不进行设置的话,HI3536将会认为都是同一帧数据,因此只拿第一帧数据其他帧将会丢弃。

HI_VOID ReadFrameFromYuvData(char  *pcVideoData, HI_U8 * pY, HI_U8 * pU, HI_U8 * pV, HI_U32 width, HI_U32 height, HI_U32 stride, HI_U32 stride2)
{
    HI_U8 * pDst;

    HI_U32 u32Row;

    pDst = pY;
    for ( u32Row = 0; u32Row < height; u32Row++ )
    {
        //fread( pDst, width, 1, fp );
		memcpy(pDst,pcVideoData,width);
		pcVideoData += width;
        pDst += stride;
    }

    pDst = pU;
    for ( u32Row = 0; u32Row < height/2; u32Row++ )
    {
        //fread( pDst, width/2, 1, fp );
		memcpy(pDst,pcVideoData,width/2);
		pcVideoData += width/2;
        pDst += stride2;
    }

    pDst = pV;
    for ( u32Row = 0; u32Row < height/2; u32Row++ )
    {
        //fread( pDst, width/2, 1, fp );
		memcpy(pDst,pcVideoData,width/2);
		pcVideoData += width/2;
        pDst += stride2;
    }
}
int InitFrameInfo(uint32_t u32Width, uint32_t u32Height)
{
	 HI_U32            u32LStride;
    HI_U32             u32CStride;
    HI_U32             u32LumaSize;
    HI_U32             u32ChrmSize;
    HI_U32             u32Size;
    VB_BLK VbBlk;
    HI_U32 u32PhyAddr;
    HI_U8 *pVirAddr;
	
	VIDEO_FRAME_INFO_S g_stVFrameInfo;
	memset(&g_stVFrameInfo,0,sizeof(VIDEO_FRAME_INFO_S));

    u32LStride  = u32Stride;
    u32CStride  = u32Stride;

    u32LumaSize = (u32LStride * u32Height);
    u32ChrmSize = (u32CStride * u32Height) >> 2;/* YUV 420 */
    u32Size = u32LumaSize + (u32ChrmSize << 1);

    /* alloc video buffer block ---------------------------------------------------------- */
    VbBlk = HI_MPI_VB_GetBlock(VB_INVALID_POOLID, u32Size, NULL);
    if (VB_INVALID_HANDLE == VbBlk)
    {
        SAMPLE_PRT("HI_MPI_VB_GetBlock err! size:%d\n",u32Size);
        return -1;
    }
    u32PhyAddr = HI_MPI_VB_Handle2PhysAddr(VbBlk);
    if (0 == u32PhyAddr)
    {
        return -1;
    }

    pVirAddr = (HI_U8 *) HI_MPI_SYS_Mmap(u32PhyAddr, u32Size);
    if (NULL == pVirAddr)
    {
        return -1;
    }

    g_stVFrameInfo.u32PoolId = HI_MPI_VB_Handle2PoolId(VbBlk);
    if (VB_INVALID_POOLID == g_stVFrameInfo.u32PoolId)
    {
        return -1;
    }
	
    printf("pool id :%d, phyAddr:%x,virAddr:%x\n" ,g_stVFrameInfo.u32PoolId,u32PhyAddr,(int)pVirAddr);

    g_stVFrameInfo.stVFrame.u32PhyAddr[0] = u32PhyAddr;
    g_stVFrameInfo.stVFrame.u32PhyAddr[1] = g_stVFrameInfo.stVFrame.u32PhyAddr[0] + u32LumaSize;
    g_stVFrameInfo.stVFrame.u32PhyAddr[2] = g_stVFrameInfo.stVFrame.u32PhyAddr[1] + u32ChrmSize;

    g_stVFrameInfo.stVFrame.pVirAddr[0] = pVirAddr;
    g_stVFrameInfo.stVFrame.pVirAddr[1] = g_stVFrameInfo.stVFrame.pVirAddr[0] + u32LumaSize;
    g_stVFrameInfo.stVFrame.pVirAddr[2] = g_stVFrameInfo.stVFrame.pVirAddr[1] + u32ChrmSize;

    g_stVFrameInfo.stVFrame.u32Width  = u32Width;
    g_stVFrameInfo.stVFrame.u32Height = u32Height;
    g_stVFrameInfo.stVFrame.u32Stride[0] = u32LStride;
    g_stVFrameInfo.stVFrame.u32Stride[1] = u32CStride;
    g_stVFrameInfo.stVFrame.u32Stride[2] = u32CStride;
    g_stVFrameInfo.stVFrame.enPixelFormat = PIXEL_FORMAT_YUV_SEMIPLANAR_420;
    g_stVFrameInfo.stVFrame.u32Field = VIDEO_FIELD_INTERLACED;/* Intelaced D1,otherwise VIDEO_FIELD_FRAME */
	
	
	return 0;
}
int SendYuvFrameToEncoder(uint32_t u32TimeIndex,char  *pcYuvData)
{
	if(!pu8VirAddr || !pcVideoData)
	{
		printf("SendYuvFrameToEncoders Param error!!\n");
		return -1;
	}
    
	g_stVFrameInfo.stVFrame.u64pts     		= (GetCurrentTimeToMsecond()) ;
    g_stVFrameInfo.stVFrame.u32TimeRef 		= u32TimeIndex; //对于同一个通道,每次进入该函数u32TimeIndex应该变化
  

    /* read Y U V data from file to the addr ----------------------------------------------*/
    ReadFrameFromYuvData(pcYuvData, g_stVFrameInfo.stVFrame.pVirAddr[0],
       g_stVFrameInfo.stVFrame.pVirAddr[1], g_stVFrameInfo.stVFrame.pVirAddr[2],
       g_stVFrameInfo.stVFrame.u32Width, g_stVFrameInfo.stVFrame.u32Height,
       g_stVFrameInfo.stVFrame.u32Stride[0], g_stVFrameInfo.stVFrame.u32Stride[1] >> 1 );

    /* convert planar YUV420 to sem-planar YUV420 -----------------------------------------*/
    SAMPLE_COMM_VI_PlanToSemi(g_stVFrameInfo.stVFrame.pVirAddr[0], g_stVFrameInfo.stVFrame.u32Stride[0],
      g_stVFrameInfo.stVFrame.pVirAddr[1], g_stVFrameInfo.stVFrame.u32Stride[1],
      g_stVFrameInfo.stVFrame.pVirAddr[2], g_stVFrameInfo.stVFrame.u32Stride[1],
      g_stVFrameInfo.stVFrame.u32Width, g_stVFrameInfo.stVFrame.u32Height);
      
    s32Ret = HI_MPI_VENC_SendFrame(0, g_stVFrameInfo, 10);
	if (s32Ret)
	{
		printf("HI_MPI_VENC_SendFrame err, vi chn %d code:%#x\n",byChannelIndex,s32Ret);
		return -1;
	}

}

当调用InitFrameInfo初始化之后,调用SendYuvFrameToEncoder发送YUV数据到HI3536编码通道,每次进入该函数需要对u32TimeIndex进行设置,一般是进行累加操作。这样就能循环调用HI_MPI_VENC_SendFrame接口,使只编码为H264码流。

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值