东方未晞的老窝

Ideas worth spreading

在C6000系列DSP中使用EMCV

emcv是OpenCV针对C6000系列DSP的移植版本,目前只完成了我们工作中用到的部分。
下面对如何使用emcv做个简单的介绍:

1. 找到一个可用的demo

我们使用的是video_loopback例子,这个程序中DSP只是简单地将摄像头采集到的图像
显示出来。显示的过程是将采集帧缓冲的数据复制到显示帧缓冲中。

2. 将demo工程改为C++工程

简单的说,就是将工程中所有的*.c文件改为*.cpp文件。
因为C++基本兼容C,所以在cpp中还可以按照C语言的方式来开发。

如果开发板带的demo写的够规范,从C迁移到C++应该不会有任何问题。
不过实际的代码可能会出现一点。以videoloopback为例,在将工程改为C++之后
出现了15个错误:
代码: 全选
----------------------  seedvpm642_vedioloop.pjt - LOOP2  ----------------------
"c:/ti/c6000/cgtools/bin/cl6x" -g -fr"C:/work/test/video_loopback/LOOP2" -i"C:/work/test/video_loopback/include" -d"_DEBUG" -d"CHIP_DM642" -d"_LOOP2_" -mv6400 -@"../LOOP2.lkf" "appData.cpp"

"c:/ti/c6000/cgtools/bin/cl6x" -g -fr"C:/work/test/video_loopback/LOOP2" -i"C:/work/test/video_loopback/include" -d"_DEBUG" -d"CHIP_DM642" -d"_LOOP2_" -mv6400 -@"../LOOP2.lkf" "boot.asm"

"c:/ti/c6000/cgtools/bin/cl6x" -g -fr"C:/work/test/video_loopback/LOOP2" -i"C:/work/test/video_loopback/include" -d"_DEBUG" -d"CHIP_DM642" -d"_LOOP2_" -mv6400 -@"../LOOP2.lkf" "seedvpm642main.cpp"
"C:/work/test/video_loopback/include/edc.h", line 48: error: expected a declaration
"seedvpm642main.cpp", line 41: warning: return type "int" omitted in declaration of function "main"
1 error detected in the compilation of "seedvpm642main.cpp".

"c:/ti/c6000/cgtools/bin/cl6x" -g -fr"C:/work/test/video_loopback/LOOP2" -i"C:/work/test/video_loopback/include" -d"_DEBUG" -d"CHIP_DM642" -d"_LOOP2_" -mv6400 -@"../../LOOP2.lkf" "seedvpm642_vcapparamsPAL_EMBEDDED.cpp"
"C:/work/test/video_loopback/include/edc.h", line 48: error: expected a declaration
"C:/work/test/video_loopback/include/tvp51xx.h", line 43: error: identifier "TVP51XX_Mode" is undefined
"C:/work/test/video_loopback/include/tvp51xx.h", line 44: error: identifier "TVP51XX_AnalogFormat" is undefined
"seedvpm642_vcapparamsPAL_EMBEDDED.cpp", line 71: error: identifier "TVP51XX_MODE_PAL601" is undefined
"seedvpm642_vcapparamsPAL_EMBEDDED.cpp", line 72: error: identifier "TVP51XX_AFMT_COMPOSITE" is undefined
At end of source: error: expected a "}"
6 errors detected in the compilation of "seedvpm642_vcapparamsPAL_EMBEDDED.cpp".

"c:/ti/c6000/cgtools/bin/cl6x" -g -fr"C:/work/test/video_loopback/LOOP2" -i"C:/work/test/video_loopback/include" -d"_DEBUG" -d"CHIP_DM642" -d"_LOOP2_" -mv6400 -@"../../LOOP2.lkf" "seedvpm642_vdisparamsPAL.cpp"
"C:/work/test/video_loopback/include/edc.h", line 48: error: expected a declaration
"seedvpm642_vdisparamsPAL.cpp", line 109: error: a value of type "void *" cannot be used to initialize an entity of type "EDC_Fxns *"
"seedvpm642_vdisparamsPAL.cpp", line 118: error: a value of type "void *" cannot be used to initialize an entity of type "I2C_Handle"
At end of source: error: expected a "}"
4 errors detected in the compilation of "seedvpm642_vdisparamsPAL.cpp".

"c:/ti/c6000/cgtools/bin/cl6x" -g -fr"C:/work/test/video_loopback/LOOP2" -i"C:/work/test/video_loopback/include" -d"_DEBUG" -d"CHIP_DM642" -d"_LOOP2_" -mv6400 -@"../LOOP2.lkf" "tskloopback.cpp"
"C:/work/test/video_loopback/include/edc.h", line 48: error: expected a declaration
At end of source: error: expected a "}"
2 errors detected in the compilation of "tskloopback.cpp".

"c:/ti/c6000/cgtools/bin/cl6x" -g -fr"C:/work/test/video_loopback/LOOP2" -i"C:/work/test/video_loopback/include" -d"_DEBUG" -d"CHIP_DM642" -d"_LOOP2_" -mv6400 -@"../LOOP2.lkf" "tskvideocapturevp1.cpp"
"C:/work/test/video_loopback/include/edc.h", line 48: error: expected a declaration
At end of source: error: expected a "}"
2 errors detected in the compilation of "tskvideocapturevp1.cpp".

"c:/ti/c6000/cgtools/bin/cl6x" -g -fr"C:/work/test/video_loopback/LOOP2" -i"C:/work/test/video_loopback/include" -d"_DEBUG" -d"CHIP_DM642" -d"_LOOP2_" -mv6400 -@"LOOP2.lkf" "seedvpm642cfg.s62"

"c:/ti/c6000/cgtools/bin/cl6x" -g -fr"C:/work/test/video_loopback/LOOP2" -i"C:/work/test/video_loopback/include" -d"_DEBUG" -d"CHIP_DM642" -d"_LOOP2_" -mv6400 -@"LOOP2.lkf" "seedvpm642cfg_c.c"

Build Complete,
  15 Errors, 1 Warnings, 0 Remarks.


错误虽然感觉很多,其实只有简单的几类。首先看看第一个错误:
代码: 全选
C:/work/test/video_loopback/include/edc.h", line 48: error: expected a declaration


找到对应的代码:
代码: 全选
// edc.h

