[记录]为android平台交叉编译ffmpeg问题与解决方法

在NDK出现之后,几乎所有非平台依赖的用c或c++的项目都可以很方便编译出可在android平台使用的目标程序,这里记录一下在编译ffmpeg时遇到的问题与解决方法。

#注意:在编译前,个人觉得最好是先在默认的情况下编译,不要先修改你还没有遇到问题的地方(就算别人遇到了,只要你还没有遇到就不要改!!),等遇到相应错误再查进行修改

 

如果在不增加第三方编解码库时,单纯只编译ffmpeg是比较容易的,众所周知地,从configure --help中就可以知道各个编译选项,这里的建议是:只加上你能明白的选项就行了,基本一次通过,下面记录的问题是在增加第三方库的时候会出现的问题。

1、undefined reference to `android_getCpuFeatures'

这个错是在加入libvpx时出现(但在单独编译libvpx时并没有出错),经搜索,在ndk目录下的source目录下发现有cpufeatures,该目录里的cpu-features就有android_getCpuFeatures的声明和定义,并且也说明了如何使用。这里采用比较原始的方式,就是自己编译了cpufeature的静态库,然后在需要的项目中在链接进去,大致步骤就是,加ndk的路径到环境变量--编译静态库文件,下面例子:

export PATH=$NDK:$PATH

gcc -c cpu-features.c

ar cvf libcpu-features.a cpu-features.o

然后就是链接到目标项目中,我是在LIBS中加入"-L路径 -lcpu-features",重新编译即可。

2、编译x264时,出现以下warning

cannot scan executable section 1 of libx264.a(dct-a.o) for Cortex-A8 erratum because it has no mapping symbols***

一开始我没有理会,不过在编译vpx时又出现过一次,所以特意找了一下,在googlecode找到一片相关的文章,具体可到这里看:https://code.google.com/p/android/issues/detail?id=40794#c4

其中的一个解决方法就是:make STRIP=     #就是不要strip了

注:在我查看ndk工具链相关的文档时,发现其有提到用

-Wl,--fix-cortex-a8
#The flag is required* to route around a CPU bug in some Cortex-A8 implementations

地址是在这里《STANDALONE-TOOLCHAIN

 

3、编译xvid时,不能正确找到链接库的错误,如下:

***ld:cannot find -lc

***ld:cannot find -ldl

经过查找,libc和dl等是存在的,所以应该是路径的问题,经测试,找到解决办法,在编译前加上LD环境变量上加入sysroot参数,如下:

export LD=$PREBUILT/linux-x86/bin/arm-linux-androideabi-ld --sysroot=$PLATFORM

4、编译faac库时,有如下错误:

mp4file_io.cpp:function MP4File::GetPosition(__sFILE*): error: undefined reference to '__cxa_allocate_exception'

***

mp4.cpp:function typeinfo for MP4Error: error: undefined reference to 'vtable for __cxxabiv1::__class_type_info'

因为编译错误的是mp4v2部分代码,所以网络上的一个解决办法是在configure配置加上--with-mp4v2=no,就是不要编译mp4v2部分源码,也就不会报错了,这个可行。

但我不满足于上面这种,所以经过查找错误函数相关信息,得知其是在:gnustl_static和stlport_static库里的函数,所以最后我发现这样子才是最好的解决办法:找到两个库的位置,加入到链接路径,比如我的做法像下面这样:

export CFLAGS="-I$NDK/sources/cxx-stl/gnu-libstdc++/4.8/include -I$NDK/sources/cxx-stl/stlport/stlport"

export LIBS="-L$NDK/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi -lgnustl_static -L$NDK/sources/cxx-stl/stlport/libs/armeabi -lstlport_static"

如果还有错,那么就把LDFLAGS(如果还是错,就把所有**FLAGS都也加上上面两个库的路径信息吧)

 

5、编译speex时,发生错误:sys/soundcard.h: No such file or directory

我直接在CC环境变量后加上--sysroot=***的参数,就编译通过了。

 

6、编译vpx时,在configure时发生错误,需要增加sdk-path配置。

 

7、编译aacplus时,在configure时有错误:configure: error: cannot check for file existence when cross compiling

从网络上找到解决办法是:在autogen.sh时加入以下参数即可,内容如下:

./autogen.sh --with-parameter-expansion-string-replace-capable-shell=/bin/bash --host=arm-linux --enable-static --disable-shared

但是我在按照上面配置时未能正确编译通过,经过测试,找到一个办法时,把平常configure的命令替换为autogen.sh,所有传给configure的参数都直接传递给autogen.sh即可,比如我的部分配置命令如下:

./autogen.sh --with-parameter-expansion-string-replace-capable-shell=/bin/bash --prefix=$PREFIX \
--host=arm-linux-androideabi --target=arm-linux-androideabi
--enable-static --disable-shared --with-sysroot=$PLATFORM

上面各变量自定替换成自己的内容即可。

 

8、出现undefined reference to '__aeabi_d2iz'等等类似'__aeabi**'的错误,是由ld提示的,不指定ld即可。

9、出现static declaration of 'lrint' follows non-static declaration等等错误,需要修改掉config.h中的对应定义即可,比如这里的‘lrint’,在config.h中应该就是‘HAVE_LRINT 0’,把0改成1即可,因为我是在ubuntu下编译,所以写了脚本自动替换掉需要替换的变量,如下:

sed -i "s/HAVE_LLRINT 0/HAVE_LLRINT 1/g" config.h
sed -i "s/HAVE_LLRINTF 0/HAVE_LLRINTF 1/g" config.h
sed -i "s/HAVE_LRINT 0/HAVE_LRINT 1/g" config.h
sed -i "s/HAVE_LRINTF 0/HAVE_LRINTF 1/g" config.h
sed -i "s/HAVE_ROUND 0/HAVE_ROUND 1/g" config.h
sed -i "s/HAVE_ROUNDF 0/HAVE_ROUNDF 1/g" config.h
sed -i "s/HAVE_ISINF 0/HAVE_ISINF 1/g" config.h
sed -i "s/HAVE_ISNAN 0/HAVE_ISNAN 1/g" config.h

 

10、在配置ffmpeg时,提示错误:ERROR: libaacplus >= 2.0.0 not found,经过查看config.log,发现提示:undefined reference to '__aeabi_idiv'等内容,经查找,未找到引用的函数属于gcc库的,所以在LIBS加上-lgcc,比如我是使用的部分配置参数是:

export LIBS="*** -L$PREBUILT/linux-x86/lib/gcc/arm-linux-androideabi/4.8 -lgcc"

另外,aacplus与vo-aacenc会冲突,网上还说vo-aacenc在高码率下比faac还差,所以果断就去掉vo-aacenc库了;而再者,aacplus与fdk-aac也是冲突的,而fdk-aac没有报错,所以就又去掉aacplus了。

 

11、编译fontconfig出现error: 'struct lconv' has no member named 'decimal_point',经过查看ndk内的相关文件,确定是因为ndk内实现的lconv结构没有decimal_point,所以我修改了fontconfig中出现错误的fcxml.c文件,将其中出错的FcStrtod函数修改为如下内容:

static double
FcStrtod (char *s, char **end)
{
#ifndef ANDROID
/******这里是原来的内容*******/
#else
 return strtod (s, end);
#endif

}

最后,附上我交叉编译ffmpeg到android平台时用的configure:

./configure --prefix="$PREFIX" \
--cross-prefix="$PREBUILT/linux-x86/bin/arm-linux-androideabi-" --sysroot="$PLATFORM" --enable-cross-compile --arch=armv --target-os=linux \
--extra-cflags="$CFLAGS" --extra-ldflags="$LDFLAGS" --extra-libs="$LIBS" \
--cc="$CC" --ar="$AR" --nm="$NM" --ld="$LD" \
--enable-gpl \
--enable-version3 \
--enable-nonfree \
--disable-doc --disable-ffprobe --disable-ffserver --disable-ffplay \
--disable-w32threads \
--disable-os2threads \
--enable-pthreads \
--disable-shared \
--enable-static \
--enable-memalign-hack \
--enable-avresample \
--enable-libvpx \
--enable-libx264 \
--enable-libxvid \
--enable-libfaac \
--enable-libfdk-aac \
--enable-libmp3lame \
--enable-libspeex \
--enable-libtheora \
--enable-libvorbis \
--enable-libopencore-amrnb \
--enable-libopencore-amrwb \
--enable-libxavs \
--enable-libvo-amrwbenc
#--enable-libaacplus
#--enable-libvo-aacenc \
#--enable-avisynth \
#--enable-runtime-cpudetect \

 

注:1、这个是完成编译后才开始来记录的,所以有些问题不记得了,不过如果以后会遇到会继续记录进来,如果你遇到问题,可留言,我可以帮忙提供解决方法。

2、如果在不清楚编译链相关内容(编译目标架构、各种参数信息)的情况下,ndk文档里推荐是直接使用ndk编译,因为其会为我们默认设置一些参数,而如果比较熟悉编译相关信息,则可以使用make-standalone-toolchain.sh。

» 本文链接地址:https://www.xidige.com/498

打开支付宝扫一扫,即可进行扫码打赏哦

扫码支持
扫码打赏,你说多少就多少

标签:

分享到:

扫一扫 在手机阅读、分享本文

上一篇: 下一篇:
评论区6人评论451人参与
  1. liufh 2014年11月26日 下午4:03  回复

    大大,请问有完成的交叉编译ffmpeg第三方编解码库的方法么,多谢哦,快被这块折磨死了

  2. peng_jianyong 2014年11月20日 下午3:27  回复

    博主,感谢你的答复,我已经成功编绎出来了。

  3. peng_jianyong 2014年11月19日 下午8:49  回复

    博主,你好!我在交叉编绎ffmpeg时,加入了--enable-libopencore-amrnb参数后,编绎时报ERROR: libopencore_amrnb not found,查看config.log里面的错误是:
    /home/downey/develop/android-ndk-r9d/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin/ld: warning: skipping incompatible /usr/local/lib/libopencore-amrnb.a while searching for opencore-amrnb
    /home/downey/develop/android-ndk-r9d/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin/ld: error: cannot find -lopencore-amrnb
    /tmp/ffconf.MZVeppH0.o:ffconf.RovLyKi1.c:function main: error: undefined reference to 'Decoder_Interface_init'
    collect2: error: ld returned 1 exit status
    我看了很多资料都没能解决,请问加第三方库,要怎么加?帮忙给个解决步骤。
    我的环境是ubuntu64位,ndk-9rd,ffmpeg2.4.2 ,
    联系方式,邮箱:305833026@qq.com , QQ:305833026

    • xidige 2014年11月20日 上午9:11  

      你好,从错误提示看,就是找不到arm平台opencore的库,你需要指定你的opencore的库的路径.指定的方法就是:在ffmpeg的configure配置CFLAGS加上opencore的include目录,在LDFLAGS加上opencore的lib目录,我是这样做的:
      ./configure --prefix=/home/xidige/libraries/armeabi --extra-cflags=" -I$opencore的库目录/include ****" --extra-ldflags="-L$opencore的库目录/lib *****" ****
      ($opencore的库目录是完整路径,星号是其他内容这里省去啦)
      我在编译opencore等第三方库时,是把它们统一在一个目录的(上面的prefix指定),这样就方便很多啦

      最后,你是不是没有编译arm平台的opencore呢?

    • peng_jianyong 2014年11月20日 上午11:54  

      对的,一直在编绎amr平台的opencore-amr的库,就是生成不了,呵呵,你那有amr平台的opencore-amr-0.1.3的编绎方法吗?主要是看不到他的configura文件。

电子邮件地址不会被公开。 必填项已用*标注

*

loading

赞助商广告