Android Linux(cygwin)配置ndk,編譯FFmpeg
一. 準備工作
這裏簡單說下爲什麼我都是選擇用新版本,因爲NDK在r18及以上版本移除了gcc,ffmpeg最新的版本也是針對交叉編譯Android平臺庫,默認使用clang編譯,編譯方式變了,當然某些文件的路徑就變了。這就是爲啥我們使用新版本,照着網上博客的編譯腳本CV大法搞不定的原因。我這裏被坑的也是一言難盡。
- linux操作系統 ,你可以選擇多種方式:比如Mac,比如樹莓派,xshell連接遠程服務器等。原諒我是windows筆記本,在MinGW和cygwin倆者間我選擇了cygwin。附上cygwin下載地址,關於其繁瑣的配置操作這裏就不在贅述了,百度一搜一大把,記住把我們是準備幹什麼的,把插件下載全!!!
- NDK,現在網上博客普遍都是用的r17及更低的版本,原諒我這個新版本強迫症患者,我選擇有多新用多新,當前最新版本r21。NDK下載地址;
- ffmpeg 當然是必須的,同樣的,選擇目前最新版本4.2.2;ffmpeg下載地址
二. 關於操作路徑
因爲我用的windows下的cygwin,所以我選擇偷懶,包括解壓,下載等工作我都選擇直接操作,命令行這個東西能不敲就不敲。
附上我的文件目錄以供參考:
如果使用cygwin操作的話,當然不能這麼直勾勾輸入這個路徑,還是需要一些其他操作。例子如下:
進入C盤 c:—— /cygdrive/c
進入D盤 d:—— /cygdrive/c
三. ffmpeg配置文件解析
原諒無比懶惰的我,直接windows下進入ffmpeg目錄,直接用記事本或者notepad++都可以,查看裏面的config文件。東西很多,只需要看show_help()
這個函數裏面的內容就行了,其他的東西可以選擇性忽略。當然你也可以正了八經的使用命令行掉用幫助信息。
摘除一些無用信息哈,把有用的東西列出來,我們用vim創建build.sh腳本,加上註釋內容如下。
#!/bin/bash
#NDK路徑
NDK=/cygdrive/e/1Developer/cygwin/home/heima/android-ndk-r21-linux-x86_64
API=21
#編譯平臺 arm aarch64 i686 x86_64
ARCH=arm
# 指定目標cpu的架構 armv7a armv8a
PLATFORM=armv7a
#隨便定義個路徑,方便下面配
TARGET=$PLATFORM-linux-androideabi
# 設置工具鏈。三種版本的ndk均不同linux:linux-x86_64mac MAC:darwin-x86_64
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin
# 設置編譯產物的輸出目錄,這裏表示在當前目錄下新建Android_out目錄
PREFIX=./AndroidLib/$PLATFORM
CFLAG="-D__ANDROID_API__=$API -U_FILE_OFFSET_BITS -DBIONIC_IOCTL_NO_SIGNEDNESS_OVERLOAD -Os -fPIC -DANDROID -D__thumb__ -mthumb -Wfatal-errors -Wno-deprecated -mfloat-abi=softfp -marm"
build_lib()
{
#執行configure腳本,用於生成makefile
./configure \
--ln_s="cp -rf" \
--prefix=$PREFIX \
# 指定交叉編譯工具
--cc=$TOOLCHAIN/$TARGET$API-clang \
--cxx=$TOOLCHAIN/$TARGET$API-clang++ \
--ld=$TOOLCHAIN/$TARGET$API-clang \
--target-os=android \
--arch=$ARCH \
--cpu=$PLATFORM \
--cross-prefix=$TOOLCHAIN/$ARCH-linux-androideabi- \
# 開啓交叉編譯
--enable-cross-compile \
--enable-shared \
--disable-static \
--enable-runtime-cpudetect \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-doc \
--disable-symver \
# 優化大小
--enable-small \
--enable-gpl \
--enable-nonfree \
--enable-version3 \
--disable-iconv \
--enable-neon \
--enable-hwaccels \
--enable-jni \
--enable-mediacodec \
# 關閉所有編碼器(播放不需要編碼)
--disable-avdevice \
--disable-decoders \
--enable-decoder=vp9 \
--enable-decoder=h264 \
--enable-decoder=mpeg4 \
--enable-decoder=aac \
--enable-decoder=h264_mediacodec \
--disable-postproc \
# 會傳給clang的參數
--extra-cflags="$CFLAG" \
--extra-ldflags="-marm"
}
#加載函數
build_lib
#make執行腳本
make clean
make install
這個東西呢,我估計你直接粘貼運行會報錯,因爲有幾個坑。
-
因爲拼接命令行裏面的的註釋也會被拼進去影響編譯,這個坑我已經踩過了,直接把
build_lib()
裏面所有的註釋刪掉再執行。 -
編碼格式的問題,因爲我是windows下直接用notepad++編譯的,所以會出些莫名其妙的錯誤,比如換行符一類的。建議直接vim命令創建文本,粘貼進去就好。
-
不幸的是仍然會有錯誤,ffmpeg爲了提高編譯速度,引入了yasm,需要安裝yasm的彙編編譯器。當然也可以選擇不安裝,直接按照提示輸入
./configure --disable-x86asm
,也不知道啥子個原因,我家裏這檯筆記本輸入命令後一直卡在這裏。等吧。。。。
最終成功關閉掉了,如下圖所示。
- 繼續運行安裝寫好的build.sh腳本,會經過漫長的等待。。。建議還是下載個yasm。。。相信我,我敲這句話時候已經等了半個小時了。
四. 關於優化
1.我實在忍受不了本地cygwin環境的烏龜速度了,恩,雲服務器,真香~
2.關於make腳本的執行,看了看資料,其實可以開啓多線程的。
make clean
make -j4
make install
五 RTMP編譯
我們可以理解爲FFmpeg只是一個編解碼的庫,如果需要視頻源,就需要引入rtmp。作爲一個實時傳輸協議(萬物皆協議),他用來拉取我們的音視頻流,然後才能用ffmpeg處理他。
在librtmp的根目錄編寫一個build_rtmp.sh
,網上隨便抄寫一個。
#!/bin/bash
NDK_ROOT=/home/android-ndk/android-ndk-r21
CPU=arm-linux-androideabi
TOOLCHAIN=$NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64
export XCFLAGS="-isysroot $NDK_ROOT/sysroot -isystem $NDK_ROOT/sysroot/usr/include/arm-linux-androideabi -D__ANDROID_API__=$API"
export XLDFLAGS="--sysroot=${NDK_ROOT}/platforms/android-$API/arch-arm "
export CROSS_COMPILE=$TOOLCHAIN/bin/arm-linux-androideabi-
make install SYS=android prefix=`pwd`/result CRYPTO= SHARED= XDEF=-DNO_SSL
執行腳本不出意外會報錯:
sh build_rtmp.sh
看下報錯信息,.o鏈接不出來,-gcc: Command not found
其中gcc編譯鏈找不到。如果是自己認真編譯過ffmpeg,並且用的是ndk-r17以上版本的一定會熟悉這個錯誤,新版本的ndk不支持gcc編譯鏈,默認爲clang。
理下思路,我們需要找到rtmp編譯文件裏面設置編譯路徑的地方。查看rtmp文件夾下的makefile,其中有2行:
CC=$(CROSS_COMPILE)gcc
LD=$(CROSS_COMPILE)ld
AR=$(CROSS_COMPILE)ar
問題原因就在這裏,make執行的時候默認去找gcc了。我們依照ffmeg的用到的方式,自己在腳本中添加編譯鏈的路徑。添加如下文件之後,發現還是報錯,絕望了。
export CC=$TOOLCHAIN/$TARGET$API-clang
export LD=$TOOLCHAIN/$TARGET$API-clang
export AR=$TOOLCHAIN/$TARGET$API-clang
既然不行,也就不執著了,還有2種方式可以選擇,
- 是換成ndkr17及以下
- 或者直接源碼放到AS裏面編譯吧。
1. Android Studio編譯
因爲我本地有現成的編譯so庫的工程,並且本地windows環境也便於操作。
簡單說,就是copy /home/rtmp/librtmp/librtmp(就是你下載的rtmp路徑/librtmp)路徑下所有的c/h,自己通過編譯器編譯。Android編譯庫文件
cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_VERBOSE_MAKEFILE on)
set(NAME rtmpdump)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/inc)
#預編譯宏
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNO_CRYPTO" )
file(GLOB rtmp_source src/*.c)
add_library(${NAME} SHARED ${rtmp_source})
set_target_properties(${NAME}
PROPERTIES
LIBRARY_OUTPUT_DIRECTORY
"${CMAKE_CURRENT_SOURCE_DIR}/lib/${ANDROID_ABI}")
camke執行,最終就會生成需要的so
2. 低版本ndk(r17c)編譯
先吐槽一句啊,xshell/xftp超級難用。
因爲上面我們發現了新版本(17以上)的ndk移除了gcc,默認clang,我又解決不了,所以我也湊合一下用下老版本的ndk吧。
編譯腳本如下
#!/bin/bash
NDK_ROOT=/home/ndk/android-ndk-r17c
CPU=arm-linux-androideabi
TOOLCHAIN=$NDK_ROOT/toolchains/$CPU-4.9/prebuilt/linux-x86_64
export XCFLAGS="-isysroot $NDK_ROOT/sysroot -isystem $NDK_ROOT/sysroot/usr/include/arm-linux-androideabi -D__ANDROID_API__=17"
export XLDFLAGS="--sysroot=${NDK_ROOT}/platforms/android-17/arch-arm "
export CROSS_COMPILE=$TOOLCHAIN/bin/arm-linux-androideabi-
make install SYS=android prefix=`pwd`/result CRYPTO= SHARED= XDEF=-DNO_SSL