首先我们根据自己项目需要,来对FFmpeg源码进行功能裁剪以减小最后APK的大小。编译好FFmpeg库后再添加自己的C、C++代码来使用FFmpeg库来实现相应的音视频编解码功能。再编写make文件将我们编写的C、C++代码打包成so库。最后就可创建Android应用工程编写java代码及JNI代码。在JNI代码中调用我们提供的C、C++接口。
下面引用雷神的一张图片来概括Android应用程序使用FFmpeg类库的流程
android-ndk-r10e-linux-x86_64.zip
首先我们将FFmpeg源码下载下来,这里提供我亲测编译通过的源码地址:
ffmpeg-3.1.3.tar.gz
下载FFmpeg源代码之后,首先需要对源代码中的configure文件进行修改。由于编译出来的动态库文件名的版本号在.so之后(例如“libavcodec.so.5.100.1”),而android平台不能识别这样文件名,所以需要修改这种文件名。在configure文件中找到下面几行代码:
SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)'
SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR)$(SLIBNAME)'
替换为下面内容即可:
SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'
按照configure、make、make install的步骤就可以得到FFmpeg的头文件和类库文件了。下面看一下build_android_allinone.sh编译脚本打包所有静态库到一个动态so库文件:
#!/bin/bash
# NDK的路径,根据自己的安装位置进行设置
NDK=/home/pengtiegang/Android/android-ndk-r10e
# 编译针对的平台,可以根据自己的需求进行设置
# 这里选择最低支持android-14, arm架构,生成的so库是放在
# libs/armeabi文件夹下的,若针对x86架构,要选择arch-x86
PLATFORM=$NDK/platforms/android-9/arch-arm
# 工具链的路径,根据编译的平台不同而不同
# arm-linux-androideabi-4.8与上面设置的PLATFORM对应,4.8为工具的版本号,
# 根据自己安装的NDK版本来确定,一般使用最新的版本
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64
function build_one
{
./configure \
--prefix=$PREFIX \
--target-os=linux \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--arch=arm \
--sysroot=$PLATFORM \
--extra-cflags="-I$PLATFORM/usr/include" \
--cc=$TOOLCHAIN/bin/arm-linux-androideabi-gcc \
--nm=$TOOLCHAIN/bin/arm-linux-androideabi-nm \
--disable-shared \
--enable-runtime-cpudetect \
--enable-gpl \
--enable-small \
--enable-cross-compile \
--disable-debug \
--enable-static \
--disable-doc \
--disable-asm \
--disable-yasm \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--disable-indevs \
--disable-devices \
--disable-bsfs \
--disable-outdevs \
--enable-filter=aresample \
--enable-bsf=aac_adtstoasc \
--enable-bsf=h264_mp4toannexb \
--enable-dct \
--enable-dwt \
--enable-lsp \
--enable-mdct \
--enable-rdft \
--enable-fft \
--enable-version3 \
--enable-nonfree \
--disable-encoders \
--enable-encoder=pcm_s16le \
--enable-encoder=aac \
--enable-encoder=libmp3lame \
--enable-encoder=libfdk_aac \
--enable-encoder=libx264 \
--enable-encoder=mp2 \
--disable-decoders \
--enable-decoder=aac \
--enable-decoder=mjpeg \
--enable-decoder=png \
--enable-decoder=gif \
--enable-decoder=mp3 \
--enable-decoder=h264 \
--enable-decoder=pcm_s16le \
--disable-parsers \
--enable-parser=mjpeg \
--enable-parser=png \
--enable-parser=aac \
--enable-parser=h264 \
--enable-parser=mpeg4video \
--enable-parser=mpegvideo \
--enable-parser=mpegaudio \
--disable-muxers \
--enable-muxer=avi \
--enable-muxer=flv \
--enable-muxer=mp4 \
--enable-muxer=m4v \
--enable-muxer=mp3 \
--enable-muxer=mov \
--enable-muxer=h264 \
--enable-muxer=wav \
--enable-muxer=adts \
--disable-demuxers \
--enable-demuxer=mjpeg \
--enable-demuxer=m4v \
--enable-demuxer=gif \
--enable-demuxer=mov \
--enable-demuxer=avi \
--enable-demuxer=flv \
--enable-demuxer=h264 \
--enable-demuxer=aac \
--enable-demuxer=mp3 \
--enable-demuxer=wav \
--disable-protocols \
--enable-protocol=rtmp \
--enable-protocol=file \
--enable-protocol=http \
--disable-filters \
--enable-filter=transpose \
--enable-filter=crop \
--enable-filter=vflip \
--enable-filter=hflip \
--disable-avdevice \
--disable-stripping \
--enable-libx264 \
--enable-libfdk-aac \
--enable-libmp3lame \
--extra-cflags="-marm -march=armv7-a -I$PLATFORM/usr/include -Iexternal_libs/fdk-aac/build/armv7a/include -Iexternal_libs/libx264/build/armv7a/include -Iexternal_libs/lame/build/armv7a/include" \
--extra-ldflags="-marm -march=armv7-a -Lexternal_libs/fdk-aac/build/armv7a/lib -Lexternal_libs/libx264/build/armv7a/lib -Lexternal_libs/lame/build/armv7a/lib" \
$ADDITIONAL_CONFIGURE_FLAG
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_TRUNC 0/HAVE_TRUNC 1/g' config.h
sed -i '' 's/HAVE_TRUNCF 0/HAVE_TRUNCF 1/g' config.h
sed -i '' 's/HAVE_CBRT 0/HAVE_CBRT 1/g' config.h
sed -i '' 's/HAVE_RINT 0/HAVE_RINT 1/g' config.h
make clean
make -j4
make install
$TOOLCHAIN/bin/arm-linux-androideabi-ld \
-rpath-link=$PLATFORM/usr/lib \
-L$PLATFORM/usr/lib \
-L$PREFIX/lib \
-soname libffmpeg.so -shared -nostdlib -Bsymbolic --whole-archive --no-undefined -o \
$PREFIX/libffmpeg.so \
libavcodec/libavcodec.a \
libavfilter/libavfilter.a \
libswresample/libswresample.a \
libavformat/libavformat.a \
libavutil/libavutil.a \
libswscale/libswscale.a \
external_libs/libx264/libx264.a \
external_libs/fdk-aac/build/armv7a/lib/libfdk-aac.a \
external_libs/lame/build/armv7a/lib/libmp3lame.a \
-lc -lm -lz -ldl -llog --dynamic-linker=/system/bin/linker \
$TOOLCHAIN/lib/gcc/arm-linux-androideabi/4.8/libgcc.a \
}
# arm v7vfp
CPU=armv7-a
OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU "
PREFIX=./android/$CPU-vfp
ADDITIONAL_CONFIGURE_FLAG=
build_one
fdk-aac、lame、libx264、vo-aac为外部三方库,上面在build_android_allinone.sh脚本中已经添加了对这些库的支持,源码在external_libs目录下。
libfdk-aac的编译脚本如下所示。
#!/bin/bash
#Type Your NDK Root Path
NDK=/home/pengtiegang/Android/android-ndk-r10e
PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64
PLATFORM=$NDK/platforms/android-9/arch-arm
export PATH=$PATH:$PREBUILT/bin:$PLATFORM/usr/include:
#export LDFLAGS="-nostdlib -Bdynamic -Wl,--whole-archive -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,nocopyreloc -Wl,-soname,/system/lib/libz.so -Wl,-rpath-link=$ARM_LIB,-dynamic-linker=/system/bin/linker -L$PLATFORM/usr/lib -L$PREBUILT/arm-linux-androideabi/lib -L$NDK/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi -lgnustl_static -L$NDK/sources/cxx-stl/stlport/libs/armeabi -lstlport_static -lc -lgcc -lm -ldl "
#export CFLAGS="-I$NDK/sources/cxx-stl/gnu-libstdc++/4.6/include -I$NDK/sources/cxx-stl/stlport/stlport -I$PLATFORM/usr/include -fpic -DANDROID -fpic -mthumb-interwork -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -Wno-psabi -march=armv5te -mtune=xscale -msoft-float -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -DANDROID -Wa,--noexecstack -MMD -MP"
export LDFLAGS="-L$PLATFORM/usr/lib -L$PREBUILT/arm-linux-androideabi/lib"
export CFLAGS="-I$PLATFORM/usr/include -fpic -mthumb-interwork -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -Wno-psabi -march=armv7-a -mtune=xscale -msoft-float -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -DANDROID -Wa,--noexecstack -MMD -MP"
export CPPFLAGS="$CFLAGS"
export CFLAGS="$CFLAGS"
export CXXFLAGS="$CFLAGS"
export LDFLAGS="$LDFLAGS"
export AS=$PREBUILT/bin/arm-linux-androideabi-as
export LD=$PREBUILT/bin/arm-linux-androideabi-ld
export CXX="$PREBUILT/bin/arm-linux-androideabi-g++ --sysroot=${PLATFORM}"
export CC="$PREBUILT/bin/arm-linux-androideabi-gcc --sysroot=${PLATFORM}"
export NM=$PREBUILT/bin/arm-linux-androideabi-nm
export STRIP=$PREBUILT/bin/arm-linux-androideabi-strip
export RANLIB=$PREBUILT/bin/arm-linux-androideabi-ranlib
export AR=$PREBUILT/bin/arm-linux-androideabi-ar
./configure --host=armv7a \
--enable-static \
--disable-shared \
--prefix=/home/pengtiegang/GitHubCode/ffmpeg-3.1.3/external_libs/fdk-aac/build/armv7a/
make clean
make -j8
make install
lame的编译脚本如下所示:
#!/bin/bash
NDK=/home/pengtiegang/Android/android-ndk-r10e
PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64
PLATFORM=$NDK/platforms/android-9/arch-arm
export PATH=$PATH:$PREBUILT/bin:$PLATFORM/usr/include:
#export LDFLAGS="-nostdlib -Bdynamic -Wl,--whole-archive -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,nocopyreloc -Wl,-soname,/system/lib/libz.so -Wl,-rpath-link=$ARM_LIB,-dynamic-linker=/system/bin/linker -L$PLATFORM/usr/lib -L$PREBUILT/arm-linux-androideabi/lib -L$NDK/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi -lgnustl_static -L$NDK/sources/cxx-stl/stlport/libs/armeabi -lstlport_static -lc -lgcc -lm -ldl "
#export CFLAGS="-I$NDK/sources/cxx-stl/gnu-libstdc++/4.6/include -I$NDK/sources/cxx-stl/stlport/stlport -I$PLATFORM/usr/include -fpic -DANDROID -fpic -mthumb-interwork -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -Wno-psabi -march=armv5te -mtune=xscale -msoft-float -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -DANDROID -Wa,--noexecstack -MMD -MP"
export LDFLAGS="-L$PLATFORM/usr/lib -L$PREBUILT/arm-linux-androideabi/lib -march=armv7-a -O3"
export CFLAGS="-I$PLATFORM/usr/include -march=armv7-a -O3"
export CPPFLAGS="$CFLAGS"
export CFLAGS="$CFLAGS"
export CXXFLAGS="$CFLAGS"
export LDFLAGS="$LDFLAGS"
export AS=$PREBUILT/bin/arm-linux-androideabi-as
export LD=$PREBUILT/bin/arm-linux-androideabi-ld
export CXX="$PREBUILT/bin/arm-linux-androideabi-g++ --sysroot=${PLATFORM}"
export CC="$PREBUILT/bin/arm-linux-androideabi-gcc --sysroot=${PLATFORM} -march=armv7-a "
export NM=$PREBUILT/bin/arm-linux-androideabi-nm
export STRIP=$PREBUILT/bin/arm-linux-androideabi-strip
export RANLIB=$PREBUILT/bin/arm-linux-androideabi-ranlib
export AR=$PREBUILT/bin/arm-linux-androideabi-ar
./configure --host=arm-linux \
--disable-shared \
--disable-frontend \
--enable-static \
--prefix=/home/pengtiegang/GitHubCode/ffmpeg-3.1.3/external_libs/lame/build/armv7a/
make clean
make -j8
make install
libx264库的编译脚本:
#!/bin/bash
NDK=/home/pengtiegang/Android/android-ndk-r10e
export PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64
export CC="$PREBUILT/bin/arm-linux-androideabi-gcc --sysroot=${PLATFORM} -march=armv7-a"
export LD="$PREBUILT/bin/arm-linux-androideabi-ld"
export AS="$PREBUILT/bin/arm-linux-androideabi-gcc"
export AR="$PREBUILT/bin/arm-linux-androideabi-ar"
export RANLIB="$PREBUILT/bin/arm-linux-androideabi-ranlib"
export PLATFORM=$NDK/platforms/android-9/arch-arm
export PREFIX=/home/pengtiegang/GitHubCode/ffmpeg-3.1.3/external_libs/libx264/build/armv7a/
export PATH=$PATH:$PREBUILT/bin:$PLATFORM/usr/include:
./configure --prefix=$PREFIX \
--enable-static \
--enable-pic \
--enable-strip \
--disable-cli \
--disable-asm \
--extra-cflags= "-march=armv7-a -mfloat-abi=softfp -mfpu=neon" \
--host=arm-linux \
--cross-prefix=$PREBUILT/bin/arm-linux-androideabi- \
--sysroot=$PLATFORM
make clean
make
make install
vo_aac的编译脚本:
#!/bin/bash
NDK=/home/pengtiegang/Android/android-ndk-r10e
PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64
PLATFORM=$NDK/platforms/android-9/arch-arm
export PATH=$PATH:$PREBUILT/bin:$PLATFORM/usr/include:
echo $PATH
export LDFLAGS="-L$PLATFORM/usr/lib"
export CFLAGS="-L$PLATFORM/usr/lib -I$PLATFORM/usr/include"
echo $LDFLAGS
./configure --host=arm-linux-androideabi \
--with-sysroot=$PLATFORM/ \
--prefix=/home/pengtiegang/GitHubCode/ffmpeg-3.1.3/external_libs/vo_aac/build/armv5/ \
--enable-armv5e \
--includedir=$PLATFORM/usr/include \
--disable-shared
make clean
make
make install
至此FFmpeg库即可编译出来了,接下来我们可以创建AS工程来测试编译的FFmpeg库是否成功可用,
可以参考下一篇文章:Android FFmpegHellWorld(最简单的使用FFMpeg库的工程实例创建)