#ifdef __cplusplus
{
#endif
#endif /* _EDC_H */


这是一个简单的笔误,作者将'}'误写为'{'了。C++中函数正规的写法是:
代码: 全选
#ifndef _EDC_H
#define _EDC_H
                               
#ifdef __cplusplus
extern "C" {
#endif

// 这是C++实现的函数
// 但是C语言中也可以使用
// 对应汇编过程名字为 _cpp_fun,和C语言的编译规则一直

void cpp_fun();

#ifdef __cplusplus
}
#endif
#endif /* _EDC_H */


添加extern "C" {语句的原因是,C++中由于支持函数重载,一个函数的名字可能有几个;
在编译到汇编的时候,这些函数可能被重新命名(不是简单的在开头添加下划线'_'),
这样C语言或汇编在链接由C++实现的函数的时候就会找不到具体位置。

将第一个错误修改之后重新编译,现在只有2个错误:
代码: 全选
----------------------  seedvpm642_vedioloop.pjt - LOOP2  ----------------------
"c:/ti/c6000/cgtools/bin/cl6x" -g -fr"C:/work/test/video_loopback/LOOP2" -i"C:/work/test/video_loopback/include" -d"_DEBUG" -d"CHIP_DM642" -d"_LOOP2_" -mv6400 -@"../LOOP2.lkf" "seedvpm642main.cpp"
"seedvpm642main.cpp", line 41: warning: return type "int" omitted in declaration of function "main"

"c:/ti/c6000/cgtools/bin/cl6x" -g -fr"C:/work/test/video_loopback/LOOP2" -i"C:/work/test/video_loopback/include" -d"_DEBUG" -d"CHIP_DM642" -d"_LOOP2_" -mv6400 -@"../../LOOP2.lkf" "seedvpm642_vcapparamsPAL_EMBEDDED.cpp"

"c:/ti/c6000/cgtools/bin/cl6x" -g -fr"C:/work/test/video_loopback/LOOP2" -i"C:/work/test/video_loopback/include" -d"_DEBUG" -d"CHIP_DM642" -d"_LOOP2_" -mv6400 -@"../../LOOP2.lkf" "seedvpm642_vdisparamsPAL.cpp"
"seedvpm642_vdisparamsPAL.cpp", line 109: error: a value of type "void *" cannot be used to initialize an entity of type "EDC_Fxns *"
"seedvpm642_vdisparamsPAL.cpp", line 118: error: a value of type "void *" cannot be used to initialize an entity of type "I2C_Handle"
2 errors detected in the compilation of "seedvpm642_vdisparamsPAL.cpp".

"c:/ti/c6000/cgtools/bin/cl6x" -g -fr"C:/work/test/video_loopback/LOOP2" -i"C:/work/test/video_loopback/include" -d"_DEBUG" -d"CHIP_DM642" -d"_LOOP2_" -mv6400 -@"../LOOP2.lkf" "tskloopback.cpp"

"c:/ti/c6000/cgtools/bin/cl6x" -g -fr"C:/work/test/video_loopback/LOOP2" -i"C:/work/test/video_loopback/include" -d"_DEBUG" -d"CHIP_DM642" -d"_LOOP2_" -mv6400 -@"../LOOP2.lkf" "tskvideocapturevp1.cpp"

Build Complete,
  2 Errors, 1 Warnings, 0 Remarks.


找到出现错误的代码(2个错误在一起):
代码: 全选
VPORT_PortParams EVMDM642_vDisParamsPort = {
    FALSE,                      /*  enableDualChan;     */ 
    VPORT_POLARITY_ACTIVE_HIGH, /* vport control pin 1 polarity    */
    VPORT_POLARITY_ACTIVE_HIGH, /* vport control pin 2 polarity    */
    VPORT_POLARITY_ACTIVE_HIGH, /* vport control pin 3 polarity    */
    &SAA7105_Fxns,
    INV,
};    
           
SAA7105_ConfParams EVMDM642_vDisParamsSAA7105 = {
  SAA7105_AFMT_SVIDEO,
  SAA7105_MODE_PAL720,
  SAA7105_IFMT_YCBCR422_INTERLACED,
  TRUE,
  TRUE,
  INV,                   /*handleI2C */
};


都是提示类型不匹配。这个错误的产生原因是C++编译器对类型的检测更加严格。
在C语言中void*指针可能方便的和其他指针转换,但是C++中可能需要手工强制转换。

INV的定义可能和NULL类似,是一个无效值:
代码: 全选
#define INV    ((void*)(-1))


我们将INV增加一个强制类型转换来遍面编译器的错误:
代码: 全选
VPORT_PortParams EVMDM642_vDisParamsPort = {
    FALSE,                      /*  enableDualChan;     */ 
    VPORT_POLARITY_ACTIVE_HIGH, /* vport control pin 1 polarity    */
    VPORT_POLARITY_ACTIVE_HIGH, /* vport control pin 2 polarity    */
    VPORT_POLARITY_ACTIVE_HIGH, /* vport control pin 3 polarity    */
    &SAA7105_Fxns,
    (EDC_Fxns *)INV
};    
           
SAA7105_ConfParams EVMDM642_vDisParamsSAA7105 = {
  SAA7105_AFMT_SVIDEO,
  SAA7105_MODE_PAL720,
  SAA7105_IFMT_YCBCR422_INTERLACED,
  TRUE,
  TRUE,
  (I2C_Handle)INV                   /*handleI2C */
};


2个结构中类型分别为(EDC_Fxns *)和 (I2C_Handle)。

然后在重新编译。编译已经没有错误,但是出现2个link错误:
代码: 全选
----------------------  seedvpm642_vedioloop.pjt - LOOP2  ----------------------
"c:/ti/c6000/cgtools/bin/cl6x" -g -fr"C:/work/test/video_loopback/LOOP2" -i"C:/work/test/video_loopback/include" -d"_DEBUG" -d"CHIP_DM642" -d"_LOOP2_" -mv6400 -@"../../LOOP2.lkf" "seedvpm642_vdisparamsPAL.cpp"

"c:/ti/c6000/cgtools/bin/cl6x" -@"LOOP2.lkf"
<Linking>

undefined                        first referenced
symbol                              in file
---------                        ----------------
_tskVideoCaptureVp1              C:/work/test/video_loopback/LOOP2/seedvpm642cfg.obj
_tskVideoLoopback                C:/work/test/video_loopback/LOOP2/seedvpm642cfg.obj
>>   error: symbol referencing errors - './LOOP2/seedvpm642_vedioloop.out' not
            built

Build Complete,
  1 Errors, 0 Warnings, 0 Remarks.

_tskVideoCaptureVp1和_tskVideoLoopback对应C++函数编译后的汇编名字。

C语言中规则是添加“_”前缀表示函数在汇编中的名称,例如main函数在汇编中为_main。
但是C++不行,原因在之前已经说过,C++有重载。比如有以下函数:
代码: 全选
void fun(const char* msg)
{
   printf("%s/n", msg);
}
void fun(int val)
{
   printf("%d/n",val);
}

int main()
{
   fun("hello");
   fun(123);
   return 0;
}


函数fun有2个,如果将fun简单用_前缀的话,就会出现2个不同的函数,但是名字都是_fun。
C++的处理方法是重命名,第一个可能被命名为_fun_const_char_XCC1,第二个可能为_fun_int_SXX。
名字中除了参数信息,可能还有一些随机字串(这样是为了避免冲突)。

现在如果想将void fun(int val)函数导出为C语言接口怎么办?这就要在声明的时候添加extern "C"修饰。
这2个的函数声明在"seedvpm642_tskvp1.h"头文件中,打开"seedvpm642_tskvp1.h",发现里面没有
代码: 全选
#ifdef __cplusplus
extern "C" {
#endif


之类的代码。这说明这个demo的"seedvpm642_tskvp1.h"头文件写的不标准,只能在C语言中用,
不能在C++中使用,修改的方式可以参考ti标准的头文件(例如<std.h>):
代码: 全选
/*
*  Copyright 2004 by SEED Incorporated.
*  All rights reserved. Property of SEED Incorporated.
*  Restricted rights to use, duplicate or disclose this code are
*  granted through contract.
*  
*/

#ifdef __cplusplus
extern "C" {
#endif

/*
* ======== tskVideoCaptureVp1Init ========
* video capture function init.
*/
void VideoCaptureVp1Init();
/*
* ======== tskVideoCaptureVp1Start ========
* video capture function start.
*/
void VideoCaptureVp1Start();
/*
* ======== tskVideoCaptureVp1 ========
* video capture function.
*/

void tskVideoCaptureVp1();

#ifdef __cplusplus
}
#endif


之前的头文件缺少void tskVideoCaptureVp1();函数声明,现在补上。另外,缺少头文件重复包含的控制,
也应该补上,类似方法如下:
代码: 全选
#ifndef XXX_H
#define XXX_H

#ifdef __cplusplus
extern "C" {
#endif

// 放各种声明

#ifdef __cplusplus
}
#endif

#endif // XXX_H


重新build,link错误还剩1个:
代码: 全选
undefined                        first referenced
symbol                              in file
---------                        ----------------
_tskVideoLoopback                C:/work/test/video_loopback/LOOP2/seedvpm642cfg.obj
>>   error: symbol referencing errors - './LOOP2/seedvpm642_vedioloop.out' not
            built

Build Complete,
  1 Errors, 3 Warnings, 0 Remarks.


同样的方法解决。

终于将demo工程改为C++。下面将emcv下载下来,放置到cmcv目录。

然后将emcv的cxcore目录中的cpp文件添加到工程,然后编译。
如果编译有错误,处理错误。迭代直到可以编译。

将cv中的cpp导入工程,确保可以编译。

暂停!!!

现在videoloopback虽然没有使用emcv的1行代码,但是在不改变程序本身功能的前提下
已经包含的emcv库资源(我们可以随时使用)。

简单的就是手工创建一些IplImage,然后测试。<highgui.h>部分下次补充。
阅读更多
个人分类: 行人检测
想对作者说点什么? 我来说一句

学习DSP C6000的好书推荐

2016年01月19日 2KB 下载

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