海思3518E开发笔记2.8——海思VENC(Video Encode)模块get stream详解

本文详细解读了HI_MPI_VENC_GetStream过程中,如何通过pthread控制线程启动与停止,以及如何异步处理多路编码流的保存,涉及文件准备、I/O管理、内存优化和环形缓冲。特别关注实时性和数据完整性保障。
摘要由CSDN通过智能技术生成

代码

/******************************************************************************
* funciton : start get venc stream process thread
******************************************************************************/
HI_S32 SAMPLE_COMM_VENC_StartGetStream(HI_S32 s32Cnt)
{
    gs_stPara.bThreadStart = HI_TRUE;
    gs_stPara.s32Cnt = s32Cnt;

    return pthread_create(&gs_VencPid, 0, SAMPLE_COMM_VENC_GetVencStreamProc, (HI_VOID*)&gs_stPara);
}

gs_VencPid是一个全局pthread_t变量
gs_stPara.bThreadStart,传进去后,用在一个while的判断中,如果不想进行while判断了,再把它变为false
gs_stPara.s32Cnt = s32Cnt记录了通道数,在上面通道数判断的时候进行了赋值

get stream流程讲解

线程执行SAMPLE_COMM_VENC_GetVencStreamProc获取venc编码后的视频流


第一步step 1: check & prepare save-file & venc-fd,根据通道数量依次对每个通道进行检查HI_MPI_VENC_GetChnAttr获取通道的属性,如果获取失败则说明通道有问题;接着SAMPLE_COMM_VENC_GetFilePostfix获取文件名后缀,通过判断通道属性中的payload将.h264.h265或者.jpg放入szFilePostfix中,然后将通道名、后缀名作为视频存储的文件名调用fopen;最后HI_MPI_VENC_GetFd设置venc 保存文件fd,第一步结束

编码完成后,生成的裸流在编码通道内部放着。想要在外面操作,就需要一个接口去操作编码通道内部的裸流数据。再通过这个结构拿到的fd,将裸流数据写到本地文件中。

因为它是流,所以只能一段一段去读


第二步step 2: Start to get streams of each channel。

这一步是这个线程的主while循环,判断条件为结构体中的一个参数。判断条件的结构体是一个全局变量,是可以在外部进行赋值的(按两下回车的地方将它置为false,在主线程控制拉流线程是否结束)。

由于有三路码流,一路是720p、一路是vga、一路xvga。我们也不知道mpp内部编码是如何实现,于是我们不知道这三路码流哪一路先出来。
解决方法是我们将三路码流的三路文件异步去对待就完了。即,使用select实现一个线程,通过记录I/O流的状态来同时管理多个I/O


接着按顺序判断是否每一路都准备好,若准备好,则
HI_MPI_VENC_Query查询一帧流中的数据包数量,如果有误则退出

接着检查当前包是否为空,为空则进入下一个通道进行操作
如果不为空,则继续往下走。申请一段内存,将编码好的视频流从编码通道中读到内存中

然后调用MPIHI_MPI_VENC_GetStream在限定时间内获取一帧视频流,获取失败则退出
如果能够成功获取,继续保存完整码流

保存码流,通过传入payload type进行判断裸流格式,从而进行保存,保存代码如下

HI_S32 SAMPLE_COMM_VENC_SaveH264(FILE* fpH264File, VENC_STREAM_S *pstStream)
{
    HI_S32 i;

    
    for (i = 0; i < pstStream->u32PackCount; i++)
    {
        fwrite(pstStream->pstPack[i].pu8Addr+pstStream->pstPack[i].u32Offset,
               pstStream->pstPack[i].u32Len-pstStream->pstPack[i].u32Offset, 1, fpH264File);

        fflush(fpH264File);
    }
    
    return HI_SUCCESS; 
}

数据结构如下

typedef struct hiVENC_PACK_S
{
    HI_U32   u32PhyAddr;                         /*the physics address of stream*/
    HI_U8   *pu8Addr;                            /*the virtual address of stream*/
    HI_U32   u32Len;                             /*the length of stream*/
    
    HI_U64   u64PTS;                                /*PTS*/
    HI_BOOL  bFrameEnd;                             /*frame end*/
    
    VENC_DATA_TYPE_U  DataType;                     /*the type of stream*/
    HI_U32   u32Offset;

	HI_U32 u32DataNum;
	VENC_PACK_INFO_S stPackInfo[8];
}VENC_PACK_S;

使用fflush确保了实时写入falsh,这样就不会出现53分断电,视频只存到51分的情况。摄像头对实时性要求非常高,所以需要确保实时写入。

海思的代码中,为缓存开了一个足够大的buffer进行操作,有时候DDR资源不够,就需要使用环形buffer


在存完后释放空间。每个方案的设计不同,海思方案需要进行release。海思在设计时,query会返回很多状态信息,getstream需要传入很多状态信息,架构设计完全可以将这里放到SDK内部去维护,但是海思让使用者去维护。这是为了灵活性这样设计的。


最后将之前malloc的空间释放掉,文件指针close

主线程中将while的判断条件置为false,将线程资源回收

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Spark!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值