Android視頻直播甩牺、點播播放器哪家強?

最近在項目中要加入視頻直播和點播功能累奈,那么問題來了贬派,我需要一個播放器來播放視頻流急但,那該如何選擇呢?除了原生的VideoView(VideoView表示臣妾做不到案惴Α)波桩,還有一些播放器如Vitamio,B站開源的IjkPlayer等请敦,當然各大直播云服務(wù)商也提供了自己的播放器镐躲。花兩天時間調(diào)研了幾家侍筛,順便記錄下來分享給大家萤皂,看一看到底哪家強。

先說下在測試樣本選擇上我是如何考慮的:

  1. 開源播放器大V選一家匣椰,直播云廠商選一家裆熙。
    ijk無可厚非是開源播放器中的首選,關(guān)于如何玩轉(zhuǎn)ijk的文章也很多禽笑,口碑也比較好入录。而云服務(wù)廠商好歹是靠賣直播、點播產(chǎn)品賺錢的蒲每,播放器作為直播點播服務(wù)中重要的一環(huán)也是人家吃飯的工具纷跛,而且可以說被很多直播大客戶驗證過的,最重要的這些播放器SDK竟然都是免費的邀杏,不拿來用太浪費了贫奠。
  2. 視頻云廠商播放器評測的選擇。
    因為我司原生app本身體積比較大了望蜡,所以對我來說包體大小是第一要考慮的點唤崭。而所有在云廠商里,我選了包體最小的七牛作為測試樣本脖律。大家可以根據(jù)自己業(yè)務(wù)需求再選擇測試樣本谢肾。

當然,這里只是做了幾次數(shù)據(jù)采樣小泉,需要結(jié)果更具說服力芦疏,可能還需要更多的測試條件和測試數(shù)據(jù),不過我們可以從當前獲取到的數(shù)據(jù)推斷:

  1. 不管是軟解碼和硬解碼微姊,PLDroidPlayer的首開速度都要遠快于IjkPlayer酸茴;
  2. 在軟解碼條件下,PLDroidPlayer的Cpu和內(nèi)存消耗都要略低于IjkPlayer兢交;
  3. 在硬解碼條件下薪捍,PLDroidPlayer的Cpu和內(nèi)存消耗都要高于IjkPlayer。

數(shù)據(jù)統(tǒng)計

table1.png

包體

table2.png

注:

  1. IjkPlayer通過gradle下載下來為aar包,存放在目錄C:\Users\(用戶名)\.gradle\caches\modules-2\files-2.1\tv.danmaku.ijk.media酪穿。PLDroidPlayer為jar包凳干。
  2. IjkPlayer至少需要用到兩個包,分別是java包和armv7a包被济。
  3. IjkPlayer和PLDroid均可以支持Https救赐,IjkPlayer需要單獨編譯,PLDroid只需添加libqcOpenSSL.so庫即可溉潭。這里對比的是不帶Https功能的净响。

功能點

這里只是對主要功能點進行對比,更多PLDroidPlayer功能點介紹可以查看https://github.com/pili-engineering/PLDroidPlayer喳瓣,而ijkPlayer并沒有對其功能進行介紹:https://github.com/Bilibili/ijkplayer

table3.png

基礎(chǔ)

在進行對比之前,我們需要對直播相關(guān)的基礎(chǔ)概念做一些簡單介紹赞别,如果對這一塊比較熟悉的同學(xué)可以跳過畏陕。

視頻直播

視頻直播就是視頻數(shù)據(jù)從采集端(攝像頭)通過網(wǎng)絡(luò)實時推送到播放端(手機,電腦仿滔,電視等)惠毁,我們最早接觸到的視頻直播可能就是電視直播了,但隨著智能手機發(fā)展崎页,移動直播興起鞠绰,它的視頻采集端是手機,播放端通常也是手機飒焦。

視頻點播

視頻點播就是一段已經(jīng)錄制好的視頻數(shù)據(jù)蜈膨,用戶可以點擊播放。由于是已經(jīng)錄制完成的視頻數(shù)據(jù)牺荠,所以還可以控制播放進度翁巍。

直播協(xié)議

