存档在 ‘dsp’ 分类

基于DM8127 &IPNC RDK 3.8的实时图像处理阶段记录

2015年1月13日

1.最近对IPNC RDK3.8整个开发套件的框架结构和大部分代码进行了熟悉,感觉总体上还行,但是很多细节上的地方还是很迷糊。
2.对RVM LINK进行了改造,实现了CAMER–>VPSS—>DSP(processlink也行)—>VPSS—>DISPLAY的link。
3.对输出的YUV422格式有了一定了解,并在DSP上实现了灰度图像处理。
4.接下来就是真正的算法移植.

Enjoy!!
20150113_213902

yuv422 转 gray image

2015年1月13日

Could you describe in more detail what you want the grey image format to be?

If you just want a luminance/brightness value for each pixel than you can just strip the Y values out of the existing YCbCr buffer for processing which would give you an array of byte values, one for each pixel, where the value represents the brightness of the pixel. I am not sure I understand why you want to convert to a RGB888 format if all you require is a grey version of the image.

In the code example here on the wiki there is actually a function that will take a YCbCr buffer and make it appear greyscale by wiping out all the color data, you could do a similar operation to make a buffer greyscale data in the format you are trying to work with.

//make the image greyscale by setting all chrominance to 0x80
void process_imagebw( void* currentFrame,  int yRows, int xPixels)
{
   
 int xx = 0;
 
     for( xx = 0; xx < (yRows * xPixels)*2; xx+=2 )//just operating on the chroma
      {

            *( ( (unsigned char*)currentFrame ) + xx ) = 0x80; //set all chroma to midpoint 0x80
         }

 
} // End process_imagebw()

参考文献:
1.http://e2e.ti.com/search?q=YUV422
2.http://e2e.ti.com/support/dsp/davinci_digital_media_processors/f/99/p/6155/23101#23101
3.http://e2e.ti.com/support/dsp/davinci_digital_media_processors/f/100/p/8521/34684#34684
4.http://e2e.ti.com/support/dsp/davinci_digital_media_processors/f/99/t/121390
5.http://www.filtermeister.com/wiki/index.php?page=RGB+to+Grayscale+Conversion
6.http://processors.wiki.ti.com/index.php?title=Accessing_pixels_in_a_frame_on_DM643x

IPNC RDK OSD流程

2015年1月7日

1. 工作原理

1.1 Process link

OSD link是所谓的process link。即,该link没有output queue,而是直接在input queue的buffer上做操作。其数据流向如下图

  • 1. prev link将frame buffer送给process的input queue
  • 2. process link在input queue中取出buffer,对buffer的数据进行操作
  • 3. process link将该buffer归还给prev link的empty queue
  • 4. prev link检测到该buffer是从一个process link还回来的,于是又将其发送到next link去。

1.2 OSD简述

OSD Link功能运行在C67 DSP核上,一般工作在Capture Link之后,用来在采集到的视频帧上叠加一个图片(LOGO或是标题等)。待叠加的图片pic存放在共享内存SR0中(RGB或者YUV点阵格式)。当一帧数据frame从capture link送到OSD link,DSP首先启动EDMA将pic和frame的一部分从共享内存和DDR中搬移到内部L2中去。然后DSP根据预先设置的alpha参数,对pic和frame相应位置的每一点做alpha blend。计算好的结果被EDMA搬回输入的frame buffer中去覆盖原有的数据。由于OSD link属于Process link,该frame buffer会被送到下一个link中去,从而完成OSD效果。

