天天看點

EasyPlayer視訊源切換

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視訊源切換

關于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

繼續閱讀