Android中整合ffmpeg(一):編譯ffmpeg
阿新 • • 發佈:2018-12-01
- 方案選擇
Android中整合ffmpeg的codec功能無非兩種方式:
-
- JNI直接呼叫,主要用於App開發(無許可權修改系統底層),如EXOPlayer,JPlayer等。
- 整合ffmpeg到OMX,即封裝ffmpeg為OMX的plugin,然後實現component介面。
考慮到效能問題,我選取的方案二即整合ffmpeg到OMX。首先第一個問題就是ffmpeg的編譯。也有兩種方式:
-
- 整合ffmpeg原始碼到整個Android系統工程,獨立寫bp或mk進行編譯。(由於ffmpeg配置複雜,參考網上的一些現成mk進行修改發現工作量比較巨大)
- 獨立NDK編譯ffmpeg成動態庫或靜態庫,然後通過prebuild的方式整合。(由於OMX的plugin是直接動態載入動態庫,無編譯上的依賴,此種方法編譯跟普通的ffmpeg編譯類似,故推薦該方法)
- FFmpeg配置
32bit編譯配置:
#!/bin/bash chmod 777 ./configure #chmod 777 ./version.sh NDK=/disk2/wuxingde/android-ndk-r16b SYSROOT=$NDK/platforms/android-27/arch-arm TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9View Code/prebuilt/linux-x86_64 CROSS=$TOOLCHAIN/bin/arm-linux-androideabi- ISYSROOT=$NDK/sysroot ASM=$ISYSROOT/usr/include/arm-linux-androideabi CC=$TOOLCHAIN/bin/arm-linux-androideabi-gcc NM=$TOOLCHAIN/bin/arm-linux-androideabi-nm CPU=arm PREFIX=./android/$CPU ADDI_CFLAGS="-marm" function build_one { ./configure \ --prefix=$PREFIX \--target-os=linux \ --arch=$CPU \ --enable-cross-compile \ --incdir=$NDK/sysroot/usr/include \ --sysroot=$SYSROOT \ --cross-prefix=$CROSS \ --cc=$CC \ --nm=$NM \ --extra-cflags="-I$ASM -isysroot $ISYSROOT -Os -fpic $ADDI_CFLAGS" \ --enable-shared \ --enable-static \ --disable-asm \ --enable-pic \ --disable-doc \ --disable-ffmpeg \ --disable-ffplay \ --disable-ffprobe \ --disable-ffserver \ --disable-avdevice \ --disable-doc \ --disable-symver \ --disable-debug \ --disable-encoders \ --disable-muxers \ --enable-avresample \ --disable-pthreads \ --enable-swresample make make install } rm -rf $PREFIX make distclean build_one
說明:
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等選項為:
View Code
3. ffmpeg增加動態庫匯出函式,只需要修改原始碼所在目錄的.v檔案,如在libavformat/libavformat.v中增加匯出ffurl_register_protocol方法供外部程式碼連結。
64bit編譯配置:
#!/bin/bash chmod 777 ./configure #chmod 777 ./version.sh NDK=/disk2/wuxingde/android-ndk-r16b SYSROOT=$NDK/platforms/android-27/arch-arm64 TOOLCHAIN=$NDK/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64 ISYSROOT=$NDK/sysroot ASM=$ISYSROOT/usr/include/aarch64-linux-android CC=$TOOLCHAIN/bin/aarch64-linux-android-gcc NM=$TOOLCHAIN/bin/aarch64-linux-android-nm CPU=aarch64 PREFIX=$(pwd)/android/$CPU #ADDI_CFLAGS="-marm" function build_one { ./configure \ --prefix=$PREFIX \ --target-os=linux \ --arch=$CPU \ --enable-cross-compile \ --incdir=$NDK/sysroot/usr/include \ --sysroot=$SYSROOT \ --cross-prefix=$TOOLCHAIN/bin/aarch64-linux-android- \ --cc=$CC \ --nm=$NM \ --extra-cflags="-I$ASM -isysroot $ISYSROOT -Os -fpic" \ --enable-shared \ --enable-static \ --enable-asm \ --enable-pic \ --disable-doc \ --disable-ffmpeg \ --disable-ffplay \ --disable-ffprobe \ --disable-ffserver \ --disable-avdevice \ --disable-doc \ --disable-symver \ --disable-debug \ --disable-encoders \ --disable-muxers \ --enable-avresample \ --disable-pthreads \ --enable-swresample make make install } rm -rf $PREFIX make distclean build_oneView 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=配置,不要隨意加額外一些定義,可能會導致連結不上的問題。