1. 程式人生 > >FFmpeg原始碼簡單分析:configure

FFmpeg原始碼簡單分析:configure

=====================================================

FFmpeg的庫函式原始碼分析文章列表:

【架構圖】

【通用】

【解碼】

【編碼】

【其它】

【指令碼】

【H.264】

=====================================================


本文記錄FFmpeg的Configure指令碼的原始碼。Configure一方面用於檢測FFmpeg的編譯環境,另一方面根據使用者配置的選項生成config.mak,config.h檔案(可能還有config.asm),提供給Makefile使用。由於FFmpeg的configure指令碼很複雜(一個4000-5000行的Shell指令碼),難以逐行細緻的分析,因此本文簡單梳理一下它的結構。

PS1:Configure的日誌位於config.log檔案中。檢視該檔案有助於分析Configure的過程。

PS2:使用“sh -x script_name.sh”可以除錯Shell指令碼。

Configure檔案的整體流程

Configure檔案的整體流程如下所示。

Configure的整體流程可以分成以下幾步:

Set Default Value:設定各個變數預設值;

Parse Options:解析輸入的選項;

Check Compiler:檢查編譯器;

die_license_disabled():檢查GPL等協議的設定情況;

Check:檢查編譯環境(數學函式,第三方類庫等);

Echo info:控制檯上列印配置資訊;

Write basic info:向config.mak中寫入一些基本資訊; 

print_config():向config.h、config.mak、config.asm中寫入所有配置資訊;

print_enabled():向config.mak寫入所有enabled的元件資訊;

pkgconfig_generate():向libavXXX/libavXXX.pc中寫入pkgconfig資訊(XXX代表avcodec,avformat等);

下文簡單梳理一下這些步驟。

Set Default Value

Set Default Value部分設定一些Configure的預設值。例如下面的程式碼。
# 預設引數 default parameters
# 日誌
logfile="config.log"

# 安裝路徑 installation paths
prefix_default="/usr/local"
bindir_default='${prefix}/bin'
datadir_default='${prefix}/share/ffmpeg'
incdir_default='${prefix}/include'
libdir_default='${prefix}/lib'
mandir_default='${prefix}/share/man'
shlibdir_default="$libdir_default"
postproc_version_default="current"

# 工具鏈 toolchain
ar_default="ar"
cc_default="gcc"
cxx_default="g++"
cc_version=\"unknown\"
host_cc_default="gcc"
install="install"
ln_s="ln -sf"
nm_default="nm"
objformat="elf"
pkg_config_default=pkg-config
ranlib="ranlib"
strip_default="strip"
yasmexe_default="yasm"

nm_opts='-g'
nogas=":"

# 機器 machine
arch_default=$(uname -m)
cpu="generic"

# 作業系統 OS
target_os_default=$(tolower $(uname -s))
host_os=$target_os_default

# alternative libpostproc version
ALT_PP_VER_MAJOR=51
ALT_PP_VER_MINOR=2
ALT_PP_VER_MICRO=101
ALT_PP_VER=$ALT_PP_VER_MAJOR.$ALT_PP_VER_MINOR.$ALT_PP_VER_MICRO

# 選項 configurable options
# PROGRAM_LIST內容是 ffplay ffprobe ffserver ffmpeg
enable $PROGRAM_LIST

enable avcodec
enable avdevice
enable avfilter
enable avformat
enable avutil
enable postproc
enable stripping
enable swresample
enable swscale

enable asm
enable debug
enable doc
enable fastdiv
enable network
enable optimizations
enable safe_bitstream_reader
enable static
enable swscale_alpha

# 編譯選項 build settings
SHFLAGS='-shared -Wl,-soname,$$(@F)'
FFSERVERLDFLAGS=-Wl,-E
# 字首字尾
LIBPREF="lib"
LIBSUF=".a"
FULLNAME='$(NAME)$(BUILDSUF)'
# 名稱
LIBNAME='$(LIBPREF)$(FULLNAME)$(LIBSUF)'
# 動態庫字首字尾
SLIBPREF="lib"
SLIBSUF=".so"
# 名稱
SLIBNAME='$(SLIBPREF)$(FULLNAME)$(SLIBSUF)'
SLIBNAME_WITH_VERSION='$(SLIBNAME).$(LIBVERSION)'
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)'

AS_O='-o 
[email protected]
' CC_O='-o [email protected]' CXX_O='-o [email protected]' host_cflags='-D_ISOC99_SOURCE -O3 -g' host_libs='-lm' target_path='$(CURDIR)'

需要注意的是,“enable avcodec”,“enable avformat”,“enable avutil”等中的enable()本身是一個函式。enable()的定義如下。
#把所有輸入引數的值設定為"yes"
enable(){
    set_all yes $*
}

可以看出enable()呼叫了set_all()函式。並且將第1個引數設定為“yes”,並且將呼叫enable()時候的引數傳遞給set_all()。set_all()函式的定義如下所示。
#第一個引數為值,後面的引數為變數
set_all(){
    value=$1
    shift
    for var in $*; do
        eval $var=$value
    done
}

可以看出set_all()將傳入的引數全部進行賦值。特定於enable()函式來說,就是將所有的輸入變數賦值為“yes”。由此可見,“enable avcodec”實際上相當於執行了:
avcodec=”yes”

Parse Options

Parse Options部分用於解析Configure的附加引數。該部分的程式碼如下所示。
#注意:opt不是引數列表(實際上也沒有看見opt變數的定義)
#原因是處在for迴圈中,當你沒有為in指定列表時,for會預設取命令列引數列表。
#因此“opt”這個名字實際上是可以隨便取的
for opt do
# "#"用於去除特定字元前面的字串
# optval內容為opt去掉"="以及其前面字串之後的內容
    optval="${opt#*=}"
    case "$opt" in
    # 不同的選項
    --extra-ldflags=*) add_ldflags $optval
    ;;
    --extra-libs=*) add_extralibs $optval
    ;;
    --disable-devices) disable $INDEV_LIST $OUTDEV_LIST
    ;;
    --enable-debug=*) debuglevel="$optval"
    ;;
    --disable-everything)
    map 'eval unset \${$(toupper ${v%s})_LIST}' $COMPONENT_LIST
    ;;
    --enable-*=*|--disable-*=*)
    eval $(echo "${opt%%=*}" | sed 's/--/action=/;s/-/ thing=/')
    is_in "${thing}s" $COMPONENT_LIST || die_unknown "$opt"
    eval list=\$$(toupper $thing)_LIST
    name=$(echo "${optval}" | sed "s/,/_${thing}|/g")_${thing}
    $action $(filter "$name" $list)
    ;;
    --enable-?*|--disable-?*)
    eval $(echo "$opt" | sed 's/--/action=/;s/-/ option=/;s/-/_/g')
    if is_in $option $COMPONENT_LIST; then
        test $action = disable && action=unset
        eval $action \$$(toupper ${option%s})_LIST
    elif is_in $option $CMDLINE_SELECT; then
        $action $option
    else
        die_unknown $opt
    fi
    ;;
    --list-*)
        NAME="${opt#--list-}"
        is_in $NAME $COMPONENT_LIST || die_unknown $opt
        NAME=${NAME%s}
        eval show_list $NAME \$$(toupper $NAME)_LIST
    ;;
    --help|-h) show_help
    ;;
    *)
    #% 就是從右邊開始刪除符合條件的字串(符合條件的最短字串)
    #%%是刪除符合條件的最長的字串

    #刪除“=”右邊的內容
    optname="${opt%%=*}"
    #刪除左邊的“--”
    optname="${optname#--}"
    optname=$(echo "$optname" | sed 's/-/_/g')
    #看看是否在opt列表中,不在的話就會返回錯誤
    if is_in $optname $CMDLINE_SET; then
        eval $optname='$optval'
    elif is_in $optname $CMDLINE_APPEND; then
        append $optname "$optval"
    else
         die_unknown $opt
    fi
    ;;
    esac
done

在這裡需要注意,取出opt的值一般都是“--extra-ldflags=XXX”的形式,通過“${opt#*=}”擷取獲得“=”號後面的內容作為optval,對於“--extra-ldflags=XXX”來說,optval取值為“XXX”。
然後根據opt種類的不同,以及optval取值的不同,分別作不同的處理。

Check Compiler

Check Compiler用於檢查編譯器。這部分程式碼還沒有細看,暫時不做分析。

die_license_disabled()

die_license_disabled()用於檢查是否指定了特定了License。像libx264、libfaac這些第三方類庫,都需要指定特定的License才可以使用(例如libfaac必須指定nonfree)。開啟這些第三方類庫後如果沒有指定License,Configure會立刻退出。這部分程式碼如下所示。
#檢查License
#GPL
die_license_disabled gpl libcdio
die_license_disabled gpl libx264
die_license_disabled gpl libxavs
die_license_disabled gpl libxvid
die_license_disabled gpl x11grab
#nonfree
die_license_disabled nonfree libaacplus
die_license_disabled nonfree libfaac
die_license_disabled nonfree openssl
#Version3
die_license_disabled version3 libopencore_amrnb
die_license_disabled version3 libopencore_amrwb
die_license_disabled version3 libvo_aacenc
die_license_disabled version3 libvo_amrwbenc

其中涉及到一個函式die_license_disabled(),它的定義如下所示。
#不符合License則立刻結束
die_license_disabled() {
    enabled $1 || { enabled $2 && die "$2 is $1 and --enable-$1 is not specified."; }
}

從定義可以看出,die_license_disabled()首先會看第1個引數(對應“gpl”,“nonfree”)對應的元件是否enable,如果已經enable,則正常執行完函式;如果沒有enable,則會檢查第2個引數(對應“libx264”,“libfaac”)是否enable,如果第2個引數enable了,就會報錯退出。

Check

Check部分是Configure中最重要的部分。該部分用於檢查編譯環境(例如數學函式,第三方類庫等)。這一部分涉及到很多的函式。包括check_cflags()、check_struct()、require()、check_lib()、check_header()、check_func()、check_mathfunc()等等。這些函式之間的呼叫關係如下圖所示。
下面簡單舉例下面幾個函式:

check_func():用於檢查函式。

check_header():用於檢查標頭檔案。

check_func_headers():用於同時檢查標頭檔案和函式。

check_mathfunc():用於檢查數學類函式。

require():檢查第三方類庫。

check_cflags ():用於檢查編譯器的cflags標誌引數。

下面詳細看看這幾個函式。

check_func()

check_func()用於檢查函式。它的輸入引數一個函式名。Configure中與check_func()有關的程式碼如下所示。
check_func  isatty
check_func  localtime_r
check_func  ${malloc_prefix}memalign            && enable memalign
check_func  mkstemp
check_func  mmap
check_func  ${malloc_prefix}posix_memalign      && enable posix_memalign
check_func  setrlimit
check_func  strerror_r
check_func  strptime
check_func  sched_getaffinity
check_func  sysconf
check_func  sysctl

check_func()的定義如下所示。
check_func(){
    log check_func "[email protected]"
    func=$1
    shift
    disable $func
    check_ld "cc" "[email protected]" <<EOF && enable $func
extern int $func();
int main(void){ $func(); }
EOF
}

從check_func()的定義可以看出,該函式首先將輸入的第1個引數賦值給func,然後生成一個下述內容的C語言檔案。
extern int $func();
int main(void){ $func(); }

最後呼叫check_ld()完成編譯測試。check_ld()的定義如下所示。
check_ld(){
    log check_ld "[email protected]"
    type=$1
    shift 1
    flags=''
    libs=''
    for f; do
        test "${f}" = "${f#-l}" && flags="$flags $f" || libs="$libs $f"
    done
    check_$type $($filter_cflags $flags) || return
    check_cmd $ld $LDFLAGS $flags -o $TMPE $TMPO $libs $extralibs
}

其中check_cmd()是個很簡單的函式,可以輸出日誌,如下所示。
check_cmd(){
    log "[email protected]"
    "[email protected]" >> $logfile 2>&1
}

例如,“check_func  mkstemp”相當於編譯了下述程式碼。
extern int mkstemp();
int main(void){ mkstemp(); }

check_header()

check_header()用於檢查標頭檔案。Configure中與check_header()有關的程式碼如下所示。

check_header dlfcn.h
check_header dxva2api.h -D_WIN32_WINNT=0x0600
check_header libcrystalhd/libcrystalhd_if.h
check_header malloc.h
check_header poll.h
check_header sys/mman.h
check_header sys/param.h
check_header sys/resource.h
check_header sys/select.h
check_header termios.h
check_header vdpau/vdpau.h
check_header vdpau/vdpau_x11.h
check_header X11/extensions/XvMClib.h
check_header asm/types.h

check_header()的定義如下所示。
check_header(){
    log check_header "[email protected]"
    header=$1
    shift
    disable_safe $header
    check_cpp "[email protected]" <<EOF && enable_safe $header
#include <$header>
int x;
EOF
}

從check_header()的定義可以看出,該函式首先將輸入的第1個引數賦值給header,然後生成一個下述內容的C語言檔案。
#include <$header>
int x;

最後呼叫check_cpp()完成編譯測試。check_cpp()的定義如下所示。
check_cpp(){
    log check_cpp "[email protected]"
    cat > $TMPC
    log_file $TMPC
	#-E選項,可以讓編譯器在預處理後停止,並輸出預處理結果。
    check_cmd $cc $CPPFLAGS $CFLAGS "[email protected]" -E -o $TMPO $TMPC
}

例如,“check_header malloc.h”相當於處理以下C語言檔案。
#include <malloc.h>
int x;

check_func_headers()

check_func_headers()用於同時檢查標頭檔案和函式。Configure中與check_header()有關的程式碼如下所示。
check_func_headers conio.h kbhit
check_func_headers windows.h PeekNamedPipe
check_func_headers io.h setmode
check_func_headers lzo/lzo1x.h lzo1x_999_compress
check_func_headers windows.h GetProcessAffinityMask
check_func_headers windows.h GetProcessTimes
check_func_headers windows.h MapViewOfFile
check_func_headers windows.h VirtualAlloc

check_func_headers()的定義如下所示。
check_func_headers(){
    log check_func_headers "[email protected]"
    headers=$1
    funcs=$2
    shift 2
    {
        for hdr in $headers; do
            echo "#include <$hdr>"
        done
        for func in $funcs; do
            echo "long check_$func(void) { return (long) $func; }"
        done
        echo "int main(void) { return 0; }"
    } | check_ld "cc" "[email protected]" && enable $funcs && enable_safe $headers
}

從check_func_headers()的定義可以看出,該函式首先將輸入的第1個引數賦值給header,第2個引數賦值給funcs,然後生成一個下述內容的C語言檔案。
#include <$hdr>
long check_$func (void) { return (long) $func; }
int main(void) { return 0; }

例如,“check_func_headers windows.h PeekNamedPipe”相當於處理以下C語言檔案。
#include <windows.h>
long check_PeekNamedPipe (void) { return (long) PeekNamedPipe; }
int main(void) { return 0; }

check_mathfunc()

check_mathfunc()用於檢查數學類函式。Configure中與check_mathfunc()有關的程式碼如下所示。
check_mathfunc cbrtf
check_mathfunc exp2
check_mathfunc exp2f
check_mathfunc llrint
check_mathfunc llrintf
check_mathfunc log2
check_mathfunc log2f
check_mathfunc lrint
check_mathfunc lrintf
check_mathfunc round
check_mathfunc roundf
check_mathfunc trunc
check_mathfunc truncf

check_mathfunc()的定義如下所示。
check_mathfunc(){
    log check_mathfunc "[email protected]"
	#數學函式名稱
    func=$1
    shift
    disable $func
    check_ld "cc" "[email protected]" <<EOF && enable $func
#include <math.h>
float foo(float f) { return $func(f); }
int main(void){ return (int) foo; }
EOF
}

從check_mathfunc()的定義可以看出,該函式首先將輸入的第1個引數賦值給func,然後生成一個下述內容的C語言檔案。
#include <math.h>
float foo(float f) { return $func(f); }
int main(void){ return (int) foo; }

最後呼叫check_ld()完成編譯測試。
例如,“check_mathfunc exp2”相當於編譯連線了下面這個C檔案。
#include <math.h>
float foo(float f) { return exp2(f); }
int main(void){ return (int) foo; }

require()

require()用於檢查第三方類庫。Configure中與require()有關的程式碼如下所示。

#檢查第三方類庫
# these are off by default, so fail if requested and not available
#require()函式引數的規範:(名稱,標頭檔案,函式名,附加選項)
#require2()函式引數規範類似
enabled avisynth   && require2 vfw32 "windows.h vfw.h" AVIFileInit -lavifil32
enabled frei0r     && { check_header frei0r.h || die "ERROR: frei0r.h header not found"; }
enabled gnutls     && require_pkg_config gnutls gnutls/gnutls.h gnutls_global_init
enabled libaacplus && require  "libaacplus >= 2.0.0" aacplus.h aacplusEncOpen -laacplus
enabled libass     && require_pkg_config libass ass/ass.h ass_library_init
enabled libcelt    && require libcelt celt/celt.h celt_decode -lcelt0 &&
                      { check_lib celt/celt.h celt_decoder_create_custom -lcelt0 ||
                        die "ERROR: libcelt version must be >= 0.11.0."; }
enabled libdc1394  && require_pkg_config libdc1394-2 dc1394/dc1394.h dc1394_new
enabled libdirac   && require_pkg_config dirac                          \
    "libdirac_decoder/dirac_parser.h libdirac_encoder/dirac_encoder.h"  \
    "dirac_decoder_init dirac_encoder_init"
#測試libfaac
enabled libfaac    && require2 libfaac "stdint.h faac.h" faacEncGetVersion -lfaac
enabled libfreetype && require_pkg_config freetype2 "ft2build.h freetype/freetype.h" FT_Init_FreeType
enabled libgsm     && require  libgsm gsm/gsm.h gsm_create -lgsm
enabled libmodplug && require  libmodplug libmodplug/modplug.h ModPlug_Load -lmodplug
enabled libmp3lame && require  "libmp3lame >= 3.98.3" lame/lame.h lame_set_VBR_quality -lmp3lame
enabled libnut     && require  libnut libnut.h nut_demuxer_init -lnut
enabled libopencore_amrnb  && require libopencore_amrnb opencore-amrnb/interf_dec.h Decoder_Interface_init -lopencore-amrnb
enabled libopencore_amrwb  && require libopencore_amrwb opencore-amrwb/dec_if.h D_IF_init -lopencore-amrwb
enabled libopencv  && require_pkg_config opencv opencv/cxcore.h cvCreateImageHeader
enabled libopenjpeg && require libopenjpeg openjpeg.h opj_version -lopenjpeg
enabled libpulse && require_pkg_config libpulse-simple pulse/simple.h pa_simple_new
enabled librtmp    && require_pkg_config librtmp librtmp/rtmp.h RTMP_Socket
enabled libschroedinger && require_pkg_config schroedinger-1.0 schroedinger/schro.h schro_init
enabled libspeex   && require  libspeex speex/speex.h speex_decoder_init -lspeex
enabled libstagefright_h264  && require_cpp libstagefright_h264 "binder/ProcessState.h media/stagefright/MetaData.h
    media/stagefright/MediaBufferGroup.h media/stagefright/MediaDebug.h media/stagefright/MediaDefs.h
    media/stagefright/OMXClient.h media/stagefright/OMXCodec.h" android::OMXClient -lstagefright -lmedia -lutils -lbinder
enabled libtheora  && require  libtheora theora/theoraenc.h th_info_init -ltheoraenc -ltheoradec -logg
enabled libutvideo    && require_cpp utvideo "stdint.h stdlib.h utvideo/utvideo.h utvideo/Codec.h" 'CCodec*' -lutvideo -lstdc++
enabled libv4l2    && require_pkg_config libv4l2 libv4l2.h v4l2_ioctl
enabled libvo_aacenc && require libvo_aacenc vo-aacenc/voAAC.h voGetAACEncAPI -lvo-aacenc
enabled libvo_amrwbenc && require libvo_amrwbenc vo-amrwbenc/enc_if.h E_IF_init -lvo-amrwbenc
enabled libvorbis  && require  libvorbis vorbis/vorbisenc.h vorbis_info_init -lvorbisenc -lvorbis -logg
enabled libvpx     && {
    enabled libvpx_decoder && { check_lib2 "vpx/vpx_decoder.h vpx/vp8dx.h" vpx_codec_dec_init_ver -lvpx ||
                                die "ERROR: libvpx decoder version must be >=0.9.1"; }
    enabled libvpx_encoder && { check_lib2 "vpx/vpx_encoder.h vpx/vp8cx.h" "vpx_codec_enc_init_ver VPX_CQ" -lvpx ||
                                die "ERROR: libvpx encoder version must be >=0.9.6"; } }
#測試libx264
enabled libx264    && require  libx264 x264.h x264_encoder_encode -lx264 &&
                      { check_cpp_condition x264.h "X264_BUILD >= 118" ||
                        die "ERROR: libx264 version must be >= 0.118."; }
enabled libxavs    && require  libxavs xavs.h xavs_encoder_encode -lxavs
enabled libxvid    && require  libxvid xvid.h xvid_global -lxvidcore
enabled openal     && { { for al_libs in "${OPENAL_LIBS}" "-lopenal" "-lOpenAL32"; do
                        check_lib 'AL/al.h' alGetError "${al_libs}" && break; done } ||
                        die "ERROR: openal not found"; } &&
                      { check_cpp_condition "AL/al.h" "defined(AL_VERSION_1_1)" ||
                        die "ERROR: openal version must be 1.1 or compatible"; }
enabled mlib       && require  mediaLib mlib_types.h mlib_VectorSub_S16_U8_Mod -lmlib
enabled openssl    && { check_lib openssl/ssl.h SSL_library_init -lssl -lcrypto ||
                        check_lib openssl/ssl.h SSL_library_init -lssl32 -leay32 ||
                        check_lib openssl/ssl.h SSL_library_init -lssl -lcrypto -lws2_32 -lgdi32 ||
                        die "ERROR: openssl not found"; }

由於上述程式碼量比較大。在這裡我們只選擇一個典型的例子——libx264來看一下。require()檢測libx264的定義如下所示。
#測試libx264
require libx264 x264.h x264_encoder_encode -lx264 &&
  { check_cpp_condition x264.h "X264_BUILD >= 118" ||
    die "ERROR: libx264 version must be >= 0.118."; }

從測試libx264的程式碼可以看出,require()函式的使用方式為:
require {名稱} {標頭檔案} {函式名} {附加選項}
require()函式定義如下所示。
#檢查依賴項的時候使用
require(){
    name="$1"
    header="$2"
    func="$3"
    shift 3
    check_lib $header $func "[email protected]" || die "ERROR: $name not found"
}

從require()的定義可以看出,該函式將第1個引數賦值給name,第2個引數賦值給header,第3個引數賦值給func。最後呼叫check_lib()函式。
check_lib()的定義如下所示。
#檢查類庫
check_lib(){
    log check_lib "[email protected]"
    header="$1"
    func="$2"
    shift 2
    check_header $header && check_func $func "[email protected]" && add_extralibs "[email protected]"
}

可以看出check_lib()呼叫了check_header()、check_func()等幾個函式完成檢查工作。這兩個函式在前文中已經介紹過,就不再重複了。
例如檢測libx264的時候呼叫check_header()會生成以下臨時檔案:
#include <x264.h>
int x;

check_cflags ()

check_cflags()用於檢查編譯器的cflags標誌引數。Configure中與check_cflags()有關的程式碼如下所示。
#新增一些編譯選項
# add some useful compiler flags if supported
check_cflags -Wdeclaration-after-statement
check_cflags -Wall
check_cflags -Wno-parentheses
check_cflags -Wno-switch
check_cflags -Wno-format-zero-length
check_cflags -Wdisabled-optimization
check_cflags -Wpointer-arith
check_cflags -Wredundant-decls
check_cflags -Wno-pointer-sign
check_cflags -Wcast-qual
check_cflags -Wwrite-strings
check_cflags -Wtype-limits
check_cflags -Wundef
check_cflags -Wmissing-prototypes
check_cflags -Wno-pointer-to-int-cast
check_cflags -Wstrict-prototypes
check_cflags()函式的定義如下所示。
check_cflags(){
    log check_cflags "[email protected]"
    set -- $($filter_cflags "[email protected]")
    check_cc "[email protected]" <<EOF && append CFLAGS "[email protected]"
int x;
EOF
}

從定義可以看出,check_cflags()呼叫了check_cc()執行命令。整個程式碼只有一行:
int x;
check_cc()的定義如下所示。
check_cc(){
    log check_cc "[email protected]"
    cat > $TMPC
    log_file $TMPC
	#很多檢查都呼叫了這個check_cmd
	#-c 只編譯不連結
    check_cmd $cc $CPPFLAGS $CFLAGS "[email protected]" -c -o $TMPO $TMPC
}

可以看出check_cflags()將輸入引數設定到命令列中,並最終呼叫了check_cmd。
除了上述幾個函式之外,還有其他的一些檢查編譯環境的函式,在這裡就不一一列舉了。

Echo info

Echo info用於在控制檯上列印配置資訊。Configure中該部分的程式碼如下所示。
#在控制檯輸出資訊
echo "install prefix            $prefix"
echo "source path               $source_path"
echo "C compiler                $cc"
echo "ARCH                      $arch ($cpu)"
if test "$build_suffix" != ""; then
    echo "build suffix              $build_suffix"
fi
if test "$progs_suffix" != ""; then
    echo "progs suffix              $progs_suffix"
fi
if test "$extra_version" != ""; then
    echo "version string suffix     $extra_version"
fi
#${}的特異功能:
#${file-my.file.txt}假如 $file 為空值,則使用 my.file.txt 作預設值。(保留沒設定及非空值)
#在這裡,如果某個變數為空值,則取預設值為no
echo "big-endian                ${bigendian-no}"
echo "runtime cpu detection     ${runtime_cpudetect-no}"
if enabled x86; then
    echo "${yasmexe}                      ${yasm-no}"
    echo "MMX enabled               ${mmx-no}"
    echo "MMX2 enabled              ${mmx2-no}"
    echo "3DNow! enabled            ${amd3dnow-no}"
    echo "3DNow! extended enabled   ${amd3dnowext-no}"
    echo "SSE enabled               ${sse-no}"
    echo "SSSE3 enabled             ${ssse3-no}"
    echo "AVX enabled               ${avx-no}"
    echo "CMOV enabled              ${cmov-no}"
    echo "CMOV is fast              ${fast_cmov-no}"
    echo "EBX available             ${ebx_available-no}"
    echo "EBP available             ${ebp_available-no}"
fi
if enabled arm; then
    echo "ARMv5TE enabled           ${armv5te-no}"
    echo "ARMv6 enabled             ${armv6-no}"
    echo "ARMv6T2 enabled           ${armv6t2-no}"
    echo "ARM VFP enabled           ${armvfp-no}"
    echo "IWMMXT enabled            ${iwmmxt-no}"
    echo "NEON enabled              ${neon-no}"
fi
if enabled mips; then
    echo "MMI enabled               ${mmi-no}"
fi
if enabled ppc; then
    echo "AltiVec enabled           ${altivec-no}"
    echo "PPC 4xx optimizations     ${ppc4xx-no}"
    echo "dcbzl available           ${dcbzl-no}"
fi
if enabled sparc; then
    echo "VIS enabled               ${vis-no}"
fi
echo "debug symbols             ${debug-no}"
echo "strip symbols             ${stripping-no}"
echo "optimize for size         ${small-no}"
echo "optimizations             ${optimizations-no}"
echo "static                    ${static-no}"
echo "shared                    ${shared-no}"
echo "postprocessing support    ${postproc-no}"
echo "new filter support        ${avfilter-no}"
echo "network support           ${network-no}"
echo "threading support         ${thread_type-no}"
echo "safe bitstream reader     ${safe_bitstream_reader-no}"
echo "SDL support               ${sdl-no}"
echo "Sun medialib support      ${mlib-no}"
echo "libdxva2 enabled          ${dxva2-no}"
echo "libva enabled             ${vaapi-no}"
echo "libvdpau enabled          ${vdpau-no}"
echo "AVISynth enabled          ${avisynth-no}"
echo "frei0r enabled            ${frei0r-no}"
echo "gnutls enabled            ${gnutls-no}"
echo "libaacplus enabled        ${libaacplus-no}"
echo "libass enabled            ${libass-no}"
echo "libcdio support           ${libcdio-no}"
echo "libcelt enabled           ${libcelt-no}"
echo "libdc1394 support         ${libdc1394-no}"
echo "libdirac enabled          ${libdirac-no}"
echo "libfaac enabled           ${libfaac-no}"
echo "libgsm enabled            ${libgsm-no}"
echo "libmodplug enabled        ${libmodplug-no}"
echo "libmp3lame enabled        ${libmp3lame-no}"
echo "libnut enabled            ${libnut-no}"
echo "libopencore-amrnb support ${libopencore_amrnb-no}"
echo "libopencore-amrwb support ${libopencore_amrwb-no}"
echo "libopencv support         ${libopencv-no}"
echo "libopenjpeg enabled       ${libopenjpeg-no}"
echo "libpulse enabled          ${libpulse-no}"
echo "librtmp enabled           ${librtmp-no}"
echo "libschroedinger enabled   ${libschroedinger-no}"
echo "libspeex enabled          ${libspeex-no}"
echo "libstagefright-h264 enabled    ${libstagefright_h264-no}"
echo "libtheora enabled         ${libtheora-no}"
echo "libutvideo enabled        ${libutvideo-no}"
echo "libv4l2 enabled           ${libv4l2-no}"
echo "libvo-aacenc support      ${libvo_aacenc-no}"
echo "libvo-amrwbenc support    ${libvo_amrwbenc-no}"
echo "libvorbis enabled         ${libvorbis-no}"
echo "libvpx enabled            ${libvpx-no}"
echo "libx264 enabled           ${libx264-no}"
echo "libxavs enabled           ${libxavs-no}"
echo "libxvid enabled           ${libxvid-no}"
echo "openal enabled            ${openal-no}"
echo "openssl enabled           ${openssl-no}"
echo "zlib enabled              ${zlib-no}"
echo "bzlib enabled             ${bzlib-no}"
echo

for type in decoder encoder hwaccel parser demuxer muxer protocol filter bsf indev outdev; do
    echo "Enabled ${type}s:"
    eval list=\$$(toupper $type)_LIST
    print_enabled '_*' $list | sort | pr -r -3 -t
    echo
done

license="LGPL version 2.1 or later"
if enabled nonfree; then
    license="nonfree and unredistributable"
elif enabled gplv3; then
    license="GPL version 3 or later"
elif enabled lgplv3; then
    license="LGPL version 3 or later"
elif enabled gpl; then
    license="GPL version 2 or later"
fi

echo "License: $license"

有關這段程式碼,有一個地方需要注意:很多的${}符號中的字元為“XXX-no”,這種格式的意思是如果XXX取值為空,則使用預設值“no”(這個規則比較奇特)。

Write basic info

Write basic info用於向config.mak中寫入一些基本資訊。Configure中該部分的程式碼如下所示。
#建立config.mak和config.h
#根據情況也會建立config.asm
echo "Creating config.mak and config.h..."

test -e Makefile || $ln_s "$source_path/Makefile" .

enabled stripping || strip="echo skipping strip"
#重要:需要輸出的檔案
#TMPH是一個臨時檔案,最終會拷貝給config.h
config_files="$TMPH config.mak"
#寫入config.mak檔案
#首先寫入一些基本資訊
#"<<EOF"表示後續的輸入作為子命令或子shell的輸入,直到遇到"EOF",再次返回到
#主調shell,可將其理解為分界符(delimiter)。
#最後的"EOF"必須單獨佔一行
cat > config.mak <<EOF
# Automatically generated by configure - do not modify!
ifndef FFMPEG_CONFIG_MAK
FFMPEG_CONFIG_MAK=1
FFMPEG_CONFIGURATION=$FFMPEG_CONFIGURATION
prefix=$prefix
LIBDIR=\$(DESTDIR)$libdir
SHLIBDIR=\$(DESTDIR)$shlibdir
INCDIR=\$(DESTDIR)$incdir
BINDIR=\$(DESTDIR)$bindir
DATADIR=\$(DESTDIR)$datadir
MANDIR=\$(DESTDIR)$mandir
SRC_PATH=$source_path
ifndef MAIN_MAKEFILE
SRC_PATH:=\$(SRC_PATH:.%=..%)
endif
CC_IDENT=$cc_ident
ARCH=$arch
CC=$cc
CXX=$cxx
AS=$as
LD=$ld
DEPCC=$dep_cc
YASM=$yasmexe
YASMDEP=$yasmexe
AR=$ar
RANLIB=$ranlib
CP=cp -p
LN_S=$ln_s
STRIP=$strip
CPPFLAGS=$CPPFLAGS
CFLAGS=$CFLAGS
CXXFLAGS=$CXXFLAGS
ASFLAGS=$ASFLAGS
AS_O=$CC_O
CC_O=$CC_O
CXX_O=$CXX_O
LDFLAGS=$LDFLAGS
FFSERVERLDFLAGS=$FFSERVERLDFLAGS
SHFLAGS=$SHFLAGS
YASMFLAGS=$YASMFLAGS
BUILDSUF=$build_suffix
PROGSSUF=$progs_suffix
FULLNAME=$FULLNAME
LIBPREF=$LIBPREF
LIBSUF=$LIBSUF
LIBNAME=$LIBNAME
SLIBPREF=$SLIBPREF
SLIBSUF=$SLIBSUF
EXESUF=$EXESUF
EXTRA_VERSION=$extra_version
DEPFLAGS=$DEPFLAGS
CCDEP=$CCDEP
CXXDEP=$CXXDEP
ASDEP=$ASDEP
CC_DEPFLAGS=$CC_DEPFLAGS
AS_DEPFLAGS=$AS_DEPFLAGS
HOSTCC=$host_cc
HOSTCFLAGS=$host_cflags
HOSTEXESUF=$HOSTEXESUF
HOSTLDFLAGS=$host_ldflags
HOSTLIBS=$host_libs
TARGET_EXEC=$target_exec
TARGET_PATH=$target_path
SDL_LIBS=$sdl_libs
SDL_CFLAGS=$sdl_cflags
LIB_INSTALL_EXTRA_CMD=$LIB_INSTALL_EXTRA_CMD
EXTRALIBS=$extralibs
INSTALL=$install
LIBTARGET=${LIBTARGET}
SLIBNAME=${SLIBNAME}
SLIBNAME_WITH_VERSION=${SLIBNAME_WITH_VERSION}
SLIBNAME_WITH_MAJOR=${SLIBNAME_WITH_MAJOR}
SLIB_CREATE_DEF_CMD=${SLIB_CREATE_DEF_CMD}
SLIB_EXTRA_CMD=${SLIB_EXTRA_CMD}
SLIB_INSTALL_NAME=${SLIB_INSTALL_NAME}
SLIB_INSTALL_LINKS=${SLIB_INSTALL_LINKS}
SLIB_INSTALL_EXTRA_LIB=${SLIB_INSTALL_EXTRA_LIB}
SLIB_INSTALL_EXTRA_SHLIB=${SLIB_INSTALL_EXTRA_SHLIB}
SAMPLES:=${samples:-\$(FATE_SAMPLES)}
NOREDZONE_FLAGS=$noredzone_flags
EOF
#獲取版本
#主要通過各個類庫資料夾中的version.h檔案
#讀取XXX_VERSION(相當於把標頭檔案當成一個文字來讀)
get_version(){
    name=$1
    file=$source_path/$2
# This condition will be removed when we stop supporting old libpostproc versions
if ! test "$name" = LIBPOSTPROC || test "$postproc_version" = current; then
    eval $(grep "#define ${name}_VERSION_M" "$file" | awk '{ print $2"="$3 }')
    eval ${name}_VERSION=\$${name}_VERSION_MAJOR.\$${name}_VERSION_MINOR.\$${name}_VERSION_MICRO
fi
    lcname=$(tolower $name)
    eval echo "${lcname}_VERSION=\$${name}_VERSION" >> config.mak
    eval echo "${lcname}_VERSION_MAJOR=\$${name}_VERSION_MAJOR" >> config.mak
}
#獲取版本
get_version LIBAVCODEC  libavcodec/version.h
get_version LIBAVDEVICE libavdevice/avdevice.h
get_version LIBAVFILTER libavfilter/version.h
get_version LIBAVFORMAT libavformat/version.h
get_version LIBAVUTIL   libavutil/avutil.h
get_version LIBPOSTPROC libpostproc/postprocess.h
get_version LIBSWRESAMPLE libswresample/swresample.h
get_version LIBSWSCALE  libswscale/swscale.h

關於這段程式碼,有以下幾點需要注意:
(1)“cat > config.mak <<EOF”的作用就是往config.mak中寫入文字,當遇到“EOF”的時候寫入結束
(2)get_version()用於獲取當前的FFmpeg原始碼中各個類庫的版本。通過把各個類庫資料夾下的version.h當作文字讀取之後,分析字串並且得到版本號,最終寫入config.mak檔案。

print_config()

print_config()用於向config.h、config.mak、config.asm中寫入所有配置資訊。Configure中該部分的程式碼如下所示。
#輸出所有的配置資訊包含3類:
#以“ARCH_”開頭,包含系統架構資訊
#以“HAVE_”開頭,包含系統特徵資訊
#以“CONFIG_”開頭,包含編譯配置(數量最多,包含協議、複用器、編解碼器等的配置,將近1000行)
#config_files
print_config ARCH_   "$config_files" $ARCH_LIST
print_config HAVE_   "$config_files" $HAVE_LIST
print_config CONFIG_ "$config_files" $CONFIG_LIST       \
                                     $CONFIG_EXTRA      \
                                     $ALL_COMPONENTS    \

從原始碼中可以看出,其中呼叫了一個函式print_config()。print_config()的原始碼如下所示。
# 輸出文字到config.mak,config.h等檔案
# 該函式的示例呼叫方法:print_config CONFIG_ "$config_files" $CONFIG_LIST 
print_config(){
# 字首
    pfx=$1
# 檔案列表
    files=$2
	# 位置引數可以用shift命令左移。比如shift 3表示原來的$4現在變成$1
    shift 2
	#for迴圈中,當沒有in指定列表時,for會預設取命令列引數列表。
	#在這裡取的就是$CONFIG_LIST 等
    for cfg; do
	# toupper():轉換為大寫
        ucname="$(toupper $cfg)"
		# files= config.h config.mak config.asm
		# 迴圈輸出
        for f in $files; do
		# "x#*/"代表去取x的第一個slash之後的所有內容(不包括slash)
		# "#"代表刪除從前往後最小匹配的內容
		# "f##*."代表去取f的第一個"."之後的所有內容。在這裡是“h”、“mak”等
		# 在這裡print_config_h(),print_config_mak(),print_config_asm()
            "print_config_${f##*.}" $cfg ${pfx}${ucname} >>$f
        done
    done
}

可以看出print_config()的第1個引數是寫入引數的字首(例如可以取“ARCH_”、“HAVE_”、“CONFIG_”);第2個引數是檔案列表(例如可以是“config.h config.mak config.asm”);第3個以後的的引數就是需要寫入的變數(例如$ARCH_LIST、$CONFIG_LIST等)。
print_config()有兩層迴圈:外層迴圈遍歷了所有的變數(例如$CONFIG_LIST),內層迴圈遍歷了所有檔案(例如“config.h config.mak”),其中呼叫了一個函式print_config_XXX(),其中“XXX”根據檔案字尾的不同可以取不同的值(例如“h”、“mak”)。下面舉例看兩個函式:print_config_h()和print_config_mak()。

print_config_h()

print_config_h()用於輸出配置資訊至config.h。該函式的原始碼如下所示。
#輸出config.h的時候使用
#呼叫示例:print_config_h ffplay CONFIG_FFPLAY
print_config_h(){
#command1  && command2
#&&左邊的命令(命令1)返回真(即返回0,成功被執行)後,&&右邊的命令(命令2)才能夠被執行
#command1 || command2
#||左邊的命令(命令1)未執行成功,那麼就執行||右邊的命令(命令2)
    enabled $1 && v=1 || v=0
#示例:#define CONFIG_FFPLAY 1
    echo "#define $2 $v"
}

從原始碼中可以看出,引數1是變數名稱,引數2是經過處理後準備寫入檔案的變數名稱(變數名轉換成了大寫並且添加了字首)。如果引數1所指向的變數是enabled的,那麼v取值為1,那麼寫入檔案的格式就是:
#define {處理後變數名稱} 1
如果引數1所指向的變數不是enabled的,那麼v取值為0,那麼寫入檔案的格式就是:
#define {處理後變數名稱} 0

print_config_mak()

print_config_mak()用於輸出配置資訊至config.mak。該函式的原始碼如下所示。

#輸出config.mak的時候使用
print_config_mak(){
    enabled $1 && v= || v=!
    echo "$v$2=yes"
}

從原始碼中可以看出print_config_mak()的原理和print_config_h()是類似的。如果變數是enabled的,那麼寫入檔案的格式就是:
{處理後變數名稱}=yes
如果變數不是enabled的,那麼寫入檔案的格式就是:
!{處理後變數名稱}=yes

print_enabled()

print_enabled()用於向config.mak寫入所有enabled的元件資訊。這方面功能通過print_enabled()函式完成,就不再詳細分析了。

pkgconfig_generate()

pkgconfig_generate()用於向libavXXX/libavXXX.pc中寫入pkgconfig資訊(XXX代表avcodec,avformat等)。這方面的程式碼還沒有細看,以後有機會再進行補充。


原始碼(包含註釋)

至此,FFmpeg的Configure的流程就大致梳理完畢了,最後附上和Configure有關的config.mak、config.h以及Configure本身的原始碼。

config.mak原始碼

# FFmpeg config.mak
#
# 註釋:雷霄驊
# [email protected]
# http://blog.csdn.net/leixiaohua1020
#
# Configure指令碼生成的Makefile,包含了各種配置資訊。
#
# Automatically generated by configure - do not modify!
#基本資訊
ifndef FFMPEG_CONFIG_MAK
FFMPEG_CONFIG_MAK=1
FFMPEG_CONFIGURATION=
#各種路徑========================================
prefix=/usr/local
LIBDIR=$(DESTDIR)${prefix}/lib
SHLIBDIR=$(DESTDIR)${prefix}/bin
INCDIR=$(DESTDIR)${prefix}/include
BINDIR=$(DESTDIR)${prefix}/bin
DATADIR=$(DESTDIR)${prefix}/share/ffmpeg
MANDIR=$(DESTDIR)${prefix}/share/man
#是個相對路徑
SRC_PATH=.
ifndef MAIN_MAKEFILE
SRC_PATH:=$(SRC_PATH:.%=..%)
endif
#工具集==========================================
CC_IDENT=gcc 4.6.2 (GCC)
#架構
ARCH=x86
#編譯器
CC=gcc
CXX=g++
AS=gcc
#連結器
LD=gcc
DEPCC=gcc
#彙編器
YASM=yasm
YASMDEP=yasm
#生成靜態庫.a工具
AR=ar
RANLIB=ranlib
CP=cp -p
LN_S=ln -sf
STRIP=strip
#引數集==========================================
#編譯器的引數
CPPFLAGS= -D_ISOC99_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -U__STRICT_ANSI__
CFLAGS=   -std=c99 -fno-common -fomit-frame-pointer -I/include/SDL -D_GNU_SOURCE=1 -Dmain=SDL_main -g -Wdeclaration-after-statement -Wall -Wno-parentheses -Wno-switch -Wno-format-zero-length -Wdisabled-optimization -Wpointer-arith -Wredundant-decls -Wno-pointer-sign -Wcast-qual -Wwrite-strings -Wtype-limits -Wundef -Wmissing-prototypes -Wno-pointer-to-int-cast -Wstrict-prototypes -O3 -fno-math-errno -fno-signed-zeros -fno-tree-vectorize -Werror=implicit-function-declaration -Werror=missing-prototypes
CXXFLAGS=  -D__STDC_CONSTANT_MACROS
ASFLAGS=   -g
#目標檔案有關的引數
AS_O=-o [email protected]
CC_O=-o [email protected]
CXX_O=-o [email protected]
#連結器有關的引數
LDFLAGS= -Wl,--as-needed -Wl,--warn-common -Wl,-rpath-link=libpostproc:libswresample:libswscale:libavfilter:libavdevice:libavformat:libavcodec:libavutil
FFSERVERLDFLAGS=-Wl,-E
SHFLAGS=-shared -Wl,--output-def,$$(@:$(SLIBSUF)=.def) -Wl,--out-implib,$(SUBDIR)lib$(SLIBNAME:$(SLIBSUF)=.dll.a) -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-auto-image-base -Wl,-Bsymbolic -Wl,--version-script,$(SUBDIR)lib$(NAME).ver
YASMFLAGS=-f win32  -DPREFIX
#字首字尾========================================
BUILDSUF=
PROGSSUF=
#${NAME}位於每個liavXXX/Makefile中,例如avformat
FULLNAME=$(NAME)$(BUILDSUF)
LIBPREF=lib
LIBSUF=.a
#例如libavformat.a
LIBNAME=$(LIBPREF)$(FULLNAME)$(LIBSUF)
SLIBPREF=
SLIBSUF=.dll
EXESUF=.exe
EXTRA_VERSION=
DEPFLAGS=$(CPPFLAGS) $(CFLAGS) -MM
CCDEP=
CXXDEP=$(DEPCC) $(DEPFLAGS) $< | sed -e "/^\#.*/d" -e "s,^[[:space:]]*$(*F)\\.o,$(@D)/$(*F).o," > $(@:.o=.d)
ASDEP=
CC_DEPFLAGS=-MMD -MF $(@:.o=.d) -MT [email protected]
AS_DEPFLAGS=-MMD -MF $(@:.o=.d) -MT [email protected]
HOSTCC=gcc
HOSTCFLAGS=-D_ISOC99_SOURCE -O3 -g -std=c99 -Wall
HOSTEXESUF=.exe
HOSTLDFLAGS=
HOSTLIBS=-lm
TARGET_EXEC=
TARGET_PATH=$(CURDIR)
#SDL
SDL_LIBS=-L/lib -lmingw32 -lSDLmain -lSDL -mwindows
SDL_CFLAGS=-I/include/SDL -D_GNU_SOURCE=1 -Dmain=SDL_main
LIB_INSTALL_EXTRA_CMD=$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"
#連結
EXTRALIBS=-lavicap32 -lws2_32 -L/lib -lmingw32 -lSDLmain -lSDL -mwindows -lm -lz -lpsapi 
INSTALL=install
LIBTARGET=i386
#例如libavformat.dll
SLIBNAME=$(SLIBPREF)$(FULLNAME)$(SLIBSUF)
#LIBVERSION變數位於library.mak
#例如libavformat-53.dll
#生成的Dll似乎就是這個版本的
SLIBNAME_WITH_VERSION=$(SLIBPREF)$(FULLNAME)-$(LIBVERSION)$(SLIBSUF)
#例如libavformat-53.31.100.dll
SLIBNAME_WITH_MAJOR=$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)
SLIB_CREATE_DEF_CMD=
#生成匯出庫lib,會呼叫lib.exe
SLIB_EXTRA_CMD=-lib.exe /machine:$(LIBTARGET) /def:$$(@:$(SLIBSUF)=.def) /out:$(SUBDIR)$(SLIBNAME:$(SLIBSUF)=.lib)
SLIB_INSTALL_NAME=$(SLIBNAME_WITH_MAJOR)
SLIB_INSTALL_LINKS=
SLIB_INSTALL_EXTRA_LIB=lib$(SLIBNAME:$(SLIBSUF)=.dll.a) $(SLIBNAME_WITH_MAJOR:$(SLIBSUF)=.def)
SLIB_INSTALL_EXTRA_SHLIB=$(SLIBNAME:$(SLIBSUF)=.lib)
SAMPLES:=$(FATE_SAMPLES)
NOREDZONE_FLAGS=-mno-red-zone
#版本資訊========================================
libavcodec_VERSION=53.60.100
libavcodec_VERSION_MAJOR=53
libavdevice_VERSION=53.4.100
libavdevice_VERSION_MAJOR=53
libavfilter_VERSION=2.60.100
libavfilter_VERSION_MAJOR=2
libavformat_VERSION=53.31.100
libavformat_VERSION_MAJOR=53
libavutil_VERSION=51.34.101
libavutil_VERSION_MAJOR=51
libpostproc_VERSION=52.0.100
libpostproc_VERSION_MAJOR=52
libswresample_VERSION=0.6.100
libswresample_VERSION_MAJOR=0
libswscale_VERSION=2.1.100
libswscale_VERSION_MAJOR=2
#元件配置========================================
#ARCH_
!ARCH_ALPHA=yes
!ARCH_ARM=yes
!ARCH_AVR32=yes
!ARCH_AVR32_AP=yes
!ARCH_AVR32_UC=yes
!ARCH_BFIN=yes
!ARCH_IA64=yes
!ARCH_M68K=yes
!ARCH_MIPS=yes
!ARCH_MIPS64=yes
!ARCH_PARISC=yes
!ARCH_PPC=yes
!ARCH_PPC64=yes
!ARCH_S390=yes
!ARCH_SH4=yes
!ARCH_SPARC=yes
!ARCH_SPARC64=yes
!ARCH_TOMI=yes
ARCH_X86=yes
ARCH_X86_32=yes
!ARCH_X86_64=yes
#HAVE_
!HAVE_ALTIVEC=yes
HAVE_AMD3DNOW=yes
HAVE_AMD3DNOWEXT=yes
!HAVE_ARMV5TE=yes
!HAVE_ARMV6=yes
!HAVE_ARMV6T2=yes
!HAVE_ARMVFP=yes
HAVE_AVX=yes
!HAVE_IWMMXT=yes
!HAVE_MMI=yes
HAVE_MMX=yes
HAVE_MMX2=yes
//略……
HAVE_YASM=yes
#CONFIG_
CONFIG_BSFS=yes
CONFIG_DECODERS=yes
CONFIG_DEMUXERS=yes
CONFIG_ENCODERS=yes
CONFIG_FILTERS=yes
!CONFIG_HWACCELS=yes
CONFIG_INDEVS=yes
CONFIG_MUXERS=yes
CONFIG_OUTDEVS=yes
CONFIG_PARSERS=yes
CONFIG_PROTOCOLS=yes
CONFIG_FFPLAY=yes
CONFIG_FFPROBE=yes
!CONFIG_FFSERVER=yes
CONFIG_FFMPEG=yes
!CONFIG_AVPLAY=yes
!CONFIG_AVPROBE=yes
!CONFIG_AVSERVER=yes
CONFIG_AANDCT=yes
CONFIG_AC3DSP=yes
CONFIG_AVCODEC=yes
CONFIG_AVDEVICE=yes
CONFIG_AVFILTER=yes
CONFIG_AVFORMAT=yes
!CONFIG_AVISYNTH=yes
!CONFIG_BZLIB=yes
!CONFIG_CRYSTALHD=yes
CONFIG_DCT=yes
!CONFIG_DOC=yes
CONFIG_DWT=yes
!CONFIG_DXVA2=yes
CONFIG_FASTDIV=yes
CONFIG_FFT=yes
!CONFIG_FREI0R=yes
!CONFIG_GNUTLS=yes
CONFIG_GOLOMB=yes
!CONFIG_GPL=yes
!CONFIG_GRAY=yes
CONFIG_H264CHROMA=yes
CONFIG_H264DSP=yes
CONFIG_H264PRED=yes
!CONFIG_HARDCODED_TABLES=yes
CONFIG_HUFFMAN=yes
!CONFIG_LIBAACPLUS=yes
!CONFIG_LIBASS=yes
!CONFIG_LIBCDIO=yes
!CONFIG_LIBCELT=yes
!CONFIG_LIBDC1394=yes
!CONFIG_LIBDIRAC=yes
!CONFIG_LIBFAAC=yes
!CONFIG_LIBFREETYPE=yes
!CONFIG_LIBGSM=yes
!CONFIG_LIBMODPLUG=yes
!CONFIG_LIBMP3LAME=yes
!CONFIG_LIBNUT=yes
!CONFIG_LIBOPENCORE_AMRNB=yes
!CONFIG_LIBOPENCORE_AMRWB=yes
!CONFIG_LIBOPENCV=yes
!CONFIG_LIBOPENJPEG=yes
!CONFIG_LIBPULSE=yes
!CONFIG_LIBRTMP=yes
!CONFIG_LIBSCHROEDINGER=yes
!CONFIG_LIBSPEEX=yes
!CONFIG_LIBSTAGEFRIGHT_H264=yes
!CONFIG_LIBTHEORA=yes
!CONFIG_LIBUTVIDEO=yes
!CONFIG_LIBV4L2=yes
!CONFIG_LIBVO_AACENC=yes
!CONFIG_LIBVO_AMRWBENC=yes
!CONFIG_LIBVORBIS=yes
!CONFIG_LIBVPX=yes
!CONFIG_LIBX264=yes
!CONFIG_LIBXAVS=yes
!CONFIG_LIBXVID=yes
#此處省略將近1000條…
CONFIG_RTMP_PROTOCOL=yes
CONFIG_RTMPT_PROTOCOL=yes
CONFIG_RTMPE_PROTOCOL=yes
CONFIG_RTMPTE_PROTOCOL=yes
CONFIG_RTMPS_PROTOCOL=yes
CONFIG_RTP_PROTOCOL=yes
CONFIG_TCP_PROTOCOL=yes
!CONFIG_TLS_PROTOCOL=yes
CONFIG_UDP_PROTOCOL=yes
#Test
ACODEC_TESTS=ac3_fixed adpcm_adx adpcm_ima_qt adpcm_ima_wav adpcm_ms adpcm_swf adpcm_yam alac aref flac g722 g723_1 g726 mp2 pcm_alaw pcm_f32be pcm_f32le pcm_f64be pcm_f64le pcm_mulaw pcm_s16be pcm_s16le pcm_s24be pcm_s24daud pcm_s24le pcm_s32be pcm_s32le pcm_s8 pcm_u8 wmav1 wmav2 
VCODEC_TESTS=amv asv1 asv2 cljr dnxhd_1080i dnxhd_720p dnxhd_720p_10bit dnxhd_720p_rd dv dv50 dv_411 error ffv1 flashsv flashsv2 flv h261 h263 h263p huffyuv jpeg2000 jpegls ljpeg mjpeg mpeg mpeg1b mpeg2 mpeg2_422 mpeg2_idct_int mpeg2_ilace mpeg2_ivlc_qprd mpeg2thread mpeg2thread_ilace mpeg4 mpeg4_adap mpeg4_qpel mpeg4_qprd mpeg4adv mpeg4nr mpeg4thread mpng msmpeg4 msmpeg4v2 msvideo1 prores qtrle qtrlegray rc rgb roq rv10 rv20 snow snowll svq1 v210 vref wmv1 wmv2 yuv zlib zmbv 
LAVF_TESTS=aiff alaw asf au avi bmp caf dpx dv_fmt ffm flv_fmt gif gxf jpg mkv mmf mov mpg mulaw mxf mxf_d10 nut ogg pbmpipe pcx pgm pgmpipe pixfmt png ppm ppmpipe rm rso sgi sox swf tga tiff ts voc voc_s16 wav wtv yuv4mpeg 
LAVFI_TESTS=crop crop_scale crop_scale_vflip crop_vflip null pixdesc pixfmts_copy pixfmts_crop pixfmts_hflip pixfmts_null pixfmts_pad pixfmts_scale pixfmts_vflip scale200 scale500 vflip vflip_crop vflip_vflip 
SEEK_TESTS=seek_ac3_rm seek_adpcm_ima_wav seek_adpcm_ms_wav seek_adpcm_qt_aiff seek_adpcm_swf_flv seek_adpcm_yam_wav seek_alac_m4a seek_asv1_avi seek_asv2_avi seek_dnxhd_1080i_mov seek_dnxhd_720p_dnxhd seek_dnxhd_720p_rd_dnxhd seek_dv411_dv seek_dv50_dv seek_dv_dv seek_error_mpeg4_adv_avi seek_ffv1_avi seek_flac_flac seek_flashsv_flv seek_flv_flv seek_g726_wav seek_h261_avi seek_h263_avi seek_h263p_avi seek_huffyuv_avi seek_image_bmp seek_image_jpg seek_image_pcx seek_image_pgm seek_image_ppm seek_image_sgi seek_image_tga seek_image_tiff seek_jpegls_avi seek_lavf_aif seek_lavf_al seek_lavf_asf seek_lavf_au seek_lavf_avi seek_lavf_dv seek_lavf_ffm seek_lavf_flv seek_lavf_gif seek_lavf_gxf seek_lavf_mkv seek_lavf_mmf seek_lavf_mov seek_lavf_mpg seek_lavf_mxf seek_lavf_mxf_d10 seek_lavf_nut seek_lavf_ogg seek_lavf_rm seek_lavf_swf seek_lavf_ts seek_lavf_ul seek_lavf_voc seek_lavf_wav seek_lavf_wtv seek_lavf_y4m seek_ljpeg_avi seek_mjpeg_avi seek_mp2_mp2 seek_mpeg1_mpg seek_mpeg1b_mpg seek_mpeg2_422_mpg seek_mpeg2_idct_int_mpg seek_mpeg2i_mpg seek_mpeg2ivlc_qprd_mpg seek_mpeg2reuse_mpg seek_mpeg2thread_mpg seek_mpeg2threadivlc_mpg seek_mpeg4_adap_avi seek_mpeg4_adv_avi seek_mpeg4_nr_avi seek_mpeg4_qprd_avi seek_mpeg4_rc_avi seek_mpeg4_thread_avi seek_msmpeg4_avi seek_msmpeg4v2_avi seek_odivx_mp4 seek_pbmpipe_pbm seek_pcm_alaw_wav seek_pcm_f32be_au seek_pcm_f32le_wav seek_pcm_f64be_au seek_pcm_f64le_wav seek_pcm_mulaw_wav seek_pcm_s16be_mov seek_pcm_s16le_wav seek_pcm_s24be_mov seek_pcm_s24daud_302 seek_pcm_s24le_wav seek_pcm_s32be_mov seek_pcm_s32le_wav seek_pcm_s8_mov seek_pcm_u8_wav seek_pgmpipe_pgm seek_ppmpipe_ppm seek_rgb_avi seek_roqav_roq seek_rv10_rm seek_rv20_rm seek_snow53_avi seek_snow_avi seek_svq1_mov seek_wmav1_asf seek_wmav2_asf seek_wmv1_avi seek_wmv2_avi seek_yuv_avi 
endif # FFMPEG_CONFIG_MAK


