在Android下编译ffmpeg+x264+libfdk-aac的常见问题和解决方法

来源:互联网 发布:黄岩深孔钻编程招聘 编辑:程序博客网 时间:2024/06/05 00:08

        搞多媒体开发的对ffmpeg、libfdk-aac、x264这几个库应该都比较熟悉,在此不多做介绍。最近公司需要升级多媒体库,第一步工作就是将ffmpeg+x264+libfdk-aac移植到Android平台。关于ffmpeg+libfdk-aac+x264的交叉编译步骤,网上相关的内容很多。不过由于ffmpeg的配置选项丰富,在网上查到的脚本几乎都不符合我们的需求,了解ffmpeg的编译过程后自己写了个脚本,进行简单修改后就可以对不同的CPU架构和Android API level生成不同的二进制文件。去掉公司的业务代码后,我把编译脚本和相应的开源库放到了github上,欢迎大家前去围观。github地址:https://github.com/x5miao/ffmpeg-android

      和交叉编译相关的脚本主要包括项目目录下的set-build.sh,ffmpeg/config-android.sh, x264/config-android.sh,  libfdk-aac/config-android.sh。set-build.sh主要用来设置环境变量,以及根据命令行启动不同组件的configure和编译过程。几个config-android.sh主要就是调用开源库里自带的configure脚本进行配置生成makefile文件,然后调用make生成静态库文件。

      最重要的脚本就是set-build.sh,其主要内容如下所示:

#!/bin/bash#本脚本用于设置交叉编译环境并编译libmedia各子模块,用户请根据自身的编译环境修改#相应的环境变量.#libmedia的编译仅在ubuntu下测试通过,推荐使用ubuntu14.04-64TLS.#注意:不要使用cygwin编译,否则可能出现无法编译的bug.#set -xLIBMEDIA_TARGET_PLATFORM=android-22LIBMEDIA_TARGET_ARCH_ABI=arm64-v8a #armeabi-v7a armeabi#NDK_ROOT_PATH指向Android NDK开发包的根路径NDK_ROOT_PATH=/home/xxm/android_dev/android-ndk-r13b#TOOLCHAIN版本号,请参考${NDK_ROOT_PATH}/toolchains目录下的文件夹名字修改TOOLCHAIN_VERSION=4.9#TMPDIR用来指定ffmpeg编译过程中间生成文件的保存目录,编译时请根据用户自己的本地环境指定,#编译前必须保证该temp文件夹存在FFMPEG_TMPDIR=/home/xxm/android_dev/workspace/tmpexport LIBMEDIA_TARGET_PLATFORM LIBMEDIA_TARGET_ARCH_ABI FFMPEG_TMPDIR NDK_ROOT_PATH TOOLCHAIN_VERSION#编译ffmpeg需要按照Android开发者论团的介绍先建立离线交叉编译工具链#参考网址:https://developer.android.com/ndk/guides/standalone_toolchain.html#wwc#STANDLONE_ROOT_PATH=/home/xxm/android_dev/workspace/arm-linux-androideabi#export STANDLONE_ROOT_PATH#set +xprint_helpmsg(){echo "usage:source set-env.sh [option]"    echo "option is:"printf "\t all:  rebuild all opensource library and interface files(GGCodec*.c)\n"printf "\t x264: rebuild x264 and interface files\n"printf "\t libfdk-aac: rebuild libfdk-aac and interface files\n"printf "\t ffmpeg: rebuild ffmpeg and interface files\n"printf "\t help: print this message\n\n"}build_x264(){  cd x264 && ./config-android.sh && cd ..}build_libfdk-aac(){  cd libfdk-aac && ./config-android.sh && cd ..}build_ffmpeg(){  cd ffmpeg && ./config-android.sh $1 && cd ..}build_module(){   cp out/Android.mk  out/${LIBMEDIA_TARGET_ARCH_ABI}/   ndk-build clean && ndk-build all}build(){if test "$1" = "all"; then  build_x264 && build_libfdk-aac && build_ffmpeg 2elif test "$1" = "x264"; then   build_x264 && build_ffmpeg 2elif test "$1" = "libfdk-aac"; then   build_libfdk-aac && build_ffmpeg 2elif test "$1" = "ffmpeg"; then   build_ffmpeg 2elif test "$1" = "help"; then   print_helpmsg && eixt 0else   printf "no option, just rebuild interface files\n\n" && print_helpmsgfiif test $? -eq 0;then   build_modulefi}build "$@"

       set-build.sh通过如下方式调用:  

source set-build.sh [all|ffmpeg|x264|libfdk-aac|help]     all: 所有组件都重新构建;    ffmpeg:重新构建ffmpeg的静态库;     x264:重新构建x264和ffmpeg;     libfdk-aac:重新构建libfdk-aac和ffmpeg;     help:打印command的帮助信息。

        如果需要修改目标平台的ABI和Platform,请修改LIBMEDIA_TARGET_ARCH_ABI和LIBMEDIA_TARGET_PLATFORM两个环境变量,修改这两个变量中任何一个之后必须重新用all选项重新编译所有组件。

        交叉编译的时候遇到一些坑,分享出来希望对其他人有所帮助。

(1) 编译ffmpeg时提示找不到libfdk-aac或libx264。这个问题是由于ffmpeg时交叉编译器找不到libfdk-aac/x264的头文件或静态库.a文件导致的。解决方法是将ffmpeg、libfdk-aac、libx264的--prefix选项赋值为相同的目录,并给configure脚本加上--extra-cflags=“-I${PREFIX}/include”和--extra-ldflags=“-L${PREFIX}/lib -lx264 -lfdk-aac”选项。编写脚本时注意libfdk-aac(小短线)和libfdk_aac(下划线)的区别,configure有时候需要是短线版本有时候又需要下划线版本,容易搞错。

(2) 编译了32位so文件后再编译64位so文件时,提示strtod.o的文件格式不对。这是由于对于3.2版本的ffmpeg,make clean不会删除compat下的strtod.o,strtod.d, msvcrt/snprintf.o, msvcrt/snprintf.d四个文件,只要手动删除后重新编译即可。具体可以参考简书上esonyf的这篇文章:http://www.jianshu.com/p/612ef67e42bd

(3) 调用avodec_find_decoder|encoder(AVCODEC_ID_AAC|AVCODEC_ID_H264)返回失败。造成这个问题的原因是虽然动态库里面包含了libfdk-aac和x264编解码相关的代码,却没有将其注册到ffmpeg。解决方法是configure时通过--enable-encoder=libx264|libfdk_aac选项显示启用libfdk-aac和libx264作为编解码器。

(4) configure时有时候会遇到‘C Compiler is not working’之类的错误,但是交叉编译器明显就在正确的路劲下。因为这个问题耽误了大半天的时间,后来通过分析config.log才发现当configure时如果指定了错误的编译链接选项,比如--arch指定了configure脚本不识别的体系架构、--extra-cflags里面指定了不支持的编译器选项,或者--extra-ldflags里有--nostdlib之类的选项,导致交叉编译器在测试生成可执行文件命令后返回了非0值, configure脚本就会打印出这个很有误导性的消息。对于ffmpeg可以通过分析configure的输出日志文件config.log来定位问题。不过x264的configure脚本生成的config.log里面却得不到任何线索,只能通过在其configure脚本开头添加set -x调试选项来跟踪configure脚本的执行来排查问题了。这也提醒我们,不管是写脚本或者程序文件是错误报告消息的重要性,不准确的日志消息太有误导性了。

阅读全文
0 0