直播協(xié)議常見的有三種:RTMP、Http-FLV和HLS休雌。

  • RTMP: 基于TCP協(xié)議灶壶,由Adobe設(shè)計,將音視頻數(shù)據(jù)切割成小的數(shù)據(jù)包在互聯(lián)網(wǎng)上傳輸杈曲,延時3s以內(nèi)驰凛,但拆包組包復(fù)雜,在海量并發(fā)情況下不穩(wěn)定担扑。由于不是基于Http協(xié)議恰响,存在被防火墻墻掉的可能性。
  • Http-FLV:基于Http協(xié)議魁亦,由Adobe設(shè)計渔隶,在大塊音視頻數(shù)據(jù)頭部添加標記信息,延時3s以內(nèi),海量并發(fā)穩(wěn)定间唉,手機瀏覽器支持不足绞灼。
  • HLS:基于Http協(xié)議,由Apple設(shè)計呈野,將視頻數(shù)據(jù)切分成片段(10s以內(nèi))低矮,由m3u8索引文件進行管理,高延時(10s到30s)被冒,手機瀏覽器支持較好军掂,可通過網(wǎng)頁轉(zhuǎn)發(fā)直播鏈接。

軟編碼和硬編碼

音視頻數(shù)據(jù)在互聯(lián)網(wǎng)上傳輸之前昨悼,由于存在冗余數(shù)據(jù)蝗锥,需要進行壓縮編碼,編碼存在兩種方式率触,一種是軟編碼一種是硬編碼终议。

  • 軟編碼:使用CPU進行編碼
  • 硬編碼:使用非CPU進行編碼,如GPU等

軟解碼和硬解碼

數(shù)據(jù)進行編碼之后傳輸?shù)讲シ哦舜谢龋鸵M行解碼穴张,那么解碼也有兩種方式,一種是軟解碼一種是硬解碼两曼。

  • 軟解碼:使用CPU進行解碼
  • 硬解碼:使用非CPU進行解碼

IjkPlayer

IjkPlayer是B站開源播放器皂甘,地址為:https://github.com/Bilibili/ijkplayer,基于音視頻編解碼庫FFmpeg悼凑,支持常用的直播協(xié)議偿枕。IjkPlayer只提供播放器引擎庫,不提供UI界面佛析,所以使用IjkPlayer時還需要對UI界面進行二次封裝益老,不過Github上有一些基于ijkplayer二次開發(fā)的播放器,他們對UI界面做了比較好的封裝寸莫。

通過git命令:

git clone https://github.com/Bilibili/ijkplayer.git

下載ijkplayer完整項目捺萌,然后使用Android Studio打開目錄:ijkplayer\android\ijkplayer,這個是Android的Demo項目膘茎,運行之后桃纯,效果如下:

demo1.jpg
demo2.jpg

但是,我們暫時還是無法播放示例視頻列表當中的視頻披坏,還需要編譯so庫态坦。在編譯so庫的過程中,躺坑躺到懷疑人生棒拂,跟大家分享一下伞梯,避免跟我一樣踩坑玫氢。

Windows下編譯IjkPlayer

首先大家最好不要在Windows環(huán)境下編譯,因為我使用的是Windows系統(tǒng)谜诫,所以沒有多想漾峡,下載代碼后安裝Cygwin,然后在Cygwin中安裝make喻旷,yasm生逸,裝完之后以為大功告成,開始在Cygwin的命令行中執(zhí)行編譯腳本且预,但執(zhí)行時報錯槽袄,因為sh腳本還需要轉(zhuǎn)換成unix版本,于是在Cygwin中又裝了個dos2unix锋谐,將ijkplayer中的所有的sh腳本全部轉(zhuǎn)換了一遍遍尺,然后再執(zhí)行腳本,在讀取一個配置文件configure又出了問題涮拗,還是文件格式問題狮鸭,所以可以預(yù)見即使解決了這個文件,后續(xù)可能還有一大堆的文件存在這樣的問題多搀,細思極恐,果斷棄坑灾部。

Ubuntu下編譯IjkPlayer

棄坑Windows后又在電腦的虛擬機上安裝了Ubuntu系統(tǒng)康铭,可是等在Ubuntu上面搭建完Android開發(fā)環(huán)境后,發(fā)現(xiàn)硬盤空間不足了赌髓,不要問我為什么空間不足从藤,反正就是不足了,我能怎么辦锁蠕,我只能選擇原諒自己咯夷野。后來想到我原來的一臺筆記本里面裝了Ubuntu 16.04,于是擦擦上面的灰荣倾,開機啟動悯搔。

