DM8148从DSP侧发送Frames流到A8侧程序配置

来源:互联网 发布:java 技术架构 编辑:程序博客网 时间:2024/06/16 06:06

DM8148从DSP侧发送Frames流到A8侧程序配置

最近在调试DM8148,根据需求需要将摄像头获取的数据送入DSP进行图像处理后再送入A8进行其他处理(网络发送等),在调试的过程中一直遇到数据从DSP侧发送到A8时,程序只能成功执行几次,然后A8侧的FramesInLink就获取不到数据,仔细阅读官方的例程后,总算是调通了,现在把过程记录下来。
第一次写,有不当或者错误的地方欢迎指出。
将Frames或者Bits数据流从BIOS侧发送到Linux侧时,除了正常的配置之外,还需要额外编写Linux侧中Frames/BitsIn的回调函数,并在回调函数中调用release释放被占用的ListMP资源,否则程序正常运行几次后便会因为队列/链表资源耗尽导致处理器之间的通信失败,现象是Linux能收到NEW_DATA_CMD命令,但是FramesTskMain/BitsTskMain程序中能够获得的有效帧是0(打开SYSTEM_DEBUG_IPC_RT宏后会在串口打印如下信息)
通信失败时串口的打印信息

这里以DSPFramesOut->HostFramesIn为例说明(注意如果是Vpss中只有一路Frames流或者Video中只有一路Bits流发送到Host,则只需要配置gVcamModuleContext.ipcFramesOutVpssToHostId和gVencModuleContext.ipcBitsOutRTOSId这两个参数就可以在配置Prm参数的时候直接使用MCFW库中提供的回调函(这两个可以参考multich_capturedisplay.c和multich_encode_decode.c中相关的参数配置),而不用手动编写回调函数)
由于MCFW库中并没有提供从DSP发送Frames/Bits时Linux侧的配置,因此如果需要完成从DSP发送Frames/Bits到A8侧,需要手动添加回调函数,并在回调函数中读取传过来的Frames/Bits数据。这里以Frames流从DSP发送到A8实例。
首先定义一个全局变量用于记录A8侧用来接收DSP发送来的数据的LinkID。

UInt32 gFramesDsp2HostId;

然后是两个Link的创建参数配置

        /*DSP Frames out to host*/        ipcFramesOutDspPrm.baseCreateParams.inQueParams.prevLinkId = ipcFramesInDspId;//helloWorldID;        ipcFramesOutDspPrm.baseCreateParams.inQueParams.prevLinkQueId = 0;        ipcFramesOutDspPrm.baseCreateParams.numOutQue = 1;        ipcFramesOutDspPrm.baseCreateParams.outQueParams[0].nextLink = ipcFramesInHostId0;        ipcFramesOutDspPrm.baseCreateParams.noNotifyMode = TRUE;        ipcFramesOutDspPrm.baseCreateParams.notifyPrevLink = TRUE;        ipcFramesOutDspPrm.baseCreateParams.notifyNextLink = FALSE;        ipcFramesOutDspPrm.baseCreateParams.inputFrameRate = 30;        ipcFramesOutDspPrm.baseCreateParams.outputFrameRate = 30;        /*host Frames in from DSP*/        ipcFramesInHostPrm0.baseCreateParams.inputFrameRate = 30;        ipcFramesInHostPrm0.baseCreateParams.inQueParams.prevLinkId = ipcFramesOutDspId;        ipcFramesInHostPrm0.baseCreateParams.inQueParams.prevLinkQueId = 0;        ipcFramesInHostPrm0.baseCreateParams.outQueParams[0].nextLink = SYSTEM_LINK_ID_INVALID;        ipcFramesInHostPrm0.baseCreateParams.notifyNextLink = FALSE;        ipcFramesInHostPrm0.baseCreateParams.notifyPrevLink = FALSE;        ipcFramesInHostPrm0.baseCreateParams.noNotifyMode = TRUE;        ipcFramesInHostPrm0.exportOnlyPhyAddr = TRUE;        ipcFramesInHostPrm0.cbCtx = NULL;        ipcFramesInHostPrm0.cbFxn = i_ipcFramesHostCb;

