概述
最近在做一个音视频对接的功能,需要将摄像头取到的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:%dn",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:%xn" ,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:%#xn",byChannelIndex,s32Ret);
return -1;
}
}
当调用InitFrameInfo初始化之后,调用SendYuvFrameToEncoder发送YUV数据到HI3536编码通道,每次进入该函数需要对u32TimeIndex进行设置,一般是进行累加操作。这样就能循环调用HI_MPI_VENC_SendFrame接口,使只编码为H264码流。
最后
以上就是阔达蜻蜓为你收集整理的海思3536编码H264接口HI_MPI_VENC_SendFrame不能连续调用的问题的全部内容,希望文章能够帮你解决海思3536编码H264接口HI_MPI_VENC_SendFrame不能连续调用的问题所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复