EasyPlayer RTSP Android安卓播放器實現視頻源快速切換


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 RTSP播放器

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

獲取更多信息

郵件:support@easydarwin.org

EasyDarwin開源流媒體服務器:www.EasyDarwin.org

EasyDSS商用流媒體解決方案:www.EasyDSS.com

EasyNVR無插件直播方案:www.EasyNVR.com

Copyright © EasyDarwin Team 2012-2017


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM