4
4
* Copyright (C) 2003-2004 the VideoLAN team
5
5
* Copyright © 2007 Rémi Denis-Courmont
7
* $Id: adb5696af5d0d283214979ac9db98c8462e47e11 $
7
* $Id: a1cc95317051da7d790541f7943e66f8f86d9a59 $
9
9
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
91
92
if( rtsp->psz_path == NULL )
94
assert( strlen( rtsp->psz_path ) > 0 );
95
if( rtsp->psz_path[strlen( rtsp->psz_path ) - 1] == '/' )
96
rtsp->track_fmt = "%strackID=%u";
98
rtsp->track_fmt = "%s/trackID=%u";
100
95
msg_Dbg( p_stream, "RTSP stream: host %s port %d at %s",
101
96
url->psz_host, rtsp->port, rtsp->psz_path );
172
168
/* Unicast session track */
173
169
struct rtsp_strack_t
175
sout_stream_id_t *id;
171
rtsp_stream_id_t *id;
177
char *RtspAppendTrackPath( rtsp_stream_id_t *id, const char *base )
179
const char *sep = strlen( base ) > 0 && base[strlen( base ) - 1] == '/' ?
183
if( asprintf( &url, "%s%strackID=%u", base, sep, id->track_id ) == -1 )
181
189
rtsp_stream_id_t *RtspAddId( rtsp_stream_t *rtsp, sout_stream_id_t *sid,
182
unsigned num, uint32_t ssrc,
183
191
/* Multicast stuff - TODO: cleanup */
184
192
const char *dst, int ttl,
185
193
unsigned loport, unsigned hiport )
187
char urlbuf[sizeof( "/trackID=123" ) + strlen( rtsp->psz_path )];
188
196
rtsp_stream_id_t *id = malloc( sizeof( *id ) );
189
197
httpd_url_t *url;
203
212
id->hiport = hiport;
206
/* FIXME: num screws up if any ES has been removed and re-added */
207
snprintf( urlbuf, sizeof( urlbuf ), rtsp->track_fmt, rtsp->psz_path,
215
urlbuf = RtspAppendTrackPath( id, rtsp->psz_path );
209
222
msg_Dbg( rtsp->owner, "RTSP: adding %s", urlbuf );
210
223
url = id->url = httpd_UrlNewUnique( rtsp->host, urlbuf, NULL, NULL, NULL );
212
226
if( url == NULL )
222
236
httpd_UrlCatch( url, HTTPD_MSG_GETPARAMETER, RtspCallbackId, (void *)id );
223
237
httpd_UrlCatch( url, HTTPD_MSG_TEARDOWN, RtspCallbackId, (void *)id );
238
254
for( int j = 0; j < ses->trackc; j++ )
240
if( ses->trackv[j].id == id->sout_id )
256
if( ses->trackv[j].id == id )
242
258
rtsp_strack_t *tr = ses->trackv + j;
243
rtp_del_sink( tr->id, tr->fd );
259
rtp_del_sink( tr->id->sout_id, tr->fd );
244
260
REMOVE_ELEM( ses->trackv, ses->trackc, j );
304
320
TAB_REMOVE( rtsp->sessionc, rtsp->sessionv, session );
306
322
for( i = 0; i < session->trackc; i++ )
307
rtp_del_sink( session->trackv[i].id, session->trackv[i].fd );
323
rtp_del_sink( session->trackv[i].id->sout_id, session->trackv[i].fd );
309
325
free( session->trackv );
382
398
answer->i_body = 0;
383
399
answer->p_body = NULL;
385
httpd_MsgAdd( answer, "Server", "%s", PACKAGE_STRING );
401
httpd_MsgAdd( answer, "Server", "VLC/%s", VERSION );
387
403
/* Date: is always allowed, and sometimes mandatory with RTSP/2.0. */
522
538
if( psz_session == NULL )
524
540
/* Create a dummy session ID */
525
snprintf( psz_sesbuf, sizeof( psz_sesbuf ), "%d",
541
snprintf( psz_sesbuf, sizeof( psz_sesbuf ), "%lu",
527
543
psz_session = psz_sesbuf;
529
545
answer->i_status = 200;
539
555
char ip[NI_MAXNUMERICHOST], src[NI_MAXNUMERICHOST];
540
556
rtsp_session_t *ses = NULL;
541
rtsp_strack_t track = { id->sout_id, -1, false };
557
rtsp_strack_t track = { id, -1, false };
544
560
if( httpd_ClientIP( cl, ip ) == NULL )
577
/* Ignore any unexpected incoming packet */
578
setsockopt (track.fd, SOL_SOCKET, SO_RCVBUF, &(int){ 0 },
561
580
net_GetSockAddress( track.fd, src, &sport );
563
582
vlc_mutex_lock( &rtsp->lock );
634
653
ses = RtspClientGet( rtsp, psz_session );
635
654
if( ses != NULL )
656
/* The "trackID" part must match what is done in
657
* RtspAppendTrackPath() */
637
658
/* FIXME: we really need to limit the number of tracks... */
638
659
char info[ses->trackc * ( strlen( control )
639
660
+ sizeof("url=/trackID=123;seq=65535;"
640
661
"rtptime=4294967295, ") ) + 1];
641
662
size_t infolen = 0;
663
int64_t ts = rtp_get_ts( rtsp->owner );
643
665
for( int i = 0; i < ses->trackc; i++ )
645
667
rtsp_strack_t *tr = ses->trackv + i;
646
if( ( id == NULL ) || ( tr->id == id->sout_id ) )
668
if( ( id == NULL ) || ( tr->id == id ) )
648
671
if( !tr->playing )
650
673
tr->playing = true;
651
rtp_add_sink( tr->id, tr->fd, false );
674
rtp_add_sink( tr->id->sout_id, tr->fd, false,
653
/* This is racy, as the first packets may have
654
* already been sent before we fetch this info:
655
* these extra packets might confuse the client. */
678
seq = rtp_get_seq( tr->id->sout_id );
679
char *url = RtspAppendTrackPath( tr->id, control );
656
680
infolen += sprintf( info + infolen,
657
"url=%s/trackID=%u;seq=%u;rtptime=%u, ",
659
rtp_get_num( tr->id ),
660
rtp_get_seq( tr->id ),
661
rtp_get_ts( tr->id ) );
681
"url=%s;seq=%u;rtptime=%u, ",
682
url != NULL ? url : "", seq,
683
rtp_compute_ts( tr->id->sout_id, ts ) );
664
687
if( infolen > 0 )
709
732
else /* Delete one track from the session */
710
733
for( int i = 0; i < ses->trackc; i++ )
712
if( ses->trackv[i].id == id->sout_id )
735
if( ses->trackv[i].id == id )
714
737
rtp_del_sink( id->sout_id, ses->trackv[i].fd );
715
738
REMOVE_ELEM( ses->trackv, ses->trackc, i );