zoukankan      html  css  js  c++  java
  • EasyDarwin开源流媒体服务器如何实现按需推送直播的

    --本文转自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
     在CODE上查看代码片派生到我的代码片
    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
     在CODE上查看代码片派生到我的代码片
    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("客户端都不看啦 ");  
    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
     在CODE上查看代码片派生到我的代码片
    1. SInt64 ReflectorSession::Run()  
    2. {  
    3.  if(fIfFirstRun)  
    4.   fIfFirstRun = false;//第一次的时候还没有拉流,就不要进行处理了;客户端拉流不要过慢。  
    5.  else  
    6.  {  
    7.   if(fNumOutputs == 0)  
    8.   {  
    9.    //调用角色,停止推流  
    10.    qtss_printf("没有客户端观看当前转发媒体 ");  
    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

  • 相关阅读:
    internet信息服务(iis)无法删除的解决方法
    JQuery和ASP.NET分别实现级联下拉框效果
    解决为应用程序池 提供服务的进程关闭时间超过了限制
    VS2015|Visual Studio Enterprise 2015简体中文版(企业版)
    ASP.NET MVC 4 (十) 模型验证
    基于.NET平台常用的框架整理
    业务逻辑层的设计(三)——事务的考虑
    业务逻辑层的设计(二)——让领域模型支持验证
    业务逻辑层的设计(一)——逻辑是谁的职责
    添加<!doctype html>后造成JS写的定位失效
  • 原文地址:https://www.cnblogs.com/babosa/p/9217920.html
Copyright © 2011-2022 走看看