ijkplayer 播放器:在Android端進行native調(diào)試

前言

ijkplayer是B站開源的基于FFmpeg的輕量級Android/iOS視頻播放器茸俭,強烈建議在定制的播放器的時候以ijkplayer為基礎(chǔ)進行二次開發(fā)粒梦。
對于二次開發(fā)時代碼的調(diào)試時一件重中之重的事情;在iOS平臺,ijkplayer可以直接在Xcode進行c/c++源碼的debug調(diào)試工作,而Android平臺的demo工程依賴的是ijkplayer編譯完畢的so文件硼补,而不是直接關(guān)聯(lián)到ijkplayer的Android.mk編譯腳本文件,所以要對c/c++這些native源碼的調(diào)試的話就需要多折騰一些工作熏矿。


可能遇到的問題

如果我們要在Android Studio里面對ijkplayer的native進行調(diào)試已骇,很開心的是官方提供了這么一個流程:

If you want to enable debugging ijkplayer(native modules) on Android Studio 2.2+: (experimental)
     sh android/patch-debugging-with-lldb.sh armv7a
     Install Android Studio 2.2(+)
     Preference -> Android SDK -> SDK Tools
     Select (LLDB, NDK, Android SDK Build-tools,Cmake) and install
     Open an existing Android Studio project
     Select android/ijkplayer
     Sync Project with Gradle Files
     Run -> Edit Configurations -> Debugger -> Symbol Directories
     Add "ijkplayer-armv7a/.externalNativeBuild/ndkBuild/release/obj/local/armeabi-v7a" to Symbol Directories
     Run -> Debug 'ijkplayer-example'
     if you want to reverse patches:
     sh patch-debugging-with-lldb.sh reverse armv7a

清楚明了對吧,but票编,幾乎所有人都會遇到這一個問題褪储,當你執(zhí)行這句命令的時候:

sh android/patch-debugging-with-lldb.sh armv7a

恭喜你,一般你都會發(fā)現(xiàn)如下錯誤:

patch apply ==> armv7a
git apply ==> patches/0001-gitignore-ignore-.externalNativeBuild.patch
git apply ==> patches/0002-gradle-upgrade-build-tool-to-2.2.0-beta2.patch
error: patch failed: android/ijkplayer/ijkplayer-example/build.gradle:44
error: android/ijkplayer/ijkplayer-example/build.gradle: patch does not apply
git apply ==> patches/0003-armv7a-enable-debugging-with-LLDB.patch
error: patch failed: ijkmedia/ijkplayer/Android.mk:59
error: ijkmedia/ijkplayer/Android.mk: patch does not apply
error: patch failed: ijkmedia/ijksdl/Android.mk:70
error: ijkmedia/ijksdl/Android.mk: patch does not apply
git apply ==> patches/0004-armv7a-link-prebuilt-staic-libraries-of-ffmepg.patch

what栏妖?這個腳本竟然是有問題的乱豆!
當然這是因為這個腳本是用git一些修改patch進行代碼還原,但是但是吊趾,由于這個腳本已經(jīng)太久沒有更新了宛裕,而ijkplayer的一些代碼結(jié)構(gòu)又有調(diào)整導致腳本無法從patch文件附帶的這些信息把代碼正確還原回去瑟啃。


解決思路

我們通過查看patch-debugging-with-lldb.sh,可以發(fā)現(xiàn)我們只需要按照以下幾個patch文件做對應源碼修改就可以達到調(diào)試的目的:

android/patches/0001-gitignore-ignore-.externalNativeBuild.patch
android/patches/0002-gradle-upgrade-build-tool-to-2.2.0-beta2.patch
android/patches/0003-$PARAM_TARGET-enable-debugging-with-LLDB.patch
android/patches/0004-$PARAM_TARGET-link-prebuilt-staic-libraries-of-ffmepg.patch

例如隨便打開里面一個文件例如0002-gradle-upgrade-build-tool-to-2.2.0-beta2.patch的內(nèi)容如下:

 From 5d70fa0496f9ebfbcfa3786d85c74c690d66781e Mon Sep 17 00:00:00 2001
From: ctiao <calmer91@gmail.com>
Date: Mon, 29 Aug 2016 14:50:34 +0800
Subject: [PATCH 2/2] gradle: upgrade build-tool to 2.2.0-rc1

---
 android/ijkplayer/build.gradle | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/android/ijkplayer/build.gradle b/android/ijkplayer/build.gradle
