I have a media player that uses Live555 to stream from RTSP/RTP as well as transport stream over UDP (IPTV style). When playing transport stream over UDP, I put together an SDP description like this:

s=MPEG Transport Stream over UDP
i=TS over UDP
t=0 0
a=type:broadcast
m=video <port number> UDP 33
c=IN IP4 <ip address>
b=AS:5000

Then I create a MediaSession with it, like this:

m_pLive555Session = MediaSession::createNew(*m_pLive555Env, sdpDescription);

The call initiate() on the subsession. This creates a MPEG2TransportStreamFramer, with a BasicUDPSource to feed it.

This works great as long as the port number for the UDP transport stream is even. If it is odd, liveMedia/MediaSession.cpp/MediaSubsession::initiate() forces the data delivery port to be even.

There is convention/rule that says you use even port numbers for RTP and odd for the corresponding RTCP backchannel. I'm not disputing that, but this code can also handle TS over UDP. In the case of raw transport stream over UDP there is no RTCP back channel and the port number isn't generally negotiable.

To get around the problem, I hacked initiate() to avoid changing the port number when fProtocolName is UDP, I added the diff to the end of this message. I don't have a very deep understanding of this code base, maybe this was the wrong approach, but this patch met my immediate needs. I'm guessing my case here is either fairly obscure or I missed a better way of dealing with this.

Comments and criticisms are welcome.

--Johno



diff --git a/liveMedia/MediaSession.cpp b/liveMedia/MediaSession.cpp
index 8e17d26..9b49bba 100644
--- a/liveMedia/MediaSession.cpp
+++ b/liveMedia/MediaSession.cpp
@@ -588,9 +588,18 @@ Boolean MediaSubsession::initiate(int useSpecialRTPoffset) {
     tempAddr.s_addr = connectionEndpointAddress();
         // This could get changed later, as a result of a RTSP "SETUP"

+       // ZZZ: Feb 2012
+ // do not bother forcing port to be even when using UDP, should only apply to RTP
+       //
+       bool bIsUDP = (strcmp(fProtocolName, "UDP") == 0);
+
     if (fClientPortNum != 0) {
-      // The sockets' port numbers were specified for us.  Use these:
-      fClientPortNum = fClientPortNum&~1; // even
+
+               if ( !bIsUDP )
+               {
+ // The sockets' port numbers were specified for us. Use these:
+                       fClientPortNum = fClientPortNum&~1; // even
+               }
       if (isSSM()) {
fRTPSocket = new Groupsock(env(), tempAddr, fSourceFilterAddr, fClientPortNum);
       } else {
@@ -600,20 +609,23 @@ Boolean MediaSubsession::initiate(int useSpecialRTPoffset) {
        env().setResultMsg("Failed to create RTP socket");
        break;
       }
-
-      // Set our RTCP port to be the RTP port +1
-      portNumBits const rtcpPortNum = fClientPortNum|1;
-      if (isSSM()) {
- fRTCPSocket = new Groupsock(env(), tempAddr, fSourceFilterAddr, rtcpPortNum);
-      } else {
-       fRTCPSocket = new Groupsock(env(), tempAddr, rtcpPortNum, 255);
-      }
-      if (fRTCPSocket == NULL) {
-       char tmpBuf[100];
- sprintf(tmpBuf, "Failed to create RTCP socket (port %d)", rtcpPortNum);
-       env().setResultMsg(tmpBuf);
-       break;
-      }
+
+         if ( !bIsUDP )
+         {
+                 // Set our RTCP port to be the RTP port +1
+                 portNumBits const rtcpPortNum = fClientPortNum|1;
+                 if (isSSM()) {
+ fRTCPSocket = new Groupsock(env(), tempAddr, fSourceFilterAddr, rtcpPortNum);
+                 } else {
+ fRTCPSocket = new Groupsock(env(), tempAddr, rtcpPortNum, 255);
+                 }
+                 if (fRTCPSocket == NULL) {
+                         char tmpBuf[100];
+ sprintf(tmpBuf, "Failed to create RTCP socket (port %d)", rtcpPortNum);
+                         env().setResultMsg(tmpBuf);
+                         break;
+                 }
+         }
     } else {
// Port numbers were not specified in advance, so we use ephemeral port numbers. // Create sockets until we get a port-number pair (even: RTP; even+1: RTCP). @@ -691,7 +703,7 @@ Boolean MediaSubsession::initiate(int useSpecialRTPoffset) {
     increaseReceiveBufferTo(env(), fRTPSocket->socketNum(), rtpBufSize);

     // ASSERT: fRTPSocket != NULL && fRTCPSocket != NULL
-    if (isSSM()) {
+    if (isSSM() && !bIsUDP ) {
// Special case for RTCP SSM: Send RTCP packets back to the source via unicast:
       fRTCPSocket->changeDestinationParameters(fSourceFilterAddr,0,~0);
     }

_______________________________________________
live-devel mailing list
live-devel@lists.live555.com
http://lists.live555.com/mailman/listinfo/live-devel

Reply via email to