EasyPlayer現在支援多視訊源快速切換了,我們介紹一下是如何實作的.
這個需求通常應用在一個用戶端需要檢視多個視訊源的情況,比如多個監控場景輪播.
由于EasyPlayer的播放端已經放在Fragment了,這使得SDK層可以對好多應用層的代碼做以封裝,這樣盡可能給開發者帶來友善.比如,兩個視訊源切換的時候,隻需要建立兩個PlayFragment,然後對這兩個Fragment進行顯示切換,如代碼所示:
public void onSwitchPlayer(View view) {
PlayFragment f = (PlayFragment) getSupportFragmentManager().findFragmentByTag("first");
PlayFragment s = (PlayFragment) getSupportFragmentManager().findFragmentByTag("second");
if (!s.isHidden()){
getSupportFragmentManager().beginTransaction().show(f).commit();
getSupportFragmentManager().beginTransaction().hide(s).commit();
mRenderFragment = f;
}else{
getSupportFragmentManager().beginTransaction().show(s).commit();
getSupportFragmentManager().beginTransaction().hide(f).commit();
mRenderFragment = s;
}
}
是不是很簡單?隻需要對兩個Fragment的顯示狀态進行toggle,就可以實作播放的toggle.
有的同學可能想問,這樣實際上隻是切換了目前顯示的View,實際上視訊還是會在背景播放吧?的确是這樣的,為了最快地進行視訊切換,不至于在切換過程中導緻視訊延遲\黑屏\卡頓,我們保留了背景一個視訊沒有釋放.
這樣可能有些同學覺得不好,我們也覺得不好.是以别急,接着往下看,看看PlayFragment内部又在這個過程中發生了什麼:
@Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if (hidden){
// stop
// stopRending();
if (mStreamRender != null) {
mStreamRender.pause();
}
}else{
if (mStreamRender != null) {
mStreamRender.resume();
}
}
}
可以看到,在一個Fragment被hidden時,播放狀态實際上會暫停.而當他又顯示時,播放會繼續.
又有同學可能由疑問,EasyPlayer播放RTSP時,基本上是直播需求,那直播的情況下,暫停\繼續又應該如何實作呢?我們是這樣做的:
暫停:
public void pause(){
mQueue.clear();
if (mClient != null) {
mClient.pause();
}
mQueue.clear();
}
繼續:
public void resume(){
if (mClient != null) {
mClient.resume();
}
}
暫停時,首先将緩沖隊列情調,然後調用Client的暫停;繼續時,調用Client的繼續.那Client内部又是如何實作的?
暫停:
public void pause() {
if (Looper.myLooper() != Looper.getMainLooper()){
throw new IllegalThreadStateException("please call pause in Main thread!");
}
synchronized (_channelPause) {
_channelPause.add(_channel);
}
paused = ;
Log.i(TAG,"pause:=" + );
h.postDelayed(closeTask, );
}
繼續:
public void resume() {
if (Looper.myLooper() != Looper.getMainLooper()){
throw new IllegalThreadStateException("call resume in Main thread!");
}
synchronized (_channelPause) {
_channelPause.remove(_channel);
}
h.removeCallbacks(closeTask);
if (paused == ){
Log.i(TAG,"resume:=" + );
openStream();
}
Log.i(TAG,"resume:=" + );
paused = ;
}
可見暫停時,在EasyRTSPClient内部,我們設定了一個暫停标志位,當這個标志位為ture時,我們收到的媒體資料并不回調給上層,而是直接丢棄.這樣是不是白白浪費了流量?别急,我們post了一個task,這個task在10秒之後,會關閉流的傳輸.
而繼續播放時,我們會将标志位設定為false,同時将task取消掉,這樣,如果在10秒内快速進行暫停和恢複,實際上流并沒有斷開,這樣切換時,使用者體驗是最好的.而當長時間沒有恢複的時候,也會在暫停10秒後把連結關閉,不至于消耗額外的流量.
綜上,實作了快速的切換.請看效果:

關于EasyPlayer流媒體播放器
An elegant, simple, fast android RTSP/RTMP/HLS/HTTP Player.EasyPlayer support RTSP(RTP over TCP/UDP)version & Pro version,cover all kinds of streaming media!EasyPlayer是一款精煉、高效、穩定的流媒體播放器,分為RTSP版、RTMP版和Pro版三個版本,支援各種各樣的流媒體音視訊協定和檔案的播放,在安防、網際網路、教育、錄播、IPTV等多個領域大放異彩,廣泛應用!
EasyPlayer:https://github.com/EasyDSS/EasyPlayer
點選連結加入群【EasyPlayer】:544917793
擷取更多資訊
郵件:[email protected]
EasyDarwin開源流媒體伺服器:www.EasyDarwin.org
EasyDSS商用流媒體解決方案:www.EasyDSS.com
EasyNVR無插件直播方案:www.EasyNVR.com
Copyright © EasyDarwin Team 2012-2017