config.h原始碼

/**
 * FFmpeg config.h
 *
 * 註釋:雷霄驊
 * [email protected]
 * http://blog.csdn.net/leixiaohua1020
 * 
 * Configure指令碼生成的config.h,包含了各種配置資訊。
 /
/* Automatically generated by configure - do not modify! */
#ifndef FFMPEG_CONFIG_H
#define FFMPEG_CONFIG_H
#define FFMPEG_CONFIGURATION ""
#define FFMPEG_LICENSE "LGPL version 2.1 or later"
#define FFMPEG_DATADIR "/usr/local/share/ffmpeg"
#define AVCONV_DATADIR "/usr/local/share/ffmpeg"
#define CC_TYPE "gcc"
#define CC_VERSION __VERSION__
#define restrict restrict
#define EXTERN_PREFIX "_"
#define EXTERN_ASM _
#define SLIBSUF ".dll"
#define ARCH_ALPHA 0
#define ARCH_ARM 0
#define ARCH_AVR32 0
#define ARCH_AVR32_AP 0
#define ARCH_AVR32_UC 0
#define ARCH_BFIN 0
#define ARCH_IA64 0
#define ARCH_M68K 0
#define ARCH_MIPS 0
#define ARCH_MIPS64 0
#define ARCH_PARISC 0
#define ARCH_PPC 0
#define ARCH_PPC64 0
#define ARCH_S390 0
#define ARCH_SH4 0
#define ARCH_SPARC 0
#define ARCH_SPARC64 0
#define ARCH_TOMI 0
#define ARCH_X86 1
#define ARCH_X86_32 1
#define ARCH_X86_64 0
#define HAVE_ALTIVEC 0
#define HAVE_AMD3DNOW 1
#define HAVE_AMD3DNOWEXT 1
#define HAVE_ARMV5TE 0
#define HAVE_ARMV6 0
#define HAVE_ARMV6T2 0
#define HAVE_ARMVFP 0
#define HAVE_AVX 1
#define HAVE_IWMMXT 0
#define HAVE_MMI 0
#define HAVE_MMX 1
#define HAVE_MMX2 1
//略……
#define HAVE_YASM 1
#define CONFIG_BSFS 1
#define CONFIG_DECODERS 1
#define CONFIG_DEMUXERS 1
#define CONFIG_ENCODERS 1
#define CONFIG_FILTERS 1
#define CONFIG_HWACCELS 0
#define CONFIG_INDEVS 1
#define CONFIG_MUXERS 1
#define CONFIG_OUTDEVS 1
#define CONFIG_PARSERS 1
#define CONFIG_PROTOCOLS 1
#define CONFIG_FFPLAY 1
#define CONFIG_FFPROBE 1
#define CONFIG_FFSERVER 0
#define CONFIG_FFMPEG 1
#define CONFIG_AVPLAY 0
#define CONFIG_AVPROBE 0
#define CONFIG_AVSERVER 0
#define CONFIG_AANDCT 1
#define CONFIG_AC3DSP 1
#define CONFIG_AVCODEC 1
#define CONFIG_AVDEVICE 1
#define CONFIG_AVFILTER 1
#define CONFIG_AVFORMAT 1
#define CONFIG_AVISYNTH 0
#define CONFIG_BZLIB 0
#define CONFIG_CRYSTALHD 0
#define CONFIG_DCT 1
#define CONFIG_DOC 0
#define CONFIG_DWT 1
#define CONFIG_DXVA2 0
#define CONFIG_FASTDIV 1
#define CONFIG_FFT 1
#define CONFIG_FREI0R 0
#define CONFIG_GNUTLS 0
#define CONFIG_GOLOMB 1
#define CONFIG_GPL 0
#define CONFIG_GRAY 0
#define CONFIG_H264CHROMA 1
#define CONFIG_H264DSP 1
#define CONFIG_H264PRED 1
#define CONFIG_HARDCODED_TABLES 0
#define CONFIG_HUFFMAN 1
#define CONFIG_LIBAACPLUS 0
#define CONFIG_LIBASS 0
#define CONFIG_LIBCDIO 0
#define CONFIG_LIBCELT 0
#define CONFIG_LIBDC1394 0
#define CONFIG_LIBDIRAC 0
#define CONFIG_LIBFAAC 0
#define CONFIG_LIBFREETYPE 0
#define CONFIG_LIBGSM 0
#define CONFIG_LIBMODPLUG 0
#define CONFIG_LIBMP3LAME 0
#define CONFIG_LIBNUT 0
#define CONFIG_LIBOPENCORE_AMRNB 0
#define CONFIG_LIBOPENCORE_AMRWB 0
#define CONFIG_LIBOPENCV 0
#define CONFIG_LIBOPENJPEG 0
#define CONFIG_LIBPULSE 0
#define CONFIG_LIBRTMP 0
#define CONFIG_LIBSCHROEDINGER 0
#define CONFIG_LIBSPEEX 0
#define CONFIG_LIBSTAGEFRIGHT_H264 0
#define CONFIG_LIBTHEORA 0
#define CONFIG_LIBUTVIDEO 0
#define CONFIG_LIBV4L2 0
#define CONFIG_LIBVO_AACENC 0
#define CONFIG_LIBVO_AMRWBENC 0
#define CONFIG_LIBVORBIS 0
#define CONFIG_LIBVPX 0
#define CONFIG_LIBX264 0
//此處省略將近1000條
#define CONFIG_RTMP_PROTOCOL 1
#define CONFIG_RTMPT_PROTOCOL 1
#define CONFIG_RTMPE_PROTOCOL 1
#define CONFIG_RTMPTE_PROTOCOL 1
#define CONFIG_RTMPS_PROTOCOL 1
#define CONFIG_RTP_PROTOCOL 1
#define CONFIG_TCP_PROTOCOL 1
#define CONFIG_TLS_PROTOCOL 0
#define CONFIG_UDP_PROTOCOL 1
#endif /* FFMPEG_CONFIG_H */


Configure的原始碼

#!/bin/sh
#
# FFmpeg configure script
#
# Copyright (c) 2000-2002 Fabrice Bellard
# Copyright (c) 2005-2008 Diego Biurrun
# Copyright (c) 2005-2008 Mans Rullgard
#
# 註釋:雷霄驊
# [email protected]
# http://blog.csdn.net/leixiaohua1020
#
# 添加了註釋的FFmpeg的Configure檔案
#
# Prevent locale nonsense from breaking basic text processing.
LC_ALL=C
export LC_ALL

# make sure we are running under a compatible shell
# try to make this part work with most shells

try_exec(){
    echo "Trying shell $1"
    type "$1" > /dev/null 2>&1 && exec "[email protected]"
}

unset foo
(: ${foo%%bar}) 2> /dev/null
E1="$?"

(: ${foo?}) 2> /dev/null
E2="$?"

if test "$E1" != 0 || test "$E2" = 0; then
    echo "Broken shell detected.  Trying alternatives."
    export FF_CONF_EXEC
    if test "0$FF_CONF_EXEC" -lt 1; then
        FF_CONF_EXEC=1
        try_exec bash "$0" "[email protected]"
    fi
    if test "0$FF_CONF_EXEC" -lt 2; then
        FF_CONF_EXEC=2
        try_exec ksh "$0" "[email protected]"
    fi
    if test "0$FF_CONF_EXEC" -lt 3; then
        FF_CONF_EXEC=3
        try_exec /usr/xpg4/bin/sh "$0" "[email protected]"
    fi
    echo "No compatible shell script interpreter found."
    echo "This configure script requires a POSIX-compatible shell"
    echo "such as bash or ksh."
    echo "THIS IS NOT A BUG IN FFMPEG, DO NOT REPORT IT AS SUCH."
    echo "Instead, install a working POSIX-compatible shell."
    echo "Disabling this configure test will create a broken FFmpeg."
    if test "$BASH_VERSION" = '2.04.0(1)-release'; then
        echo "This bash version ($BASH_VERSION) is broken on your platform."
        echo "Upgrade to a later version if available."
    fi
    exit 1