2. 工作流程

  1. 1. DSP的main程序创建system_main线程,system_main中调用AlgLink_init。
  2. 2. 进入AlgLink_init,创建两个AlgLink的实例。对于每一个实例,调用System_registerLink和创建task。
  3. System_registerLink主要是为了注册下面几个回调函数

    linkObj.linkGetFullFrames   = NULL;
    linkObj.linkPutEmptyFrames  = NULL;
    linkObj.linkGetFullBitBufs  = AlgLink_getFullBufs;
    linkObj.linkPutEmptyBitBufs = AlgLink_putEmptyBufs;
    linkObj.getLinkInfo         = AlgLink_getInfo;

    其中linkGetFullBitBufs是为了给next link从本link的output queue获取bitstream buffer,而linkPutEmptyBitBufs则给next link将用完的buffer归还给本link。
    由于OSD本身没有output queue,所以这两个函数实际是给共用Alglink的SCD算法使用的。

  4. 3. 创建AlgLink_tskMain线程。
  5. 4. 进入AlgLink_tskMain,当收到一条create消息时,进入下列处理,否则直接丢掉该消息返回。
  6. 5. 进入AlgLink_algCreate,内部实际是调用AlgLink_OsdalgCreate。
  7. 6. 进入AlgLink_OsdalgCreate。该函数主要做了两方面的事,一是根据传入的create arg,设置OSD的运行context(其实就是拷贝到本地的一些变量中保存啦)。二是调用SWOSD_open。
  8. 7. SWOSD_open主要为了注册两个数据结构:SWOSD_TI_IALG和SWOSD_TI_IRES。这两个是TI XDAIS标准规定的算法标准接口。前一个主要关注算法的memory需求和分配,后一个关注算法对DMA资源的需求。我们下面分开来说。
  9. l SWOSD_TI_IALG
    #define IALGFXNS  \
    &amp;SWOSD_TI_IALG,  /* module ID */                         \
    NULL,            /* activate */                          \
    SWOSD_TI_alloc,  /* alloc */                             \
    NULL,            /* control (NULL =&gt; no control ops) */  \
    NULL,            /* deactivate */                        \
    SWOSD_TI_free,   /* free */                              \
    SWOSD_TI_initObj,/* init */                              \
    NULL,            /* moved */                             \
    SWOSD_TI_numAlloc            /* numAlloc (NULL =&gt; IALG_MAXMEMRECS) */
    

    这几个函数都是为了让Application来分配算法所需要的memory资源。Application首先调用SWOSD_TI_numAlloc,得到需要的IALG_MemRec个数。每一个memRec代表一个内存块的需求,包括分配区域,内存块大小,对齐等属性。然后Application根据该个数,分配相应个数的IALG_MemRec大小的buffer,将该buffer当做参数调用SWOSD_TI_alloc。算法的SWOSD_TI_alloc函数负责填写各个IALG_MemRec结构的大小,内存区域,对齐等属性,除了base address。Application然后根据填好的各IALG_MemRec从相应的内存区分配memory,并将分配好的memory buffer地址填入base address字段。最后将整个IALG_MemRec数组传入SWOSD_TI_initObj。算法用Application分配好的memory来完成自己的初始化。
    实际上,TI为了简化操作,实现了一套framework来完成这些。在SWOSD_OPEN中,我们可以看到,通过调用DSKT2_createAlg函数,将SWOSD_TI_IALG这一套函数指针传入即可完成上面的交互过程。
    对于OSD ALG来说,其需要的内存区有两个(memTab[2])。memTab[0]用来存放OSD_obj的内容,也就是运行的一些context。memTab[1]用来进行一行的blend运算。假设一行宽度为N个pixel,每个pixel需要Mbytes,则需要的内存大小为N*M*[1(blend输入1)+1(blend输入2)+ 1( output buffer) +1 (alpha matrix)]*2(ping pong buffer)
    其中blend输入1和2分别对应video buffer和osd picture的一行。Alpha matrix暂时并未实现,其目的本来是为了可以对每一个像素点指定一个alpha值。这两个内存区都是从DSP的L2里分配。
    l SWOSD_TI_IRES
    该结构与SWOSD_TI_IALG类似,只不过其分配的是DMA资源。这里不再详细描述。注意framework也封装了一个类似的RMAN_assignResources来完成交互过程。
    OSD alg总共需要5个EDMA通道

    #define SWOSD_DMA_CH_IN_A  0x0
    #define SWOSD_DMA_CH_IN_B  0x1
    #define SWOSD_DMA_CH_ALP   0x2   //传送alpha matrix,暂无试用
    #define SWOSD_DMA_CH_OUT  0x3
    #define SWOSD_DMA_CH_AUX  0x4   //用来在alpha值为0x80时,用来完成单纯的覆盖而不是blend。暂无使用。

     

  10. 8. SWOSD_open执行完,AlgLink_algCreate执行完,即可进入消息处理循环。与OSD功能相关的是两个消息: ALG_LINK_OSD_CMD_SET_CHANNEL_WIN_PRM和SYSTEM_CMD_NEW_DATA。
  11. 9. 一般来说,create后应该先收到ALG_LINK_OSD_CMD_SET_CHANNEL_WIN_PRM消息来设置每一通道的OSD属性。存放OSD图片的SR0 buffer地址也是在这时传入。在demo程序中,这一动作是在Vcap_setDynamicParamChn中完成。
  12. 10. 当收到SYSTEM_CMD_NEW_DATA时,进入AlgLink_algProcessData。该函数首先调用System_getLinksFullFrames,从prev link中取得frame buffers。然后调用AlgLink_OsdalgProcessFrame处理每一个frame buffer,最后调用System_putLinksEmptyFrames将处理完的frame buffer返还前一个link。
    11. AlgLink_OsdalgProcessFrame调用SWOSD_blendWindow分别对Y plane(亮度)和C plane(UV通道)进行处理。
  13. 12. SWOSD_blendWindow首先调用RMAN_activateAllResources,在OSD算法中,这实际是一个空操作。然后调用SWOSD_TI_algRun核心算法。
  14. 13. SWOSD_TI_algRun使用了3个EDMA通道,记为SWOSD_DMA_CH_IN_A,SWOSD_DMA_CH_IN_B,SWOSD_DMA_CH_OUT。SWOSD_DMA_CH_IN_A负责将OSD图像中的一行从SR0搬移到L2的ping-pong buffer中,SWOSD_DMA_CH_IN_B负责将video frame中的一行从frame buffer中搬移到L2的ping-pong buffer,而SWOSD_DMA_CH_OUT负责将blend后的数据从L2 ping pongbuffer中搬移到video frame中。

