1. 程式人生 > >windows下使用ndk9編譯ffmpeg

windows下使用ndk9編譯ffmpeg

折騰了2天,終於編譯成功,不容易啊。

據說Linux下比windows的簡單,windows下問題太多,會搞崩潰,真的是這樣。在崩潰邊緣嘗試ubuntu下編譯,果然輕鬆不少。最後不想放棄,還是堅持在windows下也編譯通過。

我的編譯環境:

win8.1,cygwin1.7,ndk-r9d,ffmpeg2.2.2

首先搭建環境

一、安裝Cygwin:

NDK編譯程式碼時要用到make和gcc,所以先搭建一個Linux環境。

cygwin是在Windows平臺上執行的Unix模擬環境,通過它 就可以在不安裝Linux的情況下使用NDK來編譯C、C++程式碼。

1. 選擇安裝包列表

一開始只選擇了需要的包,安裝完成之後執行cygwin總報錯,提示找不到cygintl-8.dll或者丟失cygwin1.dll,

解決辦法:換個下載站點,重新安裝Devel下所有包

2. 測試cygwin是否安裝成功:

     cygcheck -c cygwin 列印當前cygwin的版本和執行狀態

     make -v 和 gcc -v 打印出對應的版本資訊,安裝成功

二、下載安裝NDK

http://developer.android.com/tools/sdk/ndk/index.html

下載解壓到自己喜歡的路徑就行

三、配置NDK

1. 在cygwin的安裝目錄下找到 home\使用者名稱\.bash_profile檔案,編輯

NDK=/cygdrive/android-ndk目錄

例如

     NDK=/cygdrive/e/Tools/Java/android/android-ndk-r9d      export NDK

NDK這個名字是隨便取的

2. 開啟cygwin,輸入cd $NDK,輸出上面配置的 /cygdrive/e/Tools/Java/android/android-ndk-r9d 資訊,則環境變數設定成功

接下來就可以編譯ffmpeg了 編譯過程網上很多,這裡稍微簡述下,主要是對碰到的問題及解決辦法做個總結。 一、建立個人資料夾,底下再建立jni資料夾,把下載的ffmpeg原始碼解壓至jni下,改個名,我的路徑是E:\Android\mPlayer\jni\ffmpeg

二、建立config.sh和各個Android.mk,我是直接從網上down的,有坑,後面來填

三、cygwin下cd到ffmpeg,執行config.sh 報錯: /cygdrive/e/Tools/Java/android/android-ndk-r9d/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/bin/arm-linux-androideabi-gcc is unable to create an executable file. C compiler test failed. 解決辦法: export TMPDIR=e:/Tools/cygwin64/tmp 設定臨時目錄, 還是報錯,把config.sh裡的PREBUILT和PLATFORM改成絕對路徑: PREBUILT=E:/Tools/Java/android/android-ndk-r9d/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64 PLATFORM=E:/Tools/Java/android/android-ndk-r9d/platforms/android-19/arch-arm 執行完成後,在ffmpeg目錄下生成了config.h, config.mak

