Android集成IjkPlayer


0x0000 背景

  • 項(xiàng)目需要引入直播功能,而Android原生的VideoView本身是不支持RTMP格式的流媒體播放的。
  • 市面上的開(kāi)源播放器還是挺好選擇的,相比較于IjkPlayer,其他例如Vitamio、VLC的SDK無(wú)論使用便利性還是社區(qū)的支持都差得遠(yuǎn),自己用ffmpeg寫(xiě)成本難以接受。
  • 但是!IjkPlayer在Github上的README文檔真心坑,完全按那個(gè)文檔做連編譯都過(guò)不了。。
  • 阿里巴巴20年春招啟動(dòng)!歡迎有想法的同學(xué)勾搭!詳見(jiàn)文末二維碼,Android/Java/前端都要!

0x0001 致謝


0x0002 源碼鏈接

Github:Bilibili/ijkplayer


0x0003 編譯

  • 安裝homebrew、git、yasm
    非核心內(nèi)容,請(qǐng)自行百度或谷歌
  • 配置Android SDK、NDK環(huán)境變量,在.bash_profile增加如下兩行
export ANDROID_SDK=/your/sdk/path
export ANDROID_NDK=/your/ndk/path
  • 下載源碼
git clone https://github.com/Bilibili/ijkplayer.git ijkplayer-android
cd ijkplayer-android
git checkout -B latest k0.7.8.1
  • 初始化
./init-android.sh
  • 編譯ffmpeg
cd android/contrib
./compile-ffmpeg.sh clean
./compile-ffmpeg.sh all
  • 編譯IjkPlayer
cd ..
./compile-ijk.sh all

到此為止,完成了對(duì)源碼的編譯,ijkplayer-android的目錄結(jié)構(gòu)如圖


工程結(jié)構(gòu)

0x0004 配置

  • 拷貝gradle文件
    復(fù)制/android/ijkplayer/tools文件夾到工程根目錄
  • 在工程根目錄下的build.gradle文件中增加配置
ext {
    compileSdkVersion = 25
    buildToolsVersion = "25.0.2"
    targetSdkVersion = 25
    versionCode = 700801
    versionName = "0.7.8.1"
}

前三條和你的app module的build.gradle保持一致
后兩條和IjkPlayer源碼工程中的build.gradle保持一致

  • 依賴(lài)關(guān)系
    回到剛才我們編譯成功的源碼目錄,如果將/android/ijkplayer作為一個(gè)新項(xiàng)目導(dǎo)入Android Studio,運(yùn)行ijkplayer-example,是可以作為一個(gè)獨(dú)立app run起來(lái)的
    我們先把example加入工程:
    File-New-Import Module-/android/ijkplayer/ijkplayer-example
    當(dāng)然我們希望能把IjkPlayer當(dāng)做一個(gè)第三方庫(kù)引入,而不是在example工程的基礎(chǔ)上實(shí)現(xiàn)我們的需求,那么就需要搞清楚各個(gè)module的依賴(lài)關(guān)系:


    各module依賴(lài)關(guān)系

    說(shuō)的直白一點(diǎn),arm64等5個(gè)module一看命名大家就明白是基于不同CPU編譯產(chǎn)出的so
    為了簡(jiǎn)化依賴(lài),我們把這幾個(gè)module的so文件拷貝到example module下,同時(shí)刪除這幾個(gè)module,完成后的example目錄結(jié)構(gòu)如圖


    example目錄結(jié)構(gòu)
  • 改造example module
    現(xiàn)在的example module是作為application存在的,如果要作為library引入,要處理以下三點(diǎn)


    調(diào)整example build.gradle

    example增加gradle.properties
  • 加入依賴(lài)庫(kù)
    File-Project Structure-app-Dependencies-添加ijkplayer-example


    依賴(lài)example module

0x0005 開(kāi)發(fā)

IjkVideoView本身繼承自FrameLayout,可以和普通的View一樣在layout的xml文件中直接加入
對(duì)大多數(shù)人來(lái)說(shuō),平時(shí)怎么使用VideoView,現(xiàn)在就怎么使用IjkVideoView即可


0x0006 問(wèn)題

  • 如何讓播放器填滿IjkVideoView展示
    改造SurfaceRenderView的onMeasure方法
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    if (this.getWidth() != 0) {
        setMeasuredDimension(this.getWidth(), this.getHeight());
        return;
    }
    int width = getDefaultSize(0, widthMeasureSpec);
    int height = getDefaultSize(0, heightMeasureSpec);
    setMeasuredDimension(width, height);
}
  • 啟動(dòng)之后crash
java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.

在AndroidManifest.xml中設(shè)置Activity的theme屬性

<activity
    android:name=".MainActivity"
    android:theme="@style/Theme.AppCompat.NoActionBar">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
  • 視頻流截圖(適用于api14+)
    IjkVideoView改造setRender
public void setRender(int render) {
    switch (render) {
        case RENDER_NONE:
            setRenderView(null);
            break;
        case RENDER_SURFACE_VIEW:
        case RENDER_TEXTURE_VIEW: {
            TextureRenderView renderView = new TextureRenderView(getContext());
            if (mMediaPlayer != null) {
                renderView.getSurfaceHolder().bindToMediaPlayer(mMediaPlayer);
                renderView.setVideoSize(mMediaPlayer.getVideoWidth(), mMediaPlayer.getVideoHeight());
                renderView.setVideoSampleAspectRatio(mMediaPlayer.getVideoSarNum(), mMediaPlayer.getVideoSarDen());
                renderView.setAspectRatio(mCurrentAspectRatio);
            }
            setRenderView(renderView);
            break;
        }
        default:
            Log.e(TAG, String.format(Locale.getDefault(), "invalid render %d\n", render));
            break;
    }
}

增加一個(gè)public方法

@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
public Bitmap getShortcut() {
    if (mRenderView instanceof TextureRenderView) {
        return ((TextureRenderView) mRenderView).getBitmap();
    }
    return null;
}

0x0007 后記

Android播放器的坑太多,慢慢踩,與君共勉
阿里巴巴20年春招,請(qǐng)用支付寶掃碼投遞簡(jiǎn)歷


阿里校招.jpeg
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,716評(píng)論 25 709
  • afinalAfinal是一個(gè)android的ioc,orm框架 https://github.com/yangf...
    passiontim閱讀 15,835評(píng)論 2 45
  • 每天給自己一個(gè)時(shí)間空間了解自己 昨天我們說(shuō)“當(dāng)你擺對(duì)位置你的世界就對(duì)了”。我們來(lái)看企業(yè)的“企”字,企業(yè)止于人。一個(gè)...
    家銘老師閱讀 286評(píng)論 0 0
  • 五一的假期,有多少人奔走在回家的路上?車(chē)站交錯(cuò)的人群中有你嗎?我是其中一人。 有人說(shuō)你想了解真正的自己?jiǎn)??那就去?..
    浮語(yǔ)泛花閱讀 534評(píng)論 4 2
  • 今天是2017年7月1日,我在這個(gè)房子里住了一個(gè)星期。 迄今為止,這個(gè)家里來(lái)過(guò)兩個(gè)訪客,一個(gè)是政穎,一個(gè)是絲基。 ...
    玖_編號(hào)7913閱讀 281評(píng)論 0 0

友情鏈接更多精彩內(nèi)容