EasyRTSPServer视频流媒体服务平台客户端没有及时关闭流是什么原因?

文档客
• 阅读 160

RTSP协议以客户服务器方式工作,它是一个多媒体播放控制协议,用来使用户在播放从因特网下载的实时数据时能够进行控制,如:暂停/继 续、后退、前进等。因此 RTSP 又称为“因特网录像机遥控协议”。

EasyRTSPServer是一套稳定、高效、可靠、多平台支持的RTSP-Server组件, 接口调用非常简单成熟,无需关注RTSPServer中关于客户端监听接入、音视频多路复用、RTSP具体流程、RTP打包与发送等相关问题,支持多种音视频格式,再也不用去处理整个RTSP OPTIONS/DESCRIBE/SETUP/PLAY/RTP/RTCP的复杂流程和担心内存释放的问题了,非常适合于安防领域、教育领域、互联网直播领域等。

EasyRTSPServer视频流媒体服务平台客户端没有及时关闭流是什么原因?

EasyRTSPServer解决Server端多track而客户端仅请求一个track,客户端关闭没有及时关闭流

提出问题

某通道对应的所有客户端断开后, 不能正常回调关闭。
某一通道同时支持视频和音频输出, 即video和audio两个track。
VLC和自有播放库来中的RTSPClient则都会请求(所以不存在问题);
而某些客户端则只请求了一个track, 比如video。

此时再关闭,会有两种情况:
在VLC或自有播放库来断开连接时,都会正常回调关闭;
在仅请求了video的客户端断开连接时, 一定不会回调关闭;

分析问题

在RTSPClient断开时,一定会调用RTSPServer::stopTCPStreamingOnSocket, 当流为RTP Over TCP时, 则会调用deleteStreamByTrack;
在deleteStreamByTrack函数中, 是一个for循环,检测fStreamStates的subsession, 因为sdp中存在video和audio, fNumStreamStates的值为2, 而客户端只请求了video,所以在以下的代码中,判断不成立:

  Boolean noSubsessionsRemain = True;
  for (unsigned i = 0; i < fNumStreamStates; ++i) {
    if (fStreamStates[i].subsession != NULL) {
      noSubsessionsRemain = False;        //因为存在video和audio, 所以此处条件会成立
      break;
    }
  }

因为noSubsessionsRemain为False, 所以下面的代码不会被执行;

        if (noSubsessionsRemain) delete this;

顺便说一下, delete this是删除RTSPClientSession, 在ClientSession的析构函数中,会减少引用计数,如果计数为0, 则删除fOurServerMediaSession;

解决问题

在RTSPClientConnection中增加一个计数变量, 用于记录客户端请求的track个数, 然后在deleteStreamByTrack中递减,如果为0, 则使上面的noSubsessionsRemain为True;

修改如下

        在RTSPClientConnection的声明中,增加以下两个变量
        int    clientRequestTrackNum;        //for rtp over tcp
        char fClientSessionIdStr[16];    //for rtp over udp
        
        void RTSPServer::RTSPClientSession
        ::handleCmd_SETUP(UsageEnvironment *pEnv, RTSPServer::RTSPClientConnection* ourClientConnection,
                  char const* urlPreSuffix, char const* urlSuffix, char const* fullRequestStr) {
                  
                  ......
                  
                  
            if (streamingMode == RTP_TCP) {
              // Note that we'll be streaming over the RTSP TCP connection:
              fStreamStates[trackNum].tcpSocketNum = ourClientConnection->fClientOutputSocket;
              fOurRTSPServer.noteTCPStreamingOnSocket(fStreamStates[trackNum].tcpSocketNum, this, trackNum);

                    //此处增加计数
                  ourClientConnection->clientRequestTrackNum ++;
            }        
            
            ......
        }        
        
        修改deleteStreamByTrack的声明和实现:
        
        void deleteStreamByTrack(UsageEnvironment *pEnv, unsigned trackNum, Boolean lockFlag, int *clientTrackNum);

        void RTSPServer::RTSPClientSession::deleteStreamByTrack(UsageEnvironment *pEnv, unsigned trackNum, Boolean lockFlag, int *clientTrackNum) {

            lockClientFlag = lockFlag;

          if (trackNum >= fNumStreamStates) return; // sanity check; shouldn't happen
          if (fStreamStates[trackNum].subsession != NULL) {
            fStreamStates[trackNum].subsession->deleteStream(fOurSessionId, fStreamStates[trackNum].streamToken);
            fStreamStates[trackNum].subsession = NULL;
          }
          
          // Optimization: If all subsessions have now been deleted, then we can delete ourself now:
          Boolean noSubsessionsRemain = True;
          for (unsigned i = 0; i < fNumStreamStates; ++i) {
            if (fStreamStates[i].subsession != NULL) {
              noSubsessionsRemain = False;
              break;
            }
          }

          if (NULL!=clientTrackNum)
          {
              if (*clientTrackNum > 0)        *clientTrackNum -= 1;
              if (*clientTrackNum == 0)        noSubsessionsRemain = True;
          }

          if (noSubsessionsRemain) delete this;
        }
点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
7个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
3年前
RTP、RTCP和RTSP协议基础
1RTSP概述1.1RTSP概念RTSP(RealTimeStreamProtocol)是一种基于文本的应用层协议,在语法及一些消息参数等方面,RTSP协议与HTTP协议类似。RTSP被用于建立的控制媒体流的传输,它为多媒体服务扮演“网络远程控制”的角色。RTSP本身并不用于传送媒体流数据。媒体数据的传
GoCoding GoCoding
4年前
RTSP 流相关工具介绍
RTSP(RealTimeStreamingProtocol),实时流协议,是一种应用层协议,专为流媒体使用。本文将介绍GStreamer,VLC,FFmpeg这几个工具,如何发送、接收RTSP流。前提GStreamerGStreamer:https://gstreamer.freedesktop.org/GStre
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
Java日期时间API系列36
  十二时辰,古代劳动人民把一昼夜划分成十二个时段,每一个时段叫一个时辰。二十四小时和十二时辰对照表:时辰时间24时制子时深夜11:00凌晨01:0023:0001:00丑时上午01:00上午03:0001:0003:00寅时上午03:00上午0
Stella981 Stella981
3年前
Linux应急响应(一):SSH暴力破解
0x00前言SSH是目前较可靠,专为远程登录会话和其他网络服务提供安全性的协议,主要用于给远程登录会话数据进行加密,保证数据传输的安全。SSH口令长度太短或者复杂度不够,如仅包含数字,或仅包含字母等,容易被攻击者破解,一旦被攻击者获取,可用来直接登录系统,控制服务器所有权限。0x01应急场景某天,网站