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.mkLOCAL_MODULE := ijkffmpeg
LOCAL_SRC_FILES := $(MY_APP_FFMPEG_OUTPUT_PATH)/libijkffmpeg.so
將所有平臺下的資訊修改後好了,編譯,success!
最後記得將demo裡的libLoader.loadLibrary("name");修改後再執行。
至此,結束。