前言
ffmpeg是一个超级牛逼的音视频软件,它几乎可以处理市面上常见的所有音视频格式,许多著名的软件都是基于ffmpeg的,比如kmplayer之类的播放器,格式工厂之类的格式转换软件等。并且ffmpeg可以运行在多种平台上,其中就包括了我们的Android平台。
1. 下载ffmpeg和x264
下载自然不必多说,到这个链接http://ffmpeg.org/download.html ,在右下角的Get the Sources
中,有Download Snapshot
和git snapshot
,如果你想通过git来更新代码,那就点击git snapshot
,如果不需要则选择Download Snapshot
。当然你也可以选择直接git clone的方式下载代码,带git的代码库有100多M,还是比较大的。
然后到这里http://www.videolan.org/developers/x264.html 下载最新的x264代码,同样可以下载压缩包或者直接git clone。
2. 配置
首先,确保你已经安装了ndk,如果没有安装,到这里下载最新版:https://developer.android.com/ndk/downloads/index.html 。下载完后解压到一个任意目录下。
由于ffmpeg默认的编译产物so文件后面会加上版本号,我们可以首先把编译产物命名修改成libxxxxx-.so以及libxxxxx.a
打开ffmpeg目录下的configure
文件,找到如下一段:
SLIBNAME_WITH_VERSION = '$(SLIBNAME).$(LIBVERSION)'
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_VERSION = '$(SLIBNAME).$(LIBVERSION)'
# SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)'
SLIBNAME_WITH_MAJOR = '$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD = '$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
# SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)'
SLIB_INSTALL_NAME = '$(SLIBNAME_WITH_MAJOR)'
# SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR) $(SLIBNAME)'
SLIB_INSTALL_LINKS = '$(SLIBNAME)'
接下来就是配置x264和ffmpeg了,这里我把x264放入了ffmpeg的目录,目录结构如下
├── ffmpeg
├── x264
└── others....
在ffmpeg下新建一个文件 build_x264.sh
,内容如下:
cd x264
export PLATFORM_VERSION = android-24
export ANDROID_NDK = /Users/junyuecao/Work/adt-bundle-mac-x86_64-20140702/sdk/ndk-bundle #ndk 目录根据你的安装目录
export TOOLCHAIN = ../../fftoolchain #toolchain 安装目录
export SYSROOT = $TOOLCHAIN /sysroot/
export PLATFORM = $ANDROID_NDK /platforms/$PLATFORM_VERSION /arch-arm
export PREFIX = ../android-lib #编译结果的目录
#生成toolchain目录,这一段可以在第一次运行后注释掉
$ANDROID_NDK /build/tools/make-standalone-toolchain.sh \
--toolchain = arm-linux-androideabi-4.9 \
--platform = $PLATFORM_VERSION --install-dir = $TOOLCHAIN
#
./configure \
--prefix = $PREFIX \
--enable-static \
--enable-shared \
--enable-pic \
--disable-asm \
--disable-cli \
--host = arm-linux \
--cross-prefix = $TOOLCHAIN /bin/arm-linux-androideabi- \
--sysroot = $PLATFORM
make -j8
make install
cd ..
在ffmpeg下新建一个文件 build_ffmpeg_with_x264.sh
,内容如下:
cd x264
export WD = /Users/junyuecao/Work/Misc/ffmpeg
export PLATFORM_VERSION = android-24
export ANDROID_NDK = /Users/junyuecao/Work/adt-bundle-mac-x86_64-20140702/sdk/ndk-bundle #ndk 目录根据你的安装目录
export TOOLCHAIN = $WD /../fftoolchain #toolchain 安装目录
export SYSROOT = $TOOLCHAIN /sysroot/
export PLATFORM = $ANDROID_NDK /platforms/$PLATFORM_VERSION /arch-arm
export PREFIX = $WD /android-lib #编译结果的目录
export OUT_PREFIX = $WD /../264fflib
#生成toolchain目录,这一段可以在第一次运行后注释掉
$ANDROID_NDK /build/tools/make-standalone-toolchain.sh \
--toolchain = arm-linux-androideabi-4.9 \
--platform = $PLATFORM_VERSION --install-dir = $TOOLCHAIN
#
./configure \
--prefix = $PREFIX \
--enable-static \
--enable-shared \
--enable-pic \
--disable-asm \
--disable-cli \
--host = arm-linux \
--cross-prefix = $TOOLCHAIN /bin/arm-linux-androideabi- \
--sysroot = $PLATFORM
make -j8
make install
cd ..
# 加入x264编译库
EXTRA_CFLAGS = "-I./android-lib/include"
EXTRA_LDFLAGS = "-L./android-lib/lib"
./configure \
--target-os = linux \
--prefix = $OUT_PREFIX \
--enable-cross-compile \
--enable-runtime-cpudetect \
--disable-asm \
--disable-doc \
--arch = arm \
--cc = $TOOLCHAIN /bin/arm-linux-androideabi-gcc \
--cross-prefix = $TOOLCHAIN /bin/arm-linux-androideabi- \
--disable-stripping \
--nm = $TOOLCHAIN /bin/arm-linux-androideabi-nm \
--sysroot = $PLATFORM \
--enable-gpl \
--enable-static \
--disable-shared \
--enable-version3 \
--enable-small \
--disable-vda \
--disable-iconv \
--disable-encoders \
--enable-libx264 \
--enable-encoder = libx264 \
--disable-muxers \
--enable-muxer = mov \
--enable-muxer = ipod \
--enable-muxer = psp \
--enable-muxer = mp4 \
--enable-muxer = avi \
--disable-decoders \
--enable-decoder = aac \
--enable-decoder = aac_latm \
--enable-decoder = h264 \
--enable-decoder = mpeg4 \
--disable-demuxers \
--enable-demuxer = h264 \
--enable-demuxer = mov \
--disable-parsers \
--enable-parser = aac \
--enable-parser = ac3 \
--enable-parser = h264 \
--disable-protocols \
--enable-protocol = file \
--enable-protocol = rtmp \
--disable-bsfs \
--enable-bsf = aac_adtstoasc \
--enable-bsf = h264_mp4toannexb \
--disable-indevs \
--enable-zlib \
--disable-outdevs \
--disable-ffprobe \
--disable-ffplay \
--disable-ffmpeg \
--disable-ffserver \
--disable-debug \
--extra-cflags = $EXTRA_CFLAGS \
--extra-ldflags = $EXTRA_LDFLAGS
make clean
make -j8
make install
# 这段解释见后文
$TOOLCHAIN /bin/arm-linux-androideabi-ld -rpath-link = $PLATFORM /usr/lib -L $PLATFORM /usr/lib -L $OUT_PREFIX /lib -soname libffmpeg.so -shared -nostdlib -Bsymbolic --whole-archive --no-undefined -o $OUT_PREFIX /libffmpeg.so \
android-lib/lib/libx264.a \
libavcodec/libavcodec.a \
libavfilter/libavfilter.a \
libswresample/libswresample.a \
libavformat/libavformat.a \
libavutil/libavutil.a \
libswscale/libswscale.a \
libpostproc/libpostproc.a \
libavdevice/libavdevice.a \
-lc -lm -lz -ldl -llog --dynamic-linker = /system/bin/linker $TOOLCHAIN /lib/gcc/arm-linux-androideabi/4.9.x/libgcc.a
这里有两种选择:
打包出一个ffmpeg.so文件,上面的配置就是这样的结果
每个模块打包出单独的so,那么需要对上面的配置文件做两件事:1.去掉最后一段配置(make install 后面的),2.将configure选项–enable-static –disable-shared 反过来–enable-shared –disable-static
另外在这段配置中我去掉了很多编码解码组件,只保留了我需要的组件,大家可以视情况而定,增减配置。
编译结果
最终编译结果在ffmpeg的编译脚本里的OUT_PREFIX=../264fflib
所定义的路径,对于上面说的两种方式产生的编译产物分别如下。
第一种:
.
├── include
│ ├── libavcodec
│ ├── libavdevice
│ ├── libavfilter
│ ├── libavformat
│ ├── libavutil
│ ├── libpostproc
│ ├── libswresample
│ └── libswscale
├── lib
│ ├── libavcodec.a
│ ├── libavdevice.a
│ ├── libavfilter.a
│ ├── libavformat.a
│ ├── libavutil.a
│ ├── libpostproc.a
│ ├── libswresample.a
│ ├── libswscale.a
│ └── pkgconfig
└── libffmpeg.so
只需要在Android中引入libffmpeg.so就可以使用了。
第二种:
.
├── include
│ ├── libavcodec
│ ├── libavdevice
│ ├── libavfilter
│ ├── libavformat
│ ├── libavutil
│ ├── libpostproc
│ ├── libswresample
│ └── libswscale
└── lib
├── libavcodec-57.so
├── libavcodec.so -> libavcodec-57.so
├── libavdevice-57.so
├── libavdevice.so -> libavdevice-57.so
├── libavfilter-6.so
├── libavfilter.so -> libavfilter-6.so
├── libavformat-57.so
├── libavformat.so -> libavformat-57.so
├── libavutil-55.so
├── libavutil.so -> libavutil-55.so
├── libpostproc-54.so
├── libpostproc.so -> libpostproc-54.so
├── libswresample-2.so
├── libswresample.so -> libswresample-2.so
├── libswscale-4.so
├── libswscale.so -> libswscale-4.so
└── pkgconfig
这个方式出来的话,就需要把每一个so文件都引用一遍了。
备注
我在编译单个so过程中遇到一个出线undefined reference to 'x264_picture_init'
的错误,是因为上面配置文件最后一段没有加入android-lib/lib/libx264.a
静态文件的引用导致找不到x264库的函数,这还是由于我对C语言的编译链接过程以及动态库和静态库之间的区别理解太浅。这里将静态库合并成一个so文件的过程中需要保证每一个函数都能够找到,不像动态链接库,可以在需要时再去加载库文件。
接下来
后一篇文章