小試ijkplayer編譯

同步發表於 http://avenwu.net/ijkplayer/2015/05/07/hands_on_ijkplayer_preparationnode

談到視頻播放你們都知道ffmpeg,基於其的衍生版本也不少,好比本文的ijkplayer.android

試試ijkplayer編譯

去到B站得github主頁,找到ijkplayer項目,clone源碼git

git clone git@github.com:Bilibili/ijkplayer.git

根據介紹文檔一步步開始github

./init-android.sh

執行初始化的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網絡

tools/pull-repo-ref.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

./init-config.sh

這個腳本用來安全檢查,若是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

./init-android-libyuv.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 "

眼尖的話應該看到了,這裏也是須要跟參數來決定編譯的版本,問題引刃而解。

再次編譯成功.

相關文章
相關標籤/搜索