四、cd到mPlayer,執行${NDK}/ndk-build開始編譯,${NDK}是之前配置的環境變數 下面是編譯時的各種報錯及最終的解決辦法: 1. jni/ffmpeg/libavcodec/Makefile:1: ../config.mak: No such file or directory jni/ffmpeg/libavfilter/Makefile:1: ../config.mak: No such file or directory jni/ffmpeg/libavformat/Makefile:1: ../config.mak: No such file or directory jni/ffmpeg/libavutil/Makefile:1: ../config.mak: No such file or directory jni/ffmpeg/libpostproc/Makefile:1: ../config.mak: No such file or directory jni/ffmpeg/libswscale/Makefile:1: ../config.mak: No such file or directory 處理方法: 將libavcodec, libavfilter, libavformat, libavutil, libpostproc, libswscale目錄下Makefile的include $(SUBDIR)../config.mak註釋掉 2. /cygdrive/e/Tools/Java/android/android-ndk-r9d/build/core/build-binary.mk:120: *** target file 'clean' has both : and :: entries。 停止。 處理方法: ffmpeg/libavfilter/Makefile 最後面 clean:      $(RM) $(CLEANSUFFIXES:%=libavfilter/libmpcodecs/%) 去掉 3. jni/ffmpeg/libavformat/../libavutil/libm.h:52:32: error: static declaration of 'cbrt' follows non-static declaration jni/ffmpeg/libavformat/../libavutil/libm.h:59:31: error: static declaration of 'cbrtf' follows non-static declaration jni/ffmpeg/libavformat/../libavutil/libm.h:86:38: error: expected identifier or '(' before 'sizeof' jni/ffmpeg/libavformat/../libavutil/libm.h:86:38: error: expected ')' before '?' token jni/ffmpeg/libavformat/../libavutil/libm.h:96:38: error: expected identifier or '(' before 'sizeof' jni/ffmpeg/libavformat/../libavutil/libm.h:96:38: error: expected ')' before '?' token jni/ffmpeg/libavformat/../libavutil/libm.h:141:22: error: static declaration of 'rint' follows non-static declaration jni/ffmpeg/libavformat/../libavutil/libm.h:148:43: error: static declaration of 'lrint' follows non-static declaration jni/ffmpeg/libavformat/../libavutil/libm.h:155:43: error: static declaration of 'lrintf' follows non-static declaration jni/ffmpeg/libavformat/../libavutil/libm.h:162:41: error: static declaration of 'round' follows non-static declaration jni/ffmpeg/libavformat/../libavutil/libm.h:169:40: error: static declaration of 'roundf' follows non-static declaration jni/ffmpeg/libavformat/../libavutil/libm.h:176:41: error: static declaration of 'trunc' follows non-static declaration jni/ffmpeg/libavformat/../libavutil/libm.h:183:40: error: static declaration of 'truncf' follows non-static declaration 處理方法: 把ffmpeg/libavutil/libm.h 裡的所有static方法全都註釋掉 4. E:/Tools/Java/android/android-ndk-r9d/platforms/android-19/arch-arm/usr/include/stdlib.h:54:14: error: expected identifier or '(' before 'void' E:/Tools/Java/android/android-ndk-r9d/platforms/android-19/arch-arm/usr/include/stdlib.h:54:14: error: expected ')' before numeric constant 處理方法: 修改config.sh ,--extra-cflags="-I${PLATFORM}/usr/include -fPIC -DANDROID -std=c99 " \ 5. In file included from jni/ffmpeg/libavcodec/aacdec.c:84:0: jni/ffmpeg/libavcodec/../libavutil/float_dsp.h:148:50: error: expected ';', ',' or ')' before 'v1' jni/ffmpeg/libavcodec/aacdec.c: In function 'apply_mid_side_stereo': jni/ffmpeg/libavcodec/aacdec.c:1982:29: error: 'AVFloatDSPContext' has no member named 'butterflies_float' 處理方法: 修改config.h   #define av_restrict restrict改為#define av_restrict 6. jni/ffmpeg/libavutil/parseutils.c:555:15: error: storage size of 'dt' isn't known jni/ffmpeg/libavutil/parseutils.c:650:20: error: variable 'dt2' has initializer but incomplete type jni/ffmpeg/libavutil/parseutils.c:650:38: error: invalid type argument of unary '*' (have 'int') jni/ffmpeg/libavutil/parseutils.c:650:54: error: invalid type argument of unary '*' (have 'int') jni/ffmpeg/libavutil/parseutils.c:650:23: error: storage size of 'dt2' isn't known 處理方法: libavutil下time.h改名為avtime.h, libavcodec,libavforma,libavutil下所有呼叫了libavutil/time.h的.c檔案裡,把#include裡的libavutil/time.h統統改為avtime.h。 7. in function id3v2_read_internal.part.0:jni/ffmpeg/libavformat/id3v2.c:838: error: undefined reference to 'uncompress' in function matroska_decode_buffer:jni/ffmpeg/libavformat/matroskadec.c:1181: error: undefined reference to 'inflateInit_' in function matroska_decode_buffer:jni/ffmpeg/libavformat/matroskadec.c:1189: error: undefined reference to 'inflateEnd' in function matroska_decode_buffer:jni/ffmpeg/libavformat/matroskadec.c:1196: error: undefined reference to 'inflate' in function matroska_decode_buffer:jni/ffmpeg/libavformat/matroskadec.c:1201: error: undefined reference to 'inflateEnd' 處理方法: ffmpeg目錄下Android.mk把LOCAL_WHOLE_STATIC_LIBRARIES改為LOCAL_SHARED_LIBRARIES, 即LOCAL_SHARED_LIBRARIES := libavformat libavcodec libavutil libpostproc libswscale libswresample

ubuntu下:

ffmpeg目錄下Android.mk新增一行 LOCAL_LDLIBS := -L$(NDK_PLATFORMS_ROOT)/$(TARGET_PLATFORM)/arch-arm/usr/lib -L$(LOCAL_PATH) -llog -lz -ldl -lgcc

五、OK,編譯完成,在mPlayer目錄下生成了libs和obj,libs下有libffmpeg.so