首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >RTSP客户端在会话完全设置(发出播放命令)之前发送$分隔的数据,导致405方法不允许错误。

RTSP客户端在会话完全设置(发出播放命令)之前发送$分隔的数据,导致405方法不允许错误。
EN

Stack Overflow用户
提问于 2013-08-30 05:57:41
回答 1查看 2K关注 0票数 1

我有一个自定义的基于have 555的RTSP客户端和服务器的实现。我正在使用16/08/2013构建的Live555。我正在使用交错的RTP-OVER-TCP作为防火墙进行流传输,我们将使用的防火墙不会允许我们使用UDP。(换句话说,RTP、RTCP和RTSP数据都将通过TCP发送)。在我的本地网络上,当我部署应用程序时,流工作非常完美。但是,在WAN上有一个轻微的延迟,我从服务器上得到了一个"405方法不允许“的错误。我已经能够在本地主机上模拟这种情况,方法是控制带宽,这样数据流动就会慢一点。如果我节流网络,我得到"405方法不允许“错误,如果我不节流它,我没有得到这个错误和流工作良好。我使用了网络流量检查器来观察客户端发送和接收的数据,并且我注意到,在我收到错误的情况下,客户端在发出PLAY命令之前发送一个由$分隔的数据,然后再发送一些额外的二进制数据。我认为这会使服务器感到困惑,因为服务器可能希望只在会话建立并发出PLAY命令之后才接收此类数据。

我已经尝试过手动过滤掉“不想要的”消息,直到播放命令发出为止。如果我这样做,流实际上开始,我可以渲染一个或两个帧,然后视频流似乎“冻结”。然而,在检查网络流量时,按照常规的视频流,流似乎确实是在后台流动的,但是在安装过程中,我已经丢弃了“不合适的”数据片段,这使得视频流不会呈现超过前几微秒的效果。

我很清楚,以$分隔的消息表示RTP或RTCP数据包。然而,我并不指望客户端在RTSP命令设置完流会话并启动PLAYing之前就开始发送这样的数据包。

有人能帮我解释一下这些“无序”的RTP/RTCP数据包是什么,以及客户端为什么要发送它们吗?我该如何解决这个问题?

作为参考,我将包括日志,该日志显示来自下面代表错误的客户端的消息:

代码语言:javascript
复制
##Client Sends:##
DESCRIBE rtsp://127.0.0.1:8554/ RTSP/1.0
CSeq: 2
User-Agent: LIVE555 Streaming Media v2013.08.16
Accept: application/sdp

##Client Receives:##
RTSP/1.0 200 OK
CSeq: 2
Date: Thu, Aug 29 2013 06:18:42 GMT
Content-Base: rtsp://127.0.0.1:8554/nurv/
Content-Type: application/sdp
Content-Length: 449

v=0
o=- 1377757120235695 1 IN IP4 192.168.56.1
s=MyVideo Streaming Session
i=nurv
t=0 0
a=tool:LIVE555 Streaming Media v2013.08.16
a=type:broadcast
a=control:*
a=range:npt=0-
a=x-qt-text-nam:MyVideo Streaming Session
a=x-qt-text-inf:nurv
m=video 0 RTP/AVP 96
c=IN IP4 0.0.0.0
b=AS:3750
a=rtpmap:96 H264/90000
a=control:track1
m=audio 0 RTP/AVP 96
c=IN IP4 0.0.0.0
b=AS:84602240
a=rtpmap:96 PCMU/48000/2
a=control:track2

##Client Sends:##
SETUP rtsp://127.0.0.1:8554/nurv/track1 RTSP/1.0
CSeq: 3
User-Agent: LIVE555 Streaming Media v2013.08.16
Transport: RTP/AVP/TCP;unicast;interleaved=0-1

##Client Receives:##
RTSP/1.0 200 OK
CSeq: 3
Date: Thu, Aug 29 2013 06:18:43 GMT
Transport: RTP/AVP/TCP;unicast;destination=127.0.0.1;source=127.0.0.1;interleaved=0-1
Session: 32A854D4

##Client Sends:##
SETUP rtsp://127.0.0.1:8554/nurv/track2 RTSP/1.0
CSeq: 4
User-Agent: LIVE555 Streaming Media v2013.08.16
Transport: RTP/AVP/TCP;unicast;interleaved=2-3
Session: 32A854D4

