zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    218. The Skyline Problem
    327. 区间和的个数
    37 Sudoku Solver
    36. Valid Sudoku
    差分数组(1109. 航班预订统计)
    android开发里跳过的坑——onActivityResult在启动另一个activity的时候马上回调
    重启系统media服务
    android源码mm时的编译错误no ruler to make target `out/target/common/obj/JAVA_LIBRARIES/xxxx/javalib.jar', needed by `out/target/common/obj/APPS/xxxx_intermediates/classes-full-debug.jar'. Stop.
    关于android系统启动不同activity默认过渡动画不同的一些认识
    android开发里跳过的坑——android studio 错误Error:Execution failed for task ':processDebugManifest'. > Manifest merger failed with multiple errors, see logs
  • 原文地址:https://www.cnblogs.com/babosa/p/8206954.html
Copyright © 2011-2022 走看看