搭建Android開發(fā)環(huán)境

1.安裝JDK

sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update
sudo apt-get install oracle-java8-installer
sudo apt-get install oracle-java8-set-default

//在命令行中使用java -version,java, javac命令不報命令找不到舌仍,就算安裝成功

2.安裝Android Studio

去官網(wǎng)或者國內(nèi)站點下載Linux版本的Android Studio妒貌,這里,我使用的是Android Studio3.0版本铸豁。下載完成后灌曙,將Android Studio解壓到/opt目錄,然后使用命令行執(zhí)行Andorid Studio中的bin/studio.sh啟動Android Studio节芥,進入向?qū)Ы缑嬖诖蹋驅(qū)Ы缑孀詈蟠_認去下載SDK。下載完成后SDK路徑為/home/xxx(用戶名)/Android/Sdk。

3.下載NDK

使用Android Studio下載完SDK后蚣驼,不用創(chuàng)建項目魄幕,直接打開SDK Manager,在里面去下載NDK隙姿,下載完成之后存放在sdk目錄下的ndk-bundle目錄梅垄,但這里下載的NDK版本是比較新的版本16,而ijkplayer編譯也是不支持的输玷,因為在ijkplayer\android\contrib\tools中有個sh腳本會檢查編譯環(huán)境队丝,其中有一段代碼會檢查NDK版本:

case "$IJK_NDK_REL" in
    10e*)
        ........
        echo "IJK_NDK_REL=$IJK_NDK_REL"
        case "$IJK_NDK_REL" in
            11*|12*|13*|14*)
                if test -d ${ANDROID_NDK}/toolchains/arm-linux-androideabi-4.9
                then
                    echo "NDKr$IJK_NDK_REL detected"
                else
                    echo "You need the NDKr10e or later"
                    exit 1
                fi
            ;;
            *)
                echo "You need the NDKr10e or later"
                exit 1
            ;;
        esac
    ;;
esac

可以看出來這里只支持10e,11欲鹏,12机久,13,14赔嚎,所以ndk版本低了不行膘盖,高了也不行,沒辦法尤误,我們得去重新去官網(wǎng)下載低一點的版本侠畔,如r14b。

4.配置SDK和NDK路徑

找到/home/(用戶名)/目錄损晤,使用快捷鍵Ctrl + H顯示隱藏文件软棺,找到.bashrc文件打開,配置自己的SDK和NDK路徑尤勋,例如:

export ANDROID_NDK=/home/leon/Android/andriod-ndk-r14b
export ANDROID_SDK=/home/leon/Android/Sdk
export PATH=$ANDROID_NDK:$ANDROID_SDK:$PATH

配置完成后喘落,重啟命令行,輸入ndk-build命令最冰,如果不報命令行找不到瘦棋,說明NDK環(huán)境變量配置成功。

編譯IjkPlayer

Android環(huán)境搭建好后暖哨,就可以參考官方文檔著手編譯ijkplayer了赌朋。

sudo apt-get update
sudo apt-get install git //安裝git
sudo apt-get install yasm //安裝yasm

sudo dpkg-reconfigure dash //在彈出提示框選擇“否”來使用bash

//下載ijkplayer到ijkplayer-android目錄
git clone https://github.com/Bilibili/ijkplayer.git ijkplayer-android
cd ijkplayer-android 

//使用默認配置
cd config
rm module.sh
ln -s module-lite.sh module.sh

cd ..
cd android/contrib
./compile-ffmpeg.sh clean //清理

cd ~/ijkplayer-android //返回源碼根目錄
./init-android.sh //主要是去下載ffmpeg

cd android/contrib
./compile-ffmpeg.sh clean
./compile-ffmpeg.sh all //編譯ffmpeg,all是全部編譯鹿蜀,需要等待一段時間

cd .. //回到ijkplayer-android/android
./compile-ijk.sh all //編譯ijkplayer

編譯完成后箕慧,在android/ijkplayer目錄下各個庫模塊當中找到生成的so庫:

so.png

既然so庫已經(jīng)生成,就可以使用Andorid Studio再次打開ijkplayer中的安卓示例項目(android/ijkplayer)茴恰,運行后就可以播放示例視頻了颠焦。這個帶有so庫的示例項目我已上傳到Github,地址為https://github.com/uncleleonfan/IjkplayerExample往枣,歡迎下載伐庭。

demo3.jpg

PLDroidPlayer

PLDroidPlayer 是七牛推出的一款適用于 Android 平臺的播放器 SDK粉渠,采用全自研的跨平臺播放內(nèi)核,擁有豐富的功能和優(yōu)異的性能圾另,可高度定制化和二次開發(fā)霸株。示例項目地址為:https://github.com/pili-engineering/PLDroidPlayer
PLDroidPlayer的集成要比ijkPlayer簡單很多集乔,不用自己編譯so庫去件,不用自己創(chuàng)建SurfaceView和TextureView來播放視頻∪怕罚可參考官方開發(fā)指南集成即可尤溜。

測試開發(fā)

為了保證測試的變量只是播放器引擎本身(這里暫時將播放器引擎簡單的理解為各個播放器的MediaPlayer),我們定義一個公共的UI界面即VideoView來播放視頻流汗唱,然后通過代理模式去代理不同的播放器引擎宫莱。這樣VideoView在播放視頻時,可以通過代理使用不同的播放引擎(MediaPlayer)來播放哩罪。我們這里主要測試播放器播放視頻首開的時間授霸,播放器播放視頻過程中Cpu,內(nèi)存的占用情況际插。測試項目地址為:https://github.com/uncleleonfan/PlayerCompare碘耳,測試項目運行效果:

test.gif

IMediaPlayer

定義統(tǒng)一的MediaPlayer接口。

public interface IMediaPlayer {

    void prepareAsync() throws IllegalStateException;

    void start() throws IllegalStateException;

    void stop() throws IllegalStateException;

    void pause() throws IllegalStateException;

    void release();

    void reset();

    .......
}

IMeidaPlayerProxy

定義MeidaPlayer的代理接口框弛,所有MediaPlayer的代理必須實現(xiàn)newInstance接口創(chuàng)建MediaPlayer藏畅。

interface IMediaPlayerProxy {
    IMediaPlayer newInstance();
}

IjkPlayer的MediaPlayer的代理

在使用IjkPlayer之前需要添加依賴,并且將編譯好的so庫添加到項目中的jniLibs下功咒。

//添加ijkplayer依賴
dependencies {
    compile 'tv.danmaku.ijk.media:ijkplayer-java:0.8.4'
    compile 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.8.4'
    compile 'tv.danmaku.ijk.media:ijkplayer-x86:0.8.4'

}

//IjkMediaPlayer代理,實現(xiàn)IMediaPlayer接口
public class IjkMediaPlayerProxy implements IMediaPlayerProxy, IMediaPlayer {

    //聲明一個IjkMediaPlayer對象
    private IjkMediaPlayer mIjkMediaPlayer;

    @Override
    public IMediaPlayer newInstance() {
        //創(chuàng)建IjkMeidaPlayer對象
        mIjkMediaPlayer = new IjkMediaPlayer();
        return this;
    }

    @Override
    public void prepareAsync() throws IllegalStateException {
        mIjkMediaPlayer.prepareAsync();
    }

    @Override
    public void start() throws IllegalStateException {
        mIjkMediaPlayer.start();
    }

    @Override
    public void stop() throws IllegalStateException {
        mIjkMediaPlayer.stop();
    }
    ......
}

PLDroidPlayer的MediaPlayer代理

在使用PLMediaPlayer之前參考官方文檔集成PLDroidPlayer

//PLMediaPlayer代理绞蹦,實現(xiàn)IMediaPlayer接口
public class PLMediaPlayerProxy implements IMediaPlayerProxy, IMediaPlayer {

    //定義PLMediaPlayer對象
    private PLMediaPlayer mMediaPlayer;
    //AVOptions為MediaPlayer的選項配置力奋,例如可以配置開啟硬解碼
    private AVOptions mAvOptions;


    @Override
    public IMediaPlayer newInstance() {
        //創(chuàng)建PLDroidPlayer的PLMediaPlayer對象
        mMediaPlayer = new PLMediaPlayer(mContext, mAvOptions);
        return this;
    }


    @Override
    public void prepareAsync() throws IllegalStateException {
        mMediaPlayer.prepareAsync();
    }

    @Override
    public void start() throws IllegalStateException {
        mMediaPlayer.start();
    }

    @Override
    public void stop() throws IllegalStateException {
        mMediaPlayer.stop();
    }

    ........
}

VideoView

VideoView仿照原生VideoView的實現(xiàn),這里主要修改的是MediaPlayer的邏輯幽七,方便配置使用不同播放器的MediaPlayer景殷。

public class VideoView extends SurfaceView implements IMediaPlayer.OnPreparedListener,
        IMediaPlayer.OnErrorListener,
        IMediaPlayer.OnCompletionListener,
        IMediaPlayer.OnInfoListener,
        IMediaPlayer.OnVideoSizeChangeListener{

    //定義MediaPlayer代理
    private IMediaPlayerProxy mMediaPlayerProxy;

    //定義VideoView使用的MediaPlayer
    private IMediaPlayer mMediaPlayer;


    //設(shè)置MediaPlayer的代理
    public void setMediaPlayerProxy(IMediaPlayerProxy mediaPlayerProxy) {
        mMediaPlayerProxy = mediaPlayerProxy;
    }
  
    //打開視頻
    private void openVideo() {
        if (mVideoPath == null) {
            return;
        }
        release();
        //使用代理創(chuàng)建對應(yīng)的MediaPlayer對象
        mMediaPlayer = mMediaPlayerProxy.newInstance();
        mMediaPlayer.setScreenOnWhilePlaying(true);
        mMediaPlayer.setDisplay(mSurfaceHolder);
        mMediaPlayer.setLogEnabled(BuildConfig.DEBUG);
        mMediaPlayer.setOnPreparedListener(this);
        mMediaPlayer.setOnInfoListener(this);
        mMediaPlayer.setOnCompletionListener(this);
        mMediaPlayer.setOnErrorListener(this);
        mMediaPlayer.setOnVideoSizeChangeListener(this);
        try {
            mMediaPlayer.setDataSource(mVideoPath);
            ......
            mMediaPlayer.prepareAsync();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onPrepared(IMediaPlayer iMediaPlayer) {
        iMediaPlayer.start();//開始播放
    }
}

LogUtils

LogUtils用于采樣cpu和內(nèi)存數(shù)據(jù),里面使用ScheduledThreadPoolExecutor每隔1s采樣一次數(shù)據(jù)澡屡。

//開始采樣
public void start() {
    scheduler.scheduleWithFixedDelay(new SampleTask(), 0L, 1000L, TimeUnit.MILLISECONDS);
}
//停止采樣
public void stop() {
    scheduler.shutdown();
}

//采樣任務(wù)
private class SampleTask implements Runnable {

    @Override
    public void run() {
        float cpu = sampleCPU(); //采樣CPU使用
        float mem = sampleMemory(); //采樣內(nèi)存使用
    }
}

LogView

LogView是打印Log的自定義控件猿挚,它由一個TextView和ScrollView組成,TextView在ScrollView內(nèi)部驶鹉,用來顯示log绩蜻,ScrollView用來滾動。

public class LogView extends RelativeLayout {

    public LogView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        LayoutInflater.from(context).inflate(R.layout.view_log, this);

        final TextView textView = findViewById(R.id.tv);
        final ScrollView scrollView = findViewById(R.id.scroll_view);
        final StringBuilder stringBuilder = new StringBuilder();
        
        //監(jiān)聽LogUtils的log
        LogUtils.getInstance().setOnUpdateLogListener(new LogUtils.OnUpdateLogListener() {
            @Override
            public void onUpdate(final long timestamp, final String msg) {
                //在主線程刷新界面
                post(new Runnable() {
                    @Override
                    public void run() {
                        String dateString = mSimpleDateFormat.format(new Date(timestamp));
                        String log = dateString + ": " + msg + "\n";
                        //添加一行l(wèi)og
                        stringBuilder.append(log);
                        //設(shè)置log顯示
                        textView.setText(stringBuilder.toString());
                        //滾動ScrollView到底部
                        scrollView.fullScroll(View.FOCUS_DOWN);
                    }
                });

            }
        });
    }

}

測試

測試視頻流是:

//點播MP4視頻
String path = "http://hc.yinyuetai.com/uploads/videos/common/2B40015FD4683805AAD2D7D35A80F606.mp4?sc=364e86c8a7f42de3&br=783&rd=Android";
//HLS直播流
String path = "http://ivi.bupt.edu.cn/hls/cctv1hd.m3u8";

在VieoView中室埋,MediaPlayer開始準備播放之前办绝,初始化LogUtils伊约,埋點記錄MediaPlayer的準備時間。

try {
    //設(shè)置視頻源
    mMediaPlayer.setDataSource(mVideoPath);
    //初始化LogUtils
    LogUtils.getInstance().init(getContext());
    //記錄開始準備時間
    LogUtils.getInstance().onStartPrepare();
    mMediaPlayer.prepareAsync();
} catch (IOException e) {
    e.printStackTrace();
}

當MediaPlayer準備好后孕蝉,會回調(diào)onPrepared屡律,再次記錄準備結(jié)束時間,這樣降淮,準備結(jié)束時間減去準備開始時間就是MediaPlayer準備耗時超埋,即我們的首開時間。

//準備好后的回調(diào)
@Override
public void onPrepared(IMediaPlayer iMediaPlayer) {
    //記錄準備結(jié)束時間
    LogUtils.getInstance().onEndPrepare();
    //開始播放
    iMediaPlayer.start();
    //開始每隔1s采樣佳鳖,播放結(jié)束后停止采樣霍殴,主要用于點播采樣
    LogUtils.getInstance().start();
    
    //開始每隔1s采樣,采樣5min,5min之后腋颠,自行停止繁成,主要用于直播采樣
    //LogUtils.getInstance().startForDuration(5);
}

//播放結(jié)束
@Override
public void onCompletion(IMediaPlayer iMediaPlayer) {
    //播放結(jié)束,停止采樣
    LogUtils.getInstance().stop();
}

測試IjkPlayer

創(chuàng)建一個IjkPlayerActivity使用IjkMediaPlayer來播放視頻淑玫。

public class IjkPlayerActivity extends AppCompatActivity{

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_ijkplayer);

 
        //初始化IjkPlayer
        IjkMediaPlayer.loadLibrariesOnce(null);
        IjkMediaPlayer.native_profileBegin("libijkplayer.so");

        VideoView videoView = findViewById(R.id.video_view);
        //設(shè)置IjkMediaPlayer代理
        videoView.setMediaPlayerProxy(new IjkMediaPlayerProxy());
        String path = "視頻url"
        //設(shè)置視頻url
        videoView.setVideoPath(path);
    }


    @Override
    protected void onStop() {
        super.onStop();
        //通知IjkMediaPlayer結(jié)束
        IjkMediaPlayer.native_profileEnd();
    }

}