##THIS IS THE "OUT-OF-SEQUENCE DATA THAT CAUSES THE PROBLEM. THIS SECTION IS ONLY SENT WHEN NETWORK HAS SOME LATENCY AND DOES NOT APPEAR WHEN STREAMING WORKS.##
##Client Sends:##
00000000  24 01 00 20                                        $..             

00000000  80 C9 00 01 23 7A EB 1D 81 CA 00 05 23 7A EB 1D    ....#z......#z..
00000010  6C 61 70 74 6F 70 6E 61 6D 65 0D 0A 00 00 00 00    ..LaptopName....
##END OF SECTION THAT SHOWS THE "OUT-OF-SEQUENCE" DATA.##

##Client Receives:##
RTSP/1.0 200 OK
CSeq: 4
Date: Thu, Aug 29 2013 06:18:47 GMT
Transport: RTP/AVP/TCP;unicast;destination=127.0.0.1;source=127.0.0.1;interleaved=2-3
Session: 32A854D4

##Client Sends:##
PLAY rtsp://127.0.0.1:8554/nurv/ RTSP/1.0
CSeq: 5
User-Agent: LIVE555 Streaming Media v2013.08.16
Session: 32A854D4
Range: npt=0.000-

##THIS IS THE ERROR RECEIVED FROM THE SERVER. IN CASES WHERE STREAMING WORKS, THIS ERROR IS NOT RECEIVED BUT WE RATHER START RECEIVING RTP AND RTCP PACKETS (DATA) FROM THE SERVER.##
##Client Receives:##
RTSP/1.0 405 Method Not Allowed
CSeq: 5
Date: Thu, Aug 29 2013 06:18:48 GMT
Allow: OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, GET_PARAMETER, SET_PARAMETER

##Client Sends:##
TEARDOWN rtsp://127.0.0.1:8554/nurv/ RTSP/1.0
CSeq: 6
User-Agent: LIVE555 Streaming Media v2013.08.16
Session: 32A854D4
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-09-11 07:40:26

在对Live555本身做了一些深入的调试之后,我发现它包含了一个bug。$分隔的数据基本上是RTCP "RR“数据包,这些数据包在PLAY命令发出之前错误地被发送(只应该在PLAY发出之后才会发生)。2012/10/04年构建的live555似乎包含了一个"EnableRTCPReports“标志,以指示是否可以继续发送"RR”,并且该值被设置为只有在游戏发布后才允许发送这些报告。

但是,在实际执行发送的代码中,在发送"RR“报告之前不检查此标志的条件。这就是我发现的窃听器。此bug报告已与修复一起提交给Live555项目,但我也将此修复放在这里,以供在此期间遇到的任何人使用:

livemedia/include/RTSPSource.hh中,我们有返回fEnableRTCPReports的enableRTCPReports函数。但是,const对象不能调用这一点(我们需要这样做),所以只需声明一个非常类似的函数,但是要使其安全:

代码语言:javascript
复制
...
Boolean& enableRTCPReports() { return fEnableRTCPReports; }
//****The following function is part of the fix. The same as enableRTCPReports except that it is "const" and "safe" for const object references to call, which means we can call this from RTCPInstance using the fSource object there.
Boolean constAccessibleEnableRTCPReports() const { return fEnableRTCPReports; } 
...

In livemedia/RTCP.cpp:

代码语言:javascript
复制
...
Boolean RTCPInstance::addReport(Boolean alwaysAdd) {
  // Include a SR or a RR, depending on whether we have an associated sink or source:
  if (fSink != NULL) {
    if (!alwaysAdd) {
      if (!fSink->enableRTCPReports()) return False;

      // Hack: Don't send a SR during those (brief) times when the timestamp of the
      // next outgoing RTP packet has been preset, to ensure that that timestamp gets
      // used for that outgoing packet. (David Bertrand, 2006.07.18)
      if (fSink->nextTimestampHasBeenPreset()) return False;
    }

    addSR();
  } else if (fSource != NULL) {
     //****The following IF-statement is the fix. As in the case of the Sink Node above (but using our "const-accessible" function), we first check the value of EnableRTCPReports before we do addRR().
    if (!fSource->constAccessibleEnableRTCPReports()) return false;
    addRR();
  }

  return True;
}
...
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18525980

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档