Changeset 35754abaa2da8d632456163379721ab6446a0d0c

Show
Ignore:
Timestamp:
24/08/07 17:47:34 (1 year ago)
Author:
Rémi Denis-Courmont <rem@videolan.org>
git-committer:
Rémi Denis-Courmont <rem@videolan.org> 1187970454 +0000
git-parent:

[a556cc82222056f728f8e8d889600035f8fde2df]

git-author:
Rémi Denis-Courmont <rem@videolan.org> 1187970454 +0000
Message:

Isolate RTSP from the rest of RTP

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • modules/stream_out/rtp.c

    r685ca38 r35754ab  
    167167static int HttpSetup( sout_stream_t *p_stream, vlc_url_t * ); 
    168168 
     169struct sout_stream_sys_t 
     170{ 
     171    /* sdp */ 
     172    int64_t i_sdp_id; 
     173    int     i_sdp_version; 
     174    char    *psz_sdp; 
     175    vlc_mutex_t  lock_sdp; 
     176 
     177    char        *psz_session_name; 
     178    char        *psz_session_description; 
     179    char        *psz_session_url; 
     180    char        *psz_session_email; 
     181 
     182    /* */ 
     183    vlc_bool_t b_export_sdp_file; 
     184    char *psz_sdp_file; 
     185    /* sap */ 
     186    vlc_bool_t b_export_sap; 
     187    session_descriptor_t *p_session; 
     188 
     189    httpd_host_t *p_httpd_host; 
     190    httpd_file_t *p_httpd_file; 
     191 
     192    rtsp_stream_t *rtsp; 
     193 
     194    /* */ 
     195    char *psz_destination; 
     196    int  i_port; 
     197    int  i_port_audio; 
     198    int  i_port_video; 
     199    int  i_ttl; 
     200    vlc_bool_t b_latm; 
     201 
     202    /* when need to use a private one or when using muxer */ 
     203    int i_payload_type; 
     204 
     205    /* in case we do TS/PS over rtp */ 
     206    sout_mux_t        *p_mux; 
     207    sout_access_out_t *p_access; 
     208    int               i_mtu; 
     209    sout_access_out_t *p_grab; 
     210    uint16_t          i_sequence; 
     211    uint32_t          i_timestamp_start; 
     212    uint8_t           ssrc[4]; 
     213    block_t           *packet; 
     214 
     215    /* */ 
     216    vlc_mutex_t      lock_es; 
     217    int              i_es; 
     218    sout_stream_id_t **es; 
     219}; 
     220 
     221typedef int (*pf_rtp_packetizer_t)( sout_stream_t *, sout_stream_id_t *, 
     222                                    block_t * ); 
     223 
    169224struct sout_stream_id_t 
    170225{ 
     
    301356    p_sys->i_es = 0; 
    302357    p_sys->es   = NULL; 
    303     p_sys->i_rtsp = 0; 
    304     p_sys->rtsp   = NULL; 
     358    p_sys->rtsp = NULL; 
    305359    p_sys->psz_sdp = NULL; 
    306360 
     
    315369    p_sys->p_httpd_host = NULL; 
    316370    p_sys->p_httpd_file = NULL; 
    317     p_sys->p_rtsp_host  = NULL; 
    318     p_sys->p_rtsp_url   = NULL; 
    319     p_sys->psz_rtsp_control = NULL; 
    320     p_sys->psz_rtsp_path = NULL; 
    321371 
    322372    vlc_mutex_init( p_stream, &p_sys->lock_sdp ); 
     
    548598    } 
    549599 
    550     RtspUnsetup( p_stream ); 
     600    if( p_sys->rtsp != NULL ) 
     601        RtspUnsetup( p_sys->rtsp ); 
    551602 
    552603    vlc_mutex_destroy( &p_sys->lock_sdp ); 
     
    598649        { 
    599650            msg_Err( p_stream, "you can use sdp=http:// only once" ); 
    600             return
     651            goto out
    601652        } 
    602653 
    603654        if( HttpSetup( p_stream, &url ) ) 
    604655        { 
    605             msg_Err( p_stream, "cannot export sdp as http" ); 
     656            msg_Err( p_stream, "cannot export SDP as HTTP" ); 
    606657        } 
    607658    } 
    608659    else if( url.psz_protocol && !strcasecmp( url.psz_protocol, "rtsp" ) ) 
    609660    { 
    610         if( p_sys->p_rtsp_url
     661        if( p_sys->rtsp != NULL
    611662        { 
    612663            msg_Err( p_stream, "you can use sdp=rtsp:// only once" ); 
    613             return
     664            goto out
    614665        } 
    615666 
    616667        /* FIXME test if destination is multicast or no destination at all FIXME */ 
    617         if( RtspSetup( p_stream, &url ) ) 
    618         { 
    619             msg_Err( p_stream, "cannot export sdp as rtsp" ); 
     668        p_sys->rtsp = RtspSetup( p_stream, &url ); 
     669        if( p_sys->rtsp == NULL ) 
     670        { 
     671            msg_Err( p_stream, "cannot export SDP as RTSP" ); 
    620672        } 
    621673    } 
     
    631683        { 
    632684            msg_Err( p_stream, "you can use sdp=file:// only once" ); 
    633             return
     685            goto out
    634686        } 
    635687        p_sys->b_export_sdp_file = VLC_TRUE; 
     
    644696                  url.psz_protocol ); 
    645697    } 
     698 
     699out: 
    646700    vlc_UrlClean( &url ); 
    647701} 
     
    663717           a= x-plgroup: (missing) 
    664718           RTP packets need to get the correct src IP address  */ 
    665 /*static*/ char *SDPGenerate( const sout_stream_t *p_stream, 
    666                           const char *psz_destination, vlc_bool_t b_rtsp ) 
    667 
    668     sout_stream_sys_t *p_sys = p_stream->p_sys; 
    669     int i_size; 
     719/*static*/ 
     720char *SDPGenerate( const sout_stream_t *p_stream, const char *rtsp_url ) 
     721
     722    const sout_stream_sys_t *p_sys = p_stream->p_sys; 
     723    size_t i_size; 
     724    const char *psz_destination = p_sys->psz_destination; 
    670725    char *psz_sdp, *p, ipv; 
    671726    int i; 
     
    703758            i_size += strlen( "a=fmtp:* *\r\n" ) + strlen( id->psz_fmtp ) + 10; 
    704759        } 
    705         if( b_rtsp
    706         { 
    707             i_size += strlen( "a=control:*/trackID=*\r\n" ) + strlen( p_sys->psz_rtsp_control ) + 10; 
     760        if( rtsp_url != NULL
     761        { 
     762            i_size += strlen( "a=control:*/trackID=*\r\n" ) + strlen( rtsp_url ) + 10; 
    708763        } 
    709764    } 
     
    775830                          id->psz_fmtp ); 
    776831        } 
    777         if( b_rtsp
     832        if( rtsp_url != NULL
    778833        { 
    779834            p += sprintf( p, "a=control:/trackID=%d\r\n", i ); 
     
    783838    { 
    784839       p += sprintf( p, "m=video %d RTP/AVP %d\r\n", 
    785                  p_sys->i_port, p_sys->i_payload_type ); 
     840                     p_sys->i_port, p_sys->i_payload_type ); 
    786841    } 
    787842 
     
    11371192    msg_Dbg( p_stream, "maximum RTP packet size: %d bytes", id->i_mtu ); 
    11381193 
    1139     if( p_sys->p_rtsp_url ) 
    1140         id->rtsp_id = RtspAddId( p_stream, id, id->i_port, id->i_port + 1 ); 
     1194    if( p_sys->rtsp != NULL ) 
     1195        id->rtsp_id = RtspAddId( p_sys->rtsp, id, p_sys->i_es, 
     1196                                 p_sys->psz_destination, 
     1197                                 p_sys->i_ttl, id->i_port, id->i_port + 1 ); 
    11411198 
    11421199    /* Update p_sys context */ 
     
    11451202    vlc_mutex_unlock( &p_sys->lock_es ); 
    11461203 
    1147     psz_sdp = SDPGenerate( p_stream, p_sys->psz_destination, VLC_FALSE ); 
     1204    psz_sdp = SDPGenerate( p_stream, NULL ); 
    11481205 
    11491206    vlc_mutex_lock( &p_sys->lock_sdp ); 
     
    11971254    } 
    11981255    if( id->rtsp_id ) 
    1199         RtspDelId( p_stream, id->rtsp_id ); 
     1256        RtspDelId( p_sys->rtsp, id->rtsp_id ); 
    12001257 
    12011258    vlc_mutex_destroy( &id->lock_sink ); 
     
    14781535void rtp_del_sink( sout_stream_id_t *id, sout_access_out_t *access ) 
    14791536{ 
     1537    /* NOTE: must be safe to use if access is not a sink to id */ 
    14801538    vlc_mutex_lock( &id->lock_sink ); 
    14811539    TAB_REMOVE( id->i_sink, id->sink, access ); 
  • modules/stream_out/rtp.h

    r685ca38 r35754ab  
    2323 *****************************************************************************/ 
    2424 
    25 /*ypedef struct rtsp_stream_t rtsp_stream_t;*/ 
     25typedef struct rtsp_stream_t rtsp_stream_t; 
    2626typedef struct rtsp_stream_id_t rtsp_stream_id_t; 
    27 typedef struct rtsp_client_t rtsp_client_t; 
    2827 
    29 int RtspSetup( sout_stream_t *p_stream, const vlc_url_t *url ); 
    30 void RtspUnsetup( sout_stream_t *p_stream ); 
     28rtsp_stream_t *RtspSetup( sout_stream_t *p_stream, const vlc_url_t *url ); 
     29void RtspUnsetup( rtsp_stream_t *rtsp ); 
    3130 
    32 rtsp_stream_id_t *RtspAddId( sout_stream_t *p_stream, sout_stream_id_t *sid, 
     31rtsp_stream_id_t *RtspAddId( rtsp_stream_t *rtsp, sout_stream_id_t *sid, 
     32                             unsigned i, 
     33                             const char *dst, int ttl, 
    3334                             unsigned loport, unsigned hiport ); 
    34 void RtspDelId( sout_stream_t *p_stream, rtsp_stream_id_t * ); 
     35void RtspDelId( rtsp_stream_t *rtsp, rtsp_stream_id_t * ); 
    3536 
    36 char *SDPGenerate( const sout_stream_t *p_stream, 
    37                    const char *psz_destination, vlc_bool_t b_rtsp ); 
     37char *SDPGenerate( const sout_stream_t *p_stream, const char *rtsp_url ); 
    3838 
    3939int rtp_add_sink( sout_stream_id_t *id, sout_access_out_t *access ); 
    4040void rtp_del_sink( sout_stream_id_t *id, sout_access_out_t *access ); 
    4141 
    42 typedef int (*pf_rtp_packetizer_t)( sout_stream_t *, sout_stream_id_t *, 
    43                                     block_t * ); 
    44  
    45 struct sout_stream_sys_t 
    46 { 
    47     /* sdp */ 
    48     int64_t i_sdp_id; 
    49     int     i_sdp_version; 
    50     char    *psz_sdp; 
    51     vlc_mutex_t  lock_sdp; 
    52  
    53     char        *psz_session_name; 
    54     char        *psz_session_description; 
    55     char        *psz_session_url; 
    56     char        *psz_session_email; 
    57  
    58     /* */ 
    59     vlc_bool_t b_export_sdp_file; 
    60     char *psz_sdp_file; 
    61     /* sap */ 
    62     vlc_bool_t b_export_sap; 
    63     session_descriptor_t *p_session; 
    64  
    65     httpd_host_t *p_httpd_host; 
    66     httpd_file_t *p_httpd_file; 
    67  
    68     httpd_host_t *p_rtsp_host; 
    69     httpd_url_t  *p_rtsp_url; 
    70     char         *psz_rtsp_control; 
    71     char         *psz_rtsp_path; 
    72  
    73     /* */ 
    74     char *psz_destination; 
    75     int  i_port; 
    76     int  i_port_audio; 
    77     int  i_port_video; 
    78     int  i_ttl; 
    79     vlc_bool_t b_latm; 
    80  
    81     /* when need to use a private one or when using muxer */ 
    82     int i_payload_type; 
    83  
    84     /* in case we do TS/PS over rtp */ 
    85     sout_mux_t        *p_mux; 
    86     sout_access_out_t *p_access; 
    87     int               i_mtu; 
    88     sout_access_out_t *p_grab; 
    89     uint16_t          i_sequence; 
    90     uint32_t          i_timestamp_start; 
    91     uint8_t           ssrc[4]; 
    92     block_t           *packet; 
    93  
    94     /* */ 
    95     vlc_mutex_t      lock_es; 
    96     int              i_es; 
    97     sout_stream_id_t **es; 
    98  
    99     /* */ 
    100     int              i_rtsp; 
    101     rtsp_client_t    **rtsp; 
    102 }; 
  • modules/stream_out/rtsp.c

    r685ca38 r35754ab  
    3131#include <vlc_url.h> 
    3232#include <vlc_network.h> 
     33#include <assert.h> 
    3334 
    3435#include "rtp.h" 
    3536 
    36 /* For unicast/interleaved streaming */ 
    37 struct rtsp_client_t 
    38 
    39     char    *psz_session; 
    40     int64_t i_last; /* for timeout */ 
    41  
    42     /* is it in "play" state */ 
    43     vlc_bool_t b_playing; 
    44  
    45     /* output (id-access) */ 
    46     int               i_id; 
    47     sout_stream_id_t  **id; 
    48     int               i_access; 
    49     sout_access_out_t **access; 
     37typedef struct rtsp_session_t rtsp_session_t; 
     38 
     39struct rtsp_stream_t 
     40
     41    vlc_mutex_t     lock; 
     42    sout_stream_t  *owner; 
     43    httpd_host_t   *host; 
     44    httpd_url_t    *url; 
     45    char           *psz_control; 
     46    char           *psz_path; 
     47 
     48    int             sessionc; 
     49    rtsp_session_t **sessionv; 
    5050}; 
     51 
    5152 
    5253static int  RtspCallback( httpd_callback_sys_t *p_args, 
     
    5657                            httpd_client_t *cl, 
    5758                            httpd_message_t *answer, httpd_message_t *query ); 
    58 static void RtspClientDel( sout_stream_t *p_stream, rtsp_client_t *rtsp ); 
    59  
    60 int RtspSetup( sout_stream_t *p_stream, const vlc_url_t *url ) 
    61 
    62     sout_stream_sys_t *p_sys = p_stream->p_sys; 
    63  
    64     msg_Dbg( p_stream, "rtsp setup: %s : %d / %s\n", url->psz_host, url->i_port, url->psz_path ); 
    65  
    66     p_sys->p_rtsp_host = httpd_HostNew( VLC_OBJECT(p_stream), url->psz_host, url->i_port > 0 ? url->i_port : 554 ); 
    67     if( p_sys->p_rtsp_host == NULL ) 
    68     { 
    69         return VLC_EGENERIC; 
    70     } 
    71  
    72     p_sys->psz_rtsp_path = strdup( url->psz_path ? url->psz_path : "/" ); 
    73     p_sys->psz_rtsp_control = malloc (strlen( url->psz_host ) + 20 + strlen( p_sys->psz_rtsp_path ) + 1 ); 
    74     sprintf( p_sys->psz_rtsp_control, "rtsp://%s:%d%s", 
    75              url->psz_host,  url->i_port > 0 ? url->i_port : 554, p_sys->psz_rtsp_path ); 
    76  
    77     p_sys->p_rtsp_url = httpd_UrlNewUnique( p_sys->p_rtsp_host, p_sys->psz_rtsp_path, NULL, NULL, NULL ); 
    78     if( p_sys->p_rtsp_url == NULL ) 
    79     { 
    80         return VLC_EGENERIC; 
    81     } 
    82     httpd_UrlCatch( p_sys->p_rtsp_url, HTTPD_MSG_DESCRIBE, RtspCallback, (void*)p_stream ); 
    83     httpd_UrlCatch( p_sys->p_rtsp_url, HTTPD_MSG_SETUP,    RtspCallback, (void*)p_stream ); 
    84     httpd_UrlCatch( p_sys->p_rtsp_url, HTTPD_MSG_PLAY,     RtspCallback, (void*)p_stream ); 
    85     httpd_UrlCatch( p_sys->p_rtsp_url, HTTPD_MSG_PAUSE,    RtspCallback, (void*)p_stream ); 
    86     httpd_UrlCatch( p_sys->p_rtsp_url, HTTPD_MSG_TEARDOWN, RtspCallback, (void*)p_stream ); 
    87  
    88     return VLC_SUCCESS; 
    89 
    90  
    91  
    92 void RtspUnsetup( sout_stream_t *p_stream ) 
    93 
    94     sout_stream_sys_t *p_sys = p_stream->p_sys; 
    95     while( p_sys->i_rtsp > 0 ) 
    96         RtspClientDel( p_stream, p_sys->rtsp[0] ); 
    97  
    98     if( p_sys->p_rtsp_url ) 
    99         httpd_UrlDelete( p_sys->p_rtsp_url ); 
    100  
    101     if( p_sys->p_rtsp_host ) 
    102         httpd_HostDelete( p_sys->p_rtsp_host ); 
     59static void RtspClientDel( rtsp_stream_t *rtsp, rtsp_session_t *session ); 
     60 
     61rtsp_stream_t *RtspSetup( sout_stream_t *p_stream, const vlc_url_t *url ) 
     62
     63    rtsp_stream_t *rtsp = malloc( sizeof( *rtsp ) ); 
     64 
     65    if( rtsp == NULL ) 
     66        return NULL; 
     67 
     68    rtsp->owner = p_stream; 
     69    rtsp->sessionc = 0; 
     70    rtsp->sessionv = NULL; 
     71    vlc_mutex_init( p_stream, &rtsp->lock ); 
     72 
     73    msg_Dbg( p_stream, "rtsp setup: %s : %d / %s\n", 
     74             url->psz_host, url->i_port, url->psz_path ); 
     75 
     76    rtsp->psz_path = strdup( url->psz_path ? url->psz_path : "/" ); 
     77    if( rtsp->psz_path == NULL ) 
     78        goto error; 
     79 
     80    if( asprintf( &rtsp->psz_control, "rtsp://%s:%d%s", 
     81                  url->psz_host,  url->i_port > 0 ? url->i_port : 554, 
     82                  rtsp->psz_path ) == -1 ) 
     83    { 
     84        rtsp->psz_control = NULL; 
     85        goto error; 
     86    } 
     87 
     88    rtsp->host = httpd_HostNew( VLC_OBJECT(p_stream), url->psz_host, 
     89                                url->i_port > 0 ? url->i_port : 554 ); 
     90    if( rtsp->host == NULL ) 
     91        goto error; 
     92 
     93    rtsp->url = httpd_UrlNewUnique( rtsp->host, rtsp->psz_path, NULL, NULL, 
     94                                    NULL ); 
     95    if( rtsp->url == NULL ) 
     96        goto error; 
     97 
     98    httpd_UrlCatch( rtsp->url, HTTPD_MSG_DESCRIBE, RtspCallback, (void*)rtsp ); 
     99    httpd_UrlCatch( rtsp->url, HTTPD_MSG_SETUP,    RtspCallback, (void*)rtsp ); 
     100    httpd_UrlCatch( rtsp->url, HTTPD_MSG_PLAY,     RtspCallback, (void*)rtsp ); 
     101    httpd_UrlCatch( rtsp->url, HTTPD_MSG_PAUSE,    RtspCallback, (void*)rtsp ); 
     102    httpd_UrlCatch( rtsp->url, HTTPD_MSG_TEARDOWN, RtspCallback, (void*)rtsp ); 
     103    return rtsp; 
     104 
     105error: 
     106    RtspUnsetup( rtsp ); 
     107    return NULL; 
     108
     109 
     110 
     111void RtspUnsetup( rtsp_stream_t *rtsp ) 
     112
     113    while( rtsp->sessionc > 0 ) 
     114        RtspClientDel( rtsp, rtsp->sessionv[0] ); 
     115 
     116    if( rtsp->url ) 
     117        httpd_UrlDelete( rtsp->url ); 
     118 
     119    if( rtsp->host ) 
     120        httpd_HostDelete( rtsp->host ); 
     121 
     122    vlc_mutex_destroy( &rtsp->lock ); 
    103123} 
    104124 
     
    106126struct rtsp_stream_id_t 
    107127{ 
    108     sout_stream_t    *sout_stream; 
     128    rtsp_stream_t    *stream; 
    109129    sout_stream_id_t *sout_id; 
    110130    httpd_url_t      *url; 
     131    const char       *dst; 
     132    int               ttl; 
    111133    unsigned          loport, hiport; 
    112134}; 
    113135 
    114 rtsp_stream_id_t *RtspAddId( sout_stream_t *p_stream, sout_stream_id_t *sid, 
     136 
     137/* For unicast streaming */ 
     138struct rtsp_session_t 
     139
     140    rtsp_stream_t *stream; 
     141 
     142    /* is it in "play" state */ 
     143    vlc_bool_t     b_playing; 
     144 
     145    /* output (id-access) */ 
     146    int               i_id; 
     147    sout_stream_id_t  **id; 
     148    int               i_access; 
     149    sout_access_out_t **access; 
     150 
     151    char name[0]; 
     152}; 
     153 
     154 
     155rtsp_stream_id_t *RtspAddId( rtsp_stream_t *rtsp, sout_stream_id_t *sid, 
     156                             unsigned num, 
     157                             /* Multicast stuff - TODO: cleanup */ 
     158                             const char *dst, int ttl, 
    115159                             unsigned loport, unsigned hiport ) 
    116160{ 
    117     sout_stream_sys_t *p_sys = p_stream->p_sys; 
    118     char psz_urlc[strlen( p_sys->psz_rtsp_control ) + 1 + 10]; 
     161    char urlbuf[strlen( rtsp->psz_control ) + 1 + 10]; 
    119162    rtsp_stream_id_t *id = malloc( sizeof( *id ) ); 
    120163    httpd_url_t *url; 
     
    123166        return NULL; 
    124167 
    125     id->sout_stream = p_stream
     168    id->stream = rtsp
    126169    id->sout_id = sid; 
    127     id->loport = loport; 
    128     id->hiport = loport; 
    129  
    130     sprintf( psz_urlc, "%s/trackID=%d", p_sys->psz_rtsp_path, p_sys->i_es ); 
    131     msg_Dbg( p_stream, "RTSP: adding %s\n", psz_urlc ); 
    132     url = id->url = 
    133         httpd_UrlNewUnique( p_sys->p_rtsp_host, psz_urlc, NULL, NULL, NULL ); 
     170    /* TODO: can we assume that this need not be strdup'd? */ 
     171    id->dst = dst; 
     172    if( id->dst != NULL ) 
     173    { 
     174        id->ttl = ttl; 
     175        id->loport = loport; 
     176        id->hiport = hiport; 
     177    } 
     178 
     179    sprintf( urlbuf, "%s/trackID=%d", rtsp->psz_path, num ); 
     180    msg_Dbg( rtsp->owner, "RTSP: adding %s\n", urlbuf ); 
     181    url = id->url = httpd_UrlNewUnique( rtsp->host, urlbuf, NULL, NULL, NULL ); 
    134182 
    135183    if( url == NULL ) 
     
    149197 
    150198 
    151 void RtspDelId( sout_stream_t *p_stream, rtsp_stream_id_t *id ) 
    152 
    153    httpd_UrlDelete( id->url ); 
    154    free( id ); 
    155 
    156  
    157  
    158 static rtsp_client_t *RtspClientNew( sout_stream_t *p_stream, const char *psz_session ) 
    159 
    160     rtsp_client_t *rtsp = malloc( sizeof( rtsp_client_t )); 
    161  
    162     rtsp->psz_session = strdup( psz_session ); 
    163     rtsp->i_last = 0; 
    164     rtsp->b_playing = VLC_FALSE; 
    165     rtsp->i_id = 0; 
    166     rtsp->id = NULL; 
    167     rtsp->i_access = 0; 
    168     rtsp->access = NULL; 
    169  
    170     TAB_APPEND( p_stream->p_sys->i_rtsp, p_stream->p_sys->rtsp, rtsp ); 
    171  
    172     return rtsp; 
    173 
    174  
    175  
    176 static rtsp_client_t *RtspClientGet( sout_stream_t *p_stream, const char *psz_session ) 
     199void RtspDelId( rtsp_stream_t *rtsp, rtsp_stream_id_t *id ) 
     200
     201    vlc_mutex_lock( &rtsp->lock ); 
     202    for( int i = 0; i < rtsp->sessionc; i++ ) 
     203    { 
     204        rtsp_session_t *ses = rtsp->sessionv[i]; 
     205 
     206        for( int j = 0; j < ses->i_id; j++ ) 
     207        { 
     208            if( ses->id[j] == id->sout_id ) 
     209            { 
     210                REMOVE_ELEM( ses->id, ses->i_id, j ); 
     211 
     212                assert( ses->access[j] != NULL ); 
     213                sout_AccessOutDelete( ses->access[j] ); 
     214                REMOVE_ELEM( ses->access, ses->i_access, j ); 
     215                /* FIXME: are we supposed to notify the client? */ 
     216            } 
     217        } 
     218    } 
     219 
     220    vlc_mutex_unlock( &rtsp->lock ); 
     221    httpd_UrlDelete( id->url ); 
     222    free( id ); 
     223
     224 
     225 
     226/** rtsp must be locked */ 
     227static 
     228rtsp_session_t *RtspClientNew( rtsp_stream_t *rtsp, const char *name ) 
     229
     230    rtsp_session_t *s = malloc( sizeof( *s ) + strlen( name ) + 1 ); 
     231 
     232    s->stream = rtsp; 
     233    s->b_playing = VLC_FALSE; 
     234    s->i_id = s->i_access = 0; 
     235    s->id = NULL; 
     236    s->access = NULL; 
     237    strcpy( s->name, name ); 
     238 
     239    TAB_APPEND( rtsp->sessionc, rtsp->sessionv, s ); 
     240 
     241    return s; 
     242
     243 
     244 
     245/** rtsp must be locked */ 
     246static 
     247rtsp_session_t *RtspClientGet( rtsp_stream_t *rtsp, const char *name ) 
    177248{ 
    178249    int i; 
    179250 
    180     if( !psz_session ) return NULL; 
    181  
    182     for( i = 0; i < p_stream->p_sys->i_rtsp; i++ ) 
    183     { 
    184         if( !strcmp( p_stream->p_sys->rtsp[i]->psz_session, psz_session )
    185        
    186             return p_stream->p_sys->rtsp[i]; 
    187         } 
     251    if( name == NULL ) 
     252        return NULL; 
     253 
     254    /* FIXME: use a hash/dictionary */ 
     255    for( i = 0; i < rtsp->sessionc; i++
     256   
     257        if( !strcmp( rtsp->sessionv[i]->name, name ) ) 
     258            return rtsp->sessionv[i]; 
    188259    } 
    189260    return NULL; 
     
    191262 
    192263 
    193 static void RtspClientDel( sout_stream_t *p_stream, rtsp_client_t *rtsp ) 
     264/** rtsp must be locked */ 
     265static 
     266void RtspClientDel( rtsp_stream_t *rtsp, rtsp_session_t *session ) 
    194267{ 
    195268    int i; 
    196     TAB_REMOVE( p_stream->p_sys->i_rtsp, p_stream->p_sys->rtsp, rtsp ); 
    197  
    198     for( i = 0; i < rtsp->i_access; i++ ) 
    199     { 
    200         sout_AccessOutDelete( rtsp->access[i] ); 
    201     } 
    202     if( rtsp->id )     free( rtsp->id ); 
    203     if( rtsp->access ) free( rtsp->access ); 
    204  
    205     free( rtsp->psz_session ); 
    206     free( rtsp ); 
     269    TAB_REMOVE( rtsp->sessionc, rtsp->sessionv, session ); 
     270 
     271    for( i = 0; i < session->i_access; i++ ) 
     272    { 
     273        rtp_del_sink( session->id[i], session->access[i] ); 
     274        sout_AccessOutDelete( session->access[i] ); 
     275    } 
     276 
     277    free( session->id ); 
     278    free( session->access ); 
     279    free( session ); 
    207280} 
    208281 
     
    213286                          httpd_message_t *answer, httpd_message_t *query ) 
    214287{ 
    215     sout_stream_t *p_stream = (sout_stream_t*)p_args; 
    216     sout_stream_sys_t *p_sys = p_stream->p_sys; 
    217     char *psz_destination = p_sys->psz_destination; 
    218     const char *psz_session = NULL; 
    219     const char *psz_cseq = NULL; 
     288    rtsp_stream_t *rtsp = (rtsp_stream_t *)p_args; 
     289    const char *psz_session = NULL, *psz_cseq; 
    220290 
    221291    if( answer == NULL || query == NULL ) 
     
    242312        case HTTPD_MSG_DESCRIBE: 
    243313        { 
    244             char *psz_sdp = SDPGenerate( p_stream, psz_destination, VLC_TRUE ); 
     314            char *psz_sdp = SDPGenerate( rtsp->owner, rtsp->psz_control ); 
    245315 
    246316            answer->i_status = 200; 
    247317            httpd_MsgAdd( answer, "Content-Type",  "%s", "application/sdp" ); 
    248             httpd_MsgAdd( answer, "Content-Base",  "%s", p_sys->psz_rtsp_control ); 
     318            httpd_MsgAdd( answer, "Content-Base",  "%s", rtsp->psz_control ); 
    249319            answer->p_body = (uint8_t *)psz_sdp; 
    250320            answer->i_body = strlen( psz_sdp ); 
     
    258328        case HTTPD_MSG_PLAY: 
    259329        { 
    260             rtsp_client_t *rtsp
     330            rtsp_session_t *ses
    261331            answer->i_status = 200; 
    262332 
    263333            psz_session = httpd_MsgGet( query, "Session" ); 
    264             rtsp = RtspClientGet( p_stream, psz_session ); 
    265             if( rtsp && !rtsp->b_playing ) 
     334 
     335            vlc_mutex_lock( &rtsp->lock ); 
     336            ses = RtspClientGet( rtsp, psz_session ); 
     337            if( ( ses != NULL ) && !ses->b_playing ) 
    266338            { 
    267                 int i_id; 
    268339                /* FIXME */ 
    269                 rtsp->b_playing = VLC_TRUE; 
    270  
    271                 vlc_mutex_lock( &p_sys->lock_es ); 
    272                 for( i_id = 0; i_id < rtsp->i_id; i_id++ ) 
    273                 { 
    274                     sout_stream_id_t *id = rtsp->id[i_id]; 
    275                     int i; 
    276  
    277                     for( i = 0; i < p_sys->i_es; i++ ) 
    278                     { 
    279                         if( id == p_sys->es[i] ) 
    280                             break; 
    281                     } 
    282                     if( i >= p_sys->i_es ) continue; 
    283  
    284                     rtp_add_sink( id, rtsp->access[i_id] ); 
    285                 } 
    286                 vlc_mutex_unlock( &p_sys->lock_es ); 
     340                ses->b_playing = VLC_TRUE; 
     341 
     342                for( int i_id = 0; i_id < ses->i_id; i_id++ ) 
     343                    rtp_add_sink( ses->id[i_id], ses->access[i_id] ); 
    287344            } 
     345            vlc_mutex_unlock( &rtsp->lock ); 
    288346            break; 
    289347        } 
     
    296354        case HTTPD_MSG_TEARDOWN: 
    297355        { 
    298             rtsp_client_t *rtsp
     356            rtsp_session_t *ses
    299357 
    300358            /* for now only multicast so easy again */ 
     
    302360 
    303361            psz_session = httpd_MsgGet( query, "Session" ); 
    304             rtsp = RtspClientGet( p_stream, psz_session ); 
    305             if( rtsp ) 
    306             { 
    307                 int i_id; 
    308  
    309                 vlc_mutex_lock( &p_sys->lock_es ); 
    310                 for( i_id = 0; i_id < rtsp->i_id; i_id++ ) 
    311                 { 
    312                     sout_stream_id_t *id = rtsp->id[i_id]; 
    313                     int i; 
    314  
    315                     for( i = 0; i < p_sys->i_es; i++ ) 
    316                     { 
    317                         if( id == p_sys->es[i] ) 
    318                             break; 
    319                     } 
    320                     if( i >= p_sys->i_es ) continue; 
    321  
    322                     rtp_del_sink( id, rtsp->access[i_id] ); 
    323                 } 
    324                 vlc_mutex_unlock( &p_sys->lock_es ); 
    325  
    326                 RtspClientDel( p_stream, rtsp ); 
    327             } 
     362 
     363            vlc_mutex_lock( &rtsp->lock ); 
     364            ses = RtspClientGet( rtsp, psz_session ); 
     365            if( ses != NULL ) 
     366                RtspClientDel( rtsp, ses ); 
     367            vlc_mutex_unlock( &rtsp->lock ); 
    328368            break; 
    329369        } 
     
    377417                           httpd_message_t *answer, httpd_message_t *query ) 
    378418{ 
    379     rtsp_stream_id_t *id = (rtsp_stream_id_t*)p_args; 
    380     sout_stream_t    *p_stream = id->sout_stream
     419    rtsp_stream_id_t *id = (rtsp_stream_id_t *)p_args; 
     420    sout_stream_t    *p_stream = id->stream->owner
    381421    sout_stream_id_t *sid = id->sout_id; 
    382     sout_stream_sys_t *p_sys = p_stream->p_sys; 
    383422    char psz_session_init[21]; 
    384423    const char *psz_session; 
     
    484523                if( b_multicast ) 
    485524                { 
    486                     if( p_sys->psz_destination == NULL ) 
     525                    const char *dst = id->dst; 
     526                    if( dst == NULL ) 
    487527                        continue; 
    488528 
     
    492532                                  "RTP/AVP/UDP;destination=%s;port=%u-%u;" 
    493533                                  "ttl=%d;mode=play", 
    494                                   p_sys->psz_destination, id->loport, 
    495                                   id->hiport, 
    496                                   ( p_sys->i_ttl > 0 ) ? p_sys->i_ttl : 1 ); 
     534                                  dst, id->loport, id->hiport, 
     535                                  ( id->ttl > 0 ) ? id->ttl : 1 ); 
    497536                } 
    498537                else 
    499538                { 
    500                     char ip[NI_MAXNUMERICHOST], psz_access[22], 
    501                          url[NI_MAXNUMERICHOST + 8]
     539                    char ip[NI_MAXNUMERICHOST], url[NI_MAXNUMERICHOST + 8]; 
     540                    static const char access[] = "udp{raw,rtcp}"
    502541                    sout_access_out_t *p_access; 
    503                     rtsp_client_t *rtsp = NULL; 
    504  
    505                     if( ( hiport - loport ) != ( id->hiport - id->loport ) ) 
    506                         continue; 
    507  
    508                     if( psz_session == NULL ) 
    509                     { 
    510                         psz_session = psz_session_init; 
    511                         rtsp = RtspClientNew( p_stream, psz_session ); 
    512                     } 
    513                     else 
    514                     { 
    515                         /* FIXME: we probably need to remove an access out, 
    516                          * if there is already one for the same ID */ 
    517                         rtsp = RtspClientGet( p_stream, psz_session ); 
    518                         if( rtsp == NULL ) 
    519                         { 
    520                             answer->i_status = 454; 
    521                             continue; 
    522                         } 
    523                     } 
     542                    rtsp_session_t *ses = NULL; 
    524543 
    525544                    if( httpd_ClientIP( cl, ip ) == NULL ) 
     
    528547                        continue; 
    529548                    } 
    530  
    531                     if( p_sys->i_ttl > 0 ) 
    532                         snprintf( psz_access, sizeof( psz_access ), 
    533                                   "udp{raw,rtcp,ttl=%d}", p_sys->i_ttl ); 
    534                     else 
    535                         strcpy( psz_access, "udp{raw,rtcp}" ); 
    536549 
    537550                    snprintf( url, sizeof( url ), 
     
    539552                              ip, loport ); 
    540553 
    541                     p_access = sout_AccessOutNew( p_stream->p_sout, 
    542                                                   psz_access, url ); 
     554                    p_access = sout_AccessOutNew( p_stream->p_sout, access, 
     555                                                  url ); 
    543556                    if( p_access == NULL ) 
    544557                    { 
    545558                        msg_Err( p_stream, 
    546559                                 "cannot create access output for %s://%s", 
    547                                  psz_access, url ); 
     560                                 access, url ); 
    548561                        answer->i_status = 500; 
    549                         break; 
    550                     } 
    551  
    552                     TAB_APPEND( rtsp->i_id, rtsp->id, sid ); 
    553                     TAB_APPEND( rtsp->i_access, rtsp->access, p_access ); 
     562                        continue; 
     563                    } 
     564 
     565                    vlc_mutex_lock( &id->stream->lock ); 
     566                    if( psz_session == NULL ) 
     567                    { 
     568                        psz_session = psz_session_init; 
     569                        ses = RtspClientNew( id->stream, psz_session ); 
     570                    } 
     571                    else 
     572                    { 
     573                        /* FIXME: we probably need to remove an access out, 
     574                         * if there is already one for the same ID */ 
     575                        ses = RtspClientGet( id->stream, psz_session ); 
     576                        if( ses == NULL ) 
     577                        { 
     578                            answer->i_status = 454; 
     579                            vlc_mutex_unlock( &id->stream->lock ); 
     580                            continue; 
     581                        } 
     582                    } 
     583 
     584                    assert( ses->i_id == ses->i_access ); 
     585                    TAB_APPEND( ses->i_id, ses->id, sid ); 
     586                    TAB_APPEND( ses->i_access, ses->access, p_access ); 
     587                    assert( ses->i_id == ses->i_access ); 
     588                    vlc_mutex_unlock( &id->stream->lock ); 
    554589 
    555590                    char *src = var_GetNonEmptyString (p_access, "src-addr"); 
     
    569604                                      "client_port=%u-%u;server_port=%u-%u;" 
    570605                                      "mode=play", 
    571                                       src, loport, hiport, sport, sport + 1 ); 
     606                                      src, loport, loport + 1, sport, sport + 1 ); 
    572607                    } 
    573608                    else 
     
    577612                                      "client_port=%u-%u;server_port=%u-%u;" 
    578613                                      "mode=play", 
    579                                       loport, hiport, sport, sport + 1 ); 
     614                                      loport, loport + 1, sport, sport + 1 ); 
    580615                    } 
    581616