[vlc-devel] [PATCH] rtsp: clean up multicast handling

Pierre Ynard linkfanel at yahoo.fr
Mon Dec 13 22:13:11 CET 2010


I had to refactor the way muxed streams are set up: am I missing some
rationale about the special cases for SAP?

Also, if I understand correctly, RTSP multicast transport syntax expects
a range of ports, so it can't work with muxed RTP + RTCP, can it? Or is
it okay to give the same port twice?

Should I write a proper net_GetMcastHopLimit() function in the core and
export it?


diff --git a/modules/stream_out/rtp.c b/modules/stream_out/rtp.c
index 3883758..22be882 100644
--- a/modules/stream_out/rtp.c
+++ b/modules/stream_out/rtp.c
@@ -402,6 +402,7 @@ static int Open( vlc_object_t *p_this )
     p_sys->i_port_audio = var_GetInteger( p_stream, SOUT_CFG_PREFIX "port-audio" );
     p_sys->i_port_video = var_GetInteger( p_stream, SOUT_CFG_PREFIX "port-video" );
     p_sys->rtcp_mux     = var_GetBool( p_stream, SOUT_CFG_PREFIX "rtcp-mux" );
+    /* FIXME: RTSP won't handle properly multicast + RTCP mux */
 
     if( p_sys->i_port_audio && p_sys->i_port_video == p_sys->i_port_audio )
     {
@@ -543,8 +544,6 @@ static int Open( vlc_object_t *p_this )
     psz = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "mux" );
     if( psz != NULL )
     {
-        sout_stream_id_t *id;
-
         /* Check muxer type */
         if( strncasecmp( psz, "ps", 2 )
          && strncasecmp( psz, "mpeg1", 5 )
@@ -578,20 +577,6 @@ static int Open( vlc_object_t *p_this )
             return VLC_EGENERIC;
         }
 
-        id = Add( p_stream, NULL );
-        if( id == NULL )
-        {
-            sout_MuxDelete( p_sys->p_mux );
-            sout_AccessOutDelete( p_sys->p_grab );
-            vlc_mutex_destroy( &p_sys->lock_sdp );
-            vlc_mutex_destroy( &p_sys->lock_ts );
-            vlc_mutex_destroy( &p_sys->lock_es );
-            free( p_sys->psz_vod_session );
-            free( p_sys->psz_destination );
-            free( p_sys );
-            return VLC_EGENERIC;
-        }
-
         p_sys->packet = NULL;
 
         p_stream->pf_add  = MuxAdd;
@@ -638,6 +623,16 @@ static int Open( vlc_object_t *p_this )
     /* update p_sout->i_out_pace_nocontrol */
     p_stream->p_sout->i_out_pace_nocontrol++;
 
+    if( p_sys->p_mux != NULL )
+    {
+        sout_stream_id_t *id = Add( p_stream, NULL );
+        if( id == NULL )
+        {
+            Close( p_this );
+            return VLC_EGENERIC;
+        }
+    }
+
     return VLC_SUCCESS;
 }
 
@@ -654,21 +649,17 @@ static void Close( vlc_object_t * p_this )
 
     if( p_sys->p_mux )
     {
-        assert( p_sys->i_es == 1 );
+        assert( p_sys->i_es <= 1 );
 
         sout_MuxDelete( p_sys->p_mux );
-        Del( p_stream, p_sys->es[0] );
+        if ( p_sys->i_es > 0 )
+            Del( p_stream, p_sys->es[0] );
         sout_AccessOutDelete( p_sys->p_grab );
 
         if( p_sys->packet )
         {
             block_Release( p_sys->packet );
         }
-        if( p_sys->b_export_sap )
-        {
-            p_sys->p_mux = NULL;
-            SapSetup( p_stream );
-        }
     }
 
     if( p_sys->rtsp != NULL )
@@ -728,22 +719,9 @@ static void SDPHandleUrl( sout_stream_t *p_stream, const char *psz_url )
             goto out;
         }
 
-        /* FIXME test if destination is multicast or no destination at all */
         p_sys->rtsp = RtspSetup( VLC_OBJECT(p_stream), NULL, &url );
         if( p_sys->rtsp == NULL )
             msg_Err( p_stream, "cannot export SDP as RTSP" );
