由于工做的关系和本身的兴趣缘由,我尝试了本身从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