ipcFramesInHostPrm0.cbFxn表示A8侧收到数据后调用的回调函数指针,ipcFramesInHostPrm0.cbCtx为传入ipcFramesInHostPrm0.cbFxn的形参,这里使用gFrames2HostID来记录linkID,没有参数需要传向ipcFramesInHostPrm0.cbFxn,所以这里设置为NULL。
然后是回调函数Void i_ipcFramesHostCb(Ptr cbCtx)。

/*DSP 帧到host的回调函数,其中cbCtx为NULL*/Void i_ipcFramesHostCb(Ptr cbCtx){    UInt32 status = 0;    VIDEO_FRAMEBUF_LIST_S bufList;    OSA_printf("----------ipc Frames get from DSP Host link ID is %X-------------\n", gFramesDsp2HostId);    #if 1    VDsp_getFullVideoFrames(gFramesDsp2HostId, &bufList, 0);    OSA_printf("----------host get frames in ListMP-------------\n");    if (bufList.numFrames){            status = VDsp_putEmptyVideoFrames(gFramesDsp2HostId, &bufList);            OSA_assert(0 == status);            OSA_printf("----------Host release frames to MCFW-------------\n");    }    #endif}

关于这个函数的实现可以参考ti_vcap.c中static Void * App_ipcFramesSendRecvFxn(Void * prm)函数,这里实现与官方的稍有差异,官方库中App_ipcFramesSendRecvFxn为一个在初始化时候创建的线程,该线程创建完成后,便进入等待状态,回调函数仅向App_ipcFramesSendRecvFxn发送一个信号量,用来启动线程,线程启动后,进行处理相关操作。
接下来是VDsp_putEmptyVideoFrames和VDsp_getFullVideoFrames的实现。这两个函数的实现同样是参考ti_vcap.c中Vcam_getFullVideoFrames和Vcam_getFullVideoFrames的实现。

/*释放帧*/Int32 VDsp_putEmptyVideoFrames(UInt32 linkID, VIDEO_FRAMEBUF_LIST_S *pFrameBufList){    VIDEO_FRAMEBUF_S *pSrcBuf;    VIDFrame_Buf     *pDstBuf;    VIDFrame_BufList  vidBufList;    UInt32 i;    Int status = 0;    vidBufList.numFrames = pFrameBufList->numFrames;    for (i = 0; i < vidBufList.numFrames; i++)    {        pSrcBuf = &pFrameBufList->frames[i];        pDstBuf = &vidBufList.frames[i];        Vcam_copyVidFrameInfoMcFw2Link(pDstBuf,pSrcBuf);    }    if (vidBufList.numFrames)    {        status =        IpcFramesInLink_putEmptyVideoFrames(linkID,                                            &vidBufList);    }    return 0;}/*Host 获取从DSP传过来的帧*/Int32 VDsp_getFullVideoFrames(UInt32 linkID,                              VIDEO_FRAMEBUF_LIST_S *pFrameBufList, UInt32 timeout){    VIDFrame_BufList  vidBufList;    VIDFrame_Buf     *pInBuf;    VIDEO_FRAMEBUF_S *pOutBuf;    UInt32 i;    pFrameBufList->numFrames = 0;    vidBufList.numFrames = 0;    IpcFramesInLink_getFullVideoFrames(linkID, &vidBufList);    pFrameBufList->numFrames = vidBufList.numFrames;    for (i = 0; i < vidBufList.numFrames; i++)    {        pOutBuf = &pFrameBufList->frames[i];        pInBuf = &vidBufList.frames[i];        Vcam_copyVidFrameInfoLink2McFw(pOutBuf,pInBuf);    }    return 0;}

配置完成后,上电通过串口可以看到如下连续的打印信息,表示配置成功,A8侧读取到DSP发送的Frames流
配置成功后串口打印

原创粉丝点击