其流程如下:
等待SWOSD_DMA_CH_IN_A和SWOSD_DMA_CH_IN_B 对ping buffer的搬移完成
SWOSD_DMA_CH_IN_A和SWOSD_DMA_CH_IN_B启动pong buffer的搬移。
DSP计算alpha blend的值,写入L2的out pong buffer。
等待SWOSD_DMA_CH_OUT ping buffer搬移完成
启动SWOSD_DMA_CH_OUT pong buffer的搬移
其中ping pong buffer的切换由EDMA参数自动变换,运行过程中无需再手动切换ping pong buffer地址。

mpsclr和Scaler link

2015年1月7日

mpsclr是把大的分辨率缩放到1080p,Scaler只能缩放1080p以下的分辨率包括1080p

想实现 sclr不缩放,就是1:1的输出, 是不是创建参数设置如下就好了:

pSclrPrm->scaleMode = SCLR_SCALE_MODE_RATIO;
pSclrPrm->outScaleFactor.ratio.widthRatio.numerator =1;
pSclrPrm->outScaleFactor.ratio.heightRatio.numerator =1;

这个是按分辨率缩放的

sclrPrm.scaleMode =SCALE_MODE_ABSOLUTE;
sclrPrm.outScaleFactor.absoluteResolution.outWidth = 352;
sclrPrm.outScaleFactor.absoluteResolution.outHeight = 288;

我是先接mpsclr,再接sclr的。我选的不是缩放倍数,是指定缩放后的图片的大小。

代码如下:

//mpsclr
mpSclrPrm.inQueParams.prevLinkId = gMultiCh_VdecVdisObj.ipcInVpssId;
ipcInVpssPrm.outQueParams[0].nextLink = gMultiCh_VdecVdisObj.mpSclrId;

mpSclrPrm.pathId = MP_SCLR_LINK_SC5;
mpSclrPrm.numCh = 2;
mpSclrPrm.enableLineSkip = FALSE;

mpSclrPrm.outQueParams.nextLink = gMultiCh_VdecVdisObj.sclrId;

//sclr
SclrLink_CreateParams_Init(&sclrPrm);
sclrPrm.inQueParams.prevLinkId = gMultiCh_VdecVdisObj.mpSclrId;
sclrPrm.inQueParams.prevLinkQueId = 0;
sclrPrm.outQueParams.nextLink = gMultiCh_VdecVdisObj.ipcFramesOutVpssId;
sclrPrm.tilerEnable = FALSE;
sclrPrm.enableLineSkipSc = FALSE;
sclrPrm.inputFrameRate = 10;
sclrPrm.outputFrameRate = 10;
sclrPrm.scaleMode = DEI_SCALE_MODE_ABSOLUTE;
sclrPrm.outScaleFactor.absoluteResolution.outWidth = 352;
sclrPrm.outScaleFactor.absoluteResolution.outHeight = 288;

