]> git.sesse.net Git - vlc/blob - modules/stream_out/rtp.c
Check sending error (fixes #134; closes #514)
[vlc] / modules / stream_out / rtp.c
1 /*****************************************************************************
2  * rtp.c: rtp stream output module
3  *****************************************************************************
4  * Copyright (C) 2003-2004 the VideoLAN team
5  * Copyright © 2007 Rémi Denis-Courmont
6  * $Id$
7  *
8  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28
29 #include <vlc/vlc.h>
30 #include <vlc_sout.h>
31 #include <vlc_block.h>
32
33 #include <vlc_httpd.h>
34 #include <vlc_url.h>
35 #include <vlc_network.h>
36 #include <vlc_charset.h>
37 #include <vlc_strings.h>
38
39 #include "rtp.h"
40
41 #ifdef HAVE_UNISTD_H
42 #   include <sys/types.h>
43 #   include <unistd.h>
44 #   include <fcntl.h>
45 #   include <sys/stat.h>
46 #endif
47 #ifdef HAVE_LINUX_DCCP_H
48 #   include <linux/dccp.h>
49 #endif
50 #ifndef IPPROTO_DCCP
51 # define IPPROTO_DCCP 33
52 #endif
53 #ifndef IPPROTO_UDPLITE
54 # define IPPROTO_UDPLITE 136
55 #endif
56
57 #include <errno.h>
58
59 /*****************************************************************************
60  * Module descriptor
61  *****************************************************************************/
62
63 #define DST_TEXT N_("Destination")
64 #define DST_LONGTEXT N_( \
65     "This is the output URL that will be used." )
66 #define SDP_TEXT N_("SDP")
67 #define SDP_LONGTEXT N_( \
68     "This allows you to specify how the SDP (Session Descriptor) for this RTP "\
69     "session will be made available. You must use an url: http://location to " \
70     "access the SDP via HTTP, rtsp://location for RTSP access, and sap:// " \
71     "for the SDP to be announced via SAP." )
72 #define MUX_TEXT N_("Muxer")
73 #define MUX_LONGTEXT N_( \
74     "This allows you to specify the muxer used for the streaming output. " \
75     "Default is to use no muxer (standard RTP stream)." )
76
77 #define NAME_TEXT N_("Session name")
78 #define NAME_LONGTEXT N_( \
79     "This is the name of the session that will be announced in the SDP " \
80     "(Session Descriptor)." )
81 #define DESC_TEXT N_("Session descriptipn")
82 #define DESC_LONGTEXT N_( \
83     "This allows you to give a short description with details about the stream, " \
84     "that will be announced in the SDP (Session Descriptor)." )
85 #define URL_TEXT N_("Session URL")
86 #define URL_LONGTEXT N_( \
87     "This allows you to give an URL with more details about the stream " \
88     "(often the website of the streaming organization), that will " \
89     "be announced in the SDP (Session Descriptor)." )
90 #define EMAIL_TEXT N_("Session email")
91 #define EMAIL_LONGTEXT N_( \
92     "This allows you to give a contact mail address for the stream, that will " \
93     "be announced in the SDP (Session Descriptor)." )
94 #define PHONE_TEXT N_("Session phone number")
95 #define PHONE_LONGTEXT N_( \
96     "This allows you to give a contact telephone number for the stream, that will " \
97     "be announced in the SDP (Session Descriptor)." )
98
99 #define PORT_TEXT N_("Port")
100 #define PORT_LONGTEXT N_( \
101     "This allows you to specify the base port for the RTP streaming." )
102 #define PORT_AUDIO_TEXT N_("Audio port")
103 #define PORT_AUDIO_LONGTEXT N_( \
104     "This allows you to specify the default audio port for the RTP streaming." )
105 #define PORT_VIDEO_TEXT N_("Video port")
106 #define PORT_VIDEO_LONGTEXT N_( \
107     "This allows you to specify the default video port for the RTP streaming." )
108
109 #define TTL_TEXT N_("Hop limit (TTL)")
110 #define TTL_LONGTEXT N_( \
111     "This is the hop limit (also known as \"Time-To-Live\" or TTL) of " \
112     "the multicast packets sent by the stream output (0 = use operating " \
113     "system built-in default).")
114
115 #define RTCP_MUX_TEXT N_("RTP/RTCP multiplexing")
116 #define RTCP_MUX_LONGTEXT N_( \
117     "This sends and receives RTCP packet multiplexed over the same port " \
118     "as RTP packets." )
119
120 #define DCCP_TEXT N_("DCCP transport")
121 #define DCCP_LONGTEXT N_( \
122     "This enables DCCP instead of UDP as a transport for RTP." )
123 #define TCP_TEXT N_("TCP transport")
124 #define TCP_LONGTEXT N_( \
125     "This enables TCP instead of UDP as a transport for RTP." )
126 #define UDP_LITE_TEXT N_("UDP-Lite transport")
127 #define UDP_LITE_LONGTEXT N_( \
128     "This enables UDP-Lite instead of UDP as a transport for RTP." )
129
130 #define RFC3016_TEXT N_("MP4A LATM")
131 #define RFC3016_LONGTEXT N_( \
132     "This allows you to stream MPEG4 LATM audio streams (see RFC3016)." )
133
134 static int  Open ( vlc_object_t * );
135 static void Close( vlc_object_t * );
136
137 #define SOUT_CFG_PREFIX "sout-rtp-"
138 #define MAX_EMPTY_BLOCKS 200
139
140 vlc_module_begin();
141     set_shortname( _("RTP"));
142     set_description( _("RTP stream output") );
143     set_capability( "sout stream", 0 );
144     add_shortcut( "rtp" );
145     set_category( CAT_SOUT );
146     set_subcategory( SUBCAT_SOUT_STREAM );
147
148     add_string( SOUT_CFG_PREFIX "dst", "", NULL, DST_TEXT,
149                 DST_LONGTEXT, VLC_TRUE );
150     add_string( SOUT_CFG_PREFIX "sdp", "", NULL, SDP_TEXT,
151                 SDP_LONGTEXT, VLC_TRUE );
152     add_string( SOUT_CFG_PREFIX "mux", "", NULL, MUX_TEXT,
153                 MUX_LONGTEXT, VLC_TRUE );
154
155     add_string( SOUT_CFG_PREFIX "name", "", NULL, NAME_TEXT,
156                 NAME_LONGTEXT, VLC_TRUE );
157     add_string( SOUT_CFG_PREFIX "description", "", NULL, DESC_TEXT,
158                 DESC_LONGTEXT, VLC_TRUE );
159     add_string( SOUT_CFG_PREFIX "url", "", NULL, URL_TEXT,
160                 URL_LONGTEXT, VLC_TRUE );
161     add_string( SOUT_CFG_PREFIX "email", "", NULL, EMAIL_TEXT,
162                 EMAIL_LONGTEXT, VLC_TRUE );
163     add_string( SOUT_CFG_PREFIX "phone", "", NULL, PHONE_TEXT,
164                 PHONE_LONGTEXT, VLC_TRUE );
165
166     add_integer( SOUT_CFG_PREFIX "port", 1234, NULL, PORT_TEXT,
167                  PORT_LONGTEXT, VLC_TRUE );
168     add_integer( SOUT_CFG_PREFIX "port-audio", 1230, NULL, PORT_AUDIO_TEXT,
169                  PORT_AUDIO_LONGTEXT, VLC_TRUE );
170     add_integer( SOUT_CFG_PREFIX "port-video", 1232, NULL, PORT_VIDEO_TEXT,
171                  PORT_VIDEO_LONGTEXT, VLC_TRUE );
172
173     add_integer( SOUT_CFG_PREFIX "ttl", 0, NULL, TTL_TEXT,
174                  TTL_LONGTEXT, VLC_TRUE );
175
176     add_bool( SOUT_CFG_PREFIX "rtcp-mux", VLC_FALSE, NULL,
177               RTCP_MUX_TEXT, RTCP_MUX_LONGTEXT, VLC_FALSE );
178
179     add_bool( SOUT_CFG_PREFIX "dccp", VLC_FALSE, NULL,
180               DCCP_TEXT, DCCP_LONGTEXT, VLC_FALSE );
181     add_bool( SOUT_CFG_PREFIX "tcp", VLC_FALSE, NULL,
182               TCP_TEXT, TCP_LONGTEXT, VLC_FALSE );
183     add_bool( SOUT_CFG_PREFIX "udplite", VLC_FALSE, NULL,
184               UDP_LITE_TEXT, UDP_LITE_LONGTEXT, VLC_FALSE );
185
186     add_bool( SOUT_CFG_PREFIX "mp4a-latm", 0, NULL, RFC3016_TEXT,
187                  RFC3016_LONGTEXT, VLC_FALSE );
188
189     set_callbacks( Open, Close );
190 vlc_module_end();
191
192 /*****************************************************************************
193  * Exported prototypes
194  *****************************************************************************/
195 static const char *ppsz_sout_options[] = {
196     "dst", "name", "port", "port-audio", "port-video", "*sdp", "ttl", "mux",
197     "description", "url", "email", "phone",
198     "rtcp-mux", "dccp", "tcp", "udplite",
199     "mp4a-latm", NULL
200 };
201
202 static sout_stream_id_t *Add ( sout_stream_t *, es_format_t * );
203 static int               Del ( sout_stream_t *, sout_stream_id_t * );
204 static int               Send( sout_stream_t *, sout_stream_id_t *,
205                                block_t* );
206 static sout_stream_id_t *MuxAdd ( sout_stream_t *, es_format_t * );
207 static int               MuxDel ( sout_stream_t *, sout_stream_id_t * );
208 static int               MuxSend( sout_stream_t *, sout_stream_id_t *,
209                                   block_t* );
210
211 static sout_access_out_t *GrabberCreate( sout_stream_t *p_sout );
212 static void ThreadSend( vlc_object_t *p_this );
213
214 static void SDPHandleUrl( sout_stream_t *, char * );
215
216 static int SapSetup( sout_stream_t *p_stream );
217 static int FileSetup( sout_stream_t *p_stream );
218 static int HttpSetup( sout_stream_t *p_stream, vlc_url_t * );
219
220 struct sout_stream_sys_t
221 {
222     /* SDP */
223     char    *psz_sdp;
224     vlc_mutex_t  lock_sdp;
225
226     /* SDP to disk */
227     vlc_bool_t b_export_sdp_file;
228     char *psz_sdp_file;
229
230     /* SDP via SAP */
231     vlc_bool_t b_export_sap;
232     session_descriptor_t *p_session;
233
234     /* SDP via HTTP */
235     httpd_host_t *p_httpd_host;
236     httpd_file_t *p_httpd_file;
237
238     /* RTSP */
239     rtsp_stream_t *rtsp;
240
241     /* */
242     char     *psz_destination;
243     uint8_t   proto;
244     uint8_t   i_ttl;
245     uint16_t  i_port;
246     uint16_t  i_port_audio;
247     uint16_t  i_port_video;
248     vlc_bool_t b_latm;
249     vlc_bool_t rtcp_mux;
250
251     /* when need to use a private one or when using muxer */
252     int i_payload_type;
253
254     /* in case we do TS/PS over rtp */
255     sout_mux_t        *p_mux;
256     sout_access_out_t *p_grab;
257     block_t           *packet;
258
259     /* */
260     vlc_mutex_t      lock_es;
261     int              i_es;
262     sout_stream_id_t **es;
263 };
264
265 typedef int (*pf_rtp_packetizer_t)( sout_stream_t *, sout_stream_id_t *,
266                                     block_t * );
267
268 typedef struct rtp_sink_t
269 {
270     int rtp_fd;
271     rtcp_sender_t *rtcp;
272 } rtp_sink_t;
273
274 struct sout_stream_id_t
275 {
276     VLC_COMMON_MEMBERS
277
278     sout_stream_t *p_stream;
279     /* rtp field */
280     uint16_t    i_sequence;
281     uint8_t     i_payload_type;
282     uint8_t     ssrc[4];
283
284     /* for sdp */
285     char        *psz_rtpmap;
286     char        *psz_fmtp;
287     int          i_clock_rate;
288     int          i_port;
289     int          i_cat;
290     int          i_bitrate;
291
292     /* Packetizer specific fields */
293     pf_rtp_packetizer_t pf_packetize;
294     int          i_mtu;
295
296     /* Packets sinks */
297     vlc_mutex_t       lock_sink;
298     int               sinkc;
299     rtp_sink_t       *sinkv;
300     rtsp_stream_id_t *rtsp_id;
301     int              *listen_fd;
302
303     block_fifo_t     *p_fifo;
304     int64_t           i_caching;
305 };
306
307
308 /*****************************************************************************
309  * Open:
310  *****************************************************************************/
311 static int Open( vlc_object_t *p_this )
312 {
313     sout_stream_t       *p_stream = (sout_stream_t*)p_this;
314     sout_instance_t     *p_sout = p_stream->p_sout;
315     sout_stream_sys_t   *p_sys = NULL;
316     config_chain_t      *p_cfg = NULL;
317     char                *psz;
318     vlc_bool_t          b_rtsp = VLC_FALSE;
319
320     config_ChainParse( p_stream, SOUT_CFG_PREFIX,
321                        ppsz_sout_options, p_stream->p_cfg );
322
323     p_sys = malloc( sizeof( sout_stream_sys_t ) );
324     if( p_sys == NULL )
325         return VLC_ENOMEM;
326
327     p_sys->psz_destination = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "dst" );
328
329     p_sys->i_port       = var_GetInteger( p_stream, SOUT_CFG_PREFIX "port" );
330     p_sys->i_port_audio = var_GetInteger( p_stream, SOUT_CFG_PREFIX "port-audio" );
331     p_sys->i_port_video = var_GetInteger( p_stream, SOUT_CFG_PREFIX "port-video" );
332     p_sys->rtcp_mux   = var_GetBool( p_stream, SOUT_CFG_PREFIX "rtcp-mux" );
333
334     p_sys->psz_sdp_file = NULL;
335
336     if( p_sys->i_port_audio == p_sys->i_port_video )
337     {
338         msg_Err( p_stream, "audio and video port cannot be the same" );
339         p_sys->i_port_audio = 0;
340         p_sys->i_port_video = 0;
341     }
342
343     for( p_cfg = p_stream->p_cfg; p_cfg != NULL; p_cfg = p_cfg->p_next )
344     {
345         if( !strcmp( p_cfg->psz_name, "sdp" )
346          && ( p_cfg->psz_value != NULL )
347          && !strncasecmp( p_cfg->psz_value, "rtsp:", 5 ) )
348         {
349             b_rtsp = VLC_TRUE;
350             break;
351         }
352     }
353     if( !b_rtsp )
354     {
355         psz = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "sdp" );
356         if( psz != NULL )
357         {
358             if( !strncasecmp( psz, "rtsp:", 5 ) )
359                 b_rtsp = VLC_TRUE;
360             free( psz );
361         }
362     }
363
364     /* Transport protocol */
365     p_sys->proto = IPPROTO_UDP;
366
367     if( var_GetBool( p_stream, SOUT_CFG_PREFIX "dccp" ) )
368     {
369         p_sys->proto = IPPROTO_DCCP;
370         p_sys->rtcp_mux = VLC_TRUE; /* Force RTP/RTCP mux */
371     }
372 #if 0
373     else
374     if( var_GetBool( p_stream, SOUT_CFG_PREFIX "tcp" ) )
375     {
376         p_sys->proto = IPPROTO_TCP;
377         p_sys->rtcp_mux = VLC_TRUE; /* Force RTP/RTCP mux */
378     }
379     else
380 #endif
381     if( var_GetBool( p_stream, SOUT_CFG_PREFIX "udplite" ) )
382         p_sys->proto = IPPROTO_UDPLITE;
383
384     if( ( p_sys->psz_destination == NULL ) && !b_rtsp )
385     {
386         msg_Err( p_stream, "missing destination and not in RTSP mode" );
387         free( p_sys );
388         return VLC_EGENERIC;
389     }
390
391     p_sys->i_ttl = var_GetInteger( p_stream, SOUT_CFG_PREFIX "ttl" );
392     if( p_sys->i_ttl == 0 )
393     {
394         /* Normally, we should let the default hop limit up to the core,
395          * but we have to know it to build our SDP properly, which is why
396          * we ask the core. FIXME: broken when neither sout-rtp-ttl nor
397          * ttl are set. */
398         p_sys->i_ttl = config_GetInt( p_stream, "ttl" );
399     }
400
401     p_sys->b_latm = var_GetBool( p_stream, SOUT_CFG_PREFIX "mp4a-latm" );
402
403     p_sys->i_payload_type = 96;
404     p_sys->i_es = 0;
405     p_sys->es   = NULL;
406     p_sys->rtsp = NULL;
407     p_sys->psz_sdp = NULL;
408
409     p_sys->b_export_sap = VLC_FALSE;
410     p_sys->b_export_sdp_file = VLC_FALSE;
411     p_sys->p_session = NULL;
412
413     p_sys->p_httpd_host = NULL;
414     p_sys->p_httpd_file = NULL;
415
416     p_stream->p_sys     = p_sys;
417
418     vlc_mutex_init( p_stream, &p_sys->lock_sdp );
419     vlc_mutex_init( p_stream, &p_sys->lock_es );
420
421     psz = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "mux" );
422     if( psz != NULL )
423     {
424         sout_stream_id_t *id;
425
426         /* Check muxer type */
427         if( strncasecmp( psz, "ps", 2 )
428          && strncasecmp( psz, "mpeg1", 5 )
429          && strncasecmp( psz, "ts", 2 ) )
430         {
431             msg_Err( p_stream, "unsupported muxer type for RTP (only TS/PS)" );
432             free( psz );
433             vlc_mutex_destroy( &p_sys->lock_sdp );
434             vlc_mutex_destroy( &p_sys->lock_es );
435             free( p_sys );
436             return VLC_EGENERIC;
437         }
438
439         p_sys->p_grab = GrabberCreate( p_stream );
440         p_sys->p_mux = sout_MuxNew( p_sout, psz, p_sys->p_grab );
441         free( psz );
442
443         if( p_sys->p_mux == NULL )
444         {
445             msg_Err( p_stream, "cannot create muxer" );
446             sout_AccessOutDelete( p_sys->p_grab );
447             vlc_mutex_destroy( &p_sys->lock_sdp );
448             vlc_mutex_destroy( &p_sys->lock_es );
449             free( p_sys );
450             return VLC_EGENERIC;
451         }
452
453         id = Add( p_stream, NULL );
454         if( id == NULL )
455         {
456             sout_MuxDelete( p_sys->p_mux );
457             sout_AccessOutDelete( p_sys->p_grab );
458             vlc_mutex_destroy( &p_sys->lock_sdp );
459             vlc_mutex_destroy( &p_sys->lock_es );
460             free( p_sys );
461             return VLC_EGENERIC;
462         }
463
464         p_sys->packet = NULL;
465
466         p_stream->pf_add  = MuxAdd;
467         p_stream->pf_del  = MuxDel;
468         p_stream->pf_send = MuxSend;
469     }
470     else
471     {
472         p_sys->p_mux    = NULL;
473         p_sys->p_grab   = NULL;
474
475         p_stream->pf_add    = Add;
476         p_stream->pf_del    = Del;
477         p_stream->pf_send   = Send;
478     }
479
480     psz = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "sdp" );
481     if( psz != NULL )
482     {
483         config_chain_t *p_cfg;
484
485         SDPHandleUrl( p_stream, psz );
486
487         for( p_cfg = p_stream->p_cfg; p_cfg != NULL; p_cfg = p_cfg->p_next )
488         {
489             if( !strcmp( p_cfg->psz_name, "sdp" ) )
490             {
491                 if( p_cfg->psz_value == NULL || *p_cfg->psz_value == '\0' )
492                     continue;
493
494                 /* needed both :sout-rtp-sdp= and rtp{sdp=} can be used */
495                 if( !strcmp( p_cfg->psz_value, psz ) )
496                     continue;
497
498                 SDPHandleUrl( p_stream, p_cfg->psz_value );
499             }
500         }
501         free( psz );
502     }
503
504     /* update p_sout->i_out_pace_nocontrol */
505     p_stream->p_sout->i_out_pace_nocontrol++;
506
507     return VLC_SUCCESS;
508 }
509
510 /*****************************************************************************
511  * Close:
512  *****************************************************************************/
513 static void Close( vlc_object_t * p_this )
514 {
515     sout_stream_t     *p_stream = (sout_stream_t*)p_this;
516     sout_stream_sys_t *p_sys = p_stream->p_sys;
517
518     /* update p_sout->i_out_pace_nocontrol */
519     p_stream->p_sout->i_out_pace_nocontrol--;
520
521     if( p_sys->p_mux )
522     {
523         assert( p_sys->i_es == 1 );
524         Del( p_stream, p_sys->es[0] );
525
526         sout_MuxDelete( p_sys->p_mux );
527         sout_AccessOutDelete( p_sys->p_grab );
528         if( p_sys->packet )
529         {
530             block_Release( p_sys->packet );
531         }
532         if( p_sys->b_export_sap )
533         {
534             p_sys->p_mux = NULL;
535             SapSetup( p_stream );
536         }
537     }
538
539     if( p_sys->rtsp != NULL )
540         RtspUnsetup( p_sys->rtsp );
541
542     vlc_mutex_destroy( &p_sys->lock_sdp );
543     vlc_mutex_destroy( &p_sys->lock_es );
544
545     if( p_sys->p_httpd_file )
546         httpd_FileDelete( p_sys->p_httpd_file );
547
548     if( p_sys->p_httpd_host )
549         httpd_HostDelete( p_sys->p_httpd_host );
550
551     free( p_sys->psz_sdp );
552
553     if( p_sys->b_export_sdp_file )
554     {
555 #ifdef HAVE_UNISTD_H
556         unlink( p_sys->psz_sdp_file );
557 #endif
558         free( p_sys->psz_sdp_file );
559     }
560     free( p_sys->psz_destination );
561     free( p_sys );
562 }
563
564 /*****************************************************************************
565  * SDPHandleUrl:
566  *****************************************************************************/
567 static void SDPHandleUrl( sout_stream_t *p_stream, char *psz_url )
568 {
569     sout_stream_sys_t *p_sys = p_stream->p_sys;
570     vlc_url_t url;
571
572     vlc_UrlParse( &url, psz_url, 0 );
573     if( url.psz_protocol && !strcasecmp( url.psz_protocol, "http" ) )
574     {
575         if( p_sys->p_httpd_file )
576         {
577             msg_Err( p_stream, "you can use sdp=http:// only once" );
578             goto out;
579         }
580
581         if( HttpSetup( p_stream, &url ) )
582         {
583             msg_Err( p_stream, "cannot export SDP as HTTP" );
584         }
585     }
586     else if( url.psz_protocol && !strcasecmp( url.psz_protocol, "rtsp" ) )
587     {
588         if( p_sys->rtsp != NULL )
589         {
590             msg_Err( p_stream, "you can use sdp=rtsp:// only once" );
591             goto out;
592         }
593
594         /* FIXME test if destination is multicast or no destination at all */
595         p_sys->rtsp = RtspSetup( p_stream, &url );
596         if( p_sys->rtsp == NULL )
597         {
598             msg_Err( p_stream, "cannot export SDP as RTSP" );
599         }
600
601         if( p_sys->p_mux != NULL )
602         {
603             sout_stream_id_t *id = p_sys->es[0];
604             id->rtsp_id = RtspAddId( p_sys->rtsp, id, 0,
605                                      p_sys->psz_destination, p_sys->i_ttl,
606                                      id->i_port, id->i_port + 1 );
607         }
608     }
609     else if( ( url.psz_protocol && !strcasecmp( url.psz_protocol, "sap" ) ) ||
610              ( url.psz_host && !strcasecmp( url.psz_host, "sap" ) ) )
611     {
612         p_sys->b_export_sap = VLC_TRUE;
613         SapSetup( p_stream );
614     }
615     else if( url.psz_protocol && !strcasecmp( url.psz_protocol, "file" ) )
616     {
617         if( p_sys->b_export_sdp_file )
618         {
619             msg_Err( p_stream, "you can use sdp=file:// only once" );
620             goto out;
621         }
622         p_sys->b_export_sdp_file = VLC_TRUE;
623         psz_url = &psz_url[5];
624         if( psz_url[0] == '/' && psz_url[1] == '/' )
625             psz_url += 2;
626         p_sys->psz_sdp_file = strdup( psz_url );
627     }
628     else
629     {
630         msg_Warn( p_stream, "unknown protocol for SDP (%s)",
631                   url.psz_protocol );
632     }
633
634 out:
635     vlc_UrlClean( &url );
636 }
637
638 /*****************************************************************************
639  * SDPGenerate
640  *****************************************************************************/
641 /*static*/
642 char *SDPGenerate( const sout_stream_t *p_stream, const char *rtsp_url )
643 {
644     const sout_stream_sys_t *p_sys = p_stream->p_sys;
645     char *psz_sdp;
646     struct sockaddr_storage dst;
647     socklen_t dstlen;
648     int i;
649     /*
650      * When we have a fixed destination (typically when we do multicast),
651      * we need to put the actual port numbers in the SDP.
652      * When there is no fixed destination, we only support RTSP unicast
653      * on-demand setup, so we should rather let the clients decide which ports
654      * to use.
655      * When there is both a fixed destination and RTSP unicast, we need to
656      * put port numbers used by the fixed destination, otherwise the SDP would
657      * become totally incorrect for multicast use. It should be noted that
658      * port numbers from SDP with RTSP are only "recommendation" from the
659      * server to the clients (per RFC2326), so only broken clients will fail
660      * to handle this properly. There is no solution but to use two differents
661      * output chain with two different RTSP URLs if you need to handle this
662      * scenario.
663      */
664     int inclport;
665
666     if( p_sys->psz_destination != NULL )
667     {
668         inclport = 1;
669
670         /* Oh boy, this is really ugly! (+ race condition on lock_es) */
671         dstlen = sizeof( dst );
672         if( p_sys->es[0]->listen_fd != NULL )
673             getsockname( p_sys->es[0]->listen_fd[0],
674                          (struct sockaddr *)&dst, &dstlen );
675         else
676             getpeername( p_sys->es[0]->sinkv[0].rtp_fd,
677                          (struct sockaddr *)&dst, &dstlen );
678     }
679     else
680     {
681         inclport = 0;
682
683         /* Dummy destination address for RTSP */
684         memset (&dst, 0, sizeof( struct sockaddr_in ) );
685         dst.ss_family = AF_INET;
686 #ifdef HAVE_SA_LEN
687         dst.ss_len =
688 #endif
689         dstlen = sizeof( struct sockaddr_in );
690     }
691
692     psz_sdp = vlc_sdp_Start( VLC_OBJECT( p_stream ), SOUT_CFG_PREFIX,
693                              NULL, 0, (struct sockaddr *)&dst, dstlen );
694     if( psz_sdp == NULL )
695         return NULL;
696
697     /* TODO: a=source-filter */
698     if( p_sys->rtcp_mux )
699         sdp_AddAttribute( &psz_sdp, "rtcp-mux", NULL );
700
701     if( rtsp_url != NULL )
702         sdp_AddAttribute ( &psz_sdp, "control", "%s", rtsp_url );
703
704     /* FIXME: locking?! */
705     for( i = 0; i < p_sys->i_es; i++ )
706     {
707         sout_stream_id_t *id = p_sys->es[i];
708         const char *mime_major; /* major MIME type */
709         const char *proto = "RTP/AVP"; /* protocol */
710
711         switch( id->i_cat )
712         {
713             case VIDEO_ES:
714                 mime_major = "video";
715                 break;
716             case AUDIO_ES:
717                 mime_major = "audio";
718                 break;
719             case SPU_ES:
720                 mime_major = "text";
721                 break;
722             default:
723                 continue;
724         }
725
726         if( rtsp_url == NULL )
727         {
728             switch( p_sys->proto )
729             {
730                 case IPPROTO_UDP:
731                     break;
732                 case IPPROTO_TCP:
733                     proto = "TCP/RTP/AVP";
734                     break;
735                 case IPPROTO_DCCP:
736                     proto = "DCCP/RTP/AVP";
737                     break;
738                 case IPPROTO_UDPLITE:
739                     continue;
740             }
741         }
742
743         sdp_AddMedia( &psz_sdp, mime_major, proto, inclport * id->i_port,
744                       id->i_payload_type, VLC_FALSE, id->i_bitrate,
745                       id->psz_rtpmap, id->psz_fmtp);
746
747         if( rtsp_url != NULL )
748         {
749             assert( strlen( rtsp_url ) > 0 );
750             vlc_bool_t addslash = ( rtsp_url[strlen( rtsp_url ) - 1] != '/' );
751             sdp_AddAttribute ( &psz_sdp, "control",
752                                addslash ? "%s/trackID=%u" : "%strackID=%u",
753                                rtsp_url, i );
754         }
755         else
756         {
757             if( id->listen_fd != NULL )
758                 sdp_AddAttribute( &psz_sdp, "setup", "passive" );
759 #if 0
760             if( p_sys->proto == IPPROTO_DCCP )
761                 sdp_AddAttribute( &psz_sdp, "dccp-service-code", 
762                                   "SC:RTP%c", toupper( mime_major[0] ) );
763 #endif
764         }
765     }
766
767     return psz_sdp;
768 }
769
770 /*****************************************************************************
771  * RTP mux
772  *****************************************************************************/
773 static int rtp_packetize_l16  ( sout_stream_t *, sout_stream_id_t *, block_t * );
774 static int rtp_packetize_l8   ( sout_stream_t *, sout_stream_id_t *, block_t * );
775 static int rtp_packetize_mpa  ( sout_stream_t *, sout_stream_id_t *, block_t * );
776 static int rtp_packetize_mpv  ( sout_stream_t *, sout_stream_id_t *, block_t * );
777 static int rtp_packetize_ac3  ( sout_stream_t *, sout_stream_id_t *, block_t * );
778 static int rtp_packetize_split( sout_stream_t *, sout_stream_id_t *, block_t * );
779 static int rtp_packetize_mp4a ( sout_stream_t *, sout_stream_id_t *, block_t * );
780 static int rtp_packetize_mp4a_latm ( sout_stream_t *, sout_stream_id_t *, block_t * );
781 static int rtp_packetize_h263 ( sout_stream_t *, sout_stream_id_t *, block_t * );
782 static int rtp_packetize_h264 ( sout_stream_t *, sout_stream_id_t *, block_t * );
783 static int rtp_packetize_amr  ( sout_stream_t *, sout_stream_id_t *, block_t * );
784 static int rtp_packetize_spx  ( sout_stream_t *, sout_stream_id_t *, block_t * );
785 static int rtp_packetize_t140 ( sout_stream_t *, sout_stream_id_t *, block_t * );
786
787 static void sprintf_hexa( char *s, uint8_t *p_data, int i_data )
788 {
789     static const char hex[16] = "0123456789abcdef";
790     int i;
791
792     for( i = 0; i < i_data; i++ )
793     {
794         s[2*i+0] = hex[(p_data[i]>>4)&0xf];
795         s[2*i+1] = hex[(p_data[i]   )&0xf];
796     }
797     s[2*i_data] = '\0';
798 }
799
800
801 /** Add an ES as a new RTP stream */
802 static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
803 {
804     /* NOTE: As a special case, if we use a non-RTP
805      * mux (TS/PS), then p_fmt is NULL. */
806     sout_stream_sys_t *p_sys = p_stream->p_sys;
807     sout_stream_id_t  *id;
808     int               i_port, cscov = -1;
809     char              *psz_sdp;
810
811     id = vlc_object_create( p_stream, sizeof( sout_stream_id_t ) );
812     if( id == NULL )
813         return NULL;
814     vlc_object_attach( id, p_stream );
815
816     /* Choose the port */
817     i_port = 0;
818     if( p_fmt == NULL )
819         ;
820     else
821     if( p_fmt->i_cat == AUDIO_ES && p_sys->i_port_audio > 0 )
822     {
823         i_port = p_sys->i_port_audio;
824         p_sys->i_port_audio = 0;
825     }
826     else
827     if( p_fmt->i_cat == VIDEO_ES && p_sys->i_port_video > 0 )
828     {
829         i_port = p_sys->i_port_video;
830         p_sys->i_port_video = 0;
831     }
832
833     while( i_port == 0 )
834     {
835         if( p_sys->i_port != p_sys->i_port_audio
836          && p_sys->i_port != p_sys->i_port_video )
837         {
838             i_port = p_sys->i_port;
839             p_sys->i_port += 2;
840             break;
841         }
842         p_sys->i_port += 2;
843     }
844
845     id->p_stream   = p_stream;
846
847     id->i_sequence = rand()&0xffff;
848     id->i_payload_type = p_sys->i_payload_type;
849     id->ssrc[0] = rand()&0xff;
850     id->ssrc[1] = rand()&0xff;
851     id->ssrc[2] = rand()&0xff;
852     id->ssrc[3] = rand()&0xff;
853
854     id->psz_rtpmap = NULL;
855     id->psz_fmtp   = NULL;
856     id->i_clock_rate = 90000; /* most common case */
857     id->i_port     = i_port;
858     if( p_fmt != NULL )
859     {
860         id->i_cat  = p_fmt->i_cat;
861         id->i_bitrate = p_fmt->i_bitrate/1000; /* Stream bitrate in kbps */
862     }
863     else
864     {
865         id->i_cat  = VIDEO_ES;
866         id->i_bitrate = 0;
867     }
868
869     id->pf_packetize = NULL;
870     id->i_mtu = config_GetInt( p_stream, "mtu" );
871     if( id->i_mtu <= 12 + 16 )
872         id->i_mtu = 576 - 20 - 8; /* pessimistic */
873
874     msg_Dbg( p_stream, "maximum RTP packet size: %d bytes", id->i_mtu );
875
876     vlc_mutex_init( p_stream, &id->lock_sink );
877     id->sinkc = 0;
878     id->sinkv = NULL;
879     id->rtsp_id = NULL;
880     id->p_fifo = NULL;
881     id->listen_fd = NULL;
882
883     id->i_caching =
884         (int64_t)1000 * var_GetInteger( p_stream, SOUT_CFG_PREFIX "caching");
885
886     if( p_sys->psz_destination != NULL )
887         switch( p_sys->proto )
888         {
889             case IPPROTO_TCP:
890             case IPPROTO_DCCP:
891                 id->listen_fd = net_Listen( VLC_OBJECT(p_stream),
892                                             p_sys->psz_destination, i_port,
893                                             p_sys->proto );
894                 if( id->listen_fd == NULL )
895                 {
896                     msg_Err( p_stream, "passive COMEDIA RTP socket failed" );
897                     goto error;
898                 }
899                 break;
900
901             default:
902             {
903                 int ttl = (p_sys->i_ttl > 0) ? p_sys->i_ttl : -1;
904                 int fd = net_ConnectDgram( p_stream, p_sys->psz_destination,
905                                            i_port, ttl, p_sys->proto );
906                 if( fd == -1 )
907                 {
908                     msg_Err( p_stream, "cannot create RTP socket" );
909                     goto error;
910                 }
911                 rtp_add_sink( id, fd, p_sys->rtcp_mux );
912             }
913         }
914
915     if( p_fmt == NULL )
916     {
917         char *psz = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "mux" );
918
919         if( psz == NULL ) /* Uho! */
920             ;
921         else
922         if( strncmp( psz, "ts", 2 ) == 0 )
923         {
924             id->i_payload_type = 33;
925             id->psz_rtpmap = strdup( "MP2T/90000" );
926         }
927         else
928         {
929             id->psz_rtpmap = strdup( "MP2P/90000" );
930         }
931     }
932     else
933     switch( p_fmt->i_codec )
934     {
935         case VLC_FOURCC( 's', '1', '6', 'b' ):
936             if( p_fmt->audio.i_channels == 1 && p_fmt->audio.i_rate == 44100 )
937             {
938                 id->i_payload_type = 11;
939             }
940             else if( p_fmt->audio.i_channels == 2 &&
941                      p_fmt->audio.i_rate == 44100 )
942             {
943                 id->i_payload_type = 10;
944             }
945             if( asprintf( &id->psz_rtpmap, "L16/%d/%d", p_fmt->audio.i_rate,
946                           p_fmt->audio.i_channels ) == -1 )
947                 id->psz_rtpmap = NULL;
948             id->i_clock_rate = p_fmt->audio.i_rate;
949             id->pf_packetize = rtp_packetize_l16;
950             break;
951         case VLC_FOURCC( 'u', '8', ' ', ' ' ):
952             if( asprintf( &id->psz_rtpmap, "L8/%d/%d", p_fmt->audio.i_rate,
953                           p_fmt->audio.i_channels ) == -1 )
954                 id->psz_rtpmap = NULL;
955             id->i_clock_rate = p_fmt->audio.i_rate;
956             id->pf_packetize = rtp_packetize_l8;
957             break;
958         case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
959             id->i_payload_type = 14;
960             id->psz_rtpmap = strdup( "MPA/90000" );
961             id->pf_packetize = rtp_packetize_mpa;
962             break;
963         case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
964             id->i_payload_type = 32;
965             id->psz_rtpmap = strdup( "MPV/90000" );
966             id->pf_packetize = rtp_packetize_mpv;
967             break;
968         case VLC_FOURCC( 'a', '5', '2', ' ' ):
969             id->psz_rtpmap = strdup( "ac3/90000" );
970             id->pf_packetize = rtp_packetize_ac3;
971             break;
972         case VLC_FOURCC( 'H', '2', '6', '3' ):
973             id->psz_rtpmap = strdup( "H263-1998/90000" );
974             id->pf_packetize = rtp_packetize_h263;
975             break;
976         case VLC_FOURCC( 'h', '2', '6', '4' ):
977             id->psz_rtpmap = strdup( "H264/90000" );
978             id->pf_packetize = rtp_packetize_h264;
979             id->psz_fmtp = NULL;
980
981             if( p_fmt->i_extra > 0 )
982             {
983                 uint8_t *p_buffer = p_fmt->p_extra;
984                 int     i_buffer = p_fmt->i_extra;
985                 char    *p_64_sps = NULL;
986                 char    *p_64_pps = NULL;
987                 char    hexa[6+1];
988
989                 while( i_buffer > 4 &&
990                        p_buffer[0] == 0 && p_buffer[1] == 0 &&
991                        p_buffer[2] == 0 && p_buffer[3] == 1 )
992                 {
993                     const int i_nal_type = p_buffer[4]&0x1f;
994                     int i_offset;
995                     int i_size      = 0;
996
997                     msg_Dbg( p_stream, "we found a startcode for NAL with TYPE:%d", i_nal_type );
998
999                     i_size = i_buffer;
1000                     for( i_offset = 4; i_offset+3 < i_buffer ; i_offset++)
1001                     {
1002                         if( !memcmp (p_buffer + i_offset, "\x00\x00\x00\x01", 4 ) )
1003                         {
1004                             /* we found another startcode */
1005                             i_size = i_offset;
1006                             break;
1007                         }
1008                     }
1009                     if( i_nal_type == 7 )
1010                     {
1011                         p_64_sps = vlc_b64_encode_binary( &p_buffer[4], i_size - 4 );
1012                         sprintf_hexa( hexa, &p_buffer[5], 3 );
1013                     }
1014                     else if( i_nal_type == 8 )
1015                     {
1016                         p_64_pps = vlc_b64_encode_binary( &p_buffer[4], i_size - 4 );
1017                     }
1018                     i_buffer -= i_size;
1019                     p_buffer += i_size;
1020                 }
1021                 /* */
1022                 if( p_64_sps && p_64_pps &&
1023                     ( asprintf( &id->psz_fmtp,
1024                                 "packetization-mode=1;profile-level-id=%s;"
1025                                 "sprop-parameter-sets=%s,%s;", hexa, p_64_sps,
1026                                 p_64_pps ) == -1 ) )
1027                     id->psz_fmtp = NULL;
1028                 free( p_64_sps );
1029                 free( p_64_pps );
1030             }
1031             if( !id->psz_fmtp )
1032                 id->psz_fmtp = strdup( "packetization-mode=1" );
1033             break;
1034
1035         case VLC_FOURCC( 'm', 'p', '4', 'v' ):
1036         {
1037             char hexa[2*p_fmt->i_extra +1];
1038
1039             id->psz_rtpmap = strdup( "MP4V-ES/90000" );
1040             id->pf_packetize = rtp_packetize_split;
1041             if( p_fmt->i_extra > 0 )
1042             {
1043                 sprintf_hexa( hexa, p_fmt->p_extra, p_fmt->i_extra );
1044                 if( asprintf( &id->psz_fmtp,
1045                               "profile-level-id=3; config=%s;", hexa ) == -1 )
1046                     id->psz_fmtp = NULL;
1047             }
1048             break;
1049         }
1050         case VLC_FOURCC( 'm', 'p', '4', 'a' ):
1051         {
1052             id->i_clock_rate = p_fmt->audio.i_rate;
1053
1054             if(!p_sys->b_latm)
1055             {
1056                 char hexa[2*p_fmt->i_extra +1];
1057
1058                 if( asprintf( &id->psz_rtpmap, "mpeg4-generic/%d",
1059                               p_fmt->audio.i_rate ) == -1 )
1060                     id->psz_rtpmap = NULL;
1061                 id->pf_packetize = rtp_packetize_mp4a;
1062                 sprintf_hexa( hexa, p_fmt->p_extra, p_fmt->i_extra );
1063                 if( asprintf( &id->psz_fmtp,
1064                               "streamtype=5; profile-level-id=15; "
1065                               "mode=AAC-hbr; config=%s; SizeLength=13; "
1066                               "IndexLength=3; IndexDeltaLength=3; Profile=1;",
1067                               hexa ) == -1 )
1068                     id->psz_fmtp = NULL;
1069             }
1070             else
1071             {
1072                 char hexa[13];
1073                 int i;
1074                 unsigned char config[6];
1075                 unsigned int aacsrates[15] = {
1076                     96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
1077                     16000, 12000, 11025, 8000, 7350, 0, 0 };
1078
1079                 for( i = 0; i < 15; i++ )
1080                     if( p_fmt->audio.i_rate == aacsrates[i] )
1081                         break;
1082
1083                 config[0]=0x40;
1084                 config[1]=0;
1085                 config[2]=0x20|i;
1086                 config[3]=p_fmt->audio.i_channels<<4;
1087                 config[4]=0x3f;
1088                 config[5]=0xc0;
1089
1090                 if( asprintf( &id->psz_rtpmap, "MP4A-LATM/%d/%d",
1091                               p_fmt->audio.i_rate,
1092                               p_fmt->audio.i_channels ) == -1)
1093                     id->psz_rtpmap = NULL;
1094                 id->pf_packetize = rtp_packetize_mp4a_latm;
1095                 sprintf_hexa( hexa, config, 6 );
1096                 if( asprintf( &id->psz_fmtp, "profile-level-id=15; "
1097                               "object=2; cpresent=0; config=%s", hexa ) == -1 )
1098                     id->psz_fmtp = NULL;
1099             }
1100             break;
1101         }
1102         case VLC_FOURCC( 's', 'a', 'm', 'r' ):
1103             id->psz_rtpmap = strdup( p_fmt->audio.i_channels == 2 ?
1104                                      "AMR/8000/2" : "AMR/8000" );
1105             id->psz_fmtp = strdup( "octet-align=1" );
1106             id->i_clock_rate = p_fmt->audio.i_rate;
1107             id->pf_packetize = rtp_packetize_amr;
1108             break;
1109         case VLC_FOURCC( 's', 'a', 'w', 'b' ):
1110             id->psz_rtpmap = strdup( p_fmt->audio.i_channels == 2 ?
1111                                      "AMR-WB/16000/2" : "AMR-WB/16000" );
1112             id->psz_fmtp = strdup( "octet-align=1" );
1113             id->i_clock_rate = p_fmt->audio.i_rate;
1114             id->pf_packetize = rtp_packetize_amr;
1115             break;
1116         case VLC_FOURCC( 's', 'p', 'x', ' ' ):
1117             id->i_payload_type = p_sys->i_payload_type++;
1118             if( asprintf( &id->psz_rtpmap, "SPEEX/%d",
1119                           p_fmt->audio.i_rate ) == -1)
1120                 id->psz_rtpmap = NULL;
1121             id->i_clock_rate = p_fmt->audio.i_rate;
1122             id->pf_packetize = rtp_packetize_spx;
1123             break;
1124         case VLC_FOURCC( 't', '1', '4', '0' ):
1125             id->psz_rtpmap = strdup( "t140/1000" );
1126             id->i_clock_rate = 1000;
1127             id->pf_packetize = rtp_packetize_t140;
1128             break;
1129
1130         default:
1131             msg_Err( p_stream, "cannot add this stream (unsupported "
1132                      "codec:%4.4s)", (char*)&p_fmt->i_codec );
1133             goto error;
1134     }
1135
1136     if( cscov != -1 )
1137         cscov += 8 /* UDP */ + 12 /* RTP */;
1138     if( id->sinkc > 0 )
1139         net_SetCSCov( id->sinkv[0].rtp_fd, cscov, -1 );
1140
1141     if( id->i_payload_type == p_sys->i_payload_type )
1142         p_sys->i_payload_type++;
1143
1144     if( p_sys->rtsp != NULL )
1145         id->rtsp_id = RtspAddId( p_sys->rtsp, id, p_sys->i_es,
1146                                  p_sys->psz_destination,
1147                                  p_sys->i_ttl, id->i_port, id->i_port + 1 );
1148
1149     id->p_fifo = block_FifoNew( p_stream );
1150     if( vlc_thread_create( id, "RTP send thread", ThreadSend,
1151                            VLC_THREAD_PRIORITY_HIGHEST, VLC_FALSE ) )
1152         goto error;
1153
1154     /* Update p_sys context */
1155     vlc_mutex_lock( &p_sys->lock_es );
1156     TAB_APPEND( p_sys->i_es, p_sys->es, id );
1157     vlc_mutex_unlock( &p_sys->lock_es );
1158
1159     psz_sdp = SDPGenerate( p_stream, NULL );
1160
1161     vlc_mutex_lock( &p_sys->lock_sdp );
1162     free( p_sys->psz_sdp );
1163     p_sys->psz_sdp = psz_sdp;
1164     vlc_mutex_unlock( &p_sys->lock_sdp );
1165
1166     msg_Dbg( p_stream, "sdp=\n%s", p_sys->psz_sdp );
1167
1168     /* Update SDP (sap/file) */
1169     if( p_sys->b_export_sap ) SapSetup( p_stream );
1170     if( p_sys->b_export_sdp_file ) FileSetup( p_stream );
1171
1172     return id;
1173
1174 error:
1175     Del( p_stream, id );
1176     return NULL;
1177 }
1178
1179 static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
1180 {
1181     sout_stream_sys_t *p_sys = p_stream->p_sys;
1182
1183     if( id->p_fifo != NULL )
1184     {
1185         vlc_object_kill( id );
1186         block_FifoWake( id->p_fifo );
1187         vlc_thread_join( id );
1188         block_FifoRelease( id->p_fifo );
1189     }
1190
1191     vlc_mutex_lock( &p_sys->lock_es );
1192     TAB_REMOVE( p_sys->i_es, p_sys->es, id );
1193     vlc_mutex_unlock( &p_sys->lock_es );
1194
1195     /* Release port */
1196     if( id->i_port > 0 )
1197     {
1198         if( id->i_cat == AUDIO_ES && p_sys->i_port_audio == 0 )
1199             p_sys->i_port_audio = id->i_port;
1200         else if( id->i_cat == VIDEO_ES && p_sys->i_port_video == 0 )
1201             p_sys->i_port_video = id->i_port;
1202     }
1203
1204     free( id->psz_rtpmap );
1205     free( id->psz_fmtp );
1206
1207     if( id->rtsp_id )
1208         RtspDelId( p_sys->rtsp, id->rtsp_id );
1209     if( id->sinkc > 0 )
1210         rtp_del_sink( id, id->sinkv[0].rtp_fd ); /* sink for explicit dst= */
1211     if( id->listen_fd != NULL )
1212         net_ListenClose( id->listen_fd );
1213
1214     vlc_mutex_destroy( &id->lock_sink );
1215
1216     /* Update SDP (sap/file) */
1217     if( p_sys->b_export_sap && !p_sys->p_mux ) SapSetup( p_stream );
1218     if( p_sys->b_export_sdp_file ) FileSetup( p_stream );
1219
1220     vlc_object_detach( id );
1221     vlc_object_destroy( id );
1222     return VLC_SUCCESS;
1223 }
1224
1225 static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
1226                  block_t *p_buffer )
1227 {
1228     block_t *p_next;
1229
1230     assert( p_stream->p_sys->p_mux == NULL );
1231
1232     while( p_buffer != NULL )
1233     {
1234         p_next = p_buffer->p_next;
1235         if( id->pf_packetize( p_stream, id, p_buffer ) )
1236             break;
1237
1238         block_Release( p_buffer );
1239         p_buffer = p_next;
1240     }
1241     return VLC_SUCCESS;
1242 }
1243
1244 /****************************************************************************
1245  * SAP:
1246  ****************************************************************************/
1247 static int SapSetup( sout_stream_t *p_stream )
1248 {
1249     sout_stream_sys_t *p_sys = p_stream->p_sys;
1250     sout_instance_t   *p_sout = p_stream->p_sout;
1251
1252     /* Remove the previous session */
1253     if( p_sys->p_session != NULL)
1254     {
1255         sout_AnnounceUnRegister( p_sout, p_sys->p_session);
1256         p_sys->p_session = NULL;
1257     }
1258
1259     if( ( p_sys->i_es > 0 || p_sys->p_mux ) && p_sys->psz_sdp && *p_sys->psz_sdp )
1260     {
1261         announce_method_t *p_method = sout_SAPMethod();
1262         p_sys->p_session = sout_AnnounceRegisterSDP( p_sout, SOUT_CFG_PREFIX,
1263                                                      p_sys->psz_sdp,
1264                                                      p_sys->psz_destination,
1265                                                      p_method );
1266         sout_MethodRelease( p_method );
1267     }
1268
1269     return VLC_SUCCESS;
1270 }
1271
1272 /****************************************************************************
1273 * File:
1274 ****************************************************************************/
1275 static int FileSetup( sout_stream_t *p_stream )
1276 {
1277     sout_stream_sys_t *p_sys = p_stream->p_sys;
1278     FILE            *f;
1279
1280     if( ( f = utf8_fopen( p_sys->psz_sdp_file, "wt" ) ) == NULL )
1281     {
1282         msg_Err( p_stream, "cannot open file '%s' (%m)",
1283                  p_sys->psz_sdp_file );
1284         return VLC_EGENERIC;
1285     }
1286
1287     fputs( p_sys->psz_sdp, f );
1288     fclose( f );
1289
1290     return VLC_SUCCESS;
1291 }
1292
1293 /****************************************************************************
1294  * HTTP:
1295  ****************************************************************************/
1296 static int  HttpCallback( httpd_file_sys_t *p_args,
1297                           httpd_file_t *, uint8_t *p_request,
1298                           uint8_t **pp_data, int *pi_data );
1299
1300 static int HttpSetup( sout_stream_t *p_stream, vlc_url_t *url)
1301 {
1302     sout_stream_sys_t *p_sys = p_stream->p_sys;
1303
1304     p_sys->p_httpd_host = httpd_HostNew( VLC_OBJECT(p_stream), url->psz_host,
1305                                          url->i_port > 0 ? url->i_port : 80 );
1306     if( p_sys->p_httpd_host )
1307     {
1308         p_sys->p_httpd_file = httpd_FileNew( p_sys->p_httpd_host,
1309                                              url->psz_path ? url->psz_path : "/",
1310                                              "application/sdp",
1311                                              NULL, NULL, NULL,
1312                                              HttpCallback, (void*)p_sys );
1313     }
1314     if( p_sys->p_httpd_file == NULL )
1315     {
1316         return VLC_EGENERIC;
1317     }
1318     return VLC_SUCCESS;
1319 }
1320
1321 static int  HttpCallback( httpd_file_sys_t *p_args,
1322                           httpd_file_t *f, uint8_t *p_request,
1323                           uint8_t **pp_data, int *pi_data )
1324 {
1325     sout_stream_sys_t *p_sys = (sout_stream_sys_t*)p_args;
1326
1327     vlc_mutex_lock( &p_sys->lock_sdp );
1328     if( p_sys->psz_sdp && *p_sys->psz_sdp )
1329     {
1330         *pi_data = strlen( p_sys->psz_sdp );
1331         *pp_data = malloc( *pi_data );
1332         memcpy( *pp_data, p_sys->psz_sdp, *pi_data );
1333     }
1334     else
1335     {
1336         *pp_data = NULL;
1337         *pi_data = 0;
1338     }
1339     vlc_mutex_unlock( &p_sys->lock_sdp );
1340
1341     return VLC_SUCCESS;
1342 }
1343
1344 /****************************************************************************
1345  * RTP send
1346  ****************************************************************************/
1347 static void ThreadSend( vlc_object_t *p_this )
1348 {
1349     sout_stream_id_t *id = (sout_stream_id_t *)p_this;
1350     unsigned i_caching = id->i_caching;
1351 #ifdef HAVE_TEE
1352     int fd[5] = { -1, -1, -1, -1, -1 };
1353
1354     if( pipe( fd ) )
1355         fd[0] = fd[1] = -1;
1356     else
1357     if( pipe( fd ) )
1358         fd[2] = fd[3] = -1;
1359     else
1360         fd[4] = open( "/dev/null", O_WRONLY );
1361 #endif
1362
1363     while( !id->b_die )
1364     {
1365         block_t *out = block_FifoGet( id->p_fifo );
1366         if( out == NULL )
1367             continue; /* Forced wakeup */
1368
1369         mtime_t  i_date = out->i_dts + i_caching;
1370         ssize_t  len = out->i_buffer;
1371
1372 #ifdef HAVE_TEE
1373         if( fd[4] != -1 )
1374             len = write( fd[1], out->p_buffer, len);
1375         if( len == -1 )
1376             continue; /* Uho - should not happen */
1377 #endif
1378         mwait( i_date );
1379
1380         vlc_mutex_lock( &id->lock_sink );
1381         unsigned deadc = 0; /* How many dead sockets? */
1382         int deadv[id->sinkc]; /* Dead sockets list */
1383
1384         for( int i = 0; i < id->sinkc; i++ )
1385         {
1386             SendRTCP( id->sinkv[i].rtcp, out );
1387
1388 #ifdef HAVE_TEE
1389             tee( fd[0], fd[3], len, 0 );
1390             if( splice( fd[2], NULL, id->sinkv[i].rtp_fd, NULL, len,
1391                         SPLICE_F_NONBLOCK ) >= 0 )
1392                 continue;
1393
1394             /* splice failed */
1395             splice( fd[2], NULL, fd[4], NULL, len, 0 );
1396 #endif
1397             if( ( send( id->sinkv[i].rtp_fd, out->p_buffer, len, 0 ) < 0 )
1398              && ( errno != EAGAIN ) )
1399                 deadv[deadc++] = id->sinkv[i].rtp_fd;
1400         }
1401         vlc_mutex_unlock( &id->lock_sink );
1402
1403         block_Release( out );
1404 #ifdef HAVE_TEE
1405         splice( fd[0], NULL, fd[4], NULL, len, 0 );
1406 #endif
1407
1408         for( unsigned i = 0; i < deadc; i++ )
1409         {
1410             msg_Dbg( id, "removing socket %d", deadv[i] );
1411             rtp_del_sink( id, deadv[i] );
1412         }
1413
1414         /* Hopefully we won't overflow the SO_MAXCONN accept queue */
1415         while( id->listen_fd != NULL )
1416         {
1417             int fd = net_Accept( id, id->listen_fd, 0 );
1418             if( fd == -1 )
1419                 break;
1420             msg_Dbg( id, "adding socket %d", fd );
1421             rtp_add_sink( id, fd, VLC_TRUE );
1422         }
1423     }
1424
1425 #ifdef HAVE_TEE
1426     for( unsigned i = 0; i < 5; i++ )
1427         close( fd[i] );
1428 #endif
1429 }
1430
1431 static inline void rtp_packetize_send( sout_stream_id_t *id, block_t *out )
1432 {
1433     block_FifoPut( id->p_fifo, out );
1434 }
1435
1436 int rtp_add_sink( sout_stream_id_t *id, int fd, vlc_bool_t rtcp_mux )
1437 {
1438     rtp_sink_t sink = { fd, NULL };
1439     sink.rtcp = OpenRTCP( VLC_OBJECT( id->p_stream ), fd, IPPROTO_UDP,
1440                           rtcp_mux );
1441     if( sink.rtcp == NULL )
1442         msg_Err( id, "RTCP failed!" );
1443
1444     vlc_mutex_lock( &id->lock_sink );
1445     INSERT_ELEM( id->sinkv, id->sinkc, id->sinkc, sink );
1446     vlc_mutex_unlock( &id->lock_sink );
1447     return VLC_SUCCESS;
1448 }
1449
1450 void rtp_del_sink( sout_stream_id_t *id, int fd )
1451 {
1452     rtp_sink_t sink = { fd, NULL };
1453
1454     /* NOTE: must be safe to use if fd is not included */
1455     vlc_mutex_lock( &id->lock_sink );
1456     for( int i = 0; i < id->sinkc; i++ )
1457     {
1458         if (id->sinkv[i].rtp_fd == fd)
1459         {
1460             sink = id->sinkv[i];
1461             REMOVE_ELEM( id->sinkv, id->sinkc, i );
1462             break;
1463         }
1464     }
1465     vlc_mutex_unlock( &id->lock_sink );
1466
1467     CloseRTCP( sink.rtcp );
1468     net_Close( sink.rtp_fd );
1469 }
1470
1471 uint16_t rtp_get_seq( const sout_stream_id_t *id )
1472 {
1473     /* This will return values for the next packet.
1474      * Accounting for caching would not be totally trivial. */
1475     return id->i_sequence;
1476 }
1477
1478 /* FIXME: this is pretty bad - if we remove and then insert an ES
1479  * the number will get unsynched from inside RTSP */
1480 unsigned rtp_get_num( const sout_stream_id_t *id )
1481 {
1482     sout_stream_sys_t *p_sys = id->p_stream->p_sys;
1483     int i;
1484
1485     vlc_mutex_lock( &p_sys->lock_es );
1486     for( i = 0; i < p_sys->i_es; i++ )
1487     {
1488         if( id == p_sys->es[i] )
1489             break;
1490     }
1491     vlc_mutex_unlock( &p_sys->lock_es );
1492
1493     return i;
1494 }
1495
1496
1497 /****************************************************************************
1498  * rtp_packetize_*:
1499  ****************************************************************************/
1500 static void rtp_packetize_common( sout_stream_id_t *id, block_t *out,
1501                                   int b_marker, int64_t i_pts )
1502 {
1503     uint32_t i_timestamp = i_pts * (int64_t)id->i_clock_rate / I64C(1000000);
1504
1505     out->p_buffer[0] = 0x80;
1506     out->p_buffer[1] = (b_marker?0x80:0x00)|id->i_payload_type;
1507     out->p_buffer[2] = ( id->i_sequence >> 8)&0xff;
1508     out->p_buffer[3] = ( id->i_sequence     )&0xff;
1509     out->p_buffer[4] = ( i_timestamp >> 24 )&0xff;
1510     out->p_buffer[5] = ( i_timestamp >> 16 )&0xff;
1511     out->p_buffer[6] = ( i_timestamp >>  8 )&0xff;
1512     out->p_buffer[7] = ( i_timestamp       )&0xff;
1513
1514     memcpy( out->p_buffer + 8, id->ssrc, 4 );
1515
1516     out->i_buffer = 12;
1517     id->i_sequence++;
1518 }
1519
1520 static int rtp_packetize_mpa( sout_stream_t *p_stream, sout_stream_id_t *id,
1521                               block_t *in )
1522 {
1523     int     i_max   = id->i_mtu - 12 - 4; /* payload max in one packet */
1524     int     i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1525
1526     uint8_t *p_data = in->p_buffer;
1527     int     i_data  = in->i_buffer;
1528     int     i;
1529
1530     for( i = 0; i < i_count; i++ )
1531     {
1532         int           i_payload = __MIN( i_max, i_data );
1533         block_t *out = block_New( p_stream, 16 + i_payload );
1534
1535         /* rtp common header */
1536         rtp_packetize_common( id, out, (i == i_count - 1)?1:0, in->i_pts );
1537         /* mbz set to 0 */
1538         out->p_buffer[12] = 0;
1539         out->p_buffer[13] = 0;
1540         /* fragment offset in the current frame */
1541         out->p_buffer[14] = ( (i*i_max) >> 8 )&0xff;
1542         out->p_buffer[15] = ( (i*i_max)      )&0xff;
1543         memcpy( &out->p_buffer[16], p_data, i_payload );
1544
1545         out->i_buffer   = 16 + i_payload;
1546         out->i_dts    = in->i_dts + i * in->i_length / i_count;
1547         out->i_length = in->i_length / i_count;
1548
1549         rtp_packetize_send( id, out );
1550
1551         p_data += i_payload;
1552         i_data -= i_payload;
1553     }
1554
1555     return VLC_SUCCESS;
1556 }
1557
1558 /* rfc2250 */
1559 static int rtp_packetize_mpv( sout_stream_t *p_stream, sout_stream_id_t *id,
1560                               block_t *in )
1561 {
1562     int     i_max   = id->i_mtu - 12 - 4; /* payload max in one packet */
1563     int     i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1564
1565     uint8_t *p_data = in->p_buffer;
1566     int     i_data  = in->i_buffer;
1567     int     i;
1568     int     b_sequence_start = 0;
1569     int     i_temporal_ref = 0;
1570     int     i_picture_coding_type = 0;
1571     int     i_fbv = 0, i_bfc = 0, i_ffv = 0, i_ffc = 0;
1572     int     b_start_slice = 0;
1573
1574     /* preparse this packet to get some info */
1575     if( in->i_buffer > 4 )
1576     {
1577         uint8_t *p = p_data;
1578         int      i_rest = in->i_buffer;
1579
1580         for( ;; )
1581         {
1582             while( i_rest > 4 &&
1583                    ( p[0] != 0x00 || p[1] != 0x00 || p[2] != 0x01 ) )
1584             {
1585                 p++;
1586                 i_rest--;
1587             }
1588             if( i_rest <= 4 )
1589             {
1590                 break;
1591             }
1592             p += 3;
1593             i_rest -= 4;
1594
1595             if( *p == 0xb3 )
1596             {
1597                 /* sequence start code */
1598                 b_sequence_start = 1;
1599             }
1600             else if( *p == 0x00 && i_rest >= 4 )
1601             {
1602                 /* picture */
1603                 i_temporal_ref = ( p[1] << 2) |((p[2]>>6)&0x03);
1604                 i_picture_coding_type = (p[2] >> 3)&0x07;
1605
1606                 if( i_rest >= 4 && ( i_picture_coding_type == 2 ||
1607                                     i_picture_coding_type == 3 ) )
1608                 {
1609                     i_ffv = (p[3] >> 2)&0x01;
1610                     i_ffc = ((p[3]&0x03) << 1)|((p[4]>>7)&0x01);
1611                     if( i_rest > 4 && i_picture_coding_type == 3 )
1612                     {
1613                         i_fbv = (p[4]>>6)&0x01;
1614                         i_bfc = (p[4]>>3)&0x07;
1615                     }
1616                 }
1617             }
1618             else if( *p <= 0xaf )
1619             {
1620                 b_start_slice = 1;
1621             }
1622         }
1623     }
1624
1625     for( i = 0; i < i_count; i++ )
1626     {
1627         int           i_payload = __MIN( i_max, i_data );
1628         block_t *out = block_New( p_stream,
1629                                              16 + i_payload );
1630         uint32_t      h = ( i_temporal_ref << 16 )|
1631                           ( b_sequence_start << 13 )|
1632                           ( b_start_slice << 12 )|
1633                           ( i == i_count - 1 ? 1 << 11 : 0 )|
1634                           ( i_picture_coding_type << 8 )|
1635                           ( i_fbv << 7 )|( i_bfc << 4 )|( i_ffv << 3 )|i_ffc;
1636
1637         /* rtp common header */
1638         rtp_packetize_common( id, out, (i == i_count - 1)?1:0,
1639                               in->i_pts > 0 ? in->i_pts : in->i_dts );
1640
1641         /* MBZ:5 T:1 TR:10 AN:1 N:1 S:1 B:1 E:1 P:3 FBV:1 BFC:3 FFV:1 FFC:3 */
1642         out->p_buffer[12] = ( h >> 24 )&0xff;
1643         out->p_buffer[13] = ( h >> 16 )&0xff;
1644         out->p_buffer[14] = ( h >>  8 )&0xff;
1645         out->p_buffer[15] = ( h       )&0xff;
1646
1647         memcpy( &out->p_buffer[16], p_data, i_payload );
1648
1649         out->i_buffer   = 16 + i_payload;
1650         out->i_dts    = in->i_dts + i * in->i_length / i_count;
1651         out->i_length = in->i_length / i_count;
1652
1653         rtp_packetize_send( id, out );
1654
1655         p_data += i_payload;
1656         i_data -= i_payload;
1657     }
1658
1659     return VLC_SUCCESS;
1660 }
1661
1662 static int rtp_packetize_ac3( sout_stream_t *p_stream, sout_stream_id_t *id,
1663                               block_t *in )
1664 {
1665     int     i_max   = id->i_mtu - 12 - 2; /* payload max in one packet */
1666     int     i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1667
1668     uint8_t *p_data = in->p_buffer;
1669     int     i_data  = in->i_buffer;
1670     int     i;
1671
1672     for( i = 0; i < i_count; i++ )
1673     {
1674         int           i_payload = __MIN( i_max, i_data );
1675         block_t *out = block_New( p_stream, 14 + i_payload );
1676
1677         /* rtp common header */
1678         rtp_packetize_common( id, out, (i == i_count - 1)?1:0, in->i_pts );
1679         /* unit count */
1680         out->p_buffer[12] = 1;
1681         /* unit header */
1682         out->p_buffer[13] = 0x00;
1683         /* data */
1684         memcpy( &out->p_buffer[14], p_data, i_payload );
1685
1686         out->i_buffer   = 14 + i_payload;
1687         out->i_dts    = in->i_dts + i * in->i_length / i_count;
1688         out->i_length = in->i_length / i_count;
1689
1690         rtp_packetize_send( id, out );
1691
1692         p_data += i_payload;
1693         i_data -= i_payload;
1694     }
1695
1696     return VLC_SUCCESS;
1697 }
1698
1699 static int rtp_packetize_split( sout_stream_t *p_stream, sout_stream_id_t *id,
1700                                 block_t *in )
1701 {
1702     int     i_max   = id->i_mtu - 12; /* payload max in one packet */
1703     int     i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1704
1705     uint8_t *p_data = in->p_buffer;
1706     int     i_data  = in->i_buffer;
1707     int     i;
1708
1709     for( i = 0; i < i_count; i++ )
1710     {
1711         int           i_payload = __MIN( i_max, i_data );
1712         block_t *out = block_New( p_stream, 12 + i_payload );
1713
1714         /* rtp common header */
1715         rtp_packetize_common( id, out, ((i == i_count - 1)?1:0),
1716                               (in->i_pts > 0 ? in->i_pts : in->i_dts) );
1717         memcpy( &out->p_buffer[12], p_data, i_payload );
1718
1719         out->i_buffer   = 12 + i_payload;
1720         out->i_dts    = in->i_dts + i * in->i_length / i_count;
1721         out->i_length = in->i_length / i_count;
1722
1723         rtp_packetize_send( id, out );
1724
1725         p_data += i_payload;
1726         i_data -= i_payload;
1727     }
1728
1729     return VLC_SUCCESS;
1730 }
1731
1732 /* rfc3016 */
1733 static int rtp_packetize_mp4a_latm( sout_stream_t *p_stream, sout_stream_id_t *id,
1734                                 block_t *in )
1735 {
1736     int     i_max   = id->i_mtu - 14;              /* payload max in one packet */
1737     int     latmhdrsize = in->i_buffer / 0xff + 1;
1738     int     i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1739
1740     uint8_t *p_data = in->p_buffer, *p_header = NULL;
1741     int     i_data  = in->i_buffer;
1742     int     i;
1743
1744     for( i = 0; i < i_count; i++ )
1745     {
1746         int     i_payload = __MIN( i_max, i_data );
1747         block_t *out;
1748
1749         if( i != 0 )
1750             latmhdrsize = 0;
1751         out = block_New( p_stream, 12 + latmhdrsize + i_payload );
1752
1753         /* rtp common header */
1754         rtp_packetize_common( id, out, ((i == i_count - 1) ? 1 : 0),
1755                               (in->i_pts > 0 ? in->i_pts : in->i_dts) );
1756
1757         if( i == 0 )
1758         {
1759             int tmp = in->i_buffer;
1760
1761             p_header=out->p_buffer+12;
1762             while( tmp > 0xfe )
1763             {
1764                 *p_header = 0xff;
1765                 p_header++;
1766                 tmp -= 0xff;
1767             }
1768             *p_header = tmp;
1769         }
1770
1771         memcpy( &out->p_buffer[12+latmhdrsize], p_data, i_payload );
1772
1773         out->i_buffer   = 12 + latmhdrsize + i_payload;
1774         out->i_dts    = in->i_dts + i * in->i_length / i_count;
1775         out->i_length = in->i_length / i_count;
1776
1777         rtp_packetize_send( id, out );
1778
1779         p_data += i_payload;
1780         i_data -= i_payload;
1781     }
1782
1783     return VLC_SUCCESS;
1784 }
1785
1786 static int rtp_packetize_l16( sout_stream_t *p_stream, sout_stream_id_t *id,
1787                               block_t *in )
1788 {
1789     int     i_max   = id->i_mtu - 12; /* payload max in one packet */
1790     int     i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1791
1792     uint8_t *p_data = in->p_buffer;
1793     int     i_data  = in->i_buffer;
1794     int     i_packet = 0;
1795
1796     while( i_data > 0 )
1797     {
1798         int           i_payload = (__MIN( i_max, i_data )/4)*4;
1799         block_t *out = block_New( p_stream, 12 + i_payload );
1800
1801         /* rtp common header */
1802         rtp_packetize_common( id, out, 0,
1803                               (in->i_pts > 0 ? in->i_pts : in->i_dts) );
1804         memcpy( &out->p_buffer[12], p_data, i_payload );
1805
1806         out->i_buffer   = 12 + i_payload;
1807         out->i_dts    = in->i_dts + i_packet * in->i_length / i_count;
1808         out->i_length = in->i_length / i_count;
1809
1810         rtp_packetize_send( id, out );
1811
1812         p_data += i_payload;
1813         i_data -= i_payload;
1814         i_packet++;
1815     }
1816
1817     return VLC_SUCCESS;
1818 }
1819
1820 static int rtp_packetize_l8( sout_stream_t *p_stream, sout_stream_id_t *id,
1821                              block_t *in )
1822 {
1823     int     i_max   = id->i_mtu - 12; /* payload max in one packet */
1824     int     i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1825
1826     uint8_t *p_data = in->p_buffer;
1827     int     i_data  = in->i_buffer;
1828     int     i_packet = 0;
1829
1830     while( i_data > 0 )
1831     {
1832         int           i_payload = (__MIN( i_max, i_data )/2)*2;
1833         block_t *out = block_New( p_stream, 12 + i_payload );
1834
1835         /* rtp common header */
1836         rtp_packetize_common( id, out, 0,
1837                               (in->i_pts > 0 ? in->i_pts : in->i_dts) );
1838         memcpy( &out->p_buffer[12], p_data, i_payload );
1839
1840         out->i_buffer   = 12 + i_payload;
1841         out->i_dts    = in->i_dts + i_packet * in->i_length / i_count;
1842         out->i_length = in->i_length / i_count;
1843
1844         rtp_packetize_send( id, out );
1845
1846         p_data += i_payload;
1847         i_data -= i_payload;
1848         i_packet++;
1849     }
1850
1851     return VLC_SUCCESS;
1852 }
1853
1854 static int rtp_packetize_mp4a( sout_stream_t *p_stream, sout_stream_id_t *id,
1855                                block_t *in )
1856 {
1857     int     i_max   = id->i_mtu - 16; /* payload max in one packet */
1858     int     i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1859
1860     uint8_t *p_data = in->p_buffer;
1861     int     i_data  = in->i_buffer;
1862     int     i;
1863
1864     for( i = 0; i < i_count; i++ )
1865     {
1866         int           i_payload = __MIN( i_max, i_data );
1867         block_t *out = block_New( p_stream, 16 + i_payload );
1868
1869         /* rtp common header */
1870         rtp_packetize_common( id, out, ((i == i_count - 1)?1:0),
1871                               (in->i_pts > 0 ? in->i_pts : in->i_dts) );
1872         /* AU headers */
1873         /* AU headers length (bits) */
1874         out->p_buffer[12] = 0;
1875         out->p_buffer[13] = 2*8;
1876         /* for each AU length 13 bits + idx 3bits, */
1877         out->p_buffer[14] = ( in->i_buffer >> 5 )&0xff;
1878         out->p_buffer[15] = ( (in->i_buffer&0xff)<<3 )|0;
1879
1880         memcpy( &out->p_buffer[16], p_data, i_payload );
1881
1882         out->i_buffer   = 16 + i_payload;
1883         out->i_dts    = in->i_dts + i * in->i_length / i_count;
1884         out->i_length = in->i_length / i_count;
1885
1886         rtp_packetize_send( id, out );
1887
1888         p_data += i_payload;
1889         i_data -= i_payload;
1890     }
1891
1892     return VLC_SUCCESS;
1893 }
1894
1895
1896 /* rfc2429 */
1897 #define RTP_H263_HEADER_SIZE (2)  // plen = 0
1898 #define RTP_H263_PAYLOAD_START (14)  // plen = 0
1899 static int rtp_packetize_h263( sout_stream_t *p_stream, sout_stream_id_t *id,
1900                                block_t *in )
1901 {
1902     uint8_t *p_data = in->p_buffer;
1903     int     i_data  = in->i_buffer;
1904     int     i;
1905     int     i_max   = id->i_mtu - 12 - RTP_H263_HEADER_SIZE; /* payload max in one packet */
1906     int     i_count;
1907     int     b_p_bit;
1908     int     b_v_bit = 0; // no pesky error resilience
1909     int     i_plen = 0; // normally plen=0 for PSC packet
1910     int     i_pebit = 0; // because plen=0
1911     uint16_t h;
1912
1913     if( i_data < 2 )
1914     {
1915         return VLC_EGENERIC;
1916     }
1917     if( p_data[0] || p_data[1] )
1918     {
1919         return VLC_EGENERIC;
1920     }
1921     /* remove 2 leading 0 bytes */
1922     p_data += 2;
1923     i_data -= 2;
1924     i_count = ( i_data + i_max - 1 ) / i_max;
1925
1926     for( i = 0; i < i_count; i++ )
1927     {
1928         int      i_payload = __MIN( i_max, i_data );
1929         block_t *out = block_New( p_stream,
1930                                   RTP_H263_PAYLOAD_START + i_payload );
1931         b_p_bit = (i == 0) ? 1 : 0;
1932         h = ( b_p_bit << 10 )|
1933             ( b_v_bit << 9  )|
1934             ( i_plen  << 3  )|
1935               i_pebit;
1936
1937         /* rtp common header */
1938         //b_m_bit = 1; // always contains end of frame
1939         rtp_packetize_common( id, out, (i == i_count - 1)?1:0,
1940                               in->i_pts > 0 ? in->i_pts : in->i_dts );
1941
1942         /* h263 header */
1943         out->p_buffer[12] = ( h >>  8 )&0xff;
1944         out->p_buffer[13] = ( h       )&0xff;
1945         memcpy( &out->p_buffer[RTP_H263_PAYLOAD_START], p_data, i_payload );
1946
1947         out->i_buffer = RTP_H263_PAYLOAD_START + i_payload;
1948         out->i_dts    = in->i_dts + i * in->i_length / i_count;
1949         out->i_length = in->i_length / i_count;
1950
1951         rtp_packetize_send( id, out );
1952
1953         p_data += i_payload;
1954         i_data -= i_payload;
1955     }
1956
1957     return VLC_SUCCESS;
1958 }
1959
1960 /* rfc3984 */
1961 static int
1962 rtp_packetize_h264_nal( sout_stream_t *p_stream, sout_stream_id_t *id,
1963                         const uint8_t *p_data, int i_data, int64_t i_pts,
1964                         int64_t i_dts, vlc_bool_t b_last, int64_t i_length )
1965 {
1966     const int i_max = id->i_mtu - 12; /* payload max in one packet */
1967     int i_nal_hdr;
1968     int i_nal_type;
1969
1970     if( i_data < 5 )
1971         return VLC_SUCCESS;
1972
1973     i_nal_hdr = p_data[3];
1974     i_nal_type = i_nal_hdr&0x1f;
1975
1976     /* Skip start code */
1977     p_data += 3;
1978     i_data -= 3;
1979
1980     /* */
1981     if( i_data <= i_max )
1982     {
1983         /* Single NAL unit packet */
1984         block_t *out = block_New( p_stream, 12 + i_data );
1985         out->i_dts    = i_dts;
1986         out->i_length = i_length;
1987
1988         /* */
1989         rtp_packetize_common( id, out, b_last, i_pts );
1990         out->i_buffer = 12 + i_data;
1991
1992         memcpy( &out->p_buffer[12], p_data, i_data );
1993
1994         rtp_packetize_send( id, out );
1995     }
1996     else
1997     {
1998         /* FU-A Fragmentation Unit without interleaving */
1999         const int i_count = ( i_data-1 + i_max-2 - 1 ) / (i_max-2);
2000         int i;
2001
2002         p_data++;
2003         i_data--;
2004
2005         for( i = 0; i < i_count; i++ )
2006         {
2007             const int i_payload = __MIN( i_data, i_max-2 );
2008             block_t *out = block_New( p_stream, 12 + 2 + i_payload );
2009             out->i_dts    = i_dts + i * i_length / i_count;
2010             out->i_length = i_length / i_count;
2011
2012             /* */
2013             rtp_packetize_common( id, out, (b_last && i_payload == i_data), i_pts );
2014             out->i_buffer = 14 + i_payload;
2015
2016             /* FU indicator */
2017             out->p_buffer[12] = 0x00 | (i_nal_hdr & 0x60) | 28;
2018             /* FU header */
2019             out->p_buffer[13] = ( i == 0 ? 0x80 : 0x00 ) | ( (i == i_count-1) ? 0x40 : 0x00 )  | i_nal_type;
2020             memcpy( &out->p_buffer[14], p_data, i_payload );
2021
2022             rtp_packetize_send( id, out );
2023
2024             i_data -= i_payload;
2025             p_data += i_payload;
2026         }
2027     }
2028     return VLC_SUCCESS;
2029 }
2030
2031 static int rtp_packetize_h264( sout_stream_t *p_stream, sout_stream_id_t *id,
2032                                block_t *in )
2033 {
2034     const uint8_t *p_buffer = in->p_buffer;
2035     int i_buffer = in->i_buffer;
2036
2037     while( i_buffer > 4 && ( p_buffer[0] != 0 || p_buffer[1] != 0 || p_buffer[2] != 1 ) )
2038     {
2039         i_buffer--;
2040         p_buffer++;
2041     }
2042
2043     /* Split nal units */
2044     while( i_buffer > 4 )
2045     {
2046         int i_offset;
2047         int i_size = i_buffer;
2048         int i_skip = i_buffer;
2049
2050         /* search nal end */
2051         for( i_offset = 4; i_offset+2 < i_buffer ; i_offset++)
2052         {
2053             if( p_buffer[i_offset] == 0 && p_buffer[i_offset+1] == 0 && p_buffer[i_offset+2] == 1 )
2054             {
2055                 /* we found another startcode */
2056                 i_size = i_offset - ( p_buffer[i_offset-1] == 0 ? 1 : 0);
2057                 i_skip = i_offset;
2058                 break;
2059             }
2060         }
2061         /* TODO add STAP-A to remove a lot of overhead with small slice/sei/... */
2062         rtp_packetize_h264_nal( p_stream, id, p_buffer, i_size,
2063                                 (in->i_pts > 0 ? in->i_pts : in->i_dts), in->i_dts,
2064                                 (i_size >= i_buffer), in->i_length * i_size / in->i_buffer );
2065
2066         i_buffer -= i_skip;
2067         p_buffer += i_skip;
2068     }
2069     return VLC_SUCCESS;
2070 }
2071
2072 static int rtp_packetize_amr( sout_stream_t *p_stream, sout_stream_id_t *id,
2073                               block_t *in )
2074 {
2075     int     i_max   = id->i_mtu - 14; /* payload max in one packet */
2076     int     i_count = ( in->i_buffer + i_max - 1 ) / i_max;
2077
2078     uint8_t *p_data = in->p_buffer;
2079     int     i_data  = in->i_buffer;
2080     int     i;
2081
2082     /* Only supports octet-aligned mode */
2083     for( i = 0; i < i_count; i++ )
2084     {
2085         int           i_payload = __MIN( i_max, i_data );
2086         block_t *out = block_New( p_stream, 14 + i_payload );
2087
2088         /* rtp common header */
2089         rtp_packetize_common( id, out, ((i == i_count - 1)?1:0),
2090                               (in->i_pts > 0 ? in->i_pts : in->i_dts) );
2091         /* Payload header */
2092         out->p_buffer[12] = 0xF0; /* CMR */
2093         out->p_buffer[13] = p_data[0]&0x7C; /* ToC */ /* FIXME: frame type */
2094
2095         /* FIXME: are we fed multiple frames ? */
2096         memcpy( &out->p_buffer[14], p_data+1, i_payload-1 );
2097
2098         out->i_buffer   = 14 + i_payload-1;
2099         out->i_dts    = in->i_dts + i * in->i_length / i_count;
2100         out->i_length = in->i_length / i_count;
2101
2102         rtp_packetize_send( id, out );
2103
2104         p_data += i_payload;
2105         i_data -= i_payload;
2106     }
2107
2108     return VLC_SUCCESS;
2109 }
2110
2111 static int rtp_packetize_t140( sout_stream_t *p_stream, sout_stream_id_t *id,
2112                                block_t *in )
2113 {
2114     const size_t   i_max  = id->i_mtu - 12;
2115     const uint8_t *p_data = in->p_buffer;
2116     size_t         i_data = in->i_buffer;
2117
2118     for( unsigned i_packet = 0; i_data > 0; i_packet++ )
2119     {
2120         size_t i_payload = i_data;
2121
2122         /* Make sure we stop on an UTF-8 character boundary
2123          * (assuming the input is valid UTF-8) */
2124         if( i_data > i_max )
2125         {
2126             i_payload = i_max;
2127
2128             while( ( p_data[i_payload] & 0xC0 ) == 0x80 )
2129             {
2130                 if( i_payload == 0 )
2131                     return VLC_SUCCESS; /* fishy input! */
2132
2133                 i_payload--;
2134             }
2135         }
2136
2137         block_t *out = block_New( p_stream, 12 + i_payload );
2138         if( out == NULL )
2139             return VLC_SUCCESS;
2140
2141         rtp_packetize_common( id, out, 0, in->i_pts + i_packet );
2142         memcpy( out->p_buffer + 12, p_data, i_payload );
2143
2144         out->i_buffer = 12 + i_payload;
2145         out->i_dts    = out->i_pts;
2146         out->i_length = 0;
2147
2148         rtp_packetize_send( id, out );
2149
2150         p_data += i_payload;
2151         i_data -= i_payload;
2152     }
2153
2154     return VLC_SUCCESS;
2155 }
2156
2157 /*****************************************************************************
2158  * Non-RTP mux
2159  *****************************************************************************/
2160
2161 /** Add an ES to a non-RTP muxed stream */
2162 static sout_stream_id_t *MuxAdd( sout_stream_t *p_stream, es_format_t *p_fmt )
2163 {
2164     sout_input_t      *p_input;
2165     sout_mux_t *p_mux = p_stream->p_sys->p_mux;
2166     assert( p_mux != NULL );
2167
2168     p_input = sout_MuxAddStream( p_mux, p_fmt );
2169     if( p_input == NULL )
2170     {
2171         msg_Err( p_stream, "cannot add this stream to the muxer" );
2172         return NULL;
2173     }
2174
2175     return (sout_stream_id_t *)p_input;
2176 }
2177
2178
2179 static int MuxSend( sout_stream_t *p_stream, sout_stream_id_t *id,
2180                     block_t *p_buffer )
2181 {
2182     sout_mux_t *p_mux = p_stream->p_sys->p_mux;
2183     assert( p_mux != NULL );
2184
2185     sout_MuxSendBuffer( p_mux, (sout_input_t *)id, p_buffer );
2186     return VLC_SUCCESS;
2187 }
2188
2189
2190 /** Remove an ES from a non-RTP muxed stream */
2191 static int MuxDel( sout_stream_t *p_stream, sout_stream_id_t *id )
2192 {
2193     sout_mux_t *p_mux = p_stream->p_sys->p_mux;
2194     assert( p_mux != NULL );
2195
2196     sout_MuxDeleteStream( p_mux, (sout_input_t *)id );
2197     return VLC_SUCCESS;
2198 }
2199
2200
2201 static int AccessOutGrabberWriteBuffer( sout_stream_t *p_stream,
2202                                         const block_t *p_buffer )
2203 {
2204     sout_stream_sys_t *p_sys = p_stream->p_sys;
2205     sout_stream_id_t *id = p_sys->es[0];
2206
2207     int64_t  i_dts = p_buffer->i_dts;
2208
2209     uint8_t         *p_data = p_buffer->p_buffer;
2210     unsigned int    i_data  = p_buffer->i_buffer;
2211     unsigned int    i_max   = id->i_mtu - 12;
2212
2213     unsigned i_packet = ( p_buffer->i_buffer + i_max - 1 ) / i_max;
2214
2215     while( i_data > 0 )
2216     {
2217         unsigned int i_size;
2218
2219         /* output complete packet */
2220         if( p_sys->packet &&
2221             p_sys->packet->i_buffer + i_data > i_max )
2222         {
2223             rtp_packetize_send( id, p_sys->packet );
2224             p_sys->packet = NULL;
2225         }
2226
2227         if( p_sys->packet == NULL )
2228         {
2229             /* allocate a new packet */
2230             p_sys->packet = block_New( p_stream, id->i_mtu );
2231             rtp_packetize_common( id, p_sys->packet, 1, i_dts );
2232             p_sys->packet->i_dts = i_dts;
2233             p_sys->packet->i_length = p_buffer->i_length / i_packet;
2234             i_dts += p_sys->packet->i_length;
2235         }
2236
2237         i_size = __MIN( i_data,
2238                         (unsigned)(id->i_mtu - p_sys->packet->i_buffer) );
2239
2240         memcpy( &p_sys->packet->p_buffer[p_sys->packet->i_buffer],
2241                 p_data, i_size );
2242
2243         p_sys->packet->i_buffer += i_size;
2244         p_data += i_size;
2245         i_data -= i_size;
2246     }
2247
2248     return VLC_SUCCESS;
2249 }
2250
2251
2252 static int AccessOutGrabberWrite( sout_access_out_t *p_access,
2253                                   block_t *p_buffer )
2254 {
2255     sout_stream_t *p_stream = (sout_stream_t*)p_access->p_sys;
2256
2257     while( p_buffer )
2258     {
2259         block_t *p_next;
2260
2261         AccessOutGrabberWriteBuffer( p_stream, p_buffer );
2262
2263         p_next = p_buffer->p_next;
2264         block_Release( p_buffer );
2265         p_buffer = p_next;
2266     }
2267
2268     return VLC_SUCCESS;
2269 }
2270
2271
2272 static sout_access_out_t *GrabberCreate( sout_stream_t *p_stream )
2273 {
2274     sout_access_out_t *p_grab;
2275
2276     p_grab = vlc_object_create( p_stream->p_sout, sizeof( *p_grab ) );
2277     if( p_grab == NULL )
2278         return NULL;
2279
2280     p_grab->p_module    = NULL;
2281     p_grab->p_sout      = p_stream->p_sout;
2282     p_grab->psz_access  = strdup( "grab" );
2283     p_grab->p_cfg       = NULL;
2284     p_grab->psz_path    = strdup( "" );
2285     p_grab->p_sys       = (sout_access_out_sys_t *)p_stream;
2286     p_grab->pf_seek     = NULL;
2287     p_grab->pf_write    = AccessOutGrabberWrite;
2288     return p_grab;
2289 }
2290
2291 static int rtp_packetize_spx( sout_stream_t *p_stream, sout_stream_id_t *id,
2292                               block_t *in )
2293 {
2294     uint8_t *p_buffer = in->p_buffer;
2295     int i_data_size, i_payload_size, i_payload_padding;
2296     i_data_size = i_payload_size = in->i_buffer;
2297     i_payload_padding = 0;
2298     block_t *p_out;
2299
2300     if ( in->i_buffer + 12 > id->i_mtu )
2301     {
2302         msg_Warn( p_stream, "Cannot send packet larger than output MTU" );
2303         return VLC_SUCCESS;
2304     }
2305
2306     /*
2307       RFC for Speex in RTP says that each packet must end on an octet 
2308       boundary. So, we check to see if the number of bytes % 4 is zero.
2309       If not, we have to add some padding. 
2310
2311       This MAY be overkill since packetization is handled elsewhere and 
2312       appears to ensure the octet boundary. However, better safe than
2313       sorry.
2314     */
2315     if ( i_payload_size % 4 )
2316     {
2317         i_payload_padding = 4 - ( i_payload_size % 4 );
2318         i_payload_size += i_payload_padding;
2319     }
2320
2321     /* 
2322       Allocate a new RTP p_output block of the appropriate size. 
2323       Allow for 12 extra bytes of RTP header. 
2324     */
2325     p_out = block_New( p_stream, 12 + i_payload_size );
2326
2327     if ( i_payload_padding )
2328     {
2329         /* 
2330           The padding is required to be a zero followed by all 1s.
2331         */
2332         char c_first_pad, c_remaining_pad;
2333         c_first_pad = 0x7F;
2334         c_remaining_pad = 0xFF;
2335
2336         /* 
2337           Allow for 12 bytes before the i_data_size because
2338           of the expected RTP header added during
2339           rtp_packetize_common.
2340         */
2341         p_out->p_buffer[12 + i_data_size] = c_first_pad; 
2342         switch (i_payload_padding)
2343         {
2344             case 2:
2345                 p_out->p_buffer[12 + i_data_size + 1] = c_remaining_pad; 
2346                 break;
2347             case 3:
2348                 p_out->p_buffer[12 + i_data_size + 1] = c_remaining_pad; 
2349                 p_out->p_buffer[12 + i_data_size + 2] = c_remaining_pad; 
2350                 break;
2351         }
2352     } 
2353
2354     /* Add the RTP header to our p_output buffer. */
2355     rtp_packetize_common( id, p_out, 0, (in->i_pts > 0 ? in->i_pts : in->i_dts) );
2356     /* Copy the Speex payload to the p_output buffer */
2357     memcpy( &p_out->p_buffer[12], p_buffer, i_data_size );
2358
2359     p_out->i_buffer = 12 + i_payload_size;
2360     p_out->i_dts = in->i_dts;
2361     p_out->i_length = in->i_length;
2362
2363     /* Queue the buffer for actual transmission. */
2364     rtp_packetize_send( id, p_out );
2365     return VLC_SUCCESS;
2366 }