1. 程式人生 > >ijkplayer入門之目錄介紹及編譯

ijkplayer入門之目錄介紹及編譯

ijkPlayer主要包含了android, extra, ijkmedia, ios幾個核心原始碼目錄

android 目錄包括了android 平臺上層介面提供、用例等等

----ijkplayer:android 測試用例,直接匯入android studio後可以使用(但需要事先先編譯好so庫)

----compile-ijk.sh:ijkplayer總的編譯指令碼檔案,生成libijksdl.so和libijkplayer.so檔案,並同時將這兩檔案及相應平臺的libijkffmpeg.so拷貝到android-ijkplayer-ijkplayer-xxx目錄下,拷貝目錄是android-contrib-ffmpeg-xxx(下面會介紹到)

----contrib----compile-ffmpeg.sh:ffmpeg總的編譯指令碼檔案,最終呼叫的是tools下的do-compile-ffmpeg.sh,執行後在會contrib目錄下升成一個build資料夾,在該資料夾下生成各個平臺的的so庫檔案。編譯時可以選擇只編譯相應用平臺。

----contrib----ffmpeg-xxx:不同平臺的ffmpeg的原始碼目錄

----contrib----tools:ffmpeg的編譯指令碼所需的工具,包括了ndk版本要求檢查

----config:ffmpeg的module配置目錄,可以對ffmpeg進行裁剪優化等等,這個裁剪包括了支援哪些編解碼器、流媒體協議等等

----extra:這個目錄只是用來備份相關原始碼,如ffmpeg、libyuv等等,如contrib-ffmpeg-xxx不同平臺的原始碼就是從這拷貝過去的

----ijkmedia:最主要的核心程式碼

----ijkmedia----ijkplayer核心程式碼實現,其中包括與android上層互動的實現、基本的解協議、編解碼的基本流程。

----ijkmedia----ijksdl:音視訊渲染相關,ijksdk依賴了第三方開源庫libyuv

----ijkmedia----ijkj4a:這個和音訊的輸出有關

----ios:ios平臺開發相關的

除了上面提到compile-ijk.sh和compile-ffmpeg.sh外還有一個也很重要的指令碼檔案init-android.sh,其實這個應該先介紹的,從執行順序來講。

----init-android.sh:拉取ffmpeg的原始碼到extra中,並依次拷貝到android-contrib-ffmpeg-xxx裡,接著執行以下指令碼檔案

./init-config.sh 配置ffmpeg的module,可以對ffmpeg進行定製

./init-android-libyuv.sh 拉取libyuv的原始碼到extra,並拷貝到ijkmedia

./init-android-soundtouch.sh 拉取soundtouch的原始碼到extra,並拷貝到ijkmedia

然後我們來簡單理一下流程

1、執行init-config.sh指令碼,接取ffmpeg及相關原始碼

2、執行compile-ffmpeg.sh,編譯得到libijkffpeg.so庫

3、執行compile-ijk.sh,編譯得到libijkijkplayer.so和libijksdl.so庫

剛好遇到一個需求修改so庫的名稱

初看可能會覺得這需求有點奇怪,好好的為什麼要修改so庫的名稱呢?

其實是因為在開發過程中我們遇到了這樣的現象:前提,我們為上層提供定製的播放器,在提供了正確的so庫後,但上層反饋回來的日誌列印的ijk及ffmpeg的版本卻是錯的?實步排除了so沒有正確替換的可能性,經排查,原為上層app是內建app,內建app的lib庫是需要統一拷貝到/system/lib下的,那在這種情況下會出現同名覆蓋的情況,所以出現了這樣的需求。

剛好可以拿著這個來熟悉上面的流程

第一個自然要修改是的libijkffmpeg.so的名字了,第一步是拉取原始碼,所以走第二步,從上面可以知道編譯ffmpeg最終呼叫的是android-contrib-tools-do-compile-ffmpeg.sh指令碼,開啟後搜尋ijkffmpeg關鍵字(表示我也不是很懂這塊的囧)

$CC -lm -lz -shared --sysroot=$FF_SYSROOT -Wl,--no-undefined -Wl,-z,noexecstack $FF_EXTRA_LDFLAGS \
    -Wl,-soname,libijkffmpeg.so \
    $FF_C_OBJ_FILES \
    $FF_ASM_OBJ_FILES \
    $FF_DEP_LIBS \
    -o $FF_PREFIX/libijkffmpeg.so
編譯so的命令-soname 這不是so的名字嘛,-o,檔案輸出,很大膽的先改了再說。接著連結檔案
ln -s $FF_PREFIX/include $FF_PREFIX/shared/include
ln -s $FF_PREFIX/libijkffmpeg.so $FF_PREFIX/shared/lib/libijkffmpeg.so
輸出檔案改了,後續自然也要改著改。

還有最後一處,替換字串,自然也要修改了

for f in $FF_PREFIX/lib/pkgconfig/*.pc; do
    # in case empty dir
    if [ ! -f $f ]; then
        continue
    fi
    cp $f $FF_PREFIX/shared/lib/pkgconfig
    f=$FF_PREFIX/shared/lib/pkgconfig/`basename $f`
    # OSX sed doesn't have in-place(-i)
    mysedi $f 's/\/output/\/output\/shared/g'
    mysedi $f 's/-lavcodec/-lijkffmpeg/g'
    mysedi $f 's/-lavfilter/-lijkffmpeg/g'
    mysedi $f 's/-lavformat/-lijkffmpeg/g'
    mysedi $f 's/-lavutil/-lijkffmpeg/g'
    mysedi $f 's/-lswresample/-lijkffmpeg/g'
    mysedi $f 's/-lswscale/-lijkffmpeg/g'

修改好後,執行init-config.sh指令碼,成功後我們可以在android-contrib-build資料夾下找相應用平臺編譯出來的so庫,名字也改成了libxxxffmpeg.so(按原先規範來改)

接著是libijkplayer.so和libijksdl.so,一樣從上面我們可以知道是執行compile-ijk.sh後生成的,player包括了與andorid上層互動,即jni,而我們在ijkmedia裡的ijkplayer和ijksdl原始碼目錄gh各自找到了熟悉Android.mk

ijkplayer要依賴於ijksdl,所以我們先看ijksdl

LOCAL_SHARED_LIBRARIES := ijkffmpeg
LOCAL_STATIC_LIBRARIES := cpufeatures yuv_static ijkj4a

LOCAL_MODULE := ijksdl
LOCAL_SHARED_LIBRARIES:要連結到本模組的動態庫 LOCAL_MODULE:模組名稱
二話不說直接改了 最後是ijkplayer,一樣的
LOCAL_SHARED_LIBRARIES := ijkffmpeg ijksdl
LOCAL_STATIC_LIBRARIES := android-ndk-profiler ijksoundtouch
LOCAL_MODULE := ijkplayer
然後很開心的去編譯了./compile-ijk.sh 然後霹靂啪啦的報錯了,漏了一個地方 根據報錯資訊,我們很容易定位到了android/ijkplayer/ijkplayer-xxx/src/main/jni/ffmpeg/Android.mk
LOCAL_MODULE := ijkffmpeg
LOCAL_SRC_FILES := $(MY_APP_FFMPEG_OUTPUT_PATH)/libijkffmpeg.so
將所有平臺下的資訊修改後好了,編譯,success!

最後記得將demo裡的libLoader.loadLibrary("name");修改後再執行。

至此,結束。