DSP端执行步骤

2015年1月7日

Int32 main(void)
—–>调用
System_start(C6XDSP_main);实际上也会调用Void System_procStart();
—–>调用
gSystem_objCommon.tsk = Task_create(System_main, &tskParams, NULL);
—–>调用
Void System_main(UArg arg0, UArg arg1)
Int32 System_init()
—–>调用
Void System_initLinks()
—–>调用
Int32 AlgLink_init()
—–>创建Task(Utils_tskCreate)
Void AlgLink_tskMain(struct Utils_TskHndl *pTsk, Utils_MsgHndl * pMsg)
—–>调用
status = AlgLink_algCreate(pObj, Utils_msgGetPrm(pMsg));
—–>循环接收CMD
比如当case SYSTEM_CMD_NEW_DATA时,
AlgLink_algProcessData(pObj);
—–>处理RAWYUV 或者FRAMES
AlgLink_ScdalgProcessData(&pObj->scdAlg, &frameList, &pObj->outObj[0].bufOutQue);
AlgLink_OsdalgProcessFrame(&pObj->osdAlg, pFrame);

link之间帧交换的帧结构

2015年1月6日
/**
 *  \brief FVID2 frame buffer structure.
 *
 *  Unless specified otherwise, all fields in this structure are
 *
 *  [IN]  for FVID2_queue(), FVID2_processFrames() operation.
 *  [OUT] for FVID2_dequeue(), FVID2_getProcessedFrames() operation.
 *
 */
typedef struct
{
    Ptr                 addr[FVID2_MAX_FIELDS][FVID2_MAX_PLANES];
    /**<
         FVID2 buffer pointers for supporting multiple addresses like
         Y, U, V etc for a given frame. The interpretation of these pointers
         depend on the format configured for the driver.
         The first dimension represents the field and the second dimension
         represents the color plane.
         Not all pointers are valid for a given format.

         Representation of YUV422 Planar Buffer:
         Field 0 Y -> addr[0][0], Field 1 Y -> addr[1][0]
         Field 0 U -> addr[0][1], Field 1 U -> addr[1][1]
         Field 0 V -> addr[0][2], Field 1 V -> addr[1][2]
         Other pointers are not valid.

         Representation of YUV422 Interleaved Buffer:
         Field 0 YUV -> addr[0][0], Field 1 YUV -> addr[1][0]
         Other pointers are not valid.

         Representation of YUV420SP or YUV422SP Buffer:
         Field 0 Y  -> addr[0][0], Field 1 Y  -> addr[1][0]
         Field 0 UV -> addr[0][1], Field 1 UV -> addr[1][1]
         Other pointers are not valid.

         Representation of RGB888 Buffer
         Field 0 RGB -> addr[0][0], Field 1 RGB -> addr[1][0],
         Other pointers are not valid.

         For progressive mode data formats
         or when fields are processed by driver in frame mode.
         addr[1][x] is not used.

         Instead of using numerical for accessing the buffers, the application
         can use the macros defined for each buffer formats like
         FVID2_YUV_INT_ADDR_IDX, FVID2_RGB_ADDR_IDX, FVID2_FID_TOP etc. */

    UInt32              fid;
    /**< Indicates whether this frame belong to top or bottom field.
         For valid values see #FVID2_Fid. */
    UInt32              channelNum;
    /**< Channel number to which this FVID2 frame belongs to. */

    UInt32              timeStamp;
    /**< Time stamp returned by the driver, in units of msecs.
         Only valid for frames received using FVID2_dequeue(). */
    Ptr                 appData;
    /**< Additional application parameter per frame. This is not modified by
         driver. */

    Ptr                 perFrameCfg;
    /**< Per frame configuration parameters like scaling ratio, positioning,
         cropping etc...
         This should be set to NULL if not used.

         This can be used by application to control driver behaviour on a per
         frame basis, example changing scaling ratio for scalar driver.

         This can be used by application to get per frame status, example
         detected frame width, height from capture driver.

         This could be set to NULL if not used. In this case, the driver will
         use the last supplied configuration.

         The exact structure type that is passed is driver specific. */

    Ptr                 blankData;
    /**< Blanking data associated with this video frame.
         This could be set to NULL if not used. */

    Ptr                 drvData;
    /**< Used by driver. Application should not modify this. */

    FVID2_SubFrameInfo    *subFrameInfo;
    /**< Used for SubFrame level processing information exchange between
         application and driver.
         This could be set to NULL if sub-frame level processing  is not used. */

    Ptr                 reserved;
    /**< For future use. Not used currently. Set this to NULL. */

} FVID2_Frame;

