rtsprtplive555rtsp-clientrtcp

RTSP client sending $-delimited data before session has been completely set up (PLAY command issued) resulting in a 405 Method Not Allowed Error


I have a custom live555-based implementation of an RTSP client and server. I am using the 16/08/2013 build of Live555. I am streaming using Interleaved RTP-OVER-TCP as the firewalls we'll be using won't allow us to use UDP. (In other words, RTP, RTCP and RTSP data will all be sent via TCP). On my local network when I deploy the application, streaming works perfectly. However, over a WAN where there is a slight delay I get a "405 Method Not Allowed" error from the server. I have been able to simulate this on my localhost by throttling my bandwidth so that data flows a little slower. If I throttle the network, I get the "405 Method Not Allowed" error and if I don't throttle it, I don't get this error and streaming works fine. I have used a network traffic inspector to observe the data that the client sends and receives and I have noticed that in cases where I get the error, the client sends a $-delimited piece of data followed by some additional binary data BEFORE the PLAY command is issued. I think this confuses the server as the server probably expects to receive such data only after the session has been established and the PLAY command issued.

I have manually tried filtering out the "unwanted" messages until such time as the PLAY command has been issued. If I do this, streaming actually starts and I am able to render one or two frames, after which the video stream seems to "freeze". When inspecting the network traffic, however, it seems like the stream is indeed flowing in the background as per regular video streaming, but the fact that I have discarded the "out of place" pieces of data during SETUP causes the video stream not to render beyond the first few microseconds.

I am well aware that $-delimited messages represent RTP or RTCP packets. Yet, I wasn't expecting the client to start sending such packets before the RTSP commands have finished setting up the streaming session and started PLAYing.

Can someone perhaps assist in explaining to me what these "out of sequence" RTP/RTCP packets are and why the client would be sending them? How can I solve this problem?

For reference, I am including the log showing the messages from the client below representing the error:

##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

Solution

  • After doing some in-depth debugging on Live555 itself, I have found that it contains a bug. The $-delimited data is basically RTCP "RR" packets that wrongly get sent before the PLAY command has been issued (it should only happen after PLAY has been issued). The 2012/10/04 build of live555 seems to have included a "EnableRTCPReports" flag to indicate whether sending of "RR" can proceed or not and this value is set to allow sending of these reports only after the PLAY has been issued.

    However, in the code that actually does the sending, there is a condition under which this flag is not checked before sending out the "RR" report. This is the bug that I found. This bug report has been submitted to the Live555 project along with the fix, but I am placing the fix here as well for anyone encountering it in the meantime:

    In livemedia/include/RTSPSource.hh we have the enableRTCPReports function to return fEnableRTCPReports. However, this cannot be called by a const object (which is what we'll need to do), so simply declare a very similar function, but make it const and safe:

    ...
    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:

    ...
    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;
    }
    ...