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

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宏后会在串口打印如下信息)
DM8148从DSP侧发送Frames流到A8侧程序配置_第1张图片

这里以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流
配置成功后串口打印

你可能感兴趣的:(dm8148学习,DM8148,DSP)