IPNC usecase选择宏

2015年1月6日
#ifdef IPNC_DSS_ON
    vsysParams.systemUseCase = VSYS_USECASE_MULTICHN_TRISTREAM_FULLFTR;
#else
    vsysParams.systemUseCase = VSYS_USECASE_MULTICHN_TRISTREAM_LOWPWR;
#endif

#ifdef CAPTURE_DISPLAY_MODE
    vsysParams.systemUseCase = VSYS_USECASE_DUALCHN_DISPLAY;
#endif

#ifdef CAPTURE_MCTNF_DISP_MODE
	vsysParams.systemUseCase = VSYS_USECASE_MCTNF_DEMO;
#endif

    if(gUI_mcfw_config.vaUseCase == TRUE)
    {
        vsysParams.systemUseCase = VSYS_USECASE_TRISTREAM_SMARTANALYTICS;
    }

    if((gUI_mcfw_config.vaUseCase == FALSE) && (gUI_mcfw_config.demoUseCase != 0))
    {
        vsysParams.systemUseCase = VSYS_USECASE_DUALCHN_DEMO;
        if((gUI_mcfw_config.snfEnable == TRUE) ||
        (gUI_mcfw_config.tnfEnable == TRUE) ||
        (gUI_mcfw_config.ldcEnable == TRUE) ) // as LDC is part of VNF lib
            gUI_mcfw_config.vnfUseCase = TRUE;
    }
#ifdef ENC_A8_DEC_USE_CASE
    vsysParams.systemUseCase = VSYS_USECASE_ENC_A8_DEC;
#endif

#ifdef QUAD_STREAM_NF_USE_CASE
    vsysParams.systemUseCase = VSYS_USECASE_MULTICHN_QUADSTREAM_NF;
#endif

#ifdef RVM_DEMO_MODE
	vsysParams.systemUseCase = VSYS_USECASE_RVM_DEMO;
#endif

IPNC SDK3.8 RVM_DEMO_MODE UseCase

2015年1月5日

.\ipnc_rdk\ipnc_mcfw\mcfw\src_bios6\links_c6xdsp\system\system_c6xdsp.c

Int32 System_init()中

 System_initLinks();

.\ipnc_rdk\ipnc_mcfw\mcfw\src_bios6\links_c6xdsp\system\System_c6xdsp.c

Void System_initLinks()中

 AlgLink_init();
VaLink_init();
NullLink_init();
MergeLink_init();
SelectLink_init();
RvmLink_init();

文件为.ipnc_rdk\ipnc_mcfw\mcfw\src_bios6\links_c6xdsp\rvm\rvmLink_tsk.c

Int32 RvmLink_init()中

 status = Utils_tskCreate(&pObj->tsk,
RvmLink_tskMain,
RVM_LINK_TSK_PRI,
gRvmLink_tskStack[rvmId],
RVM_LINK_TSK_STACK_SIZE, pObj, tskName);

文件为.ipnc_rdk\ipnc_mcfw\mcfw\src_bios6\links_c6xdsp\rvm\rvmLink_tsk.c

Void RvmLink_tskMain(struct Utils_TskHndl * pTsk, Utils_MsgHndl * pMsg)中

 /* create the rvm algorithm */
status = RvmLink_create(pObj, Utils_msgGetPrm(pMsg));

文件为.ipnc_rdk\ipnc_mcfw\mcfw\src_bios6\links_c6xdsp\rvm\rvmLink_tsk.c

在Int32 RvmLink_create(RvmLink_Obj * pObj, RvmLink_CreateParams * pPrm)中

/* Allocate LUT memory */
pObj->pLut = Utils_memAlloc(RVM_LINK_LUT_SIZE,32);
UTILS_assert(pObj->pLut != NULL);