-        else
-        if( p_sys->p_mux != NULL )
-        {
-            sout_stream_id_t *id = p_sys->es[0];
-            rtsp_stream_id_t *rtsp_id = RtspAddId( p_sys->rtsp, id,
-                                GetDWBE( id->ssrc ), id->rtp_fmt.clock_rate,
-                                p_sys->psz_destination, p_sys->i_ttl,
-                                id->i_port, id->i_port + 1 );
-            vlc_mutex_lock( &p_sys->lock_es );
-            id->rtsp_id = rtsp_id;
-            vlc_mutex_unlock( &p_sys->lock_es );
-        }
     }
     else if( ( url.psz_protocol && !strcasecmp( url.psz_protocol, "sap" ) ) ||
              ( url.psz_host && !strcasecmp( url.psz_host, "sap" ) ) )
@@ -1043,6 +1021,7 @@ static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
 
     id->i_seq_sent_next = id->i_sequence;
 
+    int mcast_fd = -1;
     if( p_sys->psz_destination != NULL )
     {
         /* Choose the port */
@@ -1130,6 +1109,8 @@ static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
                 setsockopt (fd, SOL_SOCKET, SO_RCVBUF, &(int){ 0 },
                             sizeof (int));
                 rtp_add_sink( id, fd, p_sys->rtcp_mux, NULL );
+                /* FIXME: test if this is multicast  */
+                mcast_fd = fd;
             }
         }
     }
@@ -1166,11 +1147,8 @@ static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
                                           p_sys->i_pts_offset );
 
     if( p_sys->rtsp != NULL )
-        id->rtsp_id = RtspAddId( p_sys->rtsp, id,
-                                 GetDWBE( id->ssrc ),
-                                 id->rtp_fmt.clock_rate,
-                                 p_sys->psz_destination,
-                                 p_sys->i_ttl, id->i_port, id->i_port + 1 );
+        id->rtsp_id = RtspAddId( p_sys->rtsp, id, GetDWBE( id->ssrc ),
+                                 id->rtp_fmt.clock_rate, mcast_fd );
 
     id->p_fifo = block_FifoNew();
     if( unlikely(id->p_fifo == NULL) )
@@ -1246,7 +1224,7 @@ static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
     vlc_mutex_destroy( &id->lock_sink );
 
     /* Update SDP (sap/file) */
-    if( p_sys->b_export_sap && !p_sys->p_mux ) SapSetup( p_stream );
+    if( p_sys->b_export_sap ) SapSetup( p_stream );
     if( p_sys->psz_sdp_file != NULL ) FileSetup( p_stream );
 
     free( id );
@@ -1297,7 +1275,7 @@ static int SapSetup( sout_stream_t *p_stream )
         p_sys->p_session = NULL;
     }
 
