--本文转自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. 【Tyvj2133&BZOJ1146】网络管理Network(树套树,DFS序,树状数组,主席树,树上差分)

    题意:有一棵N个点的树,每个点有一个点权a[i],要求在线实现以下操作: 1:将X号点的点权修改为Y 2:查询X到Y的路径上第K大的点权 n,q<=80000 a[i]<=10^8 思路: ...

  2. 【Visual Studio】error LNK2038: 检测到“_MSC_VER”的不匹配项: 值“1600”不匹配值“1800” (转)

    1.案例一 _MSC_VER 定义编译器的版本.下面是一些编译器版本的_MSC_VER值:MS VC++ 10.0 _MSC_VER = 1600MS VC++ 9.0 _MSC_VER = 1500 ...

  3. Git基础篇【转】

    转自:https://i.cnblogs.com/EditPosts.aspx?opt=1 1.设置名字与邮箱 $ Git config –global user.name “YourName” $ ...

  4. bzero 字符数组清零

    原来bzero()是这个功能,学习啦.下面的文章可以好好参考,出处:http://hi.baidu.com/wg_wang/item/5fa42c15c73b8efa9c778af8 bzero &a ...

  5. python常用模块1

    一. 什么是模块: 常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀. 但其实import加载的模块分为四个通用类别: 1 使用python编写的代码 ...

  6. PAT 甲级 1087 All Roads Lead to Rome(SPFA+DP)

    题目链接 All Roads Lead to Rome 题目大意:求符合题意(三关键字)的最短路.并且算出路程最短的路径有几条. 思路:求最短路并不难,SPFA即可,关键是求总路程最短的路径条数. 我 ...

  7. Vijos——P1137 组合数

    https://vijos.org/p/1137 描述 组合公式 C=N!/(M!*(N-M)!). 问题是求 C 中不同的质因子的个数例如 N=7, M=4. C=7!/(3!*4!)=5040/( ...

  8. [LibreOJ β Round #4] 子集

    显然是个二分图,直接求最大独立就行了. #include<bits/stdc++.h> #define ll long long #define pb push_back using na ...

  9. nginx--cookies转发

    nginx根据cookie分流   nginx根据cookie分流众所周知,nginx可以根据url path进行分流,殊不知对于cookie分流也很强大,同时这也是我上篇提到的小流量实验的基础. 二 ...

  10. javascript 对象初探 (六)--- call()和apply()初探

    在javascript中,每个函数都具有call()和apply()两个方法,您可以用她们来触发函数,并指定相关的调用参数. 此外,这两个方法还有另一个功能,就是她可以让一个对象去‘借用‘另一个对象的 ...