Commit a4208fa8 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

Use plain sockets rather than the UDP access output for RTSP.

This saves:
 - one malloc() per packet per client } due to
 - one memcpy() per packet per client } block_Duplicate()
 - one mwait() per packet per client, and
 - one thread per client per track

So it should really help scale RTSP broadcast up.
However, in its current state, it removes the pts synchronization,
which might not be such a great idea. I will re-add it later.
parent d208c448
...@@ -240,13 +240,13 @@ struct sout_stream_id_t ...@@ -240,13 +240,13 @@ struct sout_stream_id_t
pf_rtp_packetizer_t pf_packetize; pf_rtp_packetizer_t pf_packetize;
int i_mtu; int i_mtu;
/* for sending the packets */ /* Packets sinks */
sout_access_out_t *p_access; sout_access_out_t *p_access;
vlc_mutex_t lock_sink; vlc_mutex_t lock_sink;
int i_sink; int fdc;
sout_access_out_t **sink; int *fdv;
rtsp_stream_id_t *rtsp_id; rtsp_stream_id_t *rtsp_id;
}; };
...@@ -322,7 +322,7 @@ static int Open( vlc_object_t *p_this ) ...@@ -322,7 +322,7 @@ static int Open( vlc_object_t *p_this )
{ {
if( !b_rtsp ) if( !b_rtsp )
{ {
msg_Err( p_stream, "missing destination and not in rtsp mode" ); msg_Err( p_stream, "missing destination and not in RTSP mode" );
free( p_sys ); free( p_sys );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
...@@ -387,8 +387,8 @@ static int Open( vlc_object_t *p_this ) ...@@ -387,8 +387,8 @@ static int Open( vlc_object_t *p_this )
id->p_stream = p_stream; id->p_stream = p_stream;
vlc_mutex_init( p_stream, &id->lock_sink ); vlc_mutex_init( p_stream, &id->lock_sink );
id->i_sink = 0; id->fdc = 0;
id->sink = NULL; id->fdv = NULL;
id->rtsp_id = NULL; id->rtsp_id = NULL;
/* Check muxer type */ /* Check muxer type */
...@@ -918,8 +918,8 @@ static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt ) ...@@ -918,8 +918,8 @@ static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
id->rtsp_id = NULL; id->rtsp_id = NULL;
vlc_mutex_init( p_stream, &id->lock_sink ); vlc_mutex_init( p_stream, &id->lock_sink );
id->i_sink = 0; id->fdc = 0;
id->sink = NULL; id->fdv = NULL;
switch( p_fmt->i_codec ) switch( p_fmt->i_codec )
{ {
...@@ -1206,7 +1206,7 @@ static int Del( sout_stream_t *p_stream, sout_stream_id_t *id ) ...@@ -1206,7 +1206,7 @@ static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
RtspDelId( p_sys->rtsp, id->rtsp_id ); RtspDelId( p_sys->rtsp, id->rtsp_id );
vlc_mutex_destroy( &id->lock_sink ); vlc_mutex_destroy( &id->lock_sink );
free( id->sink ); free( id->fdv );
/* Update SDP (sap/file) */ /* Update SDP (sap/file) */
if( p_sys->b_export_sap && !p_sys->p_mux ) SapSetup( p_stream ); if( p_sys->b_export_sap && !p_sys->p_mux ) SapSetup( p_stream );
...@@ -1362,9 +1362,9 @@ static void rtp_packetize_send( sout_stream_id_t *id, block_t *out ) ...@@ -1362,9 +1362,9 @@ static void rtp_packetize_send( sout_stream_id_t *id, block_t *out )
{ {
int i; int i;
vlc_mutex_lock( &id->lock_sink ); vlc_mutex_lock( &id->lock_sink );
for( i = 0; i < id->i_sink; i++ ) for( i = 0; i < id->fdc; i++ )
{ {
sout_AccessOutWrite( id->sink[i], block_Duplicate( out ) ); send( id->fdv[i], out->p_buffer, out->i_buffer, 0 );
} }
vlc_mutex_unlock( &id->lock_sink ); vlc_mutex_unlock( &id->lock_sink );
...@@ -1378,20 +1378,21 @@ static void rtp_packetize_send( sout_stream_id_t *id, block_t *out ) ...@@ -1378,20 +1378,21 @@ static void rtp_packetize_send( sout_stream_id_t *id, block_t *out )
} }
} }
int rtp_add_sink( sout_stream_id_t *id, sout_access_out_t *access ) int rtp_add_sink( sout_stream_id_t *id, int fd )
{ {
vlc_mutex_lock( &id->lock_sink ); vlc_mutex_lock( &id->lock_sink );
TAB_APPEND( id->i_sink, id->sink, access ); TAB_APPEND( id->fdc, id->fdv, fd );
vlc_mutex_unlock( &id->lock_sink ); vlc_mutex_unlock( &id->lock_sink );
return VLC_SUCCESS; return VLC_SUCCESS;
} }
void rtp_del_sink( sout_stream_id_t *id, sout_access_out_t *access ) void rtp_del_sink( sout_stream_id_t *id, int fd )
{ {
/* NOTE: must be safe to use if access is not a sink to id */ /* NOTE: must be safe to use if fd is not included */
vlc_mutex_lock( &id->lock_sink ); vlc_mutex_lock( &id->lock_sink );
TAB_REMOVE( id->i_sink, id->sink, access ); TAB_REMOVE( id->fdc, id->fdv, fd );
vlc_mutex_unlock( &id->lock_sink ); vlc_mutex_unlock( &id->lock_sink );
net_Close( fd );
} }
static int rtp_packetize_mpa( sout_stream_t *p_stream, sout_stream_id_t *id, static int rtp_packetize_mpa( sout_stream_t *p_stream, sout_stream_id_t *id,
......
...@@ -36,6 +36,6 @@ void RtspDelId( rtsp_stream_t *rtsp, rtsp_stream_id_t * ); ...@@ -36,6 +36,6 @@ void RtspDelId( rtsp_stream_t *rtsp, rtsp_stream_id_t * );
char *SDPGenerate( const sout_stream_t *p_stream, const char *rtsp_url ); char *SDPGenerate( const sout_stream_t *p_stream, const char *rtsp_url );
int rtp_add_sink( sout_stream_id_t *id, sout_access_out_t *access ); int rtp_add_sink( sout_stream_id_t *id, int fd );
void rtp_del_sink( sout_stream_id_t *id, sout_access_out_t *access ); void rtp_del_sink( sout_stream_id_t *id, int fd );
...@@ -154,7 +154,7 @@ struct rtsp_session_t ...@@ -154,7 +154,7 @@ struct rtsp_session_t
struct rtsp_strack_t struct rtsp_strack_t
{ {
sout_stream_id_t *id; sout_stream_id_t *id;
sout_access_out_t *access; int fd;
vlc_bool_t playing; vlc_bool_t playing;
}; };
...@@ -217,9 +217,8 @@ void RtspDelId( rtsp_stream_t *rtsp, rtsp_stream_id_t *id ) ...@@ -217,9 +217,8 @@ void RtspDelId( rtsp_stream_t *rtsp, rtsp_stream_id_t *id )
if( ses->trackv[j].id == id->sout_id ) if( ses->trackv[j].id == id->sout_id )
{ {
rtsp_strack_t *tr = ses->trackv + j; rtsp_strack_t *tr = ses->trackv + j;
sout_AccessOutDelete( tr->access ); net_Close( tr->fd );
REMOVE_ELEM( ses->trackv, ses->trackc, j ); REMOVE_ELEM( ses->trackv, ses->trackc, j );
/* FIXME: are we supposed to notify the client? */
} }
} }
} }
...@@ -283,10 +282,7 @@ void RtspClientDel( rtsp_stream_t *rtsp, rtsp_session_t *session ) ...@@ -283,10 +282,7 @@ void RtspClientDel( rtsp_stream_t *rtsp, rtsp_session_t *session )
TAB_REMOVE( rtsp->sessionc, rtsp->sessionv, session ); TAB_REMOVE( rtsp->sessionc, rtsp->sessionv, session );
for( i = 0; i < session->trackc; i++ ) for( i = 0; i < session->trackc; i++ )
{ rtp_del_sink( session->trackv[i].id, session->trackv[i].fd );
rtp_del_sink( session->trackv[i].id, session->trackv[i].access );
sout_AccessOutDelete( session->trackv[i].access );
}
free( session->trackv ); free( session->trackv );
free( session ); free( session );
...@@ -491,10 +487,10 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id, ...@@ -491,10 +487,10 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id,
} }
else else
{ {
char ip[NI_MAXNUMERICHOST], url[NI_MAXNUMERICHOST + 8]; char ip[NI_MAXNUMERICHOST], src[NI_MAXNUMERICHOST];
static const char access[] = "udp{raw,rtcp}";
rtsp_session_t *ses = NULL; rtsp_session_t *ses = NULL;
rtsp_strack_t track = { id->sout_id, NULL, VLC_FALSE }; rtsp_strack_t track = { id->sout_id, -1, VLC_FALSE };
int sport;
if( httpd_ClientIP( cl, ip ) == NULL ) if( httpd_ClientIP( cl, ip ) == NULL )
{ {
...@@ -502,25 +498,18 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id, ...@@ -502,25 +498,18 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id,
continue; continue;
} }
snprintf( url, sizeof( url ), track.fd = net_ConnectDgram( p_stream, ip, loport, -1,
( strchr( ip, ':' ) != NULL ) IPPROTO_UDP );
? "[%s]:%d" : "%s:%d", if( track.fd == -1 )
ip, loport );
track.access = sout_AccessOutNew( p_stream->p_sout,
access, url );
if( track.access == NULL )
{ {
msg_Err( p_stream, msg_Err( p_stream,
"cannot create access output for %s://%s", "cannot create RTP socket for %s port %u",
access, url ); ip, loport );
answer->i_status = 500; answer->i_status = 500;
continue; continue;
} }
char *src = var_GetNonEmptyString( track.access, net_GetSockAddress( track.fd, src, &sport );
"src-addr" );
int sport = var_GetInteger( track.access, "src-port" );
vlc_mutex_lock( &rtsp->lock ); vlc_mutex_lock( &rtsp->lock );
if( psz_session == NULL ) if( psz_session == NULL )
...@@ -549,7 +538,7 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id, ...@@ -549,7 +538,7 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id,
httpd_ServerIP( cl, ip ); httpd_ServerIP( cl, ip );
if( ( src != NULL ) && strcmp( src, ip ) ) if( strcmp( src, ip ) )
{ {
/* Specify source IP if it is different from the RTSP /* Specify source IP if it is different from the RTSP
* control connection server address */ * control connection server address */
...@@ -573,7 +562,6 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id, ...@@ -573,7 +562,6 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id,
} }
answer->i_status = 200; answer->i_status = 200;
free( src );
} }
break; break;
} }
...@@ -602,7 +590,7 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id, ...@@ -602,7 +590,7 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id,
&& ( ( id == NULL ) || ( tr->id == id->sout_id ) ) ) && ( ( id == NULL ) || ( tr->id == id->sout_id ) ) )
{ {
tr->playing = VLC_TRUE; tr->playing = VLC_TRUE;
rtp_add_sink( tr->id, tr->access ); rtp_add_sink( tr->id, tr->fd );
} }
} }
} }
...@@ -650,8 +638,7 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id, ...@@ -650,8 +638,7 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id,
{ {
if( ses->trackv[i].id == id->sout_id ) if( ses->trackv[i].id == id->sout_id )
{ {
rtp_del_sink( id->sout_id, ses->trackv[i].access ); rtp_del_sink( id->sout_id, ses->trackv[i].fd );
sout_AccessOutDelete( ses->trackv[i].access );
REMOVE_ELEM( ses->trackv, ses->trackc, i ); REMOVE_ELEM( ses->trackv, ses->trackc, i );
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment