EasyCameraPro在直播过程中不发送START_STREAM_ACK响应的bug解决

15 篇文章 3 订阅
5 篇文章 0 订阅

EasyCameraPro在直播过程中不发送START_STREAM_ACK响应的bug解决

EasyCameraPro是一款按需直播的RTMP协议流媒体推送APP.EasyCameraPro在启动后,登录到EasyDSS服务器,在收到视频播放请求后,启动推送,并由服务器转发给播放端进行播放.当播放端停止播放时,服务器会给EasyCameraPro发送停止视频的命令,这时候,EasyCameraPro会停止推送.

主要有如下几种场景:

  • 首次请求推送的过程:
Created with Raphaël 2.1.0 播放器 播放器 服务器 服务器 EasyCameraPro EasyCameraPro 1 请求播放 2 请开始推送 3 推送 4 转发
  • 已经开始推送,第二个播放器再请求时:
Created with Raphaël 2.1.0 EasyCameraPro EasyCameraPro 服务器 服务器 播放器 播放器 推送中 1 请求播放 2 转发
  • 最后一个播放器断开的情况

    Created with Raphaël 2.1.0 播放器 播放器 服务器 服务器 EasyCameraPro EasyCameraPro 1 断开 没有客户端链接了 2 请断开推送 3 推送断开

在我们测试的过程中发现,有时候服务器向EasyCameraPro请求推送时,EasyCameraPro会出现不应答的情况.这会导致播放端一直在等待中.而有时候却又是正常的!

看看代码是怎么回事?

@Subscribe
public void onPushOK(final PushOK ok) {

  AsyncTask.execute(new Runnable() {
    @Override
    public void run() {
      JSONObject body = ok.startStreamingReqBody;
      Object channel = body.opt("Channel");
      ...
        respStr = buildOutStreamContent(respStr);
      String info = String.format("Send MSG_SD_PUSH_STREAM_ACK RTMP [%s:%d]", body.optString("Server_IP"), body.optInt("Server_PORT"));
      final String finalRespStr = respStr;

      try {
        synchronized (mOS) {
          mOS.write(finalRespStr);
          mOS.flush();
        }
      } catch (Exception ex) {
        ex.fillInStackTrace();
      }
    }
  });

}

通过Bus收到PushOK请求后,会向服务器发送MSG_SD_PUSH_STREAM_ACK响应,由于Bus事件是在主线程接收到,所以这里我们需使用AsyncTask进行异步发送.

有经验的程序员马上就可以看出问题所在,即AsyncTask.execute方法,会将Runnable默认执行在内置的SerialExecutor中:

    private static class SerialExecutor implements Executor {
        final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
        Runnable mActive;

        public synchronized void execute(final Runnable r) {
            mTasks.offer(new Runnable() {
                public void run() {
                    try {
                        r.run();
                    } finally {
                        scheduleNext();
                    }
                }
            });
            if (mActive == null) {
                scheduleNext();
            }
        }

        protected synchronized void scheduleNext() {
            if ((mActive = mTasks.poll()) != null) {
                THREAD_POOL_EXECUTOR.execute(mActive);
            }
        }
    }

这个Executor,是按照顺序执行的.即所有的Runnable会排序依次执行,每次只能执行一个.

所以,MSG_SD_PUSH_STREAM_ACK没有发送出去的原因肯定是Executor中已有任务在排队了,我们这个任务没能及时执行所导致.

于是我们将AsyncTask.execute改成AsyncTask.THREAD_POOL_EXECUTOR.execute,使得我们的任务执行在线程池中,再试下,问题就解决了.

于EasyRTMP推流SDK

EasyRTMP是一套调用简单、功能完善、运行高效稳定的RTMP功能组件,经过多年实战和线上运行打造,支持RTMP推送断线重连、环形缓冲、智能丢帧、网络事件回调,支持Windows、Linux、arm(hisiv100/hisiv200/hisiv300/hisiv400/etc..)、Android、iOS平台,支持市面上绝大部分的RTMP流媒体服务器,包括Red5、Ngnix_rtmp、crtmpserver等主流RTMP服务器,能够完美应用于各种行业的直播需求,手机直播、桌面直播、摄像机直播、课堂直播等等方面!

点击链接加入群【EasyRTMP-RTMP直播推送】:587254841

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值