-    if( ( p_sys->i_es > 0 || p_sys->p_mux ) && p_sys->psz_sdp && *p_sys->psz_sdp )
+    if( p_sys->i_es > 0 && p_sys->psz_sdp && *p_sys->psz_sdp )
     {
         announce_method_t *p_method = sout_SAPMethod();
         p_sys->p_session = sout_AnnounceRegisterSDP( p_sout,
diff --git a/modules/stream_out/rtp.h b/modules/stream_out/rtp.h
index e9c1655..f901249 100644
--- a/modules/stream_out/rtp.h
+++ b/modules/stream_out/rtp.h
@@ -31,8 +31,7 @@ void RtspUnsetup( rtsp_stream_t *rtsp );
 
 rtsp_stream_id_t *RtspAddId( rtsp_stream_t *rtsp, sout_stream_id_t *sid,
                              uint32_t ssrc, unsigned clock_rate,
-                             const char *dst, int ttl,
-                             unsigned loport, unsigned hiport );
+                             int mcast_fd );
 void RtspDelId( rtsp_stream_t *rtsp, rtsp_stream_id_t * );
 
 char *RtspAppendTrackPath( rtsp_stream_id_t *id, const char *base );
diff --git a/modules/stream_out/rtsp.c b/modules/stream_out/rtsp.c
index 278da6e..900fbec 100644
--- a/modules/stream_out/rtsp.c
+++ b/modules/stream_out/rtsp.c
@@ -170,13 +170,11 @@ struct rtsp_stream_id_t
 {
     rtsp_stream_t    *stream;
     sout_stream_id_t *sout_id;
-    unsigned          clock_rate; /* needed to compute rtptime in RTP-Info */
     httpd_url_t      *url;
-    const char       *dst;
-    int               ttl;
     unsigned          track_id;
     uint32_t          ssrc;
-    uint16_t          loport, hiport;
+    unsigned          clock_rate; /* needed to compute rtptime in RTP-Info */
+    int               mcast_fd;
 };
 
 
@@ -226,9 +224,7 @@ char *RtspAppendTrackPath( rtsp_stream_id_t *id, const char *base )
 
 rtsp_stream_id_t *RtspAddId( rtsp_stream_t *rtsp, sout_stream_id_t *sid,
                              uint32_t ssrc, unsigned clock_rate,
-                             /* Multicast stuff - TODO: cleanup */
-                             const char *dst, int ttl,
-                             unsigned loport, unsigned hiport )
+                             int mcast_fd)
 {
     if (rtsp->track_id > 999)
     {
@@ -248,13 +244,7 @@ rtsp_stream_id_t *RtspAddId( rtsp_stream_t *rtsp, sout_stream_id_t *sid,
     id->track_id = rtsp->track_id;
     id->ssrc = ssrc;
     id->clock_rate = clock_rate;
-    id->dst = dst;
-    if( id->dst != NULL )
-    {
-        id->ttl = ttl;
-        id->loport = loport;
-        id->hiport = hiport;
-    }
+    id->mcast_fd = mcast_fd;
 
     urlbuf = RtspAppendTrackPath( id, rtsp->psz_path );
     if( urlbuf == NULL )
@@ -684,7 +674,7 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id,
                  tpt = transport_next( tpt ) )
             {
                 bool b_multicast = true, b_unsupp = false;
-                unsigned loport = 5004, hiport = 5005; /* from RFC3551 */
+                unsigned loport = 5004, hiport; /* from RFC3551 */
 
                 /* Check transport protocol. */
                 /* Currently, we only support RTP/AVP over UDP */
@@ -752,10 +742,17 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id,
 
                 if( b_multicast )
                 {
-                    const char *dst = id->dst;
-                    if( dst == NULL )
+                    char dst[NI_MAXNUMERICHOST];
+                    int dport, ttl;
+                    if( id->mcast_fd == -1 )
                         continue;
 
+                    net_GetPeerAddress( id->mcast_fd, dst, &dport );
+
+                    if (getsockopt(id->mcast_fd, SOL_IP, IP_MULTICAST_TTL,
+                                   &ttl, &(socklen_t){ sizeof (ttl) }))
+                        ttl = 1;
+
                     if( psz_session == NULL )
                     {
                         /* Create a dummy session ID */
@@ -768,8 +765,7 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id,
                     httpd_MsgAdd( answer, "Transport",
                                   "RTP/AVP/UDP;destination=%s;port=%u-%u;"
                                   "ttl=%d;mode=play",
-                                  dst, id->loport, id->hiport,
-                                  ( id->ttl > 0 ) ? id->ttl : 1 );
+                                  dst, dport, dport + 1, ttl );
                 }
                 else
                 {
diff --git a/modules/stream_out/vod.c b/modules/stream_out/vod.c
index a5c64cb..1773477 100644
--- a/modules/stream_out/vod.c
+++ b/modules/stream_out/vod.c
@@ -301,7 +301,7 @@ static vod_media_t *MediaNew( vod_t *p_vod, const char *psz_name,
     {
         media_es_t *p_es = p_media->es[i];
         p_es->rtsp_id = RtspAddId(p_media->rtsp, NULL, 0,
-                                  p_es->rtp_fmt.clock_rate, NULL, 0, 0, 0);
+                                  p_es->rtp_fmt.clock_rate, -1);
         if (p_es->rtsp_id == NULL)
             goto error;
     }


Regards,

-- 
Pierre Ynard
"Une âme dans un corps, c'est comme un dessin sur une feuille de papier."



More information about the vlc-devel mailing list