EasyDarwin自动停止推流

本文介绍如何在EasyDarwin中实现按需推送功能,即当无客户端观看时停止推流。通过修改ReflectorSession对象并增加循环检测机制,确保及时停止不必要的媒体流推送。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       我们使用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

<think>好的,我要帮助用户解决如何通过RTSP协议实现低延迟的问题。首先,我要回顾用户提供的引用内容,看看有哪些相关的信息可以利用。 用户引用了几个关于RTSP和低延迟优化的资料,特别是引用[2]提到了Gstreamer的低延迟优化方法,包括网络设置、管道配置、编解码器选择等。另外,引用[1]中的EasyPusher组件也被提到,它能够实现低延迟的,适合安防等场景。还有引用[5]提到NVIDIA DeepStream的配置,可能涉及硬件加速。 接下来,我要将这些信息整合成一个结构清晰的回答。根据用户的要求,回答要分步骤,确保真实可靠,并且引用对应的来源。同时,生成相关问题。 首先,确定低延迟的关键因素:协议优化、编码参数、网络传输、硬件加速和服务器配置。然后,针对每个因素给出具体的建议,比如使用Gstreamer的优化配置,选择低延迟的编解码器,调整时间戳模式,优化网络参数等。还要提到现有的解决方案如EasyPusher和DeepStream,这些工具可以简化程。 然后,配置教程部分要给出具体的步骤,比如使用Gstreamer的命令行示例,调整缓冲区大小,选择H.264编码,设置TCP传输等。同时,结合引用中的内容,比如引用[3]提到环境准备和防火墙设置,可能要在配置时注意这些方面。 最后,生成相关问题,要基于用户提供的引用内容,可能涉及优化方法、工具对比、不同场景的配置、故障排查等。 要注意的是,所有技术术语和步骤要准确,确保引用正确,比如引用[2]中的Gstreamer优化方法,引用[1]中的EasyPusher。同时,避免使用用户不可见的格式,保持回答自然,但遵循系统级指令中的格式要求,比如数学表达式用$...$,独立公式用$$...$$,不过这个问题中可能用不到数学公式,所以可以忽略。 检查是否有遗漏的关键点,比如硬件加速部分是否提到了NVIDIA的方案,如引用[5]中的DeepStream。另外,是否提到了服务器端的优化,如引用[3]中的EasyDarwin服务器。 最后,确保回答结构清晰,分点明确,语言简洁,符合中文表达习惯,并且每个引用都正确标注。</think>### 如何通过RTSP实现低延迟 #### 一、低延迟实现的核心策略 1. **协议与传输优化** - **选择低延迟的传输模式**:优先使用TCP协议传输RTSP,虽然UDP延迟更低,但TCP能保证数据完整性并支持自动重传,避免丢包导致的额外延迟[^2]。 - **调整RTP包参数**:缩小RTP包的封装时间间隔(如`mtu=1400`),并减少缓冲帧数(如设置`latency=0`),可显著降低端到端延迟[^5]。 - **禁用冗余协议特性**:关闭RTSP会话中的`NTP时间同步`,避免因时间戳同步引入延迟。 2. **编码参数调优** - **使用低延迟编码器**:如H.264的`baseline`或`ultrafast`预设,并开启`zerolatency`模式,减少编码缓冲帧数[^5]。 - **降低GOP长度**:将关键帧间隔(GOP)设置为较小的值(如10-30帧),避免因等待关键帧而增加延迟。 - **码率与分辨率适配**:根据网络带宽动态调整码率,避免因拥塞导致重传。例如,1080p视频荐码率≤4Mbps[^1][^4]。 3. **硬件与网络加速** - **启用硬件编解码**:利用NVIDIA GPU的NVENC/NVDEC或Intel QSV加速编码过程,降低CPU负载和编码延迟。 - **优化网络栈**:调整内核参数如`net.core.rmem_max`和`net.ipv4.tcp_tw_reuse`,提升网络吞吐量。 --- #### 二、配置实践与工具荐 1. **基于Gstreamer的配置** ```bash # 示例:摄像头采集+硬件编码+RTSP(延迟≤300ms) gst-launch-1.0 v4l2src device=/dev/video0 ! videoconvert ! nvvidconv ! "video/x-raw(memory:NVMM),format=NV12" \ ! nvv4l2h264enc preset=2 zerolatency=1 bitrate=4000000 ! h264parse ! rtph264pay config-interval=1 pt=96 \ ! queue max-size-buffers=0 max-size-time=0 ! udpsink host=目标服务器IP port=5004 ``` - **关键参数**: - `zerolatency=1`:启用零延迟编码模式。 - `config-interval=1`:减少SPS/PPS头信息重复发送频率。 2. **使用专用组件** - **EasyPusher方案**:通过封装好的API实现低延迟,支持Android/iOS/Windows多平台,默认优化后延迟可控制在300-500ms。 ```java // Android示例:屏幕采集 EasyPusher.setVideoEncoderType(EasyPusher.VIDEO_CODEC_H264); EasyPusher.setLatencyMode(EasyPusher.LATENCY_MODE_REALTIME); EasyPusher.startPublish("rtsp://server_ip:554/live"); ``` 3. **服务器端优化** - **选择高效流媒体服务器**:如EasyDarwin或Nginx-RTMP,支持快速转发和低缓冲配置[^3]。 - **调整服务器缓冲区**:限制接收缓冲区大小(如EasyDarwin中设置`recv_buffer_size=64k`),避免数据积压。 --- #### 三、性能验证与调优 1. **延迟测量方法** - **端到端测试**:在端插入时间戳水印,播放端计算解码时间差,荐工具:Wireshark + FFmpeg。 - **Gstreamer内置统计**:通过`identity signal-handoffs=TRUE`打印帧处理时间戳[^2]。 2. **常见问题解决** - **卡顿与花屏**:检查编码器是否开启B帧(建议禁用)或GOP过长,同时确保网络带宽稳定。 - **时间戳跳跃**:在管道中插入`rtpjitterbuffer latency=50`,平滑时间戳波动[^2]。 --- #### 四、典型应用场景 1. **安防监控**:通过IP摄像头+EasyPusher实现实时画面传输,延迟≤500ms。 2. **工业遥控**:基于Gstreamer低延迟,满足远程机械控制的实时性要求[^5]。 3. **直播互动**:结合WebRTC或HLS低延迟模式,实现主播与观众实时交互[^4]。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值