另外巾腕,在VideoView初始化MediaPlayer時,可以調(diào)用enableMediaCodec()來開啟IjkPlayer的硬解碼:

private void openVideo() {
        .......
        mMediaPlayer.enableMediaCodec();
 }

測試PLDroidPlayer

創(chuàng)建一個PLDroidPlayerActivity使用PLMediaPlayer來播放視頻。

public class PLDroidPlayerActivity extends AppCompatActivity{

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pldroid);

        VideoView mVideoView = findViewById(R.id.video_view);

        //配置AVoptions來開啟硬編碼爵赵,默認為軟編碼
        AVOptions avOptions = new AVOptions();
        avOptions.setInteger(AVOptions.KEY_MEDIACODEC, AVOptions.MEDIA_CODEC_HW_DECODE);

        mVideoView.setMediaPlayerProxy(new PLMediaPlayerProxy(this, avOptions));
        String path = "視頻url";
        mVideoView.setVideoPath(path);
    }

}

測試結(jié)果

Round 1

  • 機型:Moto G (2代)
  • 系統(tǒng)版本:5.1
  • 數(shù)據(jù)源:String path = "http://ivi.bupt.edu.cn/hls/cctv1hd.m3u8";
  • 軟硬編碼:軟解碼
  • 采樣時長:5min
  • IjkPlayer版本:0.8.4
  • PLDroid版本:2.0.3

IjkPlayer結(jié)果

  • 首開時間:1559ms
  • CPU占比最小值:5.00%
  • CPU占比最大值:80.72%
  • 平均CPU占比:30.69%
  • 內(nèi)存使用最小值:63.49MB
  • 內(nèi)存使用最大值:114.92MB
  • 平均內(nèi)存:110.19MB
ijk_soft.jpg