index 0de03ec..6132c1d 100644
--- a/android/ijkplayer/build.gradle
+++ b/android/ijkplayer/build.gradle
@@ -5,7 +5,7 @@ buildscript {
         jcenter()
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:2.1.3'
+        classpath 'com.android.tools.build:gradle:2.2.0-rc1'

         classpath 'com.github.dcendents:android-maven-gradle-plugin:1.4.1'
         classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7'
--
2.7.4 (Apple Git-66) 

留意這些+-這些所在的行的內(nèi)容揩尸,熟悉git的同學應該就知道蛹屿,這里應該是要刪除掉

classpath 'com.android.tools.build:gradle:2.1.3'

然后把這一行添加上去

classpath 'com.android.tools.build:gradle:2.2.0-rc1'

其他文件也是以此類推,當然ijkplayer的源碼不斷的迭代岩榆,可能有些修改已經(jīng)對不上了错负,并且有些修改也并不需必須的,所以這里我們就不完整對patch里面的每一行修改都進行修改勇边,而是分析出這些patch的主要更改點在什么地方犹撒。


解決重點

通過分析這幾個patch文件,我們可以明確得出主要的修改如下:

ijkplayer-xxxabi工程只保留armv7a

修改文件:ijkplayer/setting.gradle
修改內(nèi)容:將其他的非armv7a的cpu架構(gòu)的庫刪掉或者注釋

//刪除armv5粒褒、x86-64识颊、x86、arm64這些工程
//include ':ijkplayer-armv5', ':ijkplayer-x86_64'
include ':ijkplayer-armv7a'
//include ':ijkplayer-arm64'
//include ':ijkplayer-x86'

升級工程的gradle版本

修改文件:ijkplayer/build.gradle
修改內(nèi)容:將gradle版本升級到2.2以上

dependencies {
    //classpath 'com.android.tools.build:gradle:2.1.3'
    classpath 'com.android.tools.build:gradle:3.0.1'
}

ijkplayer-armv7a工程關(guān)聯(lián)Android.mk編譯腳本

修改文件:ijkplayer/ijkplayer-armv7a/build.gradle
修改內(nèi)容:不要指定jni的lib庫文件夾位置

android {
    //刪除以下內(nèi)容
    //sourceSets.main {
    //  jniLibs.srcDirs 'src/main/libs'
    //  jni.srcDirs = [] // This prevents the auto generation of Android.mk
    //}
}

修改內(nèi)容:添加native代碼主編譯腳本Android.mk的文件路徑

android {
    //添加以下內(nèi)容
    externalNativeBuild {
        ndkBuild {
            path "src/main/jni/Android.mk"
        }
    }
}

修改內(nèi)容:設(shè)置編譯腳本的參數(shù)

android {
    defaultConfig {
        //添加以下內(nèi)容
        externalNativeBuild {
            ndkBuild {
                arguments "NDK_APPLICATION:=src/main/jni/Application.mk"
                abiFilters "armeabi-v7a"
            }
        }
    }
}

修改內(nèi)容:開啟工程的debug模式

android {
    buildTypes {
        //添加以下內(nèi)容
        debug {
            debuggable true
            jniDebuggable true
            ndk {
                debuggable true
            }
        }
    }
}

修改ffmpeg的編譯腳本

修改文件:ijkplayer/ijkplayer-armv7a/src/main/jni/ffmpeg/Android.mk
修改內(nèi)容:將ffmpeg的鏈接方式由動態(tài)庫方式改為靜態(tài)庫方式

LOCAL_PATH := $(call my-dir)

#刪除ffmpeg動態(tài)庫相關(guān)
#include $(CLEAR_VARS)
#LOCAL_MODULE := ijkffmpeg
#LOCAL_SRC_FILES := #$(MY_APP_FFMPEG_OUTPUT_PATH)/libijkffmpeg.so
#Include $(PREBUILT_SHARED_LIBRARY)

#添加ffmpeg靜態(tài)庫相關(guān)如下全部
include $(CLEAR_VARS)
LOCAL_MODULE    := avcodec
LOCAL_SRC_FILES := $(MY_APP_FFMPEG_OUTPUT_PATH)/lib/libavcodec.a
LOCAL_EXPORT_C_INCLUDES := $(MY_APP_FFMPEG_INCLUDE_PATH)
LOCAL_C_INCLUDES += $(MY_APP_FFMPEG_INCLUDE_PATH)
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE    := avformat
LOCAL_SRC_FILES := $(MY_APP_FFMPEG_OUTPUT_PATH)/lib/libavformat.a
LOCAL_EXPORT_C_INCLUDES := $(MY_APP_FFMPEG_INCLUDE_PATH)
LOCAL_C_INCLUDES += $(MY_APP_FFMPEG_INCLUDE_PATH)
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE    := swscale
LOCAL_SRC_FILES := $(MY_APP_FFMPEG_OUTPUT_PATH)/lib/libswscale.a
LOCAL_EXPORT_C_INCLUDES := $(MY_APP_FFMPEG_OUTPUT_PATH)/include
LOCAL_C_INCLUDES += $(MY_APP_FFMPEG_INCLUDE_PATH)
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE    := avutil
LOCAL_SRC_FILES := $(MY_APP_FFMPEG_OUTPUT_PATH)/lib/libavutil.a
LOCAL_EXPORT_C_INCLUDES := $(MY_APP_FFMPEG_INCLUDE_PATH)
LOCAL_C_INCLUDES += $(MY_APP_FFMPEG_INCLUDE_PATH)
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE    := avfilter
LOCAL_SRC_FILES := $(MY_APP_FFMPEG_OUTPUT_PATH)/lib/libavfilter.a
LOCAL_EXPORT_C_INCLUDES := $(MY_APP_FFMPEG_INCLUDE_PATH)
LOCAL_C_INCLUDES += $(MY_APP_FFMPEG_INCLUDE_PATH)
include $(PREBUILT_STATIC_LIBRARY)

LOCAL_MODULE    := swresample
LOCAL_SRC_FILES := $(MY_APP_FFMPEG_OUTPUT_PATH)/lib/libswresample.a
LOCAL_EXPORT_C_INCLUDES := $(MY_APP_FFMPEG_INCLUDE_PATH)
LOCAL_C_INCLUDES += $(MY_APP_FFMPEG_INCLUDE_PATH)
include $(PREBUILT_STATIC_LIBRARY)

修改ijkplayer的編譯腳本

修改文件:ijkplayer/ijkmedia/ijkplayer/Android.mk
修改內(nèi)容:添加兩個本地庫-lm -lz

LOCAL_CFLAGS += -std=c99
#LOCAL_LDLIBS += -llog -landroid
LOCAL_LDLIBS += -llog -landroid -lm -lz

修改內(nèi)容:將ffmpeg由動態(tài)鏈接方式改為靜態(tài)鏈接方式

#LOCAL_SHARED_LIBRARIES := ijkffmpeg ijksdl
#LOCAL_STATIC_LIBRARIES := android-ndk-profiler ijksoundtouch
LOCAL_SHARED_LIBRARIES := ijksdl
LOCAL_STATIC_LIBRARIES := android-ndk-profiler ijksoundtouch avformat avcodec swscale swresample avfilter avutil

修改ijksdl編譯腳本

修改文件:ijkplayer/ijkmedia/ijksdl/Android.mk
修改內(nèi)容:將ffmpeg由動態(tài)鏈接方式改為靜態(tài)鏈接方式

#LOCAL_SHARED_LIBRARIES := ijkffmpeg
#LOCAL_STATIC_LIBRARIES := cpufeatures yuv_static ijkj4a
LOCAL_STATIC_LIBRARIES := cpufeatures yuv_static ijkj4a avformat avcodec swscale swresample avfilter avutil

屏蔽掉java層對于ffmpeg動態(tài)庫的加載

修改文件:ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IjkMediaPlayer.java
修改內(nèi)容:由于ffmpeg采用了靜態(tài)庫導入奕坟,所以這里并不需要加載ffmpeg的動態(tài)庫祥款。

public static void loadLibrariesOnce(IjkLibLoader libLoader) {
    synchronized (IjkMediaPlayer.class) {
        if (!mIsLibLoaded) {
            if (libLoader == null)
                libLoader = sLocalLibLoader;
            //這里屏蔽掉ijkffmpeg庫的加載
            //libLoader.loadLibrary("ijkffmpeg");
            libLoader.loadLibrary("ijksdl");
            libLoader.loadLibrary("ijkplayer");
            mIsLibLoaded = true;
        }
    }
}

example工程同步修改

修改文件:ijkplayer/ijkplayer-example/build.gradle
修改內(nèi)容:將cpu的類型指定為armv7a,并且開啟debug模式

android {
    //指定armeabi-v7a
    defaultConfig {
        externalNativeBuild {
            ndkBuild {
                abiFilters "armeabi-v7a"
            }
        }
    }
    buildTypes {
        //添加debug模式的指定
        debug {
            jniDebuggable true
        }
    }
}

修改內(nèi)容:刪除掉非armeabi-v7a工程的依賴

dependencies {
    //all32Compile project(':ijkplayer-armv5')
    all32Compile project(':ijkplayer-armv7a')
    //all32Compile project(':ijkplayer-x86')

    //all64Compile project(':ijkplayer-armv5')
    all64Compile project(':ijkplayer-armv7a')
    //all64Compile project(':ijkplayer-arm64')
    //all64Compile project(':ijkplayer-x86')
    //all64Compile project(':ijkplayer-x86_64')
}

ndk庫的關(guān)聯(lián)

修改文件:ijkplayer/local.properties
修改內(nèi)容:ijkplayer由于需要依賴ndk進行編譯月杉,所以我們要指定本機的ndk目錄地址刃跛,并且確保這個ndk版本必須在r12到r14之間的版本,千萬不要用到sdk里面的那個ndk苛萎。

ndk.dir=<你的ndk路徑>

關(guān)閉編譯優(yōu)化方便調(diào)試

修改文件:ijkplayer/ijkplayer-armv7a/src/main/jni/Application.mk
修改內(nèi)容:c代碼在編譯的時候可能過度優(yōu)化導致調(diào)試的時候看不到變量的值桨昙,我們可以將-O3的優(yōu)化級別改為-O0

APP_CFLAGS := 
    #將O3的優(yōu)化級別降低為O0
    #-O3 -Wall -pipe \
     -O0 -Wall -pipe \
    -ffast-math \
    -fstrict-aliasing -Werror=strict-aliasing \
    -Wno-psabi -Wa,--noexecstack \
    -DANDROID -DNDEBUG

可能會遇到的錯誤

如果發(fā)現(xiàn)這個報錯

All flavors must now belong to a named flavor dimension. Learn more at https://d.android.com/r/tools/flavorDimensions-missing-error-message.html

ijkplayer/ijkplayer-example/build.gradle中添加

android {
  defaultConfig {
    #這個值需要與工程下的ijkplayer/build.gradle中的versionCode相同
    flavorDimensions "800800"
  }
}

如果發(fā)現(xiàn)這個報錯

AAPT2 error: check logs for details

ijkplayer/gradle.properties中添加

android.enableAapt2=false

結(jié)語

這篇文章簡單介紹了怎么在Android Studio中對ijkplayer工程進行源碼調(diào)試的必要修改步驟,這也是對于分析源碼或者二次開發(fā)都有非常有用的幫助腌歉。

本文發(fā)布于簡書

End!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末绊率,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子究履,更是在濱河造成了極大的恐慌,老刑警劉巖脸狸,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件最仑,死亡現(xiàn)場離奇詭異,居然都是意外死亡炊甲,警方通過查閱死者的電腦和手機泥彤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來卿啡,“玉大人吟吝,你說我怎么就攤上這事【蹦龋” “怎么了剑逃?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵浙宜,是天一觀的道長。 經(jīng)常有香客問我蛹磺,道長粟瞬,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任萤捆,我火速辦了婚禮裙品,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘俗或。我一直安慰自己市怎,他們只是感情好,可當我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布辛慰。 她就那樣靜靜地躺著区匠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪昆雀。 梳的紋絲不亂的頭發(fā)上辱志,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天,我揣著相機與錄音狞膘,去河邊找鬼揩懒。 笑死,一個胖子當著我的面吹牛挽封,可吹牛的內(nèi)容都是我干的已球。 我是一名探鬼主播,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼辅愿,長吁一口氣:“原來是場噩夢啊……” “哼智亮!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起点待,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤阔蛉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后癞埠,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體状原,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年苗踪,在試婚紗的時候發(fā)現(xiàn)自己被綠了颠区。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡通铲,死狀恐怖毕莱,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤朋截,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布蛹稍,位于F島的核電站,受9級特大地震影響质和,放射性物質(zhì)發(fā)生泄漏稳摄。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一饲宿、第九天 我趴在偏房一處隱蔽的房頂上張望厦酬。 院中可真熱鬧,春花似錦瘫想、人聲如沸仗阅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽减噪。三九已至,卻和暖如春车吹,著一層夾襖步出監(jiān)牢的瞬間筹裕,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工窄驹, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留朝卒,地道東北人。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓乐埠,卻偏偏與公主長得像抗斤,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子丈咐,可洞房花燭夜當晚...
    茶點故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內(nèi)容