httpd_host_t *host;
httpd_url_t *url;
char *psz_path;
+ const char *track_fmt;
unsigned port;
int sessionc;
rtsp_stream_t *rtsp = malloc( sizeof( *rtsp ) );
if( rtsp == NULL || ( url->i_port > 99999 ) )
+ {
+ free( rtsp );
return NULL;
+ }
rtsp->owner = p_stream;
rtsp->sessionc = 0;
rtsp->sessionv = NULL;
+ rtsp->host = NULL;
+ rtsp->url = NULL;
+ rtsp->psz_path = NULL;
vlc_mutex_init( p_stream, &rtsp->lock );
- msg_Dbg( p_stream, "rtsp setup: %s : %d / %s\n",
- url->psz_host, url->i_port, url->psz_path );
-
rtsp->port = (url->i_port > 0) ? url->i_port : 554;
- if( url->psz_path != NULL )
- rtsp->psz_path = strdup( url->psz_path + 1 );
+ rtsp->psz_path = strdup( ( url->psz_path != NULL ) ? url->psz_path : "/" );
+ if( rtsp->psz_path == NULL )
+ goto error;
+
+ assert( strlen( rtsp->psz_path ) > 0 );
+ if( rtsp->psz_path[strlen( rtsp->psz_path ) - 1] == '/' )
+ rtsp->track_fmt = "%strackID=%u";
else
- rtsp->psz_path = NULL;
+ rtsp->track_fmt = "%s/trackID=%u";
+
+ msg_Dbg( p_stream, "RTSP stream: host %s port %d at %s",
+ url->psz_host, rtsp->port, rtsp->psz_path );
rtsp->host = httpd_HostNew( VLC_OBJECT(p_stream), url->psz_host,
rtsp->port );
if( rtsp->host == NULL )
goto error;
- rtsp->url = httpd_UrlNewUnique( rtsp->host,
- url->psz_path ? url->psz_path : "/", NULL,
- NULL, NULL );
+ rtsp->url = httpd_UrlNewUnique( rtsp->host, rtsp->psz_path,
+ NULL, NULL, NULL );
if( rtsp->url == NULL )
goto error;
if( rtsp->host )
httpd_HostDelete( rtsp->host );
+ free( rtsp->psz_path );
vlc_mutex_destroy( &rtsp->lock );
}
httpd_url_t *url;
const char *dst;
int ttl;
- unsigned loport, hiport;
+ uint32_t ssrc;
+ uint16_t loport, hiport;
};
rtsp_stream_id_t *RtspAddId( rtsp_stream_t *rtsp, sout_stream_id_t *sid,
- unsigned num,
+ unsigned num, uint32_t ssrc,
/* Multicast stuff - TODO: cleanup */
const char *dst, int ttl,
unsigned loport, unsigned hiport )
{
- char urlbuf[sizeof( "//trackID=123" ) + strlen( rtsp->psz_path )];
+ char urlbuf[sizeof( "/trackID=123" ) + strlen( rtsp->psz_path )];
rtsp_stream_id_t *id = malloc( sizeof( *id ) );
httpd_url_t *url;
id->stream = rtsp;
id->sout_id = sid;
+ id->ssrc = ssrc;
/* TODO: can we assume that this need not be strdup'd? */
id->dst = dst;
if( id->dst != NULL )
id->hiport = hiport;
}
- snprintf( urlbuf, sizeof( urlbuf ), "/%s/trackID=%u", rtsp->psz_path,
+ /* FIXME: num screws up if any ES has been removed and re-added */
+ snprintf( urlbuf, sizeof( urlbuf ), rtsp->track_fmt, rtsp->psz_path,
num );
- msg_Dbg( rtsp->owner, "RTSP: adding %s\n", urlbuf );
+ msg_Dbg( rtsp->owner, "RTSP: adding %s", urlbuf );
url = id->url = httpd_UrlNewUnique( rtsp->host, urlbuf, NULL, NULL, NULL );
if( url == NULL )
sout_stream_t *p_stream = rtsp->owner;
char psz_sesbuf[17];
const char *psz_session = NULL, *psz;
+ char control[sizeof("rtsp://[]:12345") + NI_MAXNUMERICHOST
+ + strlen( rtsp->psz_path )];
if( answer == NULL || query == NULL || cl == NULL )
return VLC_SUCCESS;
+ else
+ {
+ /* Build self-referential control URL */
+ char ip[NI_MAXNUMERICHOST], *ptr;
+
+ httpd_ServerIP( cl, ip );
+ ptr = strchr( ip, '%' );
+ if( ptr != NULL )
+ *ptr = '\0';
+
+ if( strchr( ip, ':' ) != NULL )
+ sprintf( control, "rtsp://[%s]:%u%s", ip, rtsp->port,
+ rtsp->psz_path );
+ else
+ sprintf( control, "rtsp://%s:%u%s", ip, rtsp->port,
+ rtsp->psz_path );
+ }
/* */
answer->i_proto = HTTPD_PROTO_RTSP;
- answer->i_version= query->i_version;
+ answer->i_version= 0;
answer->i_type = HTTPD_MSG_ANSWER;
answer->i_body = 0;
answer->p_body = NULL;
+ if( query->i_proto != HTTPD_PROTO_RTSP )
+ {
+ answer->i_status = 505;
+ }
+ else
if( httpd_MsgGet( query, "Require" ) != NULL )
{
answer->i_status = 551;
break;
}
- char ip[NI_MAXNUMERICHOST], *ptr;
- char control[sizeof("rtsp://[]:12345/") + sizeof( ip )
- + strlen( rtsp->psz_path )];
-
- /* Build self-referential URL */
- httpd_ServerIP( cl, ip );
- ptr = strchr( ip, '%' );
- if( ptr != NULL )
- *ptr = '\0';
-
- if( strchr( ip, ':' ) != NULL )
- sprintf( control, "rtsp://[%s]:%u/%s", ip, rtsp->port,
- ( rtsp->psz_path != NULL ) ? rtsp->psz_path : "" );
- else
- sprintf( control, "rtsp://%s:%u/%s", ip, rtsp->port,
- ( rtsp->psz_path != NULL ) ? rtsp->psz_path : "" );
-
- ptr = SDPGenerate( rtsp->owner, control );
-
answer->i_status = 200;
httpd_MsgAdd( answer, "Content-Type", "%s", "application/sdp" );
httpd_MsgAdd( answer, "Content-Base", "%s", control );
- answer->p_body = (uint8_t *)ptr;
- answer->i_body = strlen( ptr );
+ answer->p_body = (uint8_t *)SDPGenerate( rtsp->owner, control );
+ if( answer->p_body != NULL )
+ answer->i_body = strlen( (char *)answer->p_body );
+ else
+ answer->i_status = 500;
break;
}
httpd_MsgAdd( answer, "Transport",
"RTP/AVP/UDP;unicast;source=%s;"
"client_port=%u-%u;server_port=%u-%u;"
- "mode=play",
+ "ssrc=%08X;mode=play",
src, loport, loport + 1, sport,
- sport + 1 );
+ sport + 1, id->ssrc );
}
else
{
httpd_MsgAdd( answer, "Transport",
"RTP/AVP/UDP;unicast;"
"client_port=%u-%u;server_port=%u-%u;"
- "mode=play",
- loport, loport + 1, sport, sport + 1 );
+ "ssrc=%08X;mode=play",
+ loport, loport + 1, sport, sport + 1,
+ id->ssrc );
}
answer->i_status = 200;
ses = RtspClientGet( rtsp, psz_session );
if( ses != NULL )
{
+ /* FIXME: we really need to limit the number of tracks... */
+ char info[ses->trackc * ( strlen( control )
+ + sizeof("/trackID=123;seq=65535, ") ) + 1];
+ size_t infolen = 0;
+
for( int i = 0; i < ses->trackc; i++ )
{
rtsp_strack_t *tr = ses->trackv + i;
- if( !tr->playing
- && ( ( id == NULL ) || ( tr->id == id->sout_id ) ) )
+ if( ( id == NULL ) || ( tr->id == id->sout_id ) )
{
- tr->playing = VLC_TRUE;
- rtp_add_sink( tr->id, tr->fd );
+ if( !tr->playing )
+ {
+ tr->playing = VLC_TRUE;
+ rtp_add_sink( tr->id, tr->fd, VLC_FALSE );
+ }
+ infolen += sprintf( info + infolen,
+ "%s/trackID=%u;seq=%u, ", control,
+ rtp_get_num( tr->id ),
+ rtp_get_seq( tr->id ) );
}
}
+ if( infolen > 0 )
+ {
+ info[infolen - 2] = '\0'; /* remove trailing ", " */
+ httpd_MsgAdd( answer, "RTP-Info", "%s", info );
+ }
}
vlc_mutex_unlock( &rtsp->lock );