PLDroidPlayer結(jié)果

  • 首開時間:198ms
  • CPU占比最小值:3.11%
  • CPU占比最大值:67.18%
  • 平均CPU占比:30.25%
  • 內(nèi)存使用最小值:32.34MB
  • 內(nèi)存使用最大值:93.47MB
  • 平均內(nèi)存:87.41MB
pl_soft.jpg

Round 2

  • 機型:Moto G (2代)
  • 系統(tǒng)版本:5.1
  • 數(shù)據(jù)源:String path = "http://ivi.bupt.edu.cn/hls/cctv1hd.m3u8";
  • 軟硬編碼:硬解碼
  • 采樣時長:5min
  • IjkPlayer版本:0.8.4
  • PLDroid版本:2.0.3

IjkPlayer結(jié)果

  • 首開時間:2280ms
  • CPU占比最小值:1.36%
  • CPU占比最大值:17.37%
  • 平均CPU占比:10.10%
  • 內(nèi)存使用最小值:45.37MB
  • 內(nèi)存使用最大值:52.34MB
  • 平均內(nèi)存:48.81MB
ijk_hard.jpg

PLDroidPlayer結(jié)果

  • 首開時間:174ms
  • CPU占比最小值:2.00%
  • CPU占比最大值:69.23%
  • 平均CPU占比:28.00%
  • 內(nèi)存使用最小值:30.98MB
  • 內(nèi)存使用最大值:85.87MB
  • 平均內(nèi)存:81.67MB
pl_hard.jpg
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末椒丧,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子佛寿,更是在濱河造成了極大的恐慌,老刑警劉巖但壮,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件冀泻,死亡現(xiàn)場離奇詭異,居然都是意外死亡蜡饵,警方通過查閱死者的電腦和手機弹渔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來溯祸,“玉大人肢专,你說我怎么就攤上這事〗垢ǎ” “怎么了博杖?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長筷登。 經(jīng)常有香客問我剃根,道長,這世上最難降的妖魔是什么前方? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任跟继,我火速辦了婚禮种冬,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘舔糖。我一直安慰自己娱两,他們只是感情好,可當我...
    茶點故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布金吗。 她就那樣靜靜地躺著十兢,像睡著了一般。 火紅的嫁衣襯著肌膚如雪摇庙。 梳的紋絲不亂的頭發(fā)上旱物,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天,我揣著相機與錄音卫袒,去河邊找鬼宵呛。 笑死,一個胖子當著我的面吹牛夕凝,可吹牛的內(nèi)容都是我干的宝穗。 我是一名探鬼主播,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼码秉,長吁一口氣:“原來是場噩夢啊……” “哼逮矛!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起转砖,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤须鼎,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后府蔗,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體晋控,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年姓赤,在試婚紗的時候發(fā)現(xiàn)自己被綠了糖荒。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡模捂,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蜘矢,到底是詐尸還是另有隱情狂男,我是刑警寧澤,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布品腹,位于F島的核電站岖食,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏舞吭。R本人自食惡果不足惜泡垃,卻給世界環(huán)境...
    茶點故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一析珊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蔑穴,春花似錦忠寻、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至捐腿,卻和暖如春纵朋,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背茄袖。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工操软, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人宪祥。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓聂薪,卻偏偏與公主長得像,于是被迫代替她去往敵國和親品山。 傳聞我的和親對象是個殘疾皇子胆建,可洞房花燭夜當晚...
    茶點故事閱讀 45,092評論 2 355

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,190評論 25 707
  • 前言 隨著音視頻領(lǐng)域的火熱,在很多領(lǐng)域(教育肘交,游戲笆载,娛樂,體育涯呻,跑步凉驻,餐飲,音樂等)嘗試做音視頻直播/點播功能复罐,那...
    passiontim閱讀 3,290評論 1 46
  • 前言 隨著音視頻領(lǐng)域的火熱涝登,在很多領(lǐng)域(教育,游戲效诅,娛樂胀滚,體育,跑步乱投,餐飲咽笼,音樂等)嘗試做音視頻直播/點播功能,那...
    yabin小站閱讀 45,876評論 45 518
  • 文/SweetAnna 每個人都約定過戚炫。 當約定的事一方在你不知情的情況下發(fā)生變故的時候剑刑,...
    SweetAnna閱讀 140評論 0 0
  • Zhejiang royal Tibetan cabinet private museum products re...
    御藏閣閱讀 1,075評論 0 0