EasyDarwin自动停止推流
原文转自:http://blog.csdn.net/ss00_2012/article/details/51441753
我们使用EasyDarwin的推流转发来进行媒体直播的时候,有时会有这样一个需求,当推流端推送的媒体没有客户端观看时,就希望推流端不再推送,也就是实现按需推送,当推流端使用4G网络时这个需求会更加强烈。
需求明确,那么说下实现。实现分为两步:触发和通知。
触发,EasyDarwin为每一路推流转发维护一个ReflectorSession对象,该对象的fNumOutputs属性用来指示当前拉流客户端的数量。当客户端停止拉流时会调用QTSSReflectorModule::DestroySession()->QTSSReflectorModule::RemoveOutput()->ReflectorSession::RemoveOutput(),其中ReflectorSession::RemoveOutput()代码如下:
- void ReflectorSession::RemoveOutput(ReflectorOutput* inOutput, Bool16 isClient)
- {
- (void)atomic_sub(&fNumOutputs, 1);
- for (UInt32 y = 0; y < fSourceInfo->GetNumStreams(); y++)
- {
- fStreamArray[y]->RemoveOutput(inOutput);
- if (isClient)
- fStreamArray[y]->DecEyeCount();
- }
- }
其中(void)atomic_sub(&fNumOutputs, 1);用来减少当前的客户端数量,我们可以在此判断fNumOutputs是否为0,为0就表示满足我们的触发条件,修改后的代码如下:
- void ReflectorSession::RemoveOutput(ReflectorOutput* inOutput, Bool16 isClient)
- {
- (void)atomic_sub(&fNumOutputs, 1);
- for (UInt32 y = 0; y < fSourceInfo->GetNumStreams(); y++)
- {
- fStreamArray[y]->RemoveOutput(inOutput);
- if (isClient)
- fStreamArray[y]->DecEyeCount();
- }
- //移除客户端之后判断fNumOutputs是否为0,add
- if(fNumOutputs == 0)
- {
- //调用角色,停止推流
- qtss_printf("客户端都不看啦\n");
- QTSS_RoleParams theParams;
- theParams.easyStreamStopParams.inSerial = fSerial;
- theParams.easyStreamStopParams.inChannel= fChannel;
- QTSSModule* theModule = QTSServerInterface::GetModule(QTSSModule::kStreamStopRole, 0);
- (void)theModule->CallDispatch(Easy_StreamStop_Role, &theParams);
- }
- //
- }
触发之后我们就调用Easy_StreamStop_Role角色来通知完成停止推流。
上述触发并不完美,对于推流之后并没有客户端拉流这种情况无法处理。因此我们又增加了循环检测的机制,通过将ReflectorSession继承Task,然后在其Run函数里循环检测fNumOutputs是否为0可以有效的解决这种情况,ReflectorSession::Run()代码如下:
- SInt64 ReflectorSession::Run()
- {
- if(fIfFirstRun)
- fIfFirstRun = false;//第一次的时候还没有拉流,就不要进行处理了;客户端拉流不要过慢。
- else
- {
- if(fNumOutputs == 0)
- {
- //调用角色,停止推流
- qtss_printf("没有客户端观看当前转发媒体\n");
- QTSS_RoleParams theParams;
- theParams.easyStreamStopParams.inSerial = fSerial;
- theParams.easyStreamStopParams.inChannel= fChannel;
- QTSSModule* theModule = QTSServerInterface::GetModule(QTSSModule::kStreamStopRole, 0);
- (void)theModule->CallDispatch(Easy_StreamStop_Role, &theParams);
- }
- }
- return 15*1000;
- }
另外不要忘了在ReflectorSession的构造函数中调用this->Signal(Task::kStartEvent);来开始循环检测。
通知,OK,到此触发就搞定了,下面我们就需要把停止推流这个信息告诉推流端就OK了,由谁告诉?对于推流端的管理是由EasyCMS来进行的,因此我们需要先将停止推流信息告诉EasyCMS,然后让EasyCMS告诉指定的推流端。为此我们创建了EasyCMSSession来和EasyCMS进行通讯,创建了EasyCMSModule为外面调用角色提供接口。详细代码请参考https://github.com/EasyDarwin/EasyDarwin。
相关文章
- 还在用json通信?自动生成代码不香吗
- mysql启动后自动停止_宝塔mysql总是自动停止解决方法总汇
- 基于自动编码器的赛车视角转换与分割
- mysql数据库总是自动关闭_宝塔数据库mysql总是自动停止解决总汇
- Oracle 自动生成ID实现机制(oracle自增id)
- MySQL自动启停服务管理(mysql自动停止服务)
- 处理Java 管理 Redis 过期键并自动回收(redisjava过期)
- 如何解决MySQL启动后自动停止的问题?(mysql启动后自动停止)
- Oracle自动停止:如何避免数据库运行中的中断和故障?(oracle自动停止)
- MySQL:停止自动增长(mysql 取消自增长)
- MSSQL自动升级之构建脚本(mssql 自动升级脚本)
- MSSQL自动停止功能:让你的工作更加高效(mssql自动停止)
- 为了持续改善Redis集群的自动升级版本(redis集群升级版本)
- 使用Redis提高系统负载自动释放连接数(redis自动释放连接数)
- CSSexpression控制图片自动缩放效果代码[兼容IE,Firefox]
- Js倒计时代码,当鼠标离开页面与回到页面会自动停止与开始
- jQuery实现列表自动循环滚动鼠标悬停时停止滚动
- php利用cookie实现自动登录的方法