最近在項目中要加入視頻直播和點播功能累奈,那么問題來了贬派,我需要一個播放器來播放視頻流急但,那該如何選擇呢?除了原生的VideoView(VideoView表示臣妾做不到案惴Α)波桩,還有一些播放器如Vitamio,B站開源的IjkPlayer等请敦,當然各大直播云服務(wù)商也提供了自己的播放器镐躲。花兩天時間調(diào)研了幾家侍筛,順便記錄下來分享給大家萤皂,看一看到底哪家強。
先說下在測試樣本選擇上我是如何考慮的:
- 開源播放器大V選一家匣椰,直播云廠商選一家裆熙。
ijk無可厚非是開源播放器中的首選,關(guān)于如何玩轉(zhuǎn)ijk的文章也很多禽笑,口碑也比較好入录。而云服務(wù)廠商好歹是靠賣直播、點播產(chǎn)品賺錢的蒲每,播放器作為直播點播服務(wù)中重要的一環(huán)也是人家吃飯的工具纷跛,而且可以說被很多直播大客戶驗證過的,最重要的這些播放器SDK竟然都是免費的邀杏,不拿來用太浪費了贫奠。 - 視頻云廠商播放器評測的選擇。
因為我司原生app本身體積比較大了望蜡,所以對我來說包體大小是第一要考慮的點唤崭。而所有在云廠商里,我選了包體最小的七牛作為測試樣本脖律。大家可以根據(jù)自己業(yè)務(wù)需求再選擇測試樣本谢肾。
當然,這里只是做了幾次數(shù)據(jù)采樣小泉,需要結(jié)果更具說服力芦疏,可能還需要更多的測試條件和測試數(shù)據(jù),不過我們可以從當前獲取到的數(shù)據(jù)推斷:
- 不管是軟解碼和硬解碼微姊,PLDroidPlayer的首開速度都要遠快于IjkPlayer酸茴;
- 在軟解碼條件下,PLDroidPlayer的Cpu和內(nèi)存消耗都要略低于IjkPlayer兢交;
- 在硬解碼條件下薪捍,PLDroidPlayer的Cpu和內(nèi)存消耗都要高于IjkPlayer。
數(shù)據(jù)統(tǒng)計
包體
注:
- IjkPlayer通過gradle下載下來為aar包,存放在目錄C:\Users\(用戶名)\.gradle\caches\modules-2\files-2.1\tv.danmaku.ijk.media酪穿。PLDroidPlayer為jar包凳干。
- IjkPlayer至少需要用到兩個包,分別是java包和armv7a包被济。
- IjkPlayer和PLDroid均可以支持Https救赐,IjkPlayer需要單獨編譯,PLDroid只需添加libqcOpenSSL.so庫即可溉潭。這里對比的是不帶Https功能的净响。
功能點
這里只是對主要功能點進行對比,更多PLDroidPlayer功能點介紹可以查看https://github.com/pili-engineering/PLDroidPlayer喳瓣,而ijkPlayer并沒有對其功能進行介紹:https://github.com/Bilibili/ijkplayer
基礎(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項目膘茎,運行之后桃纯,效果如下:
但是,我們暫時還是無法播放示例視頻列表當中的視頻披坏,還需要編譯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庫已經(jīng)生成,就可以使用Andorid Studio再次打開ijkplayer中的安卓示例項目(android/ijkplayer)茴恰,運行后就可以播放示例視頻了颠焦。這個帶有so庫的示例項目我已上傳到Github,地址為https://github.com/uncleleonfan/IjkplayerExample往枣,歡迎下載伐庭。
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碘耳,測試項目運行效果:
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
PLDroidPlayer結(jié)果
- 首開時間:198ms
- CPU占比最小值:3.11%
- CPU占比最大值:67.18%
- 平均CPU占比:30.25%
- 內(nèi)存使用最小值:32.34MB
- 內(nèi)存使用最大值:93.47MB
- 平均內(nèi)存:87.41MB
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
PLDroidPlayer結(jié)果
- 首開時間:174ms
- CPU占比最小值:2.00%
- CPU占比最大值:69.23%
- 平均CPU占比:28.00%
- 內(nèi)存使用最小值:30.98MB
- 內(nèi)存使用最大值:85.87MB
- 平均內(nèi)存:81.67MB