fi
#幫助選單
show_help(){
cat <<EOF
Usage: configure [options]
Options: [defaults in brackets after descriptions]

Standard options:
  --help                   print this message
  --logfile=FILE           log tests and output to FILE [config.log]
  --disable-logging        do not log configure debug information
  --prefix=PREFIX          install in PREFIX [$prefix]
  --bindir=DIR             install binaries in DIR [PREFIX/bin]
  --datadir=DIR            install data files in DIR [PREFIX/share/ffmpeg]
  --libdir=DIR             install libs in DIR [PREFIX/lib]
  --shlibdir=DIR           install shared libs in DIR [PREFIX/lib]
  --incdir=DIR             install includes in DIR [PREFIX/include]
  --mandir=DIR             install man page in DIR [PREFIX/share/man]

Configuration options:
  --disable-static         do not build static libraries [no]
  --enable-shared          build shared libraries [no]
  --enable-gpl             allow use of GPL code, the resulting libs
                           and binaries will be under GPL [no]
  --enable-version3        upgrade (L)GPL to version 3 [no]
  --enable-nonfree         allow use of nonfree code, the resulting libs
                           and binaries will be unredistributable [no]
  --disable-doc            do not build documentation
  --disable-ffmpeg         disable ffmpeg build
  --disable-ffplay         disable ffplay build
  --disable-ffprobe        disable ffprobe build
  --disable-ffserver       disable ffserver build
  --disable-avdevice       disable libavdevice build
  --disable-avcodec        disable libavcodec build
  --disable-avformat       disable libavformat build
  --disable-swresample     disable libswresample build
  --disable-swscale        disable libswscale build
  --disable-postproc       disable libpostproc build
  --disable-avfilter       disable video filter support [no]
  --disable-pthreads       disable pthreads [auto]
  --disable-w32threads     disable Win32 threads [auto]
  --disable-os2threads     disable OS/2 threads [auto]
  --enable-x11grab         enable X11 grabbing [no]
  --disable-network        disable network support [no]
  --enable-gray            enable full grayscale support (slower color)
  --disable-swscale-alpha  disable alpha channel support in swscale
  --disable-fastdiv        disable table-based division
  --enable-small           optimize for size instead of speed
  --disable-aandct         disable AAN DCT code
  --disable-dct            disable DCT code
  --disable-fft            disable FFT code
  --disable-golomb         disable Golomb code
  --disable-huffman        disable Huffman code
  --disable-lpc            disable LPC code
  --disable-mdct           disable MDCT code
  --disable-rdft           disable RDFT code
  --enable-vaapi           enable VAAPI code [autodetect]
  --enable-vda             enable VDA code [autodetect]
  --enable-vdpau           enable VDPAU code [autodetect]
  --disable-dxva2          disable DXVA2 code
  --disable-vda            disable VDA code
  --enable-runtime-cpudetect detect cpu capabilities at runtime (bigger binary)
  --enable-hardcoded-tables use hardcoded tables instead of runtime generation
  --disable-safe-bitstream-reader
                           disable buffer boundary checking in bitreaders
                           (faster, but may crash)
  --enable-memalign-hack   emulate memalign, interferes with memory debuggers
  --disable-everything     disable all components listed below
  --disable-encoder=NAME   disable encoder NAME
  --enable-encoder=NAME    enable encoder NAME
  --disable-encoders       disable all encoders
  --disable-decoder=NAME   disable decoder NAME
  --enable-decoder=NAME    enable decoder NAME
  --disable-decoders       disable all decoders
  --disable-hwaccel=NAME   disable hwaccel NAME
  --enable-hwaccel=NAME    enable hwaccel NAME
  --disable-hwaccels       disable all hwaccels
  --disable-muxer=NAME     disable muxer NAME
  --enable-muxer=NAME      enable muxer NAME
  --disable-muxers         disable all muxers
  --disable-demuxer=NAME   disable demuxer NAME
  --enable-demuxer=NAME    enable demuxer NAME
  --disable-demuxers       disable all demuxers
  --enable-parser=NAME     enable parser NAME
  --disable-parser=NAME    disable parser NAME
  --disable-parsers        disable all parsers
  --enable-bsf=NAME        enable bitstream filter NAME
  --disable-bsf=NAME       disable bitstream filter NAME
  --disable-bsfs           disable all bitstream filters
  --enable-protocol=NAME   enable protocol NAME
  --disable-protocol=NAME  disable protocol NAME
  --disable-protocols      disable all protocols
  --disable-indev=NAME     disable input device NAME
  --disable-outdev=NAME    disable output device NAME
  --disable-indevs         disable input devices
  --disable-outdevs        disable output devices
  --disable-devices        disable all devices
  --enable-filter=NAME