ijkplayer系列3:編譯ijkplayer&集成ijkplayer

編譯ijkplayer

01.準備工作

下載

從github上下載源碼,同時github上有完整的編譯流程,可以看下。

安裝Homebrew

簡稱brew。OSX上的軟件包管理系統,簡單來說,就是可以方便地安裝、卸載和管理軟件,軟件包管理在類Unix系統上可是一件非常噁心的事情。
在命令行中敲入下面的命令,安裝Homebrew,命令語句原汁原味,不需要修改:

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

中間過程可能需要按下enter鍵或者輸下密碼,照提示做就是了,很簡單的安裝過程,成功後有明顯的提示。如果安裝失敗了,請自行google/baidu,這裏不探討Homebrew相關知識。

安裝git

git是啥就不用多說了,這個應該很多人都已經裝過了,如果裝過了就不需要再安裝。利用剛纔安裝的Homebrew,在命令行中敲入下面的命令,安裝git:

brew install git

安裝yasm

貌似是一個彙編器,編譯用的,總之裝上就對了。利用剛纔安裝的Homebrew,在命令行中敲入下面的命令,安裝yasm:

brew install yasm

環境變量配置

在~/.bash_profile文件中加入下面兩行:

export ANDROID_SDK=[your sdk path]
export ANDROID_NDK=[your ndk path]

保存並退出.bash_profile,在命令行中輸入source .bash_profile使配置生效,有時需要關閉終端纔會生效。

02.編譯

初始化

將ijkplayer根目錄置爲工作目錄,執行以下命令:
1、從遠程倉庫clone ffmpeg到extra/ffmpeg,並以extra/ffmpeg爲引用,clone到5個cpu架構對應的目錄中,以armv7q爲例,路徑爲android/contrib/ffmpeg-armv7a;
2、製作config/module-lite.sh的替身config/module.sh,該文件中配置了ffmpeg編譯的配置項;
3、從遠程倉庫clone libyuv到extra/libyuv,並以extra/libyuv爲引用,clone到ijkmedia/ijkyuv中。
綜上,該腳本主要工作是從遠程倉庫下載ffmpeg和libyuv源碼到本地。

./init-android.sh

這個腳本可以做下修改,只保留一份原始ffmpeg源碼,這樣當去修改源碼的時候不會出現需要同步到其他5份的情況,同理,只保留一份libyuv。

編譯ffmpeg

將工作目錄切換到android/contrib,依次執行以下命令(必須切換,否則後續腳本運行會有問題):

清除之前編譯好的ffmpeg庫。

./compile-ffmpeg.sh clean

編譯所有cpu架構的ffmpeg庫(armv5、armv7a、arm64、x86、x86_64),其它參數參見附件的腳本。
實際的編譯腳本是android/contrib/tools/do-compile-ffmpeg.sh。
以armv7a爲例,結果輸出到android/contrib/build/ffmpeg-armv7a/output,包含頭文件、靜態庫和動態庫。

./compile-ffmpeg.sh all

編譯ijkplayer

將ijkplayer/android置爲工作目錄,執行下面命令:

編譯ijkplayer動態庫,這裏的參數all和compile-ffmpeg.sh中的效果是一樣的,其它參數的使用參考compile-ffmpeg.sh。
項目中預置了5個cpu架構對應的源碼在android/ijkplayer目錄下,以armv7a爲例,位於android/ijkplayer/ijkplayer-armv7a,我們需要編譯的mk文件和源文件位於上述目錄的src/main/jni目錄下,裏面除了Application.mk是每個cpu架構對應獨立的一份外,其它文件基本都是鏈接自ijkmedia目錄下的文件。
該過程編譯了以下幾個庫:
1、編譯libandroid-ndk-profiler.a,輸出到lib下
2、將之前編譯生成的libijkffmpeg.so拷貝到lib下
3、編譯ijkj4a靜態庫libijkj4a.a,編譯libyuv靜態庫libyuv-static.a,輸出到lib下
4、依賴libijkffmpeg.so、libijkj4a.a、libyuv-static.a、libcpufeatures.a(外部鏈接庫)編譯libijksdl.so,輸出到lib下
5、依賴libijkffmpeg.so、libijksdl.so、libandroid-ndk-profiler.a,編譯libijkplayer.so,輸出到lib下
最終輸出了libijkffmpeg.so、libijksdl.so、libijkplayer.so三個動態庫

