--本文转自EasyDarwin开源团队成员邵帅的博客:http://blog.csdn.net/ss00_2012/article/details/51441753

我们使用EasyDarwin的推流转发来进行媒体直播的时候,有时会有这样一个需求,当推流端推送的媒体没有客户端观看时,就希望推流端不再推送,也就是实现按需推送,当推流端使用4G网络时这个需求会更加强烈。

需求明确,那么说下实现。实现分为两步:触发和通知。

触发,EasyDarwin为每一路推流转发维护一个ReflectorSession对象,该对象的fNumOutputs属性用来指示当前拉流客户端的数量。当客户端停止拉流时会调用QTSSReflectorModule::DestroySession()->QTSSReflectorModule::RemoveOutput()->ReflectorSession::RemoveOutput(),其中ReflectorSession::RemoveOutput()代码如下:

[cpp] view
plain
 copy

  1. void    ReflectorSession::RemoveOutput(ReflectorOutput* inOutput, Bool16 isClient)
  2. {
  3. (void)atomic_sub(&fNumOutputs, 1);
  4. for (UInt32 y = 0; y < fSourceInfo->GetNumStreams(); y++)
  5. {
  6. fStreamArray[y]->RemoveOutput(inOutput);
  7. if (isClient)
  8. fStreamArray[y]->DecEyeCount();
  9. }
  10. }

其中(void)atomic_sub(&fNumOutputs, 1);用来减少当前的客户端数量,我们可以在此判断fNumOutputs是否为0,为0就表示满足我们的触发条件,修改后的代码如下:

[cpp] view
plain
 copy

  1. void    ReflectorSession::RemoveOutput(ReflectorOutput* inOutput, Bool16 isClient)
  2. {
  3. (void)atomic_sub(&fNumOutputs, 1);
  4. for (UInt32 y = 0; y < fSourceInfo->GetNumStreams(); y++)
  5. {
  6. fStreamArray[y]->RemoveOutput(inOutput);
  7. if (isClient)
  8. fStreamArray[y]->DecEyeCount();
  9. }
  10. //移除客户端之后判断fNumOutputs是否为0,add
  11. if(fNumOutputs == 0)
  12. {
  13. //调用角色,停止推流
  14. qtss_printf("客户端都不看啦\n");
  15. QTSS_RoleParams theParams;
  16. theParams.easyStreamStopParams.inSerial = fSerial;
  17. theParams.easyStreamStopParams.inChannel= fChannel;
  18. QTSSModule* theModule = QTSServerInterface::GetModule(QTSSModule::kStreamStopRole, 0);
  19. (void)theModule->CallDispatch(Easy_StreamStop_Role, &theParams);
  20. }
  21. //
  22. }

触发之后我们就调用Easy_StreamStop_Role角色来通知完成停止推流。

上述触发并不完美,对于推流之后并没有客户端拉流这种情况无法处理。因此我们又增加了循环检测的机制,通过将ReflectorSession继承Task,然后在其Run函数里循环检测fNumOutputs是否为0可以有效的解决这种情况,ReflectorSession::Run()代码如下:

[cpp] view
plain
 copy

  1. SInt64 ReflectorSession::Run()
  2. {
  3. if(fIfFirstRun)
  4. fIfFirstRun = false;//第一次的时候还没有拉流,就不要进行处理了;客户端拉流不要过慢。
  5. else
  6. {
  7. if(fNumOutputs == 0)
  8. {
  9. //调用角色,停止推流
  10. qtss_printf("没有客户端观看当前转发媒体\n");
  11. QTSS_RoleParams theParams;
  12. theParams.easyStreamStopParams.inSerial = fSerial;
  13. theParams.easyStreamStopParams.inChannel= fChannel;
  14. QTSSModule* theModule = QTSServerInterface::GetModule(QTSSModule::kStreamStopRole, 0);
  15. (void)theModule->CallDispatch(Easy_StreamStop_Role, &theParams);
  16. }
  17. }
  18. return 15*1000;
  19. }

另外不要忘了在ReflectorSession的构造函数中调用this->Signal(Task::kStartEvent);来开始循环检测。

通知,OK,到此触发就搞定了,下面我们就需要把停止推流这个信息告诉推流端就OK了,由谁告诉?对于推流端的管理是由EasyCMS来进行的,因此我们需要先将停止推流信息告诉EasyCMS,然后让EasyCMS告诉指定的推流端。为此我们创建了EasyCMSSession来和EasyCMS进行通讯,创建了EasyCMSModule为外面调用角色提供接口。详细代码请参考https://github.com/EasyDarwin/EasyDarwin

EasyDarwin开源流媒体服务器如何实现按需推送直播的的更多相关文章

  1. 基于EasyDarwin开源流媒体服务器框架实现EasyNVR H5无插件直播流媒体服务器方案

    背景分析 在之前的一篇博客<web无插件播放RTSP摄像机方案,拒绝插件,拥抱H5!>中,描述了实现一套H5无插件直播方案的各个组件的参考建议,又在博客<EasyNVR H5流媒体服 ...

  2. NodeJS版本EasyDarwin开源流媒体服务器开发心得

    title: Node版本EasyDarwin开发心得 date: 2018-03-27 22:46:15 tags: 年后着手Node版本EasyDarwin的开发工作,截止到今天2018年03月2 ...

  3. EasyDarwin开源流媒体服务器Golang版本:服务端录像功能发布

    EasyDarwin开源流媒体服务器(www.easydarwin.org)现在使用Go版本实现了.最新的代码提交,已经支持了推流(或者拉流)的同时进行本地存储. 本地存储的原理,是在推流的同时启动f ...

  4. EasyDarwin开源流媒体服务器Golang版本:拉转推功能之拉流实现方法

    EasyDarwin开源流媒体服务器(www.easydarwin.org),拉转推是一个很有意义的功能,它可将一个独立的RTSP数据源"拉"到服务器,再通过转发协议转发给多个客户 ...

  5. EasyDarwin开源流媒体服务器实现RTSP直播同步输出MP4、RTMP、HLS的方案思路

    背景 近期跟开源团队商量,想在EasyDarwin上继续做一些功能扩展,目前EasyDarwin开源流媒体服务器只能够实现高效的RTSP推流直播转发/分发功能,输入与输出都是RTSP/RTP流,不能够 ...

  6. EasyDarwin开源流媒体服务器性能优化之Work-stealing优化方案

    本文转自EasyDarwin开源团队成员Alex的博客:http://blog.csdn.net/cai6811376/article/details/52400226 EasyDarwin团队的Ba ...

  7. EasyDarwin开源流媒体服务器将select改为epoll的方法

    本文来自EasyDarwin团队Fantasy(fantasy(at)easydarwin.org) 一. EasyDarwin网络模型介绍 EventContext负责监听所有网络读写事件,Even ...

  8. 解决用EasyDarwin开源流媒体服务器做HLS直播时Flash Player卡住的问题

    最近在开发EasyDarwin开源流媒体服务器HLS直播的时候发现一个现象:在PC上用flash player播放HLS和在ios上面播放HLS时,效果明显不同,在ios上播放非常稳定,而在flash ...

  9. EasyDarwin开源流媒体服务器提供的TS切片/HLS直播打包库

    EasyHLS  Github:https://github.com/EasyDarwin/EasyHLS EasyHLS是什么? EasyHLS是EasyDarwin开源流媒体社区开发的一款HLS打 ...

随机推荐

  1. JavaWeb学习总结(十七)——JSP中的九个内置对象(转)

    一.JSP运行原理 每个JSP 页面在第一次被访问时,WEB容器都会把请求交给JSP引擎(即一个Java程序)去处理.JSP引擎先将JSP翻译成一个_jspServlet(实质上也是一个servlet ...

  2. 关于unity3d插件的自动打包

    开发中,迩可能会遇到在xcode里添加一些需要调用原生api的方法,可能是game center,可能是内购之类的,但是这些插件实在太多了,所以迩大可不必自己写这些插件,问题在于,国内的一些插件,像9 ...

  3. Yii使用find findAll查找出指定字段的实现方法

    Yii使用find findAll查找出指定字段的实现方法,非常实用的技巧,需要的朋友可以参考下. 用过Yii的朋友都知道,采用如下方法: 查看代码   打印 1 modelName::model() ...

  4. html5(历史管理)

    <!DOCTYPE html> <head> <meta http-equiv="Content-Type" content="text/h ...

  5. babel转码神器babel-preset-env

    简介 现如今不同的浏览器和平台chrome, opera, edge, firefox, safari, ie, ios, android, node, electron 不同的模块 "am ...

  6. java并发之hashmap源码

    在上篇博客中分析了hashmap的用法,详情查看java并发之hashmap 本篇博客重点分析下hashmap的源码(基于JDK1.8) 一.成员变量 HashMap有以下主要的成员变量 /** * ...

  7. Java中判断String对象是否为空的方法

    Java原生的方法: String对象中有一个isEmpty的方法判断是否为空,其实isEmpty完全等同于string.length()==0,注意如果String本身是null,那么使用strin ...

  8. 分布式缓存之Memcache

    〇.为什么要用分布式缓存 1.软件从单机到分布式 走向分布式第一步就是解决:多台机器共享登录信息的问题. 例如:现在有三台机器组成了一个Web的应用集群,其中一台机器用户登录,然后其他另外两台机器共享 ...

  9. java判断日期与星期

    原文:http://www.open-open.com/code/view/1440592372888 import java.text.SimpleDateFormat; import java.u ...

  10. 如果当前地图文档中有独立的Table,通过Engine如何获取该Table?

    将IMap转为ITableCollection,通过ITableCollection.get_Table(int index);来获取该Table