系統(tǒng):macOS High Sierra 10.13.4
NDK:android-ndk-r11c
FFmpeg:ffmpeg-3.3.7
最近基于ffmpeg用c++寫了一個流媒體播放器,支持播放本地/網(wǎng)絡(luò)文件阅仔、rtmp/rtsp流薪伏,想將其移植到Android中,第一步要做的工作就是編譯Android能用的ffmpeg爹殊,之前編譯ffmpeg都是使用NDK直接編譯蜕乡,問題不大,而Android的NDK更新模式就如同Android的Framework更新一樣梗夸,即新版系統(tǒng)中會不斷調(diào)整(優(yōu)化)文件位置层玲,所以做過Android系統(tǒng)開發(fā)的朋友們應(yīng)該時常遇到“No such file or directory”。廢話不多說反症,開始辛块。
1、為何不使用網(wǎng)友直接編譯好的庫铅碍?NO润绵,因為我這個播放器是跨平臺的,而ffmpeg中的AVMediaType與IOS中AVFoundation下的AVMediaType沖突了胞谈,為了兼容IOS尘盼,所以我將ffmpeg源碼中的AVMediaType全局替換成了FFMAVMediaType然后再進行編譯。
sed -i '' "s/AVMediaType/FFMAVMediaType/g" `grep -rl AVMediaType ./ffmpeg-*`
/*如果報錯:sed: RE error: illegal byte sequence
缺少環(huán)境變量烦绳,在shell輸入:
export LC_COLLATE='C'
export LC_CTYPE='C'*/
2悔叽、準(zhǔn)備NDK和FFmpeg源碼,也可以使用Android Studio的SDK Manager一鍵下載NDK爵嗅,更加方便娇澎。
NDK下載地址:https://developer.android.google.cn/ndk/downloads/
FFmpeg下載地址:http://www.ffmpeg.org/download.html
3、下載完成后進入到ffmpeg根目錄創(chuàng)建腳本build-android.sh
3.1 腳本一:一次性編譯所有平臺
#NDK位置
export NDK=/Users/luohan/Library/Android/my_ndk_bundle/android-ndk-r11c
#編譯成功后的產(chǎn)出位置
PREFIX=android
NDK_HOST_PLATFORM=darwin-x86_64
#編譯過程中的臨時文件存放
export TMPDIR=/Users/luohan/ffmpegTemp
#各平臺交叉編譯鏈位置
ARM_LINUX_TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64
ARM_LINUX_SYSROOT=$NDK/platforms/android-21/arch-arm
ARM_64_TOOLCHAIN=$NDK/toolchains/aarch64-linux-android-4.9/prebuilt/darwin-x86_64
ARM_64_SYSROOT=$NDK/platforms/android-21/arch-arm64
X86_TOOLCHAIN=$NDK/toolchains/x86-4.9/prebuilt/darwin-x86_64
X86_SYSROOT=$NDK/platforms/android-21/arch-x86
X86_64_TOOLCHAIN=$NDK/toolchains/x86_64-4.9/prebuilt/darwin-x86_64
X86_64_SYSROOT=$NDK/platforms/android-21/arch-x86_64
COMMON_OPTIONS="\
--prefix=$PREFIX/ \
--target-os=android \
--disable-static \
--enable-shared \
--enable-small \
--disable-programs \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-doc \
--disable-symver \
--disable-asm \
--enable-cross-compile \
"
function build_android {
./configure \
--libdir=${PREFIX}/libs/armeabi-v7a \
--incdir=${PREFIX}/includes/armeabi-v7a \
--pkgconfigdir=${PREFIX}/pkgconfig/armeabi-v7a \
--arch=arm \
--cpu=armv7-a \
--cross-prefix="${ARM_LINUX_TOOLCHAIN}/bin/arm-linux-androideabi-" \
--sysroot="${ARM_LINUX_SYSROOT}/" \
--extra-cflags="-march=armv7-a -mfloat-abi=softfp -mfpu=neon -I $ARM_LINUX_SYSROOT/usr/include/" \
--extra-ldexeflags=-pie \
${COMMON_OPTIONS}
make clean
make -j8 && make install
./configure \
--libdir=${PREFIX}/libs/arm64-v8a \
--incdir=${PREFIX}/includes/arm64-v8a \
--pkgconfigdir=${PREFIX}/pkgconfig/arm64-v8a \
--arch=aarch64 \
--cpu=armv8-a \
--cross-prefix="${ARM_64_TOOLCHAIN}/bin/aarch64-linux-android-" \
--sysroot="${ARM_64_SYSROOT}/" \
--extra-libs=-lgcc \
--extra-cflags="$ARM_64_SYSROOT/usr/include/" \
--extra-ldexeflags=-pie \
${COMMON_OPTIONS}
make clean
make -j8 && make install
./configure \
--libdir=${PREFIX}/libs/x86 \
--incdir=${PREFIX}/includes/x86 \
--pkgconfigdir=${PREFIX}/pkgconfig/x86 \
--arch=x86 \
--cpu=i686 \
--cross-prefix="${X86_TOOLCHAIN}/bin/i686-linux-android-" \
--sysroot="${X86_SYSROOT}/" \
--extra-cflags="$X86_SYSROOT/usr/include/" \
--extra-ldexeflags=-pie \
${COMMON_OPTIONS}
make clean
make -j8 && make install
./configure \
--libdir=${PREFIX}/libs/x86_64 \
--incdir=${PREFIX}/includes/x86_64 \
--pkgconfigdir=${PREFIX}/pkgconfig/x86_64 \
--arch=x86_64 \
--cpu=x86_64 \
--cross-prefix="${X86_64_TOOLCHAIN}/bin/x86_64-linux-android-" \
--sysroot="${X86_64_SYSROOT}/" \
--extra-cflags="$X86_64_SYSROOT/usr/include/" \
--extra-ldexeflags=-pie \
${COMMON_OPTIONS}
make clean
make -j8 && make install
};
build_android
3.1 腳本二:只針對一種平臺進行編譯
#!/bin/sh
export NDK=/Users/luohan/Library/Android/my_ndk_bundle/android-ndk-r11c
SYSROOT=$NDK/platforms/android-21/arch-arm
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64
PREFIX=android
ADDI_CFLAGS="-marm"
function build_one
{
./configure \
--prefix="${PREFIX}/" \
--enable-shared \
--disable-static \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--disable-avdevice \
--disable-doc \
--disable-symver \
--disable-asm \
--cross-prefix="${TOOLCHAIN}/bin/arm-linux-androideabi-" \
--target-os=android \
--arch=arm \
--enable-cross-compile \
--sysroot="${SYSROOT}/" \
--extra-cflags="-mfpu=neon -mfloat-abi=softfp -I $NDK/platforms/android-21/arch-arm/usr/include/" \
--extra-ldflags="$ADDI_LDFLAGS"
$ADDITIONAL_CONFIGURE_FLAG
make clean
make
make install
}
build_one
說明下為什么這里我要使用舊版的NDK趟庄,因為我們在對ffmpeg進行交叉編譯時需要引用到c庫(--extra-cflags),此前伪很,舊版NDK的c庫目錄位置在“NDK/platforms/android-21/arch-arm64/usr/include/”中戚啥,而新版NDK中所以Android版本下的usr文件夾中都移除了include文件夾,全局搜索了一下發(fā)現(xiàn)锉试,它們被集合放在另一個目錄“NDK/sysroot/usr/include/”猫十,這算是一個優(yōu)化吧,但是引入該目錄后,編譯仍然報找不到c文件拖云,具體原因不明贷笛,最后我直接使用舊版NDK進行編譯,平臺版本選擇android-21宙项,因為android-21中全平臺的c庫都有乏苦,再次編譯,成功尤筐。
編譯過程中還遇到過其他問題,有時候命令行報錯不清晰盆繁,不能說明問題掀淘,這時就需要打開config.log查看詳細(xì)報錯,能幫助我們迅速對癥下藥油昂,以下我粗略地羅列了幾個問題的解決方案:
/toolchains/aarch64-linux-android-4.9/prebuilt//bin/aarch64-linux-android-gcc is unable to create an executable file.
C compiler test failed.
/*1.gcc交叉編譯文件位置不對(可通過查看config.log獲知)革娄。
2.沒有制定臨時編譯文件存放目錄,或目錄沒有提權(quán)秕狰。*/
WARNING: /Users/luohan/Library/Android/my_ndk_bundle/android-ndk-r16-beta1/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-pkg-config not found, library detection may fail.
/*警告稠腊,這種警告可直接無視*/
/bin/sh: ranlib/usr/local/lib/libavdevice.a: No such file or directory
make: *** [install-libavdevice-static] Error 127
/*未設(shè)置臨時文件位置所致*/
CC libavcodec/aacdec.o
/var/folders/6c/zwgcjwzn7y3b5z8wzvd3b8h00000gn/T//ccjyLRuc.s: Assembler messages:
/var/folders/6c/zwgcjwzn7y3b5z8wzvd3b8h00000gn/T//ccjyLRuc.s:16330: Error: selected processor does not support ARM mode `ubfx r1,r2,#0,#4'
/var/folders/6c/zwgcjwzn7y3b5z8wzvd3b8h00000gn/T//ccjyLRuc.s:16331: Error: selected processor does not support ARM mode `ubfx r0,r2,#4,#4'
/var/folders/6c/zwgcjwzn7y3b5z8wzvd3b8h00000gn/T//ccjyLRuc.s:16491: Error: selected processor does not support ARM mode `ubfx r2,r1,#0,#2'
/var/folders/6c/zwgcjwzn7y3b5z8wzvd3b8h00000gn/T//ccjyLRuc.s:16492: Error: selected processor does not support ARM mode `ubfx r7,r1,#2,#2'
/var/folders/6c/zwgcjwzn7y3b5z8wzvd3b8h00000gn/T//ccjyLRuc.s:16494: Error: selected processor does not support ARM mode `ubfx r8,r1,#4,#2'
/var/folders/6c/zwgcjwzn7y3b5z8wzvd3b8h00000gn/T//ccjyLRuc.s:16496: Error: selected processor does not support ARM mode `ubfx r10,r1,#6,#2'
/var/folders/6c/zwgcjwzn7y3b5z8wzvd3b8h00000gn/T//ccjyLRuc.s:16501: Error: selected processor does not support ARM mode `rbit r1,r1'
/var/folders/6c/zwgcjwzn7y3b5z8wzvd3b8h00000gn/T//ccjyLRuc.s:16687: Error: selected processor does not support ARM mode `ubfx r2,r3,#0,#2'
/var/folders/6c/zwgcjwzn7y3b5z8wzvd3b8h00000gn/T//ccjyLRuc.s:16688: Error: selected processor does not support ARM mode `ubfx r1,r3,#2,#2'
/var/folders/6c/zwgcjwzn7y3b5z8wzvd3b8h00000gn/T//ccjyLRuc.s:16690: Error: selected processor does not support ARM mode `ubfx r0,r3,#4,#2'
/var/folders/6c/zwgcjwzn7y3b5z8wzvd3b8h00000gn/T//ccjyLRuc.s:16692: Error: selected processor does not support ARM mode `ubfx lr,r3,#6,#2'
/var/folders/6c/zwgcjwzn7y3b5z8wzvd3b8h00000gn/T//ccjyLRuc.s:16842: Error: selected processor does not support ARM mode `ubfx r2,r3,#0,#4'
/var/folders/6c/zwgcjwzn7y3b5z8wzvd3b8h00000gn/T//ccjyLRuc.s:16843: Error: selected processor does not support ARM mode `ubfx r1,r3,#4,#4'
make: *** [libavcodec/aacdec.o] Error 1
/*.configure中加入–-disable-asm*/