./compile-ijk.sh all

至此,我們的所有編譯工作就完成了,在這裏我有稍微省略了幾個步驟,如果編譯途中碰到錯誤,最好照着github上面的步驟一步步做下來。進入ijkplayer/android/ijkplayer目錄,這裏面的所有東西就是我們編譯後的產出,也是後續項目中會使用到的庫文件和源文件。

在這裏插入圖片描述
在這裏插入圖片描述

集成ijkplayer

下載下來的ijkplayer源碼工程是不能直接集成到項目中使用的,需要先編譯,然後集成編譯後生成的子工程,該子工程位於[ijkplayer根目錄]/android/ijkplayer。
在主工程中使用import module將ijkplayer作爲module導入主工程,路徑指向前面所說的ijkplayer編譯後的子工程。導入後會發現不止一個module,而是有好幾個module,最顯眼的是一個abi對應一個module。這和我們平常的工程結構差異挺大的,通常我們是將所有需要的abi庫都集中放到libs中。ijkplayer這樣做的好處是,可以通過在gradle文件中指定需要編譯的module來篩選需要的abi,挺有意思。
如果你看不慣他這種目錄結構,也可以將你需要的so庫挪到ijkplayer-java的libs目錄下,然後刪除所有abi對應的module。
編譯一下,如果成功就沒有問題,如果失敗了,根據提示解決問題。

常見編譯失敗問題

提示compileSdkVersion有問題
ijkplayer使用了gradle的全局配置,在每個module的gradle文件中都可以看到如下代碼

android {
    compileSdkVersion rootProject.ext.compileSdkVersion
    buildToolsVersion rootProject.ext.buildToolsVersion
}

解決方法有兩個:

  1. 在根目錄下的gradle文件中加入ext全局變量,併爲每個出現過的ext參數定義。
  2. 將所有全局變量改成常量。

提示tools/gradle-on-demand.gradle找不到

tools目錄就在之前編譯完成的ijkplayer目錄下,也就是和所有module在同個目錄下,導入module的時候可能這個目錄沒有導進來,手動copy到工程目錄下即可。

03. 我的實踐

編譯出來之後,我通過導入項目的方式把下面的項目導入到了Androidstudio,設置了sdk之後,編譯,可以看到官方Demo了:中間切了網絡。
在這裏插入圖片描述
在這裏插入圖片描述
按照博客的說法,這裏面的很多cpu類型的代碼都是可以刪除掉的。在我們製作自己的aar包的時候,可以去掉。

我們看一下這個項目的結構:
在這裏插入圖片描述
編譯IJKPlayer開源項目的so文件庫走過的路
https://www.jianshu.com/p/2c1413486b01
這個是別人的實踐,直接拷貝源碼也是一種方法。

04. 爲什麼要編譯?

交叉編譯的概念和爲什麼要交叉編譯這裏就不細說了,感興趣的可以去查資料。因爲官方提供的遠程maven依賴在交叉編譯的時候可能提供的功能有限,比如不支持某些音視頻編解碼格式,所以需要我們自己可定製的去交叉編譯自己需要的版本出來,爲了功能的擴展或者是爲了包體積的考慮等等。
這裏就有個栗子,必須得編譯一個自己版本的ijk:
編譯IJKPlayer開源項目的so文件庫走過的路
https://www.jianshu.com/p/2c1413486b01

05. 參考資料:

ijkplayer編譯so庫真沒那麼難
https://blog.csdn.net/coder_pig/article/details/79134625

什麼是交叉編譯,爲什麼要使用交叉編譯?
https://blog.csdn.net/caoshangpa/article/details/79076813

Android CPU架構及so庫兼容問題總結
https://blog.csdn.net/u010052279/article/details/81393143

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章