This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

如何在AlgLink_OsdalgProcessFrame函数中分别获取Y、U、V三个分量并分别进行处理?



1、我想在 AlgLink_OsdalgProcessFrame 里用自己的算法替换osd算法,输入的视频流是

 SWOSD_FORMAT_YUV420sp,我想分别处理 y_buffer, cb_buffer and cr_buffer ,但是我不知道

如何分别提取cb_buffer and cr_buffer,是不是我需要创建两个数组用来临时存储cb_buffer and cr_buffer,

处理完后在把处理后的值赋值回去,如下:

 int i=0,j=0;

UInt8 *y_buffer = pFrame->addr[0][0];

UInt8 cbbuffer_arr[pFrameInfo->rtChInfo.height*(pFrameInfo->rtChInfo.width/4)];

UInt8 crbuffer_arr[pFrameInfo->rtChInfo.height*(pFrameInfo->rtChInfo.width/4)];

UInt8 *pBufferStart = pFrame->addr[0][1];

 for (i= 0; i<(pFrameInfo->rtChInfo.height*pFrameInfo->rtChInfo.width)>>1; i+=2)

{

    cbbuffer_arr[j] = *(pBufferStart+i);

    crbuffer_arr[j] = *(pBufferStart+i+1);

    j++;

}

/*----我的算法接口------*/

YUV420_PROCESS(y_buffer,cbbuffer_arr,crbuffer_arr);

j=0;

/*----处理完后的y_buffer,cbbuffer_arr,crbuffer_arr再赋值回去------*/

for (i= 0; i<(pFrameInfo->rtChInfo.height*pFrameInfo->rtChInfo.width)>>1; i+=2)

{

     *(pBufferStart+i)  = cbbuffer_arr[j];

     *(pBufferStart+i+1)= crbuffer_arr[j];

    j++;

}

这样对吗?

2、If I do that in   AlgLink_OsdalgProcessFrame,whether I rewrite

UInt8 *y_buffer = pFrame->addr[0][0]+0x30000000;

