移植EMCV到DM6467(5)——修改encodedecode demo测试算法封装
2013-10-20 10:08
405 查看
1 修改encodedecode demo测试codec
接下来,我们需要将修改过后的videnc_copy集成到encodedecodedemo中,实现实时采集视频、使用EMCV添加矩形框、然后输出显示的功能。1.1 修改demo
(1)修改encodedecode.cfg
要使用videnc_copy,需要在encodedecode.cfg中修改createFromServer函数的参数,如下所示。var demoEngine = Engine.createFromServer( "encodedecode", "bin/ti_platforms_evmDM6467/all.x64P", "ti.sdo.ce.examples.servers.all_codecs" ); |
(2)修改codecs.c
由于我们不对视频进行H264编码,所以需要在codecs中注释掉相关的参数定义。#if 0 /* Use extended dynamic parameters to allow tweaking of the QP value */ static IH264VENC_DynamicParams extDynParams = { { sizeof(IVIDENC1_DynamicParams), /* size */ 576, /* inputHeight */ 720, /* inputWidth */ 25000, /* refFrameRate */ 25000, /* targetFrameRate */ 2000000, /* targetBitRate (override in app) */ 30, /* intraFrameInterval */ XDM_DECODE_AU, /* generateHeader */ 0, /* captureWidth */ IVIDEO_NA_FRAME, /* forceFrame */ 1, /* interFrameInterval */ 0 /* mbDataFlag */ }, 18, /* QPISlice */ 20, /* QPSlice */ 51, /* RateCtrlQpMax */ 0, /* RateCtrlQpMin */ 0, /* NumRowsInSlice */ 0, /* LfDisableIdc */ 0, /* LFAlphaC0Offset */ 0, /* LFBetaOffset */ 0, /* ChromaQPOffset */ 0, /* SecChromaQPOffset */ }; #endif |
(3)修改capture.c
由于encodedecode中默认是要将输入的YUV422视频流转换为YUV420再传递给video线程,而我们的videnc_copy是直接处理YUV422视频流,不需要进行转换,所以需要在Capture.c中修改部分代码。#if 0 /* Configure color conversion job */ if (Ccv_config(hCcv, hInBuf, hDstBuf) < 0) { ERR("Failed to configure 422 to 420 color conversion job\n"); cleanup(THREAD_FAILURE); } else printf("Succeed to configure 422 to 420 color conversion job.\n"); #endif frameSkip = TRUE; /* Signal that initialization is done and wait for other threads */ Rendezvous_meet(envp->hRendezvousInit); while (!gblGetQuit()) { if (frameSkip) { /* Capture an extra frame to halve the frame rate */ if (Capture_get(hCapture, &hCapBuf) < 0) { ERR("Failed to get capture buffer\n"); cleanup(THREAD_FAILURE); } if (Capture_put(hCapture, hCapBuf) < 0) { ERR("Failed to put capture buffer\n"); cleanup(THREAD_FAILURE); } } /* Get a buffer from the capture driver to encode */ if (Capture_get(hCapture, &hCapBuf) < 0) { ERR("Failed to get capture buffer\n"); cleanup(THREAD_FAILURE); } if (resize) { /* Resize buffer from 720P to a smaller resolution */ if (Resize_execute(hRsz, hCapBuf, hIntBuf) < 0) { ERR("Failed to execute resize job\n"); cleanup(THREAD_FAILURE); } hInBuf = hIntBuf; } else { hInBuf = hCapBuf; } //if (Ccv_execute(hCcv, hInBuf, hDstBuf) < 0) { // ERR("Failed to execute color conversion job\n"); // cleanup(THREAD_FAILURE); //} /* Send color converted buffer to video thread for encoding */ if (Fifo_put(envp->hOutFifo, hInBuf) < 0) { ERR("Failed to send buffer to display thread\n"); cleanup(THREAD_FAILURE); } /* Return a buffer to the capture driver */ if (Capture_put(hCapture, hCapBuf) < 0) { ERR("Failed to put capture buffer\n"); cleanup(THREAD_FAILURE); } /* Get a buffer from the video thread */ fifoRet = Fifo_get(envp->hInFifo, &hInBuf); if (fifoRet < 0) { ERR("Failed to get buffer from video thread\n"); cleanup(THREAD_FAILURE); } /* Did the video thread flush the fifo? */ if (fifoRet == Dmai_EFLUSH) { cleanup(THREAD_SUCCESS); } } |
(4)修改display.c
同样,由于videnc_copy输出的视频流为YUV422格式,不需要进行转换就可以直接传递给驱动进行显示,所以在display.c中也要修改部分代码。static Int config(Ccv_Handle hCcv, Blend_Handle hBlend, UI_Handle hUI, Buffer_Handle hSrcBuf, Buffer_Handle hDstBuf, UInt8 trans) { Blend_Config_Params bConfigParams = Blend_Config_Params_DEFAULT; Buffer_Handle hBmpBuf; Int i; #if 0 /* Configure the 420->422 color conversion job */ if (Ccv_config(hCcv, hSrcBuf, hDstBuf) < 0) { ERR("Failed to configure color conversion job\n"); return FAILURE; } #endif …… /* * Color convert the 420Psemi decoded buffer from * the video thread to the 422Psemi display. */ //if (Ccv_execute(hCcv, hSrcBuf, hDstBuf) < 0) { // ERR("Failed to execute color conversion job\n"); // cleanup(THREAD_FAILURE); //} |
(5)修改video.c
video.c中的修改较多,只讲一下主要部分。首先,注释掉与H264编解码相关的变量和参数,添加一些用于videnc_copy的变量。
VIDENC_Handle enc = NULL; String encoderName = "videnc_copy"; VIDENC_InArgs encInArgs; VIDENC_OutArgs encOutArgs; VIDENC_DynamicParams encDynParams; VIDENC_Status encStatus; XDAS_Int8 *inBuf; XDAS_Int8 *encodedBuf; XDM_BufDesc inBufDesc; XDAS_Int8 *src[XDM_MAX_IO_BUFFERS]; XDAS_Int32 inBufSizes[XDM_MAX_IO_BUFFERS]; XDM_BufDesc encodedBufDesc; XDAS_Int8 *encoded[XDM_MAX_IO_BUFFERS]; XDAS_Int32 encBufSizes[XDM_MAX_IO_BUFFERS]; Memory_AllocParams allocParams; encInArgs.size = sizeof(encInArgs); encOutArgs.size = sizeof(encOutArgs); encDynParams.size = sizeof(encDynParams); encStatus.size = sizeof(encStatus); allocParams.type = Memory_CONTIGPOOL; allocParams.flags = Memory_NONCACHED; allocParams.align = BUFALIGN; allocParams.seg = 0; inBuf = (XDAS_Int8 *)Memory_alloc(IFRAMESIZE, &allocParams); encodedBuf = (XDAS_Int8 *)Memory_alloc(EFRAMESIZE, &allocParams); /* clear and initialize the buffer descriptors */ memset(src, 0, sizeof(src[0]) * XDM_MAX_IO_BUFFERS); memset(encoded, 0, sizeof(encoded[0]) * XDM_MAX_IO_BUFFERS); src[0] = inBuf; encoded[0] = encodedBuf; inBufDesc.numBufs = encodedBufDesc.numBufs = 1; inBufDesc.bufSizes = inBufSizes; encodedBufDesc.bufSizes = encBufSizes; inBufSizes[0] = IFRAMESIZE; encBufSizes[0] = EFRAMESIZE; inBufDesc.bufs = src; encodedBufDesc.bufs = encoded; |
gfxAttrs.colorSpace = ColorSpace_YUV422PSEMI; gfxAttrs.dim.width = envp->imageWidth; gfxAttrs.dim.height = envp->imageHeight; gfxAttrs.dim.lineLength = BufferGfx_calcLineLength(gfxAttrs.dim.width, gfxAttrs.colorSpace); |
if (!envp->passThrough) { fifoRet = Fifo_get(envp->hDisplayOutFifo, &hDispBuf); memcpy(inBuf, Buffer_getUserPtr(hVidBuf), IFRAMESIZE); #ifdef CACHE_ENABLED #ifdef xdc_target__isaCompatible_64P Memory_cacheWbInv(inBuf, IFRAMESIZE); #else #error Unvalidated config - add appropriate fread-related cache maintenance #endif Memory_cacheInv(encodedBuf, EFRAMESIZE); #endif //memcpy(encodedBuf, inBuf, EFRAMESIZE); ret = VIDENC_process(enc, &inBufDesc, &encodedBufDesc, &encInArgs, &encOutArgs); if (ret < 0) { cleanup(THREAD_FAILURE); } #ifdef CACHE_ENABLED Memory_cacheWb(encodedBuf, EFRAMESIZE); #endif memcpy(Buffer_getUserPtr(hDispBuf), encodedBuf, EFRAMESIZE); Buffer_setNumBytesUsed(hDispBuf, EFRAMESIZE); /* Update global data for user interface */ gblIncVideoBytesProcessed(EFRAMESIZE); if (Fifo_put(envp->hDisplayInFifo, hDispBuf) < 0) { ERR("Failed to send buffer to display thread\n"); cleanup(THREAD_FAILURE); } /* and return input video frame to capture thread */ if (Fifo_put(envp->hCaptureInFifo, hVidBuf) < 0) { ERR("Failed to send buffer to capture thread\n"); cleanup(THREAD_FAILURE); } } else { /* Send the buffer through to the display thread unmodified */ if (Fifo_put(envp->hDisplayInFifo, hVidBuf) < 0) { ERR("Failed to send buffer to display thread\n"); cleanup(THREAD_FAILURE); } } |
#if 0 /* Get a buffer from the display thread to send to the capture thread */ if ((ret != Dmai_EFIRSTFIELD) && (Fifo_getNumEntries(envp->hDisplayOutFifo))) { do { fifoRet = Fifo_get(envp->hDisplayOutFifo, &hDispBuf); if (fifoRet < 0) { ERR("Failed to get buffer from video thread\n"); cleanup(THREAD_FAILURE); } /* Did the display thread flush the fifo? */ if (fifoRet == Dmai_EFLUSH) { cleanup(THREAD_SUCCESS); } /* The display thread is no longer using the buffer */ Buffer_freeUseMask(BufTab_getBuf(hBufTab, Buffer_getId(hDispBuf)), /*Buffer_getUseMask(BufTab_getBuf(hBufTab, Buffer_getId(hDispBuf)))*/DISPLAY_FREE); /* Get a free buffer */ hDstBuf = BufTab_getFreeBuf(hBufTab); if (hDstBuf == NULL) { ERR("Failed to get free buffer from BufTab\n"); BufTab_print(hBufTab); cleanup(THREAD_FAILURE); } /* * Reset the dimensions of the buffer in case the decoder has * changed them due to padding. */ BufferGfx_resetDimensions(hDstBuf); /* Send a buffer to the capture thread */ if (Fifo_put(envp->hCaptureInFifo, hDstBuf) < 0) { ERR("Failed to send buffer to capture thread\n"); cleanup(THREAD_FAILURE); } } while (Fifo_getNumEntries(envp->hDisplayOutFifo) > 0); } #endif |
1.2 程序运行结果
修改完之后,确认编译通过,然后下载到开发板上运行,串口调试终端输出信息如下所示。在显示器上的显示效果如下所示,证明程序运行成功。
1.3 遗留问题
从串口终端的输出信息可以看出,DSP端一直处于满负荷状态,视频处理的帧率还没有达到1fps,大约每处理1帧图像需要1.5秒左右的时间。这说明算法的效率很低,后期需要进行很多优化,主要考虑是将所有浮点运算转换为定点运算,因为DM6467的DSP是C64x+型定点DSP,做浮点运算时速度特别低。另外,可以考虑使用TI提供的DSPLIB、FastRTSLIB、IQMathLIB、IMGLIB和VLIB等库。用VLIB和IMGLIB替换掉MECV中的部分函数,用VLIB进行颜色空间转换,用FastRTS、IQMathLIB和DSPLIB来进行一些基本的数据处理,例如浮点运算、矩阵运算和乘除运算等操作。
以上这些库其实都已经集成到C6Accel中了,所以接下来的工作就是学习使用C6Accel,并将OpenCV集成进去。
相关文章推荐
- 移植EMCV到DM6467(5)——修改encodedecode demo测试算法封装
- 修改encodedecode demo测试算法封装
- 移植EMCV到DM6467(4)——video_copy例程的xDM算法封装
- 移植EMCV到DM6467(4)——video_copy例程的xDM算法封装
- 基于DM6467的OV5642视频采集编码程序设计(2)——Encode Demo测试
- 移植OpenCV的AdaBoost人脸检测算法到DM6467
- 6.对数组进行排序、求最大值和求元素和的函数采用静态成员函数的方式封装成数组算法类模板ArrayAlg,并采用相关数据进行测试。
- 高德地图的Js API 简单Demo,可以快速实现路点描线(摘自官方接口及自行修改测试)
- U-boot 2011.06 smdk6410的移植(转载-测试通过-修改)--下载后还不能运行......
- f2fs——FG_GC优化之从GREEDY算法修改为CAT算法并测试
- Android studio 百度地图demo 移植及常见错无修改fang'fa
- ExtJs6 Desktop Demo 修改测试
- PHP中json_encode、json_decode与serialize、unserialize的性能测试
- [hyddd安全性测试笔记1]URL Encode and URL Decode
- 通过demo搞懂encode_utf8和decode_utf8
- 学习笔记——《机器学习实战》KNN算法实现 约会网站测试,手写数字识别,代码,注释,错误修改
- PHP中json_encode、json_decode与serialize、unserialize的性能测试分析
- 通过demo搞懂encode_utf8和decode_utf8
- DM6467开发之U-Boot移植(3)——U-Boot移植测试
- 移植OpenCV的AdaBoost人脸检测算法到DM6467