Android中集成ffmpeg(一):编译ffmpeg

  • 方案选择

Android中集成ffmpeg的codec功能无非两种方式:

    1. JNI直接调用,主要用于App开发(无权限修改系统底层),如EXOPlayer,JPlayer等。
    2. 集成ffmpeg到OMX,即封装ffmpeg为OMX的plugin,然后实现component接口。

考虑到性能问题,我选取的方案二即集成ffmpeg到OMX。首先第一个问题就是ffmpeg的编译。也有两种方式:

    1. 集成ffmpeg源码到整个Android系统工程,独立写bp或mk进行编译。(由于ffmpeg配置复杂,参考网上的一些现成mk进行修改发现工作量比较巨大)
    2. 独立NDK编译ffmpeg成动态库或静态库,然后通过prebuild的方式集成。(由于OMX的plugin是直接动态加载动态库,无编译上的依赖,此种方法编译跟普通的ffmpeg编译类似,故推荐该方法)

 

  • FFmpeg配置

32bit编译配置:

 1 #!/bin/bash
 2 
 3 chmod 777 ./configure
 4 #chmod 777 ./version.sh
 5 NDK=/your_ndk_path/android-ndk-r16b
 6 SYSROOT=$NDK/platforms/android-27/arch-arm
 7 TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
 8 CROSS=$TOOLCHAIN/bin/arm-linux-androideabi-
 9 
10 ISYSROOT=$NDK/sysroot
11 ASM=$ISYSROOT/usr/include/arm-linux-androideabi
12 CC=$TOOLCHAIN/bin/arm-linux-androideabi-gcc
13 NM=$TOOLCHAIN/bin/arm-linux-androideabi-nm
14 
15 CPU=arm
16 PREFIX=./android/$CPU
17 ADDI_CFLAGS="-marm"
18 
19 function build_one
20 {
21 ./configure \
22 --prefix=$PREFIX \
23 --target-os=linux \
24 --arch=$CPU \
25 --enable-cross-compile \
26 --incdir=$NDK/sysroot/usr/include \
27 --sysroot=$SYSROOT \
28 --cross-prefix=$CROSS \
29 --cc=$CC \
30 --nm=$NM \
31 --extra-cflags="-I$ASM -isysroot $ISYSROOT -Os -fpic $ADDI_CFLAGS" \
32 --enable-shared \
33 --enable-static \
34 --disable-asm \
35 --enable-pic \
36 --disable-doc \
37 --disable-ffmpeg \
38 --disable-ffplay \
39 --disable-ffprobe \
40 --disable-ffserver \
41 --disable-avdevice \
42 --disable-doc \
43 --disable-symver \
44 --disable-debug \
45 --disable-encoders \
46 --disable-muxers \
47 --enable-avresample \
48 --disable-pthreads \
49 --enable-swresample
50 make
51 make install
52 }
53 
54 rm -rf $PREFIX
55 make distclean
56 build_one
View Code

 

说明:

 1. --disable-asm选项是因为在ffmpeg-2.0的版本编译出版本运行时出现错误:libavcodec.so: has text relocation。 但是在用ffmpeg-3.3版本时没有出现。也有文章说跟NDK版本也有关系。

可以通过命令检查:readelf -a aarch64/lib/libavcodec.so |grep TEXTREL

 2. 在高版本的ffmpeg(如3.3.8)中,可以直接指定--target-os=android ,否则就需要修改configure文件让输出的动态库不带版本号,修改SLIBNAME_WITH_VERSION等选项为:

SLIBNAME='$(SLIBPREF)$(FULLNAME)$(SLIBSUF)'
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)'

   3. ffmpeg增加动态库导出函数,只需要修改源码所在目录的.v文件,如在libavformat/libavformat.v中增加导出ffurl_register_protocol方法供外部代码链接。

 

64bit编译配置:

 1 #!/bin/bash
 2 
 3 chmod 777 ./configure
 4 #chmod 777 ./version.sh
 5 NDK=/disk2/wuxingde/android-ndk-r16b
 6 SYSROOT=$NDK/platforms/android-27/arch-arm64
 7 TOOLCHAIN=$NDK/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64
 8 
 9 ISYSROOT=$NDK/sysroot
10 ASM=$ISYSROOT/usr/include/aarch64-linux-android
11 CC=$TOOLCHAIN/bin/aarch64-linux-android-gcc
12 NM=$TOOLCHAIN/bin/aarch64-linux-android-nm
13 
14 CPU=aarch64
15 PREFIX=$(pwd)/android/$CPU
16 #ADDI_CFLAGS="-marm"
17 
18 function build_one
19 {
20 ./configure \
21 --prefix=$PREFIX \
22 --target-os=linux \
23 --arch=$CPU \
24 --enable-cross-compile \
25 --incdir=$NDK/sysroot/usr/include \
26 --sysroot=$SYSROOT \
27 --cross-prefix=$TOOLCHAIN/bin/aarch64-linux-android- \
28 --cc=$CC \
29 --nm=$NM \
30 --extra-cflags="-I$ASM -isysroot $ISYSROOT -Os -fpic" \
31 --enable-shared \
32 --enable-static \
33 --enable-asm \
34 --enable-pic \
35 --disable-doc \
36 --disable-ffmpeg \
37 --disable-ffplay \
38 --disable-ffprobe \
39 --disable-ffserver \
40 --disable-avdevice \
41 --disable-doc \
42 --disable-symver \
43 --disable-debug \
44 --disable-encoders \
45 --disable-muxers \
46 --enable-avresample \
47 --disable-pthreads \
48 --enable-swresample
49 make
50 make install
51 }
52 
53 rm -rf $PREFIX
54 make distclean
55 build_one
View Code

 

  • PREBUID

