我是靠谱客的博主 阔达蜻蜓,这篇文章主要介绍海思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将会认为都是同一帧数据,因此只拿第一帧数据其他帧将会丢弃。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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; } }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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; }
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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不能连续调用内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(78)

评论列表共有 0 条评论

立即
投稿
返回
顶部