您的位置:首页 > 移动开发 > Android开发

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

2017-05-22 19:50 706 查看
        搞多媒体开发的对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 -x

LIBMEDIA_TARGET_PLATFORM=android-22
LIBMEDIA_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/tmp

export 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 +x

print_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 2
elif test "$1" = "x264"; then
build_x264 && build_ffmpeg 2
elif test "$1" = "libfdk-aac"; then
build_libfdk-aac && build_ffmpeg 2
elif test "$1" = "ffmpeg"; then
build_ffmpeg 2
elif test "$1" = "help"; then
print_helpmsg && eixt 0
else
printf "no option, just rebuild interface files\n\n" && print_helpmsg
fi

if test $? -eq 0;then
build_module
fi
}

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脚本的执行来排查问题了。这也提醒我们,不管是写脚本或者程序文件是错误报告消息的重要性,不准确的日志消息太有误导性了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