由於工做的關係和本身的興趣緣由,我嘗試了本身從ubuntu 14.04 交叉編譯ffmpeg。html
我交叉編譯ffmpeg的方法,徹底是摸索獲得的。在這以前,我歷來沒有試過交叉編譯。c++
在從ubuntu成功交叉編譯以前,我屢次嘗試了在MingW、cygwin編譯ffmpeg,無一例外所有失敗。git
此次的成功徹底是巧合,由於換個電腦我不肯定我會不會仍是成功。雖然如此我依然要把此次經歷寫下來。程序員
首先,我在https://github.com/rdp/ffmpeg-windows-build-helpers得到一個交叉編譯的腳本。github
這個鏈接從http://trac.ffmpeg.org/wiki/CompilationGuide/CrossCompilingForWindows得到。ubuntu
下載它,在/home/username/目錄下解壓它,而後,windows
cd ffmpeg-windows-build-helpers-master chmod 777 cross_compile_ffmpeg.sh ./cross_compile_ffmpeg.sh
獲得一個這樣的界面:bash
2016年 01月 03日 星期日 23:16:00 CST ##################### Welcome ###################### Welcome to the ffmpeg cross-compile builder-helper script. Downloads and builds will be installed to directories within /home/ldxn/tmp/sandbox If this is not ok, then exit now, and cd to the directory where you'd like them installed, then run this script again from there. NB that once you build your compilers, you can no longer rename/move the sandbox directory, since it will have some hard coded paths in there. You can, of course, rebuild ffmpeg from within it, etc. Is /home/ldxn/tmp/sandbox ok (requires ~ 5GB space) [Y/n]?
直接回車,使用默認的Y選項。網絡
using default y Would you like to include non-free (non GPL compatible) libraries, like many high quality aac encoders [libfdk_aac] The resultant binary may not be distributable, but can be useful for in-house use. Include these non-free-license libraries [y/N]?
直接回車,使用默認的N選項。dom
using default n What version of MinGW-w64 would you like to build or update? 1. Both Win32 and Win64 2. Win32 (32-bit only) 3. Win64 (64-bit only) 4. Exit Input your choice [1-4]: 2
問你要編譯32位仍是64位,仍是32和64位,我使用2,怕有些電腦不支持64。雖然個人電腦是64的。鍵入2,回車。
Input your choice [1-4]: 2 starting to download and build cross compile version of gcc [requires working internet access] with thread count 8... building win32 cross compiler % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 77026 100 77026 0 0 9480 0 0:00:08 0:00:08 --:--:-- 19275 [1/49]: Downloading config.guess... done [2/49]: Downloading mingw-w64-4.0.4.tar.bz2...
運氣好的話,這個時候就已經開始下載了。運氣差的話,連不上網,以上步驟從新走一次就能夠了。
理論上,網絡暢通,操做系統環境沒問題,當這個腳本運行結束的時候,也就是你得到一個ffmpeg的時候了。
但程序員的平常是絕對不會如此一路順風,一波九折絕對不是誇張。
寫這篇文章的時候,我已經完成了編譯。我沒有寫博客的習慣,因此我沒有在編譯的過程當中隨時記錄當時的狀態。
如今我僅僅靠記憶,來記錄一些我碰到的問題。
make的時候找不到libpthread,這是下不了這個包,因此沒編譯。網上找到這個包的地址,在sandbox/cross_compilers/mingw-w64-build-3.6.7.local中替換原來的地址,第二個解決辦法是若是是網絡超時沒法下載,就能夠先把地址提取出來,去下好,放在正確的位置,修改mingw-w64-build-3.6.7.local的腳本,而後編譯完成後再改回來,我忘了我是使用哪一種方法了。
在個人mingw-w64-build-3.6.7.local版本中,搜索build_pthreads_w32,會轉到一個函數,以下:
build_pthreads_w32 () { if [[ -z "$pthreads_w32_ver" ]]; then pthreads_w32_ver='cvs' fi local target prefix target="$1" prefix="$2" shift 2 cd "$pkgs_dir" || print_error create_pkg_dirs 'pthread-w32' || print_error if [[ "$pthreads_w32_ver" = "$pthreads_w32_release_ver" ]]; then download_extract "ftp://sourceware.org/pub/pthreads-win32/pthreads-w32-$pthreads_w32_release_ver-release.tar.gz" if [[ ! -d "pthreads-w32-$pthreads_w32_release_ver" ]]; then mv "pthreads-w32-$pthreads_w32_release_ver-release" "pthreads-w32-$pthreads_w32_release_ver" || print_error fi else unset oldmd5 newmd5 if cd 'pthreads-w32-cvs' 2>/dev/null; then build_progress 'pthreads-w32 cvs' 'Updating' cvs update > >(build_log) 2>&1 || print_error build_progress 'done' cd '..' else build_progress 'pthreads-w32 cvs' 'Downloading' cvs -d :pserver:anonymous@sourceware.org:/cvs/pthreads-win32 checkout pthreads > >(build_log) 2>&1 || print_error build_progress 'done' mv 'pthreads' 'pthreads-w32-cvs' fi fi cd "pthreads-w32-$pthreads_w32_ver" || print_error make realclean > >(build_log) 2>&1 || print_error if [[ "${static_build[@]}" != *"disable-shared"* ]]; then build_progress 'pthreads-w32 shared' 'Building' make CROSS="$target-" realclean GC ARCH="$pthread_arch" > >(build_log) 2>&1 || print_error build_progress 'done' cp 'pthreadGC2.dll' "$prefix/lib/" || print_error cd "$prefix/lib" || print_error ln -s "./pthreadGC2.dll" "./libpthread.dll" cd "$pkgs_dir/pthread-w32/source/pthreads-w32-$pthreads_w32_ver" || print_error fi build_progress 'pthreads-w32 static' 'Building' make CROSS="$target-" realclean GC-static ARCH="$pthread_arch" > >(build_log) 2>&1 || print_error build_progress 'done' cp 'libpthreadGC2.a' "$prefix/lib/" || print_error cp 'pthread.h' 'sched.h' 'semaphore.h' "$prefix/include/" || print_error cd "$prefix/lib" || print_error ln -s "./libpthreadGC2.a" "./libpthread.a" cd '../include' || print_error for file in 'pthread.h' 'sched.h' 'semaphore.h'; do if ! ed -s "$prefix/include/$file" <<< $',s/ __declspec (dllexport)//g\n,s/ __declspec (dllimport)//g\nw\nq' > >(build_log) 2>&1; then mv "$file" "$file".orig sed 's/ __declspec (dllexport)//g;s/ __declspec (dllimport)//g' "$file".orig > "$file" rm -f "$file".orig fi done }
download_extract "ftp://sourceware.org/pub/pthreads-win32/pthreads-w32-$pthreads_w32_release_ver-release.tar.gz"就是它的地址了
你想辦法弄到一個這樣的有效的地址貼在那裏就能夠經過了。
你還須要在sandbox/mingw-w64-i686文件夾中刪除compiler.done文件,這是cross_compile_ffmpeg.sh賴以判斷mingw是否正確安裝的文件。
刪了以後,註釋如下代碼:
rm -f $zeranoe_script_name || exit 1 curl -4 https://raw.githubusercontent.com/rdp/ffmpeg-windows-build-helpers/master/patches/$zeranoe_script_name -O || exit 1
由於mingw-w64-build-3.6.7.local是被下載的,從新安裝mingw是會刪掉原來的配置,而若是刪掉了你的修改也就沒了。。。
註釋掉後的cross_compile_ffmpeg.sh install_cross_compiler 函數以下:
install_cross_compiler() { if [[ -f "mingw-w64-i686/compiler.done" && -f "mingw-w64-x86_64/compiler.done" ]]; then echo "MinGW-w64 compilers already installed, not re-installing..." return # early exit just assume they want both, don't even prompt :) fi if [[ -z $compiler_flavors ]]; then pick_compiler_flavors fi if [[ $compiler_flavors == "win32" && -f "mingw-w64-i686/compiler.done" ]]; then echo "win32 cross compiler already installed, not reinstalling" return fi if [[ $compiler_flavors == "win64" && -f "mingw-w64-x86_64/compiler.done" ]]; then echo "win64 cross compiler already installed, not reinstalling" return fi # if they get this far, they want a compiler that's not installed, I think...fire away! XXXX if 32 bit compiler installed, and request both, rebuilds 32... local zeranoe_script_name=mingw-w64-build-3.6.7.local #rm -f $zeranoe_script_name || exit 1 #curl -4 https://raw.githubusercontent.com/rdp/ffmpeg-windows-build-helpers/master/patches/$zeranoe_script_name -O || exit 1 chmod u+x $zeranoe_script_name unset CFLAGS # don't want these for the compiler itself since it creates executables to run on the local box (we have a parameter allowing them to set them for the script "all builds" basically) # pthreads version to avoid having to use cvs for it echo "starting to download and build cross compile version of gcc [requires working internet access] with thread count $gcc_cpu_count..." echo "" # --disable-shared allows c++ to be distributed at all...which seemed necessary for some random dependency... nice ./$zeranoe_script_name --clean-build --disable-shared --default-configure --pthreads-w32-ver=2-9-1 --cpu-count=$gcc_cpu_count --build-type=$compiler_flavors --gcc-ver=5.3.0 || exit 1 export CFLAGS=$original_cflags # reset it if [[ ! -f mingw-w64-i686/bin/i686-w64-mingw32-gcc && ! -f mingw-w64-x86_64/bin/x86_64-w64-mingw32-gcc ]]; then echo "no gcc cross compiler(s) seem built [?] (build failure [?]) recommend nuke sandbox dir (rm -rf sandbox) and try again!" exit 1 fi if [ -d mingw-w64-x86_64 ]; then touch mingw-w64-x86_64/compiler.done fi if [ -d mingw-w64-i686 ]; then touch mingw-w64-i686/compiler.done fi rm -f build.log clear echo "Ok, done building MinGW-w64 cross-compiler(s) successfully..." }
由於GFW的存在,和跨太平洋的網絡通訊,不少時候有些軟件是下不下來的,不是被qiang就是下載速度不給力,
這個包沒法安裝在我以爲應該是第一個緣由。
我在163的鏡像站找到了它的源碼下載地址,把163的鏡像地址替換上去,替換後以下:
build_libsndfile() { # generic_download_and_install http://www.mega-nerd.com/libsndfile/files/libsndfile-1.0.25.tar.gz libsndfile-1.0.25 generic_download_and_install http://mirrors.163.com/ubuntu/pool/main/libs/libsndfile/libsndfile_1.0.25.orig.tar.gz libsndfile-1.0.25 }
把第一個的地址註釋,改成163的地址,瞬間解決了問題。其餘的下不下來也能夠這樣解決,主要版本號相差不大應該都是能夠的。
沒法安裝gnutls-3.3.19,也能夠這樣解決。或者重頭開始,多調用幾回cross_compile_ffmpeg.sh,也能夠解決。
downloading ftp://ftp.gnutls.org/gcrypt/gnutls/v3.3/gnutls-3.3.19.tar.xz % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- 0:00:27 --:--:-- 0
curl: (7) Failed to connect to ftp.gnutls.org port 21: 拒絕鏈接
像沒法安裝gnutls-3.3.19的問題,不斷地./cross_compile_ffmpeg.sh,而後輸入n,輸入2,我受夠了。
因此我學了下bash,寫下了如此腳本,死循環!!!
#!/bin/bash while true do ./cross_compile_ffmpeg.sh wait done
新建文本,重命名爲tmp.sh,把以上代碼貼上去,放在和cross_compile_ffmpeg.sh同一目錄:
chmod 777 tmp.sh
./tmp.sh
而後要修改一下cross_compile_ffmpeg.sh,由於每次執行cross_compile_ffmpeg.sh都須要n或者2,以作一些設定,把
修改它的目的就把這些設定內置了。修改以後的cross_compile_ffmpeg.sh以下:
intro() { cat <<EOL ##################### Welcome ###################### Welcome to the ffmpeg cross-compile builder-helper script. Downloads and builds will be installed to directories within $cur_dir If this is not ok, then exit now, and cd to the directory where you'd like them installed, then run this script again from there. NB that once you build your compilers, you can no longer rename/move the sandbox directory, since it will have some hard coded paths in there. You can, of course, rebuild ffmpeg from within it, etc. EOL if [[ $sandbox_ok != 'y' && ! -d sandbox ]]; then yes_no_sel "Is $PWD/sandbox ok (requires ~ 5GB space) [Y/n]?" "y" if [[ "$user_input" = "n" ]]; then exit 1 fi fi mkdir -p "$cur_dir" cd "$cur_dir" if [[ $disable_nonfree = "y" ]]; then non_free="n" else if [[ $disable_nonfree = "n" ]]; then non_free="y" else # yes_no_sel "Would you like to include non-free (non GPL compatible) libraries, like many high quality aac encoders [libfdk_aac] #The resultant binary may not be distributable, but can be useful for in-house use. Include these non-free-license libraries [y/N]?" "n" non_free="n" #$user_input" # save it away fi fi }
把non_free的值設爲默認n
第二處:
What version of MinGW-w64 would you like to build or update? 1. Both Win32 and Win64 2. Win32 (32-bit only) 3. Win64 (64-bit only) 4. Exit Input your choice [1-4]:
把它的預設值改成2,修改後的代碼以下:
pick_compiler_flavors() { compiler_flavors=win32 # while [[ "$compiler_flavors" != [1-4] ]]; do # if [[ -n "${unknown_opts[@]}" ]]; then # echo -n 'Unknown option(s)' # for unknown_opt in "${unknown_opts[@]}"; do # echo -n " '$unknown_opt'" # done # echo ', ignored.'; echo # fi # cat <<'EOF' #What version of MinGW-w64 would you like to build or update? # 1. Both Win32 and Win64 # 2. Win32 (32-bit only) # 3. Win64 (64-bit only) # 4. Exit #EOF # echo -n 'Input your choice [1-4]: ' # read compiler_flavors # done # case "$compiler_flavors" in # 1 ) compiler_flavors=multi ;; # 2 ) compiler_flavors=win32 ;; # 3 ) compiler_flavors=win64 ;; # 4 ) echo "exiting"; exit 0 ;; # * ) clear; echo 'Your choice was not valid, please try again.'; echo ;; # esac }
這樣,調用tmp.sh以後,cross_compile_ffmpeg.sh就不斷地重複調用,直到編譯完成爲止也不會中止,bash的高手請告訴我怎麼讓它在編譯完成後停下來。。。
固然,若是你碰上了沒法下載包的問題。tmp.sh並不能幫你完成這個。因此你仍是須要是否是地看看,是否是在哪裏卡了好久了,若是是,你就應該按下ctrl+c,和改下地址了。
像安裝x265 的時候,這個腳本須要x265的最新版本。因此在build_libx265函數中,它會不斷地查詢x265的最新版本。
但我在邊下載邊編譯ffmpeg的過程當中,可能會中斷無數次,而build_libx265這個函數檢查x265的最新版本很是消耗時間。
因此我,就,註釋掉它。你也能夠這樣作。
總結:
1.我是幸運的,我沒有碰到其餘奇形怪狀我沒法解決的問題。
2.由於完成ffmpeg的交叉編譯有幾天了,我不知道是否遺漏了哪些必要的東西沒有記錄。因此若是你們看到個人隨筆後沒法解決問題,能夠在回覆裏聯繫我,雖然我不必定可以及時看獲得。。。
題外:
我如今在嘗試交叉編譯vlc,編不過去,搞了好久了,都沒用。
by:戴華豪
2016年1月3日 22:31:52