由于系统Windows XP 和 Windows CE的差异, 导致移植到Windows XP上的ffmpeg动态连接库并不能在WinCE上使用, 所以需重新移植一番.
一、在开始移植前,需要做些准备工作:
1.1 下载 cygwin 工具(Setup.exe), 注意下载 1.7.xx的版本
http://www.cygwin.com/
1.2 下载 cegcc 交叉编译工具(cegcc_mingw32ce_cygwin1.7_r1375.tar.bz2)
http://sourceforge.net/projects/cegcc/files/?source=navbar
1.3 下载 ffmpeg 源码包,
http://www.ffmpeg.org/download.html 我使用的是 FFmpeg 0.10.6 "Freedom" 的版本,版本选择不同,编译的时候会导致一些微小的差异
1.4 参考
http://www.ffmpeg.org/platform.html#Cross-compilation-for-Windows-with-Linux-1 了解相关情况
二、工具的安装
2.1 Cygwin安装
执行setup.exe 确保网络正常连接
在Cygwin Setup - Select Package这步时,需选择这些包:
autobuild, autoconf, automake, binutils, gcc, gcc-core, gcc-g++, gcc-mingw, gcc-mingw-core, gcc-mingw-g++, gcc4, gcc4-core, gcc4-g++, gccmakedep, gdb, git, make, makedepend, mingw-binutils, mingw-gcc, mingw-gcc-core, mingw-gcc-g++, mingw-runtime, mingw-zlib, pkg-config,
w32api-runtime, yasm, gettext, texi2html, bc, libogg-devel, libvorbis-devel, vim
2.2 Cegcc交叉编译器安装
把 cegcc_mingw32ce_cygwin1.7_r1375.tar.bz2 复制到 D:cygwinhome (注意自己的安装路径,默认装的是在C盘)目录下
启动 Cygwin Terminal
cd /home
tar xjvf cegcc_mingw32ce_cygwin1.7_r1375.tar.bz2
(千万要小心,不要把Cygwin安装到 FAT 文件系统的分区上,不然就等着悲吹咯!!!安装Cygwin到FAT32的分区会导致ln硬连接失败,
这样tar解包的时候,会缺少一些arm-mingw32ce-xx文件,想自己用ln命令创建,哈哈,命令执行失败报操作不允许 not permission,TNND,fuck 他大爷的)
修改 D:cygwinetcprofile 文件,在文件末尾增加相应的PATH路径
export PATH="/home/mingw32ce/bin:$PATH"
执行source /etc/profile使设置生效
3.1 ffmpeg的配置
./configure --enable-memalign-hack
--target-os=mingw32ce
--arch=arm
--cpu=armv4 ---------- 指令集 请根据设备的情况选择(armv4, armv6, armv7...)
--enable-cross-compile
--cross-prefix=arm-mingw32ce-
--enable-shared
--disable-static
--disable-doc
--disable-ffmpeg
--disable-ffplay
--disable-ffprobe
--disable-ffserver
--disable-network
--extra-ldflags=--enable-auto-import
--prefix=/home/wince
把它写到mycecfg.sh中,接着 chmod +x cecfg.sh ,然后执行 ./mycecfg.sh 结果显示:
License: LGPL version 2.1 or later
Creating config.mak and config.h...
WARNING: arm-mingw32ce-pkg-config not found, library detection may fail. ------------(注意:有些警告不能忽视,不然你可以试试)
解决办法
cd /home/mingw32ce/bin
cp /usr/bin/pkg-config.exe arm-mingw32ce-pkg-config.exe
接着再
make distclean
./mycecfg.sh
3.2 编译 make
3.2.1
/home/mingw32ce/bin/../lib/gcc/arm-mingw32ce/4.4.0/../../../../arm-mingw32ce/include/errno.h:12:25: error: no include path in which to search for errno.h
common.mak:45: recipe for target `libavdevice/alldevices.o' failed
make: *** [libavdevice/alldevices.o] Error 1
规避办法:
修改 /home/mingw32ce/arm-wince-mingw32ce/include/errno.h
注释 //#ifdef __COREDLL__
//# include_next
//#else /* __COREDLL__ */
//#endif /* Not __COREDLL__ */
==============================================================================================================
3.2.2
libavcodec/arm/dsputil_arm.S: Assembler messages:
libavcodec/arm/dsputil_arm.S:718: Error: selected processor does not support `bx lr'
common.mak:54: recipe for target `libavcodec/arm/dsputil_arm.o' failed
make: *** [libavcodec/arm/dsputil_arm.o] Error 1
规避办法:
修改 libavcodec/arm/dsputil_arm.S 将 bx lr 改为 mov pc, lr
libavcodec/arm/flacdsp_arm.S: Assembler messages:
libavcodec/arm/flacdsp_arm.S:55: Error: selected processor does not support `bxle lr'
libavcodec/arm/flacdsp_arm.S:92: Error: selected processor does not support `bxle lr'
修改 libavcodec/arm/flacdsp_arm.S 将 bxle lr 改为 movle pc, lr
另外的办法是:改变arm指令版本 --arch=arm --cpu=arm9tdmi
原因是:armv4不支持bx
===============================================================================================================
3.2.3
libavutil/log.c: In function 'colored_fputs':
libavutil/log.c:68: error: implicit declaration of function 'getenv'
common.mak:45: recipe for target `libavutil/log.o' failed
make: *** [libavutil/log.o] Error 1
根本解决办法:有兴趣的,可以参看大牛们的
http://ffmpeg.org/pipermail/ffmpeg-devel/2009-August/060679.html 的相关主题讨论
无奈的规避办法:
修改libavutil/log.c文件的代码
//use_color = getenv("AV_LOG_FORCE_COLOR") && !getenv("NO_COLOR") &&
// !getenv("AV_LOG_FORCE_NOCOLOR");
use_color = 256;
===============================================================================================================
3.2.4
libavutil/random_seed.c: In function 'get_generic_seed':
libavutil/random_seed.c:50: error: implicit declaration of function 'clock'
common.mak:45: recipe for target `libavutil/random_seed.o' failed
make: *** [libavutil/random_seed.o] Error 1
规避办法:
修改 libavutil/random_seed.c 文件
static uint32_t get_generic_seed(void)
{
//clock_t last_t = 0;
time_t last_t = 0;
int bits = 0;
uint64_t random = 0;
unsigned i;
float s = 0.000000000001;
for (i = 0; bits < 64; i++) {
time_t t = time((time_t*)NULL);
//clock_t t = clock();
if (last_t && fabs(t - last_t) > s || t == (clock_t) -1) {
if (i < 10000 && s < (1 << 24)) {
s += s;
i = t = 0;
} else {
random = 2 * random + (i & 1);
bits++;
}
}
last_t = t;
}
#ifdef AV_READ_TIME
random ^= AV_READ_TIME();
#else
random ^= time((time_t*)NULL);
//random ^= clock();
===============================================================================================================
3.2.5
/home/ffmpeg-0.10.6/libavutil/file.c:172: relocation truncated to fit : ARM_26 against undefined symbol `_errno'
libavutil/file.o: In function `av_file_map':
/home/ffmpeg-0.10.6/libavutil/file.c:89: undefined reference to `_get_osfhandle'
/home/ffmpeg-0.10.6/libavutil/file.c:89: relocation truncated to fit: ARM_26 against undefined symbol `_get_osfhandle'
/home/ffmpeg-0.10.6/libavutil/file.c:91: undefined reference to `Crea teFileMappingA'
/home/ffmpeg-0.10.6/libavutil/file.c:91: relocation truncated to fit: ARM_26 against undefined symbol `CreateFileMappingA'
/home/ffmpeg-0.10.6/libavutil/file.c:54: undefined reference to `_errno'
/home/ffmpeg-0.10.6/libavutil/file.c:54: relocation truncated to fit: ARM_26 against undefined symbol `_errno'
/home/ffmpeg-0.10.6/libavutil/file.c:61: undefined reference to `_errno'
/home/ffmpeg-0.10.6/libavutil/file.c:61: relocation truncated to fit: ARM_26 against undefined symbol `_errno'
collect2: ld returned 1 exit status
library.mak:97: recipe for target `libavutil/avutil-51.dll' failed
make: *** [libavutil/avutil-51.dll] Error 1
规避办法:
凡涉及 errno 的变量注释掉,比如 err = AVERROR(errno); 修改为 err = -1;
/*HANDLE mh, fh = (HANDLE)_get_osfhandle(fd);
mh = CreateFileMapping(fh, NULL, PAGE_READONLY, 0, 0, NULL);
if (!mh) {
av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in CreateFileMapping()
");
close(fd);
return -1;
}
ptr = MapViewOfFile(mh, FILE_MAP_READ, 0, 0, *size);
CloseHandle(mh);
if (!ptr) {
av_log(&file_log_ctx, AV_LOG_ERROR, "Error occurred in MapViewOfFile()
");
close(fd);
return -1;
}*/
close(fd);
return -1;
===============================================================================================================
3.2.6
LINK : warning LNK4012: ???arm-wince????Ч?????????ARM, EBC, IA64, MIPS, MIPS16, MIPSFPU, MIPSFPU16, SH4, THUMB, X64, or X86????????????
LINK : warning LNK4068: δ??? /MACHINE?????????? X86
????????? libavutil/avutil.lib ????? libavutil/avutil.exp
LD libavcodec/avcodec-53.dll
Info: resolving ff_log2_tab by linking to __imp_ff_log2_tab (auto-import)
Info: resolving ff_sqrt_tab by linking to __imp_ff_sqrt_tab (auto-import)
Info: resolving av_reverse by linking to __imp_av_reverse (auto-import)
Info: resolving av_md5_size by linking to __imp_av_md5_size (auto-import)
Info: resolving av_pix_fmt_descriptors by linking to __imp_av_pix_fmt_descriptors (auto-import)
Creating library file: libavcodec/libavcodec.dll.a
/home/mingw32ce/bin/../lib/gcc/arm-mingw32ce/4.4.0/../../../../arm-mingw32ce/bin/ld: warning: auto-importing has been activated without --enable-auto-import specified on the command line.
This should work unless it involves constant data structures referencing symbols from auto-imported DLLs.
lib.exe /machine:arm-wince /def:libavcodec/avcodec-53.def /out:libavcodec/avcodec.lib
解决办法:
修改 config.mak 文件
将 LDFLAGS= --enable-auto-import -Wl,--as-needed -Wl,--warn-common -Wl,-rpath-link=libpostproc:libswresample:libswscale:libavfilter:libavdevice:libavformat:libavcodec:libavutil
修改为
LDFLAGS= -Wl,--enable-auto-import -Wl,--as-needed -Wl,--warn-common -Wl,-rpath-link=libpostproc:libswresample:libswscale:libavfilter:libavdevice:libavformat:libavcodec:libavutil
或者 --extra-ldflags=--enable-auto-import 修改为 --extra-ldflags=“-Wl,--enable-auto-import"
将 LIBTARGET=arm-wince 修改为 LIBTARGET=arm
如果不想修改也没关系,只是编译出来的ffmpeg动态库DLL, 在VC项目中使用时,会报链接的错误,找不到相关函数例如 avformat_open_input的实现。
在cmd中, 用 dumpbin /exports xx.dll >> 1.txt , 在1.txt中查找到是 _avformat_open_input , 多了一个下划线 。
这个时候需要对xx.dll 重新执行 lib /machine:arm /def:xx.def /out:xx.lib 。
注意:若cmd 提示无命令,请先设置vs的相关环境变量。
==============================================================================================================
编译成功
Creating library file: libswscale/libswscale.dll.a
lib.exe /machine:arm /def:libswscale/swscale-2.def /out:libswscale/swscale.lib
Microsoft (R) Library Manager Version 9.00.21022.08
Copyright (C) Microsoft Corporation. All rights reserved.
????????? libswscale/swscale.lib ????? libswscale/swscale.exp
LD libavfilter/avfilter-2.dll
Creating library file: libavfilter/libavfilter.dll.a
lib.exe /machine:arm /def:libavfilter/avfilter-2.def /out:libavfilter/avfilter.lib
Microsoft (R) Library Manager Version 9.00.21022.08
Copyright (C) Microsoft Corporation. All rights reserved.
????????? libavfilter/avfilter.lib ????? libavfilter/avfilter.exp
LD libavdevice/avdevice-53.dll
Creating library file: libavdevice/libavdevice.dll.a
lib.exe /machine:arm /def:libavdevice/avdevice-53.def /out:libavdevice/avdevice.lib
Microsoft (R) Library Manager Version 9.00.21022.08
Copyright (C) Microsoft Corporation. All rights reserved.
????????? libavdevice/avdevice.lib ????? libavdevice/avdevice.exp
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
然后 make install
$ ls -l
总用量 11152
-rw-r--r-- 1 chfj None 364764 三月 17 18:15 avcodec.lib
-rwxr-xr-x 1 chfj None 9029651 三月 17 18:15 avcodec-53.dll
-rw-r--r-- 1 chfj None 2638 三月 17 18:15 avdevice.lib
-rwxr-xr-x 1 chfj None 11283 三月 17 18:15 avdevice-53.dll
-rw-r--r-- 1 chfj None 39214 三月 17 18:15 avfilter.lib
-rwxr-xr-x 1 chfj None 231443 三月 17 18:15 avfilter-2.dll
-rw-r--r-- 1 chfj None 141968 三月 17 18:15 avformat.lib
-rwxr-xr-x 1 chfj None 955923 三月 17 18:15 avformat-53.dll
-rw-r--r-- 1 chfj None 40876 三月 17 18:15 avutil.lib
-rwxr-xr-x 1 chfj None 153107 三月 17 18:15 avutil-51.dll
-rw-r--r-- 1 chfj None 5758 三月 17 18:15 swresample.lib
-rwxr-xr-x 1 chfj None 31232 三月 17 18:15 swresample-0.dll
-rw-r--r-- 1 chfj None 19326 三月 17 18:15 swscale.lib
-rwxr-xr-x 1 chfj None 198675 三月 17 18:15 swscale-2.dll
chfj@chen-feiyang /home/wince/bin
$ file avcodec-53.dll
avcodec-53.dll: PE32 executable (DLL) (Windows CE) ARM (stripped to external PDB), for MS Windows
四、测试
把 avcodec-53.dll、avfilter-2.dll、avformat-53.dll、avutil-51.dll、swresample-0.dll、swscale-2.dll、avdevice-53.dll 和测试的xx.exe 传到自己的WINCE设备上,执行xx.exe
xx.exe无任何反应,这时还需有相应的 mfc80u.dll, mfcm80u.dll, atl80.dll 等,外加 libgcc_s_sjlj-1.dll(位于D:cygwinhomemingw32cein) 。
后记
当上面都进行得很high的,运行调用ffmpeg函数的测试demo,demo铛弹出一出错信息框,大意是程序发生了一系列错误,需要关闭!接着通过串口打印的调试信息弹出一些关于"Data Abort"的信息。我靠,马乐个比,老天你这是在玩我吗???
心情无比郁闷,没招了,头好大!这下如何事好,交不了差鸟。
郁闷了一两天,忽然想起还有MingGW这个工具,死马当活马医。在MingGW上重来一回(只需装cegcc交叉编译器,再把cygwin1.dll、cygz.dll等几个拷贝到MingGW上即可,按出错的提示拷相关的dll)。怀着忐忑 的心情,把编好的dll 在设备上跑,阿哈,这回运行正常,哈哈,交差。
令我疑惑的事,操作步骤是一样的,一定是在MingGW我修改了什么地方和在Cygwin上的不同,但又想不起来了。