同步發表於 http://avenwu.net/ijkplayer/2015/05/07/hands_on_ijkplayer_preparationnode
談到視頻播放你們都知道ffmpeg,基於其的衍生版本也不少,好比本文的ijkplayer.android
去到B站得github主頁,找到ijkplayer項目,clone源碼git
git clone git@github.com:Bilibili/ijkplayer.git
根據介紹文檔一步步開始github
執行初始化的shell腳本,腳本會自動下載ffmpeg的主幹代碼shell
IJK_FFMPEG_UPSTREAM=git://git.videolan.org/ffmpeg.git IJK_FFMPEG_FORK=https://github.com/Bilibili/FFmpeg.git IJK_FFMPEG_COMMIT=ijk-r0.2.2-dev IJK_FFMPEG_LOCAL_REPO=extra/ffmpeg set -e TOOLS=tools echo "== pull ffmpeg base ==" sh $TOOLS/pull-repo-base.sh $IJK_FFMPEG_UPSTREAM $IJK_FFMPEG_LOCAL_REPO function pull_fork() { echo "== pull ffmpeg fork $1 ==" sh $TOOLS/pull-repo-ref.sh $IJK_FFMPEG_FORK android/ffmpeg-$1 ${IJK_FFMPEG_LOCAL_REPO} cd android/ffmpeg-$1 git checkout ${IJK_FFMPEG_COMMIT} cd - } pull_fork "armv7a" pull_fork "armv5" pull_fork "x86" pull_fork "arm64-v8a" ./init-config.sh ./init-android-libyuv.sh
簡單分析一息腳本作的事情,
首先定義了4個先關的變量,用於後文下載源碼和目錄的文件api
1. IJK_FFMPEG_UPSTREAM=git://git.videolan.org/ffmpeg.git ffmpeg的官方repo地址 2. IJK_FFMPEG_FORK=https://github.com/Bilibili/FFmpeg.git B站託管與github的ffmpeg分支 3. IJK_FFMPEG_COMMIT=ijk-r0.2.2-dev 能夠用來編譯不一樣平臺版本的代碼分支
找到tools目錄的pull-repo-ref.sh腳本,這個腳本用於獲取B站託管的github上的FFmpeg分支,根據不一樣的目標平臺放置不一樣工做目錄,後面單獨分析;安全
獲取完代碼後,檢出以前定義的特定分支,也就是ijk-r0.2.2-dev
最後再調用另外兩個腳本init-config.sh和init-android-libyuv.sh網絡
這裏腳本接受了三個參數ide
REMOTE_REPO=https://github.com/Bilibili/FFmpeg.git B站本身託管站github的FFmpeg LOCAL_WORKSPACE=android/ffmpeg-xxx 本地目標倉庫存放位置,xxx爲平臺版本 REF_REPO=extra/ffmpeg 遠程ffmpe官方倉庫clone到本地的位置
接下來經過 git clone --reference來獲取B站得FFmpeg,爲何這裏的clone加了--reference參數?實際上根據用法介紹,--reference是爲了減小從網絡獲取的文件,儘量從本地的倉庫中獲取;ui
因此B站FFmpeg應該是基於官方的ffmpeg,這樣的話,因爲一開始的時候已經獲取了官方ffmpeg代碼,在獲取B站的分支倉庫時就能夠將以前下好的官方倉庫的本地庫做爲參考倉庫;
REMOTE_REPO=$1 LOCAL_WORKSPACE=$2 REF_REPO=$3 if [ -z $1 -o -z $2 -o -z $3 ]; then echo "invalid call pull-repo.sh '$1' '$2' '$3'" elif [ ! -d $LOCAL_WORKSPACE ]; then git clone --reference $REF_REPO $REMOTE_REPO $LOCAL_WORKSPACE cd $LOCAL_WORKSPACE git repack -a else cd $LOCAL_WORKSPACE git pull --rebase cd - fi
這個腳本用來安全檢查,若是config/module.sh不存在,那麼默認將module-lite.sh拷貝做爲module.sh,至於module.sh,在前面已經提到,主要是對標準ffmpeg的剪裁控制
if [ ! -f 'config/module.sh' ]; then cp config/module-lite.sh config/module.sh
這個腳本和前面提到的相似,只不過是用來下載依賴包的
IJK_LIBYUV_UPSTREAM=https://github.com/Bilibili/libyuv.git IJK_LIBYUV_FORK=https://github.com/Bilibili/libyuv.git IJK_LIBYUV_COMMIT=ijk-r0.2.1-dev IJK_LIBYUV_LOCAL_REPO=extra/libyuv set -e TOOLS=tools echo "== pull libyuv base ==" sh $TOOLS/pull-repo-base.sh $IJK_LIBYUV_UPSTREAM $IJK_LIBYUV_LOCAL_REPO echo "== pull libyuv fork ==" sh $TOOLS/pull-repo-ref.sh $IJK_LIBYUV_FORK ijkmedia/ijkyuv ${IJK_LIBYUV_LOCAL_REPO} cd ijkmedia/ijkyuv git checkout ${IJK_LIBYUV_COMMIT} cd -
初始化完畢後就能夠依次執行下面的腳本開始編譯了
cd android ./compile-ffmpeg.sh clean ./compile-ffmpeg.sh ./compile-ijk.sh
這裏可能會遇到一些問題,根據自身環境不一樣不必定同樣;筆者在編譯時,第一次直接在master上編,結果提示有一個.h找不到,根據文檔指南切回k0.2.3後從新來就OK了,雖然上面也說了能夠在maste直接編,但其實是不行的;
最後編譯成功的話會看到幾個so的輸出
注意默認狀況下這裏之變異了armv7的幾個so庫,其餘平臺的須要跟上參數編譯
compile-ijk.sh armv5|armv7a|x86|arm64-v8a 或者 compile-ijk.sh all
可是,事情不是這麼簡單,但加上all以後,armv7仍然成功,可是x86編譯就跪了
同時armv5也跪了,緣由都是找不libijkffmpeg.so
衝armv7得輸出日誌能夠看到,這個文件是build下從各自版本的編譯文件拷貝而來;
定位到build文件夾,裏面只有armv7的相關文件,因此根本拷貝就不會成功,天然就掛了;
aven-mac-pro:android aven$ ./compile-ijk.sh all Android NDK: ERROR:/Users/aven/work/video/ijkplayer/android/ijkmediaplayer-armv5/jni/ffmpeg/Android.mk:ijkffmpeg: LOCAL_SRC_FILES points to a missing file Android NDK: Check that /libijkffmpeg.so exists or that its path is correct /Users/aven/Android/android-ndk-r10c/build/core/prebuilt-library.mk:45: *** Android NDK: Aborting . Stop. /Users/aven/work/video/ijkplayer/android [armeabi-v7a] Prebuilt : libijkffmpeg.so <= /Users/aven/work/video/ijkplayer/android/build/ffmpeg-armv7a/output/ [armeabi-v7a] Install : libijkffmpeg.so => libs/armeabi-v7a/libijkffmpeg.so [armeabi-v7a] Compile thumb : ijkplayer <= ff_cmdutils.c [armeabi-v7a] Compile thumb : ijkplayer <= ff_ffplay.c [armeabi-v7a] Compile thumb : ijkplayer <= ijkmeta.c [armeabi-v7a] Compile thumb : ijkplayer <= ijkplayer.c [armeabi-v7a] Compile thumb : ijkplayer <= ffpipeline_ffplay.c [armeabi-v7a] Compile thumb : ijkplayer <= ffpipenode_ffplay_vdec.c [armeabi-v7a] Compile thumb : ijkplayer <= ffpipenode_ffplay_vout.c [armeabi-v7a] Compile thumb : ijkplayer <= ffmpeg_api_jni.c [armeabi-v7a] Compile thumb : ijkplayer <= ijkplayer_android.c [armeabi-v7a] Compile thumb : ijkplayer <= ijkplayer_jni.c [armeabi-v7a] Compile thumb : ijkplayer <= ffpipeline_android.c [armeabi-v7a] Compile thumb : ijkplayer <= ffpipenode_android_mediacodec_vdec.c [armeabi-v7a] Compile thumb : ijkplayer <= ffpipenode_android_mediacodec_vout.c [armeabi-v7a] Compile thumb : ijksdl <= ijksdl_vout_overlay_ffmpeg.c [armeabi-v7a] Compile thumb : ijksdl <= image_convert.c [armeabi-v7a] Compile thumb : ijksdl <= android_nativewindow.c [armeabi-v7a] Compile thumb : ijksdl <= ijksdl_vout_android_nativewindow.c [armeabi-v7a] SharedLibrary : libijksdl.so [armeabi-v7a] SharedLibrary : libijkplayer.so [armeabi-v7a] Install : libijkplayer.so => libs/armeabi-v7a/libijkplayer.so [armeabi-v7a] Install : libijksdl.so => libs/armeabi-v7a/libijksdl.so [armeabi-v7a] Install : libijkutil.so => libs/armeabi-v7a/libijkutil.so /Users/aven/work/video/ijkplayer/android Android NDK: ERROR:/Users/aven/work/video/ijkplayer/android/ijkmediaplayer-x86/jni/ffmpeg/Android.mk:ijkffmpeg: LOCAL_SRC_FILES points to a missing file Android NDK: Check that /libijkffmpeg.so exists or that its path is correct /Users/aven/Android/android-ndk-r10c/build/core/prebuilt-library.mk:45: *** Android NDK: Aborting . Stop. /Users/aven/work/video/ijkplayer/android到libijkffmpeg.so
這個時候只能一步一步回溯,首先查看compile-ffmpeg.sh
UNI_BUILD_ROOT=`pwd` FF_TARGET=$1 set -e set +x FF_ALL_ARCHS="armv5 armv7a x86 arm64-v8a" FF_ACT_ARCHS="armv5 armv7a x86" echo_archs() { echo "====================" echo "[*] check archs" echo "====================" echo "FF_ALL_ARCHS = $FF_ALL_ARCHS" echo "FF_ACT_ARCHS = $FF_ACT_ARCHS" echo "" } case "$FF_TARGET" in "") echo_archs sh tools/do-compile-ffmpeg.sh armv7a ;; armv5|armv7a|x86|arm64-v8a) echo_archs sh tools/do-compile-ffmpeg.sh $FF_TARGET ;; all) echo_archs for ARCH in $FF_ACT_ARCHS do sh tools/do-compile-ffmpeg.sh $ARCH done ;; clean) echo_archs for ARCH in $FF_ALL_ARCHS do cd ffmpeg-$ARCH && git clean -xdf && cd - done rm -rf ./build/ffmpeg-* ;; check) echo_archs ;; *) echo "Usage:" echo " compile-ffmpeg.sh armv5|armv7a|x86|arm64-v8a" echo " compile-ffmpeg.sh all" echo " compile-ffmpeg.sh clean" echo " compile-ffmpeg.sh check" exit 1 ;; esac echo "\n--------------------" echo "[*] Finished" echo "--------------------" echo "# to continue to build ijkplayer, run script below," echo "sh compile-ijk.sh "
眼尖的話應該看到了,這裏也是須要跟參數來決定編譯的版本,問題引刃而解。
再次編譯成功.