UInt8 *pBufferStart = pFrame->addr[0][1]+0x30000000;

  • 建议你看下dsp下面的va_link,你把数据放回去的意思都理解错了,你是想在dsp里面做数据处理吧,那va_link可以满足你的要求,我通过修改这个link已经实现了自己的算法,你得看懂这个valink的结构,大概意思是里面有两个线程,一个主线程负责接收上一个link发过来的数据System_getLinksFullFrames,然后调用VaLink_algCopyFrames通过DMA方式将数据拷贝到自己的队列里面Utils_bufPutFullFrame,然后将数据还回去System_putLinksEmptyFrames,通知处理线程处理数据Utils_tskSendCmd(&pObj->processTsk,SYSTEM_CMD_NEW_DATA);,

    结合mcfw user guide 然后看一个link,不懂就反复看反复琢磨,我看了半个月才有点头绪,这个RDK因为是新出来的资料和手册都比较少,上手确实有点难,贵在坚持。

  • han yang1,非常感谢您的回答,我就是想在dsp里添加自己的算法,我用的是DVRRDK_04.00.00.03,在/mcfw/src_bios6/links_c6xdsp/alg_link下有个

    algLink_priv.c函数

    Int32 AlgLink_algProcessData(AlgLink_Obj * pObj)

    {

        UInt32 frameId, status =  FVID2_SOK;

        System_LinkInQueParams *pInQueParams;

        FVID2_Frame *pFrame;

        FVID2_FrameList frameList;

     pInQueParams = &pObj->createArgs.inQueParams;

       System_getLinksFullFrames(pInQueParams->prevLinkId,

                                 pInQueParams->prevLinkQueId, &frameList);

    #ifdef ENABLE_FXN_PROFILE

        AlgLink_drvFxnProfileControl(pObj);

    #endif /* #ifdef ENABLE_FXN_PROFILE */

        if (frameList.numFrames)

        {

            pObj->inFrameGetCount += frameList.numFrames;

            /* SCD should be done first as it requires to operate on raw YUV */

            if (pObj->createArgs.enableSCDAlg)

            {

                status = AlgLink_ScdAlgSubmitFrames(&pObj->scdAlg, &frameList);

            }

            for(frameId=0; frameId<frameList.numFrames; frameId++)

            {

                pFrame = frameList.frames[frameId];

                if(pFrame->channelNum >= pObj->inQueInfo.numCh)

                    continue;

                // do SW OSD

                if (pObj->createArgs.enableOSDAlg)

                {

                    AlgLink_OsdalgProcessFrame(&pObj->osdAlg, pFrame);

                }

            }

            System_putLinksEmptyFrames(pInQueParams->prevLinkId,

                                       pInQueParams->prevLinkQueId, &frameList);

        }

        return status;

    }

    我用蓝色标记的就是你说的接收上个link发送过来的数据和把数据换回去的函数,我是在红色标记的这个函数里添加自己的算法的AlgLink_OsdalgProcessFrame(&pObj->osdAlg, pFrame);这个函数里面就是负责数据的处理的,里面应该跟你说的哪个意思吧?我真是个初学者,才看了一个星期,我会按照你说的思路好好研究一下,非常感谢你的回答。

     

  • 对的,你只需要修改红色标记的函数内容来实现你的算法,pFrame结构体有你要的YUV数据,不知道你们的算法处理时间是否过长,像我们的算法处理时间比较长,所以需要另外一个线程来处理,如果仍然在这个线程里面处理的话会导致数据不能及时还回去,而造成队列阻塞出错,这点需要注意,我当时就遇到过。一个星期时间有点短,我上手这个RDK到现在差不多2个月,才有点感觉,心得就是反复看代码,还有那个mcfw手册,不过这个手册写的确实有点简陋。

  • 我这个版本里没有va_link

  • 我们要在里面添加车牌识别的接口函数,处理的图像大小是2448*2048,具体我也不大懂,刚接触。现在lib库函数加进去了,就剩接口函数的调用不知道该如何添加了。应该就剩在下面这个函数里改,我还得好好研究研究

    Int32 AlgLink_OsdalgProcessFrame(AlgLink_OsdObj * pObj, FVID2_Frame *pFrame)
    {
        UInt32 winId, fid, scaleX, divY, scaleStartX;
        AlgLink_OsdChObj *pChObj;
        SWOSD_Obj *pSwOsdObj;
        System_FrameInfo *pFrameInfo;
        UInt32 algColorKey[2];
        Bool isInterlaced, isTiled;

        isInterlaced    = FALSE;
        isTiled         = FALSE;
        fid             = 0;
        scaleX          = 1; /* Video frame Scale X */
        scaleStartX     = 1; /* Scale graphics X */
        divY            = 1;

        pChObj = &pObj->chObj[pFrame->channelNum];

        pSwOsdObj = &pChObj->osdObj;


        if(pObj->inQueInfo->chInfo[pFrame->channelNum].scanFormat == SYSTEM_SF_INTERLACED)
            isInterlaced = TRUE;

        if(SYSTEM_MT_TILEDMEM == pObj->inQueInfo->chInfo[pFrame->channelNum].memType)
            isTiled = TRUE;

        if(isInterlaced)
        {
            /* OSD plane is always progressive
               Input can be interlaced in this case we need to skip alternate lines in OSD plane
               and feed for blending
            */
            if(pFrame->fid==1)
                fid = 1;

            /* this will half the processing height */
            divY = 2;
        }

        if(pSwOsdObj->graphicsWindowPrm.format == SWOSD_FORMAT_YUV422i)
            scaleX = 2;/* Pixel offset multiplier, 2 as in 422p format each pixel is of 2 bytes.*/

        if(pSwOsdObj->graphicsWindowPrm.format == SWOSD_FORMAT_RGB888)
        {
            scaleX       = 3; /* Pixel offset multiplier, 3 as in RGB format each pixel is of 3 bytes.*/
            if(pChObj->osdObj.videoWindowPrm.format == SWOSD_FORMAT_YUV422i)
               scaleStartX  = 2; /* Pixel offset multiplier, 2 as in 422p format each pixel is of 2 bytes.*/
        }
        algColorKey[0] = AlgLink_OsdalgGetColorKey(
                            pChObj->colorKey,
                            pSwOsdObj->graphicsWindowPrm.format,
                            0
                         );

        algColorKey[1] = 0;

        if(pSwOsdObj->graphicsWindowPrm.format == SWOSD_FORMAT_YUV420sp)
        {
            algColorKey[1] = AlgLink_OsdalgGetColorKey(
                            pChObj->colorKey,
                            pSwOsdObj->graphicsWindowPrm.format,
                            1
                          );
        }

        /* NOT SUPPORTED */
        pSwOsdObj->alphaWindowAddr = NULL;

        pFrameInfo = (System_FrameInfo*)pFrame->appData;
          
        UTILS_assert(pFrameInfo!=NULL);

        if(pFrameInfo->rtChInfoUpdate)
        {
            /* Need to comment this as we dont update this when we update frameInfo in IPCFrameIn*/
    //        pSwOsdObj->videoWindowPrm.format = pFrameInfo->rtChInfo.dataFormat;
            pSwOsdObj->videoWindowPrm.startX = pFrameInfo->rtChInfo.startX;
            pSwOsdObj->videoWindowPrm.startY = pFrameInfo->rtChInfo.startY;
            pSwOsdObj->videoWindowPrm.width  = pFrameInfo->rtChInfo.width;
            pSwOsdObj->videoWindowPrm.height = pFrameInfo->rtChInfo.height;
            pSwOsdObj->videoWindowPrm.lineOffset = pFrameInfo->rtChInfo.pitch[0];
        }
        for(winId=0; winId<pChObj->numWindows; winId++)
        {
            if(!pChObj->osdWinObj[winId].enableWin)
                continue;

            /* YUV422i or YUV420SP - Y-plane processing */

            pSwOsdObj->videoWindowAddr = pFrame->addr[0][0];

            if (isTiled)
            {
                pSwOsdObj->videoWindowAddr =
                    (Ptr)Utils_tilerAddr2CpuAddr((UInt32)pFrame->addr[0][0]);
                pSwOsdObj->videoWindowPrm.lineOffset =  VPSUTILS_TILER_CNT_8BIT_PITCH;
            }

            pSwOsdObj->globalPrm.globalAlpha        = pChObj->osdWinObj[winId].globalAlpha;
            pSwOsdObj->globalPrm.transperencyEnable = pChObj->osdWinObj[winId].transperencyEnable;
            pSwOsdObj->globalPrm.transperencyColor32= algColorKey[0];
            pSwOsdObj->graphicsWindowPrm            = pChObj->osdWinObj[winId].osdWinPrm;
            pSwOsdObj->graphicsWindowAddr           =
                         pChObj->osdWinObj[winId].addr[0][0] + fid*pSwOsdObj->graphicsWindowPrm.lineOffset*scaleX;

            /* Hori.(X) startX offset in a frame, Gpx will start from this offset */
            if(pSwOsdObj->graphicsWindowPrm.format == SWOSD_FORMAT_RGB888)
                 pSwOsdObj->graphicsWindowPrm.startX *= scaleStartX;
            else
                 pSwOsdObj->graphicsWindowPrm.startX *= scaleX;

            pSwOsdObj->graphicsWindowPrm.startY     /= divY;
            pSwOsdObj->graphicsWindowPrm.width  *= scaleX;

            pSwOsdObj->graphicsWindowPrm.height     /= divY;
            pSwOsdObj->graphicsWindowPrm.lineOffset *= (scaleX * divY); // double line offset
           
            pSwOsdObj->videoWindowPrm.dataPlane = SWOSD_DATAPLANE_LUMA;
            #if 0
            AlgLink_OsdalgPrintInfo(pSwOsdObj, pFrame);
            #endif

            SWOSD_blendWindow(pSwOsdObj);

            /* YUV420SP - C -plane processing */
            if(pSwOsdObj->graphicsWindowPrm.format == SWOSD_FORMAT_YUV420sp)
            {
                pSwOsdObj->videoWindowAddr = pFrame->addr[0][1];
                if (isTiled)
                {
                    pSwOsdObj->videoWindowAddr =
                        (Ptr)Utils_tilerAddr2CpuAddr((UInt32)pFrame->addr[0][1]);
                    pSwOsdObj->videoWindowPrm.lineOffset =  VPSUTILS_TILER_CNT_16BIT_PITCH;
                }

                pSwOsdObj->graphicsWindowAddr           =
                            pChObj->osdWinObj[winId].addr[0][1] + fid*pSwOsdObj->graphicsWindowPrm.lineOffset*scaleX;

                pSwOsdObj->graphicsWindowPrm.startY /= 2;    // half width  for C plane
                pSwOsdObj->graphicsWindowPrm.height /= 2;    // half height for C plane

                pSwOsdObj->globalPrm.transperencyColor32= algColorKey[1];
                pSwOsdObj->videoWindowPrm.dataPlane = SWOSD_DATAPLANE_CHROMA;
                #if 0
                AlgLink_OsdalgPrintInfo(pSwOsdObj, pFrame);
                #endif

                SWOSD_blendWindow(pSwOsdObj);
            }       
            /* YUV420SP Frame - C -plane processing */
            if((pSwOsdObj->graphicsWindowPrm.format == SWOSD_FORMAT_RGB888) &&
                   (pChObj->osdObj.videoWindowPrm.format == SWOSD_FORMAT_YUV420sp))
            {
                pSwOsdObj->videoWindowAddr = pFrame->addr[0][1];
                if (isTiled)
                {
                    pSwOsdObj->videoWindowAddr =
                        (Ptr)Utils_tilerAddr2CpuAddr((UInt32)pFrame->addr[0][1]);
                    pSwOsdObj->videoWindowPrm.lineOffset =  VPSUTILS_TILER_CNT_16BIT_PITCH;
                }

                pSwOsdObj->graphicsWindowAddr           =
                            pChObj->osdWinObj[winId].addr[0][0] + fid*pSwOsdObj->graphicsWindowPrm.lineOffset*scaleX;

                pSwOsdObj->graphicsWindowPrm.startY /= 2;    // half width  for C plane
                pSwOsdObj->graphicsWindowPrm.height /= 2;    // half height for C plane

                pSwOsdObj->graphicsWindowPrm.lineOffset *= 2; // Double line offset of RGB888
                pSwOsdObj->globalPrm.transperencyColor32= algColorKey[0];
                pSwOsdObj->videoWindowPrm.dataPlane = SWOSD_DATAPLANE_CHROMA;
                #if 0
                AlgLink_OsdalgPrintInfo(pSwOsdObj, pFrame);
                #endif

                SWOSD_blendWindow(pSwOsdObj);
            }

        }

        return 0;
    }

  • @ han yang1

    你说的“如果算法处理时间比较长,需要另外一个线程来处理,否则会造成队列阻塞出错“,能再具体说说吗?我们现在就碰到类似的问题,算法处理的时间较长,运行时发现程序没过多久就死掉了,一直都没找到原因。

  • 你说的功能我已经实现了,不过我们的要求还很多,所以还需要往深点挖,如果需要帮助私下聊。

  • 你可以看VAlink的代码或者fdlink,里面有两个任务,一个主任务,一个处理任务,打个简单的比方,水桶装水,一共有10个空桶,前面一个link装满水后把桶给下一个link,下一个link用完水后就把桶还给上一个link这样这个流水线才能继续,否则上一个link没有空桶装水就挂掉了,所以如果当前link在使用某个桶的水时当又有装满水的桶过来了他如果不用则要把桶还回去,所以要两个任务来做,而且还桶的那个任务优先级要比处理某桶水的任务优先级高这样才能及时处理不要的桶。

  • 就我的理解来看。

    herobin 兄弟的意思是要将处理后的数据“水”还回去,而不是缓冲队列“桶”。

    Valink是没有Nextlink的。所以需要实现一个自己的link,该link应该有Nextlink。

    而且Valink应该只存在于IPNC RDK中,而不是DVR RDK。

  • 你好,simon blak :

    是这个意思,因为uv分量存储在pFrame->addr[0][1],uv是连续存储的,我想把uv分量分别提取出来分别进行处理。我不知道怎么在dsp里分配临时内存用来存储u和v分,希望您能给讲解一下。

  • 你不是已经标示问题已解答了吗??

    不知道你的算法为什么要处理UV信息,一般都只处理Y分量的。

    dsp分配内存你可以尝试用Utils_memAlloc或者Utils_memAlloc_cached,RDK里头有源码。

  • 因为要涉及到颜色的识别,所以必须得处理U和V的信息,不知道如何分别存储U和V信息。

  • 1 可以不用分别存储,如果是420sp_UV,那么通过下标转换就可以访问Y对应的UV数据,节省拷贝时间和空间。

    2如果你非要把他们分开,分配空间有两种方法,一种是从 frame buffer里面分配,调用Ptr Utils_memAlloc(UInt32 size, UInt32 align)这个函数,另外就是改memory map,将dsp的数据空间增大,然后定义一个全局数组变量。

    3 420sp_UV 在内存里的存储方式百度就知道了。

  • 非常感谢您的回答,我们图像组给的接口函数是ProcessCar(pYBuf, pUBuf, pVBuf, &str_rec_con[0], &str_rec_con[1], &str_rec_con[2]);,pYBuff,pUBuf,pVBuf都是unsigned char *类型的,是不是就应该把U,V分别存储起来?还是您说的通过下标转换就可以。问的不专业请见谅。

  • 给你的接口看来是要分开存储,你们应该有人懂yuv的存储方式,,不是yuv422i就是420sp

  • 传过来的数据就是420sp的,所以我觉得应该把u,v分开存储,处理完再把处理后的y、u、v的值赋回给pFrame->addr[0][1],另外还要把处理的结果返回给A8。

  • han yang1,你好!

    我在使用VaLink移植我们的算法时候,我去修改进入到Va算法的图像大小:

    sclrPrm.outScaleFactor.absoluteResolution.outWidth = /*320*/352;
    sclrPrm.outScaleFactor.absoluteResolution.outHeight = /*192*/288;

    修改之后,程序就跑不起来了,你能帮忙指导指导下不?谢啦!

  • 我们用的也是DVR,没有va_link。我们也是需要添加进去视频处理算法,也是比较耗时间的。不知道你们实现车牌识别算法,没有vaLink的话是怎么应付处理时间过长这个问题的啊?

  • han yang1,你好啊。我也是个刚接触DVR的菜鸟啊。我们需要在框架里面添加进自己的视频处理算法,但是算法肯定是耗时的。但是因为我们是DVR_RDK,不是IPNC_RDK,并没有找到va_link,不知道还有没有其它的办法了?我看你总是非常热心的帮助我们这些菜鸟解决问题,能不能贴下你的qq联系方式啊?我的467923580。

  • @Jack, 

    请问你改了frame size之后调通了吗?

  • @herobin: 请问你一般是怎么把处理结果传给A8啊(从DSP端)?  我一直没找到太好的方法。

  • 你好,请问一下你算法接口加进去没,现在我也是和你一样,要把接口写进去,大神能不能指点一下,留下你的qq,我的qq是85639973,谢谢可爱热心的你们

  • 你好,大神问一下你的车牌算法识别进行哪里了,现在我也在搞这个,有很多问题需要像你请教,能不能留下你的联系方式,我的qq85639973

  • ipnc_mcfw/mcfw/src_bios6/links_common/va/vaLink_tsk.c文件中,

    VaLink_init函数调用了Utils_tskCreate创建VaLink_processTskMain任务,我在VaLink_processTskMain中用Vps_printf为什么打印不出来呢,但是在VaLink_init中加Vps_printf可以打印,这是为什么呢。

    还有mcfw user guide我怎么没有找到呢,问题很低级,不好意思了

  • 你好 从DSP端传送到A8端信息 你找到好办法了吗?

  • 你好,我想在8127 dsp中添加自己的lib库,我想问下是自己重新创建link呢,还是在现有的link中添加呢