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 = 1;
Log.i(TAG,"pause:=" + 1);
h.postDelayed(closeTask, 10000);
}
繼續:
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 == 2){
Log.i(TAG,"resume:=" + 0);
openStream();
}
Log.i(TAG,"resume:=" + 0);
paused = 0;
}
可見暫停時,在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
獲取更多信息
EasyDarwin開源流媒體服務器:www.EasyDarwin.org
EasyDSS商用流媒體解決方案:www.EasyDSS.com
EasyNVR無插件直播方案:www.EasyNVR.com
Copyright © EasyDarwin Team 2012-2017