/* Read LUT data into LUT memory */
//strcpy((char*)rvmLutPrm.fileName,"/mnt/mmc/lut_9j003_5mp_2nd.dat");
strcpy((char*)rvmLutPrm.fileName,"/mnt/mmc/lut_2560x1920.dat");
//strcpy((char*)rvmLutPrm.fileName,"/mnt/mmc/lut_2048x1152.dat");
//strcpy((char*)rvmLutPrm.fileName,"/mnt/mmc/RVM_lut.bin");
rvmLutPrm.lutBufAddr = (UInt32)pObj->pLut;
rvmLutPrm.lutBufSize = RVM_LINK_LUT_SIZE;

System_linkControl(SYSTEM_LINK_ID_HOST,
SYSTEM_COMMON_READ_RVM_LUT,
&rvmLutPrm,
sizeof(SystemCommon_rvmLutPrm),
TRUE);
UTILS_assert(rvmLutPrm.errorCode == 0); 

这个assert出错

[c6xdsp ]  5943: Assertion @ Line: 117 in links_c6xdsp/rvm/rvmLink_tsk.c: rvmLutPrm.errorCode == 0 : failed !!!

DSP使用System_linkControl发送了SYSTEM_COMMON_READ_RVM_LUT命令,由A8 HOST接受,以下为A8端代码
在文件:.\ipnc_rdk\ipnc_mcfw\mcfw\src_linux\mcfw_api\ti_vsys.c

Int32 Vsys_eventHandler(UInt32 eventId, Ptr pPrm, Ptr appData)
 case SYSTEM_COMMON_READ_RVM_LUT:
 pRvmLutPrm = (SystemCommon_rvmLutPrm*)pPrm;

 pRvmLutPrm->errorCode = 0;
 sdCardMounted = 0;

 memDevFd = open("/dev/mem",O_RDWR|O_SYNC);
 if(memDevFd < 0)
 {
 OSA_printf(" ERROR: /dev/mem open failed !!!\n");
 pRvmLutPrm->errorCode = -1;
 }
 else
 {
 /* Open LUT file and find the file size */
 FILE *fp = fopen(pRvmLutPrm->fileName,"rb");
 if(fp == NULL)
 {
 /* May be SD card is not mounted,try mounting it */
 if(system("mount -t vfat /dev/mmcblk0 /mnt/mmc\n") != 0)
 {
 OSA_printf(" ERROR: SD card mount failed !!!\n");
 pRvmLutPrm->errorCode = -1;
 }
 else
 {
 sdCardMounted = 1;
 fp = fopen(pRvmLutPrm->fileName,"rb");
 }
 }

 if(fp == NULL)
 {
 OSA_printf(" ERROR: LUT file open failed !!!\n");
 pRvmLutPrm->errorCode = -1;
 }
 else
 {
 /* Go to end of file */
 fseek(fp,0,SEEK_END);

 fileSize = ftell(fp);
 pRvmLutPrm->lutFileSize = fileSize;

 /* Go to beginning of file */
 fseek(fp,0,SEEK_SET);

 if(fileSize > pRvmLutPrm->lutBufSize)
 {
 OSA_printf(" ERROR: LUT buffer is insufficient !!!\n");
 pRvmLutPrm->errorCode = -1;
 }
 else
 {
 /* Map the LUT buffer */
 virtLutBufAddr = MMAP(pRvmLutPrm->lutBufAddr,fileSize);
 if(virtLutBufAddr == NULL)
 {
 OSA_printf(" ERROR: mmap of LUT buffer failed !!!\n");
 pRvmLutPrm->errorCode = -1;
 }
 else
 {
 /* Read LUT file into LUT buffer */
 if(fread(virtLutBufAddr,1,fileSize,fp) != fileSize)
 {
 OSA_printf(" ERROR: File read failed !!!\n");
 pRvmLutPrm->errorCode = -1;
 }
 else
 {
 Cache_wb((Ptr)virtLutBufAddr,fileSize,Cache_Type_ALL,TRUE);
 }

 /* Unmap the address space */
 MUNMAP((UInt32)virtLutBufAddr,fileSize);
 }
 }

 fclose(fp);
 }

 close(memDevFd); 

 if(sdCardMounted == 1)
 {
 /* Unmount SD card */
 system("umount /mnt/mmc\n");
 }
 }

 break;

其中由于打开文件

strcpy((char*)rvmLutPrm.fileName,"/mnt/mmc/lut_2560x1920.dat");失败,
同时加载SD卡,试图在SDK中寻找这个文件失败导致。