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"
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标准的头文件(例如
):
-
代码: 全选
-
/*
* 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,然后测试。部分下次补充。