如果只用64bit版本可以直接使用下面Android.mk一次性编译:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_PREBUILT_LIBS := \
        lib/libavcodec.so \
        lib/libavformat.so \
        lib/libavutil.so \
        lib/libavfilter.so \
        lib/libswresample.so \
        lib/libavresample.so \
        lib/libswscale.so

include $(BUILD_MULTI_PREBUILT)
View Code

如果同时需要32bit和64bit版本需要使用下面Android.mk分别编译各个库:

 1 LOCAL_PATH := $(call my-dir)
 2 include $(CLEAR_VARS)
 3 
 4 LOCAL_SRC_FILES_32 := \
 5         arm/lib/libavcodec.so
 6 LOCAL_SRC_FILES_64 := \
 7         aarch64/lib/libavcodec.so
 8 LOCAL_MODULE := libavcodec
 9 LOCAL_MODULE_SUFFIX := .so
10 LOCAL_MODULE_CLASS := SHARED_LIBRARIES
11 #LOCAL_MODULE_TARGET_ARCH := arm
12 LOCAL_MULTILIB := both
13 include $(BUILD_PREBUILT)
14 
15 include $(CLEAR_VARS)
16 LOCAL_SRC_FILES_32 := \
17         arm/lib/libavformat.so
18 LOCAL_SRC_FILES_64 := \
19         aarch64/lib/libavformat.so
20 LOCAL_MODULE := libavformat
21 LOCAL_MODULE_SUFFIX := .so
22 LOCAL_MODULE_CLASS := SHARED_LIBRARIES
23 #LOCAL_MODULE_TARGET_ARCH := arm
24 LOCAL_MULTILIB := both
25 include $(BUILD_PREBUILT)
26 
27 include $(CLEAR_VARS)
28 LOCAL_SRC_FILES_32 := \
29         arm/lib/libavutil.so
30 LOCAL_SRC_FILES_64 := \
31         aarch64/lib/libavutil.so
32 LOCAL_MODULE := libavutil
33 LOCAL_MODULE_SUFFIX := .so
34 LOCAL_MODULE_CLASS := SHARED_LIBRARIES
35 #LOCAL_MODULE_TARGET_ARCH := arm
36 LOCAL_MULTILIB := both
37 include $(BUILD_PREBUILT)
38 
39 include $(CLEAR_VARS)
40 LOCAL_SRC_FILES_32 := \
41         arm/lib/libavresample.so
42 LOCAL_SRC_FILES_64 := \
43         aarch64/lib/libavresample.so
44 LOCAL_MODULE := libavresample
45 LOCAL_MODULE_SUFFIX := .so
46 LOCAL_MODULE_CLASS := SHARED_LIBRARIES
47 #LOCAL_MODULE_TARGET_ARCH := arm
48 LOCAL_MULTILIB := both
49 include $(BUILD_PREBUILT)
50 
51 include $(CLEAR_VARS)
52 LOCAL_SRC_FILES_32 := \
53         arm/lib/libavfilter.so
54 LOCAL_SRC_FILES_64 := \
55         aarch64/lib/libavfilter.so
56 LOCAL_MODULE := libavfilter
57 LOCAL_MODULE_SUFFIX := .so
58 LOCAL_MODULE_CLASS := SHARED_LIBRARIES
59 #LOCAL_MODULE_TARGET_ARCH := arm
60 LOCAL_MULTILIB := both
61 include $(BUILD_PREBUILT)
62 
63 include $(CLEAR_VARS)
64 LOCAL_SRC_FILES_32 := \
65         arm/lib/libswresample.so
66 LOCAL_SRC_FILES_64 := \
67         aarch64/lib/libswresample.so
68 LOCAL_MODULE := libswresample
69 LOCAL_MODULE_SUFFIX := .so
70 LOCAL_MODULE_CLASS := SHARED_LIBRARIES
71 #LOCAL_MODULE_TARGET_ARCH := arm
72 LOCAL_MULTILIB := both
73 include $(BUILD_PREBUILT)
74 
75 include $(CLEAR_VARS)
76 LOCAL_SRC_FILES_32 := \
77         arm/lib/libswscale.so
78 LOCAL_SRC_FILES_64 := \
79         aarch64/lib/libswscale.so
80 LOCAL_MODULE := libswscale
81 LOCAL_MODULE_SUFFIX := .so
82 LOCAL_MODULE_CLASS := SHARED_LIBRARIES
83 #LOCAL_MODULE_TARGET_ARCH := arm
84 LOCAL_MULTILIB := both
85 include $(BUILD_PREBUILT)
View Code

 

编译部分就到此结束,这部分由于Android NDK版本(我用的是android-ndk-r16b)和ffmpeg版本不同,网上很多教程都没法用,花费了很多时间。特别要注意ffmpeg中--extra-cflags=配置,不要随意加额外一些定义,可能会导致链接不上的问题。

 

posted @ 2018-12-01 17:38  startcool  阅读(3769)  评论(0编辑  收藏  举报