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
pf_rtp_packetizer_t pf_packetize;
int i_mtu;
/* for sending the packets */
/* Packets sinks */
sout_access_out_t *p_access;
vlc_mutex_t lock_sink;
int i_sink;
sout_access_out_t **sink;
rtsp_stream_id_t *rtsp_id;
int fdc;
int *fdv;
rtsp_stream_id_t *rtsp_id;
};
......@@ -322,7 +322,7 @@ static int Open( vlc_object_t *p_this )
{
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 );
return VLC_EGENERIC;
}
......@@ -387,8 +387,8 @@ static int Open( vlc_object_t *p_this )
id->p_stream = p_stream;
vlc_mutex_init( p_stream, &id->lock_sink );
id->i_sink = 0;
id->sink = NULL;
id->fdc = 0;
id->fdv = NULL;
id->rtsp_id = NULL;
/* Check muxer type */
......@@ -918,8 +918,8 @@ static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
id->rtsp_id = NULL;
vlc_mutex_init( p_stream, &id->lock_sink );
id->i_sink = 0;
id->sink = NULL;
id->fdc = 0;
id->fdv = NULL;
switch( p_fmt->i_codec )
{
......@@ -1206,7 +1206,7 @@ static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
RtspDelId( p_sys->rtsp, id->rtsp_id );
vlc_mutex_destroy( &id->lock_sink );
free( id->sink );
free( id->fdv );
/* Update SDP (sap/file) */
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 )
{
int i;
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 );
......@@ -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 );
TAB_APPEND( id->i_sink, id->sink, access );
TAB_APPEND( id->fdc, id->fdv, fd );
vlc_mutex_unlock( &id->lock_sink );
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 );
TAB_REMOVE( id->i_sink, id->sink, access );
TAB_REMOVE( id->fdc, id->fdv, fd );
vlc_mutex_unlock( &id->lock_sink );
net_Close( fd );
}
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 * );
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 );
void rtp_del_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, int fd );
......@@ -154,7 +154,7 @@ struct rtsp_session_t
struct rtsp_strack_t
{
sout_stream_id_t *id;
sout_access_out_t *access;
int fd;
vlc_bool_t playing;
};
......@@ -217,9 +217,8 @@ void RtspDelId( rtsp_stream_t *rtsp, rtsp_stream_id_t *id )
if( ses->trackv[j].id == id->sout_id )
{
rtsp_strack_t *tr = ses->trackv + j;
sout_AccessOutDelete( tr->access );
net_Close( tr->fd );
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 )
TAB_REMOVE( rtsp->sessionc, rtsp->sessionv, session );
for( i = 0; i < session->trackc; i++ )
{
rtp_del_sink( session->trackv[i].id, session->trackv[i].access );
sout_AccessOutDelete( session->trackv[i].access );
}
rtp_del_sink( session->trackv[i].id, session->trackv[i].fd );
free( session->trackv );
free( session );
......@@ -491,10 +487,10 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id,
}
else
{
char ip[NI_MAXNUMERICHOST], url[NI_MAXNUMERICHOST + 8];
static const char access[] = "udp{raw,rtcp}";
char ip[NI_MAXNUMERICHOST], src[NI_MAXNUMERICHOST];
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 )
{
......@@ -502,25 +498,18 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id,
continue;
}
snprintf( url, sizeof( url ),
( strchr( ip, ':' ) != NULL )
? "[%s]:%d" : "%s:%d",
ip, loport );
track.access = sout_AccessOutNew( p_stream->p_sout,
access, url );
if( track.access == NULL )
track.fd = net_ConnectDgram( p_stream, ip, loport, -1,
IPPROTO_UDP );
if( track.fd == -1 )
{
msg_Err( p_stream,
"cannot create access output for %s://%s",
access, url );
"cannot create RTP socket for %s port %u",
ip, loport );
answer->i_status = 500;
continue;
}
char *src = var_GetNonEmptyString( track.access,
"src-addr" );
int sport = var_GetInteger( track.access, "src-port" );
net_GetSockAddress( track.fd, src, &sport );
vlc_mutex_lock( &rtsp->lock );
if( psz_session == NULL )
......@@ -549,7 +538,7 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id,
httpd_ServerIP( cl, ip );
if( ( src != NULL ) && strcmp( src, ip ) )
if( strcmp( src, ip ) )
{
/* Specify source IP if it is different from the RTSP
* control connection server address */
......@@ -573,7 +562,6 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id,
}
answer->i_status = 200;
free( src );
}
break;
}
......@@ -602,7 +590,7 @@ static int RtspHandler( rtsp_stream_t *rtsp, rtsp_stream_id_t *id,
&& ( ( id == NULL ) || ( tr->id == id->sout_id ) ) )
{
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,
{
if( ses->trackv[i].id == id->sout_id )
{
rtp_del_sink( id->sout_id, ses->trackv[i].access );
sout_AccessOutDelete( ses->trackv[i].access );
rtp_del_sink( id->sout_id, ses->trackv[i].fd );
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