1. 程式人生 > >FFMpeg 3.2移植到android遇到的各種坑,再一次總結

FFMpeg 3.2移植到android遇到的各種坑,再一次總結

故事很長,慢慢看!

首先我又一個需求,一張jpg加上gif後,變成一個gif動圖。如果你用命令ffmpeg -i  test.jpg -vf 'movie=test.gif[wm];[in][wm]overlay=0:0[out]' out.gif命令的話,我假設你的ffmpeg -version是3.2,那麼恭喜,這個需求你很容易搞定。

不幸的是,我的android專案是2.8版本,用上面這個命令,很遺憾,只出來兩幀!2 frame。(我當初還以為我編譯的2.8版本有問題,於是從新git clone 一下2.8分支,編譯,成功,./ffmpeg 命令一敲,對不起,就是2幀。)

後來我還下載超級古老的版本0.1版本的ffmpeg,編譯後上面的命令,只出來一幀。

幸好!3.2版本很完美支援了這個需求。

於是下載了3.2版本,下載了libfaac,x264原始碼,統統編譯好。

因為這篇是總結,所以直接說坑了。

第一個坑,其實3.2版本不支援libfaac了。嘿嘿。

第二個坑,x264編譯的時候,一定要和ffmpeg的platform是一樣的,否則發現不了。即使你-I -L各種加,都沒用。

mac下的編譯指令碼:

cd x264
export NDK=/Users/nillu/Documents/Androidndk/android-ndk-r13b
export PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt
export PLATFORM=$NDK/platforms/android-9/arch-arm
export PREFIX=../android-lib/x264/

./configure --prefix=$PREFIX \
--enable-static \
--enable-pic \
--disable-asm \
--disable-cli \
--host=arm-linux \
--cross-prefix=$PREBUILT/darwin-x86_64/bin/arm-linux-androideabi- \
--sysroot=$PLATFORM

make
make install

cd ..


第三個坑,NDK版本千萬不要用Android L。這個東西你編譯處理,發現又一個strcpy是沒辦法用的,在android手機4.4.4上沒辦法執行!所以版本最好19以下,21以上,悲劇掉坑。

類似如下:

export NDK=/Users/nillu/Documents/Androidndk/android-ndk-r13b
export PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt
export PLATFORM=$NDK/platforms/android-9/arch-arm
android_9最好不過了,如果你是21,估計要悲劇。

確認3個都沒問題了,我們成功的編譯出so庫來了。FFMPEG預設編譯出的so後面帶版本號,有木有辦法libavcodec_47.so的方式?有,修改configure裡面的。差不多修改如下:

#ffmpeg預設編譯出的是so加版本好,修改後變成xx_version.so
#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)'

SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'


SO出來後!就可以放到Android專案去編譯了。

出來的東西差不多這樣子:


弄到以前的android專案後,就能運行了嗎?So naive!

仔細想想,2.8為啥不能實現我們的需求,而3.2可以?其實原因就是API介面變了,你現在用2.8的 ffmpeg.c完全不能執行的,於是需要複製現在的ffmpeg.c,ffmpeg.h,cmdutils.h等一些檔案放到android目錄。需要編譯jni和修改這些ffmpeg檔案,為什麼?

因為ffmpeg.c這些檔案,不是針對android開發,是針對linux,mac系統開發的,現在在andriod專案include的標頭檔案,其實是ffmpeg框架中很小的一部分而已。所以ffmepg.c引入的檔案,你編譯出的so以及include裡面是沒有的,我們需要修改。

修改吧,修改吧。吧exit_program return吧,不要exit(1)了。

把main方法改下吧,exit_program的都return 了。否則一執行就崩潰。把一些自己寫的函式重新折騰進去吧~~~ 一天就這麼過去了啊·~~~~

以為修改好就能運行了嗎?

it too simple! 最後查了config.h和以前一對比,發現很多開關都是0!我草,是不是編譯的so庫有問題啊?沒包括一些解碼庫啊?

cd 3.2

make clean

export NDK=/Users/nillu/Documents/Androidndk/android-ndk-r13b
export PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt
export PLATFORM=$NDK/platforms/android-9/arch-arm
export PREFIX=out_ffmpeg_android_lib_full
build_one(){
  ./configure --target-os=linux --prefix=$PREFIX \
--enable-cross-compile \
--enable-runtime-cpudetect \
--disable-asm \
--arch=arm \
--cc=$PREBUILT/darwin-x86_64/bin/arm-linux-androideabi-gcc \
--cross-prefix=$PREBUILT/darwin-x86_64/bin/arm-linux-androideabi- \
--disable-stripping \
--nm=$PREBUILT/darwin-x86_64/bin/arm-linux-androideabi-nm \
--sysroot=$PLATFORM \
--enable-gpl --enable-shared --disable-static --enable-nonfree --enable-version3 --enable-small --disable-vda --disable-iconv \
--enable-libx264 --enable-encoder=libx264 \
--enable-zlib --disable-ffprobe --disable-ffplay --disable-ffmpeg --disable-ffserver --disable-debug \
--extra-cflags="-I ../android-lib/x264/include -fPIC -DANDROID -D__thumb__ -mthumb -Wfatal-errors -Wno-deprecated -mfloat-abi=softfp -marm -march=armv7-a" \
--extra-ldflags="-L ../android-lib/x264/lib"

}

build_one

make
make install

cd ..


最後執行,OK,搞定!