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=配置,不要隨意加額外一些定義,可能會導致鏈接不上的問題。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM