]> git.sesse.net Git - vlc/blob - modules/stream_out/rtp.c
fbd4dab530c2f2763638e6426f668fb811aeb4c3
[vlc] / modules / stream_out / rtp.c
1 /*****************************************************************************
2  * rtp.c
3  *****************************************************************************
4  * Copyright (C) 2003 VideoLAN
5  * $Id: rtp.c,v 1.6 2003/11/07 18:32:24 fenrir Exp $
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>
28
29 #include <vlc/vlc.h>
30 #include <vlc/input.h>
31 #include <vlc/sout.h>
32
33 #include "httpd.h"
34 #include "network.h"
35
36 /*****************************************************************************
37  * Module descriptor
38  *****************************************************************************/
39 static int  Open ( vlc_object_t * );
40 static void Close( vlc_object_t * );
41
42 vlc_module_begin();
43     set_description( _("RTP stream") );
44     set_capability( "sout stream", 0 );
45     add_shortcut( "rtp" );
46     set_callbacks( Open, Close );
47 vlc_module_end();
48
49 /*****************************************************************************
50  * Exported prototypes
51  *****************************************************************************/
52 static sout_stream_id_t *Add ( sout_stream_t *, sout_format_t * );
53 static int               Del ( sout_stream_t *, sout_stream_id_t * );
54 static int               Send( sout_stream_t *, sout_stream_id_t *, sout_buffer_t* );
55
56
57 struct sout_stream_sys_t
58 {
59     /* sdp */
60     int64_t i_sdp_id;
61     int     i_sdp_version;
62     char    *psz_sdp;
63
64     vlc_mutex_t  lock_sdp;
65
66     httpd_t      *p_httpd;
67     httpd_host_t *p_httpd_host;
68     httpd_file_t *p_httpd_file;
69
70     /* */
71     char *psz_destination;
72     int  i_port;
73     int  i_ttl;
74
75     /* when need to use a private one or when using muxer */
76     int i_payload_type;
77
78     /* in case we do TS/PS over rtp */
79     sout_mux_t        *p_mux;
80     sout_access_out_t *p_access;
81     int               i_mtu;
82     sout_access_out_t *p_grab;
83     uint16_t          i_sequence;
84     uint32_t          i_timestamp_start;
85     uint8_t           ssrc[4];
86     sout_buffer_t     *packet;
87
88     /* */
89     int              i_es;
90     sout_stream_id_t **es;
91 };
92
93 typedef int (*pf_rtp_packetizer_t)( sout_stream_t *, sout_stream_id_t *, sout_buffer_t * );
94 struct sout_stream_id_t
95 {
96     /* rtp field */
97     uint8_t     i_payload_type;
98     uint16_t    i_sequence;
99     uint32_t    i_timestamp_start;
100     uint8_t     ssrc[4];
101
102     /* for sdp */
103     int         i_clock_rate;
104     char        *psz_rtpmap;
105     char        *psz_fmtp;
106     char        *psz_destination;
107     int         i_port;
108     int         i_cat;
109
110     /* Packetizer specific fields */
111     pf_rtp_packetizer_t pf_packetize;
112     int           i_mtu;
113
114     /* for sending the packets */
115     sout_access_out_t *p_access;
116     sout_input_t      *p_input;
117 };
118 static int AccessOutGrabberWrite( sout_access_out_t *, sout_buffer_t * );
119
120 static int  HttpCallback( httpd_file_callback_args_t *p_args,
121                           uint8_t *p_request, int i_request,
122                           uint8_t **pp_data, int *pi_data );
123
124 /*****************************************************************************
125  * Open:
126  *****************************************************************************/
127 static int Open( vlc_object_t *p_this )
128 {
129     sout_stream_t       *p_stream = (sout_stream_t*)p_this;
130     sout_instance_t     *p_sout = p_stream->p_sout;
131     sout_stream_sys_t   *p_sys;
132
133     char *val;
134
135     p_sys = malloc( sizeof( sout_stream_sys_t ) );
136     p_sys->psz_destination = sout_cfg_find_value( p_stream->p_cfg, "dst" );
137     if( ( val = sout_cfg_find_value( p_stream->p_cfg, "port" ) ) )
138     {
139         p_sys->i_port = atoi( val );
140     }
141     if( !p_sys->psz_destination || *p_sys->psz_destination == '\0' || p_sys->i_port <= 0 )
142     {
143         msg_Err( p_stream, "invalid/missing dst or port" );
144         free( p_sys );
145         return VLC_EGENERIC;
146     }
147     if( ( val = sout_cfg_find_value( p_stream->p_cfg, "ttl" ) ) )
148     {
149         p_sys->i_ttl = atoi( val );
150     }
151     else
152     {
153         p_sys->i_ttl = config_GetInt( p_stream, "ttl" );
154     }
155
156     p_sys->i_payload_type = 96;
157     p_sys->i_es = 0;
158     p_sys->es   = NULL;
159     p_sys->psz_sdp = NULL;
160
161     p_sys->i_sdp_id = mdate();
162     p_sys->i_sdp_version = 1;
163     p_sys->psz_sdp = NULL;
164     p_sys->p_httpd = NULL;
165     p_sys->p_httpd_host = NULL;
166     p_sys->p_httpd_file = NULL;
167
168     if( ( val = sout_cfg_find_value( p_stream->p_cfg, "mux" ) ) )
169     {
170         sout_access_out_t *p_grab;
171
172         char *psz_rtpmap;
173         char access[100];
174         char url[strlen( p_sys->psz_destination ) + 1 + 12 + 1];
175
176         /* Check muxer type */
177         if( !strncasecmp( val, "ps", 2 ) || !strncasecmp( val, "mpeg1", 5 ) )
178         {
179             psz_rtpmap = "MP2P/90000";
180         }
181         else if( !strncasecmp( val, "ts", 2 ) )
182         {
183             psz_rtpmap = "MP2T/90000";
184             p_sys->i_payload_type = 33;
185         }
186         else
187         {
188             msg_Err( p_stream, "unsupported muxer type with rtp (only ts/ps)" );
189             return VLC_EGENERIC;
190         }
191
192         /* create the access out */
193         if( p_sys->i_ttl > 0 )
194         {
195             sprintf( access, "udp{raw,ttl=%d}", p_sys->i_ttl );
196         }
197         else
198         {
199             sprintf( access, "udp{raw}" );
200         }
201         sprintf( url, "%s:%d", p_sys->psz_destination, p_sys->i_port );
202         if( ( p_sys->p_access = sout_AccessOutNew( p_sout, access, url ) ) == NULL )
203         {
204             msg_Err( p_stream, "cannot create the access out for %s://%s",
205                      access, url );
206             free( p_sys );
207             return VLC_EGENERIC;
208         }
209         p_sys->i_mtu = config_GetInt( p_stream, "mtu" );  /* XXX beurk */
210         if( p_sys->i_mtu <= 16 )
211         {
212             /* better than nothing */
213             p_sys->i_mtu = 1500;
214         }
215
216         /* the access out grabber TODO export it as sout_AccessOutGrabberNew */
217         p_grab = p_sys->p_grab = vlc_object_create( p_sout, sizeof( sout_access_out_t ) );
218         p_grab->p_module    = NULL;
219         p_grab->p_sout      = p_sout;
220         p_grab->psz_access  = strdup( "grab" );
221         p_grab->p_cfg       = NULL;
222         p_grab->psz_name    = strdup( "" );
223         p_grab->p_sys       = (sout_access_out_sys_t*)p_stream;
224         p_grab->pf_seek     = NULL;
225         p_grab->pf_write    = AccessOutGrabberWrite;
226
227         /* the muxer */
228         if( ( p_sys->p_mux = sout_MuxNew( p_sout, val, p_sys->p_grab ) ) == NULL )
229         {
230             msg_Err( p_stream, "cannot create the muxer (%s)", val );
231             sout_AccessOutDelete( p_sys->p_grab );
232             sout_AccessOutDelete( p_sys->p_access );
233             free( p_sys );
234             return VLC_EGENERIC;
235         }
236         p_sout->i_preheader = __MAX( p_sout->i_preheader, p_sys->p_mux->i_preheader );
237
238         /* create the SDP only once */
239         p_sys->psz_sdp = malloc( 200 + 20 + 10 + strlen( p_sys->psz_destination ) + 10 + 10 + 10 + 10 + strlen( psz_rtpmap ) );
240         sprintf( p_sys->psz_sdp,
241                  "v=0\n"
242                  "o=- "I64Fd" %d IN IP4 127.0.0.1\n"
243                  "s=NONE\n"
244                  "c=IN IP4 %s/%d\n"
245                  "m=video %d RTP/AVP %d\n"
246                  "a=rtpmap:%d %s\n",
247                  p_sys->i_sdp_id, p_sys->i_sdp_version,
248                  p_sys->psz_destination, p_sys->i_ttl,
249                  p_sys->i_port, p_sys->i_payload_type,
250                  p_sys->i_payload_type, psz_rtpmap );
251
252         fprintf( stderr, "sdp=%s", p_sys->psz_sdp );
253
254         /* create the rtp context */
255         p_sys->ssrc[0] = rand()&0xff;
256         p_sys->ssrc[1] = rand()&0xff;
257         p_sys->ssrc[2] = rand()&0xff;
258         p_sys->ssrc[3] = rand()&0xff;
259         p_sys->i_sequence = rand()&0xffff;
260         p_sys->i_timestamp_start = rand()&0xffffffff;
261         p_sys->packet = NULL;
262     }
263     else
264     {
265         p_sys->p_mux    = NULL;
266         p_sys->p_access = NULL;
267         p_sys->p_grab   = NULL;
268     }
269
270     if( ( val = sout_cfg_find_value( p_stream->p_cfg, "sdp" ) ) )
271     {
272         vlc_url_t url;
273
274         vlc_UrlParse( &url, val, 0 );
275         if( url.psz_protocol && !strcmp( url.psz_protocol, "http" ) )
276         {
277             if( ( p_sys->p_httpd = httpd_Find( VLC_OBJECT(p_stream), VLC_TRUE ) ) )
278             {
279                 p_sys->p_httpd_host = p_sys->p_httpd->pf_register_host( p_sys->p_httpd,
280                                                                         url.psz_host,
281                                                                         url.i_port );
282                 if( p_sys->p_httpd_host )
283                 {
284                     p_sys->p_httpd_file =
285                         p_sys->p_httpd->pf_register_file( p_sys->p_httpd,
286                                                           url.psz_path ? url.psz_path : "/",
287                                                           "application/sdp",
288                                                           NULL, NULL,
289                                                           HttpCallback, HttpCallback,
290                                                           (void*)p_sys );
291                 }
292             }
293             if( p_sys->p_httpd_file == NULL )
294             {
295                 msg_Err( p_stream, "cannot export sdp as http" );
296             }
297         }
298         else
299         {
300             msg_Warn( p_stream, "unknow protocol for SDP (%s)", url.psz_protocol );
301         }
302         vlc_UrlClean( &url );
303     }
304
305     vlc_mutex_init( p_stream, &p_sys->lock_sdp );
306
307     p_stream->pf_add    = Add;
308     p_stream->pf_del    = Del;
309     p_stream->pf_send   = Send;
310
311     p_stream->p_sys     = p_sys;
312
313     return VLC_SUCCESS;
314 }
315
316 /*****************************************************************************
317  * Close:
318  *****************************************************************************/
319 static void Close( vlc_object_t * p_this )
320 {
321     sout_stream_t     *p_stream = (sout_stream_t*)p_this;
322     sout_stream_sys_t *p_sys = p_stream->p_sys;
323
324     if( p_sys->p_mux )
325     {
326         sout_MuxDelete( p_sys->p_mux );
327         sout_AccessOutDelete( p_sys->p_access );
328         sout_AccessOutDelete( p_sys->p_grab );
329         if( p_sys->packet )
330         {
331             sout_BufferDelete( p_stream->p_sout, p_sys->packet );
332         }
333     }
334
335     vlc_mutex_destroy( &p_sys->lock_sdp );
336
337     if( p_sys->p_httpd_file )
338     {
339         p_sys->p_httpd->pf_unregister_file( p_sys->p_httpd, p_sys->p_httpd_file );
340     }
341     if( p_sys->p_httpd_host )
342     {
343         p_sys->p_httpd->pf_unregister_host( p_sys->p_httpd, p_sys->p_httpd_host );
344     }
345     if( p_sys->p_httpd )
346     {
347         httpd_Release( p_sys->p_httpd );
348     }
349
350     if( p_sys->psz_sdp )
351     {
352         free( p_sys->psz_sdp );
353     }
354     free( p_sys );
355 }
356
357
358 /*****************************************************************************
359  * SDPGenerate
360  *****************************************************************************/
361 static void SDPGenerate( sout_stream_t *p_stream )
362 {
363     sout_stream_sys_t *p_sys = p_stream->p_sys;
364     int i_size;
365     char *psz_sdp, *p;
366     int i;
367
368     i_size = strlen( "v=0\n" ) +
369              strlen( "o=- * * IN IP4 127.0.0.1\n" ) +
370              strlen( "s=NONE\n" ) +
371              strlen( "c=IN IP4 */*\n" ) +
372              strlen( p_sys->psz_destination ) +
373              20 + 10 + 10 + 1;
374     for( i = 0; i < p_sys->i_es; i++ )
375     {
376         sout_stream_id_t *id = p_sys->es[i];
377
378         i_size += strlen( "m=**d*o * RTP/AVP *\n" ) + 10 + 10;
379
380         if( id->psz_rtpmap )
381         {
382             i_size += strlen( "a=rtpmap:* *\n" ) + strlen( id->psz_rtpmap )+10;
383         }
384         if( id->psz_fmtp )
385         {
386             i_size += strlen( "a=fmtp:* *\n" ) + strlen( id->psz_fmtp ) + 10;
387         }
388     }
389
390     p = psz_sdp = malloc( i_size );
391     p += sprintf( p, "v=0\n" );
392     p += sprintf( p, "o=- "I64Fd" %d IN IP4 127.0.0.1\n", p_sys->i_sdp_id, p_sys->i_sdp_version );
393     p += sprintf( p, "s=NONE\n" );
394     p += sprintf( p, "c=IN IP4 %s/%d\n", p_sys->psz_destination, p_sys->i_ttl );
395
396     for( i = 0; i < p_sys->i_es; i++ )
397     {
398         sout_stream_id_t *id = p_sys->es[i];
399
400         if( id->i_cat == AUDIO_ES )
401         {
402             p += sprintf( p, "m=audio %d RTP/AVP %d\n",
403                           id->i_port, id->i_payload_type );
404         }
405         else if( id->i_cat == VIDEO_ES )
406         {
407             p += sprintf( p, "m=video %d RTP/AVP %d\n",
408                           id->i_port, id->i_payload_type );
409         }
410         else
411         {
412             continue;
413         }
414         if( id->psz_rtpmap )
415         {
416             p += sprintf( p, "a=rtpmap:%d %s\n", id->i_payload_type, id->psz_rtpmap );
417         }
418         if( id->psz_fmtp )
419         {
420             p += sprintf( p, "a=fmtp:%d %s\n", id->i_payload_type, id->psz_fmtp );
421         }
422     }
423
424     vlc_mutex_lock( &p_sys->lock_sdp );
425     free( p_sys->psz_sdp );
426     p_sys->psz_sdp = psz_sdp;
427     vlc_mutex_unlock( &p_sys->lock_sdp );
428
429     p_sys->i_sdp_version++;
430
431     fprintf( stderr, "sdp=%s", p_sys->psz_sdp );
432 }
433
434 /*****************************************************************************
435  *
436  *****************************************************************************/
437
438 static int rtp_packetize_l16  ( sout_stream_t *, sout_stream_id_t *, sout_buffer_t * );
439 static int rtp_packetize_l8   ( sout_stream_t *, sout_stream_id_t *, sout_buffer_t * );
440 static int rtp_packetize_mpa  ( sout_stream_t *, sout_stream_id_t *, sout_buffer_t * );
441 static int rtp_packetize_mpv  ( sout_stream_t *, sout_stream_id_t *, sout_buffer_t * );
442 static int rtp_packetize_ac3  ( sout_stream_t *, sout_stream_id_t *, sout_buffer_t * );
443 static int rtp_packetize_split( sout_stream_t *, sout_stream_id_t *, sout_buffer_t * );
444 static int rtp_packetize_mp4a ( sout_stream_t *, sout_stream_id_t *, sout_buffer_t * );
445
446 static void sprintf_hexa( char *s, uint8_t *p_data, int i_data )
447 {
448     static const char hex[16] = "0123456789ABCDEF";
449     int i;
450
451     for( i = 0; i < i_data; i++ )
452     {
453         s[2*i+0] = hex[(p_data[i]>>8)&0xf];
454         s[2*i+1] = hex[(p_data[i]   )&0xf];
455     }
456     s[2*i_data] = '\0';
457 }
458
459 static sout_stream_id_t * Add      ( sout_stream_t *p_stream, sout_format_t *p_fmt )
460 {
461     sout_instance_t   *p_sout = p_stream->p_sout;
462     sout_stream_sys_t *p_sys = p_stream->p_sys;
463     sout_stream_id_t  *id;
464     sout_access_out_t *p_access = NULL;
465
466     char access[100];
467     char url[strlen( p_sys->psz_destination ) + 1 + 12 + 1];
468
469     if( p_sys->p_mux != NULL )
470     {
471         sout_input_t      *p_input  = NULL;
472         if( ( p_input = sout_MuxAddStream( p_sys->p_mux, p_fmt ) ) == NULL )
473         {
474             msg_Err( p_stream, "cannot add this stream to the muxer" );
475             return NULL;
476         }
477
478         id = malloc( sizeof( sout_stream_id_t ) );
479         id->p_access    = NULL;
480         id->p_input     = p_input;
481         id->pf_packetize= NULL;
482
483         return id;
484     }
485
486     /* first try to create the access out */
487     if( p_sys->i_ttl > 0 )
488     {
489         sprintf( access, "udp{raw,ttl=%d}", p_sys->i_ttl );
490     }
491     else
492     {
493         sprintf( access, "udp{raw}" );
494     }
495     sprintf( url, "%s:%d", p_sys->psz_destination, p_sys->i_port );
496     if( ( p_access = sout_AccessOutNew( p_sout, access, url ) ) == NULL )
497     {
498         msg_Err( p_stream, "cannot create the access out for %s://%s",
499                  access, url );
500         return NULL;
501     }
502
503     /* not create the rtp specific stuff */
504     id = malloc( sizeof( sout_stream_id_t ) );
505     id->p_access   = p_access;
506     id->p_input    = NULL;
507     id->psz_rtpmap = NULL;
508     id->psz_fmtp   = NULL;
509     id->psz_destination = strdup( p_sys->psz_destination );
510     id->i_port = p_sys->i_port;
511
512     switch( p_fmt->i_fourcc )
513     {
514         case VLC_FOURCC( 's', '1', '6', 'b' ):
515             if( p_fmt->i_channels == 1 && p_fmt->i_sample_rate == 44100 )
516             {
517                 id->i_payload_type = 11;
518             }
519             else if( p_fmt->i_channels == 2 && p_fmt->i_sample_rate == 44100 )
520             {
521                 id->i_payload_type = 10;
522             }
523             else
524             {
525                 id->i_payload_type = p_sys->i_payload_type++;
526             }
527             id->psz_rtpmap = malloc( strlen( "L16/*/*" ) + 20+1 );
528             sprintf( id->psz_rtpmap, "L16/%d/%d", p_fmt->i_sample_rate, p_fmt->i_channels );
529             id->i_clock_rate = p_fmt->i_sample_rate;
530             id->pf_packetize = rtp_packetize_l16;
531             break;
532         case VLC_FOURCC( 'u', '8', ' ', ' ' ):
533             id->i_payload_type = p_sys->i_payload_type++;
534             id->psz_rtpmap = malloc( strlen( "L8/*/*" ) + 20+1 );
535             sprintf( id->psz_rtpmap, "L8/%d/%d", p_fmt->i_sample_rate, p_fmt->i_channels );
536             id->i_clock_rate = p_fmt->i_sample_rate;
537             id->pf_packetize = rtp_packetize_l8;
538             break;
539         case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
540             id->i_payload_type = 14;
541             id->i_clock_rate = 90000;
542             id->psz_rtpmap = strdup( "MPA/90000" );
543             id->pf_packetize = rtp_packetize_mpa;
544             break;
545         case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
546             id->i_payload_type = 32;
547             id->i_clock_rate = 90000;
548             id->psz_rtpmap = strdup( "MPV/90000" );
549             id->pf_packetize = rtp_packetize_mpv;
550             break;
551         case VLC_FOURCC( 'a', '5', '2', ' ' ):
552             id->i_payload_type = p_sys->i_payload_type++;
553             id->i_clock_rate = 90000;
554             id->psz_rtpmap = strdup( "ac3/90000" );
555             id->pf_packetize = rtp_packetize_ac3;
556             break;
557         case VLC_FOURCC( 'm', 'p', '4', 'v' ):
558         {
559             char hexa[2*p_fmt->i_extra_data +1];
560
561             id->i_payload_type = p_sys->i_payload_type++;
562             id->i_clock_rate = 90000;
563             id->psz_rtpmap = strdup( "MP4V-ES/90000" );
564             id->pf_packetize = rtp_packetize_split;
565             if( p_fmt->i_extra_data > 0 )
566             {
567                 id->psz_fmtp = malloc( 100 + 2 * p_fmt->i_extra_data );
568                 sprintf_hexa( hexa, p_fmt->p_extra_data, p_fmt->i_extra_data );
569                 sprintf( id->psz_fmtp,
570                          "profile-level-id=3; config=%s", hexa );
571             }
572             break;
573         }
574         case VLC_FOURCC( 'm', 'p', '4', 'a' ):
575         {
576             char hexa[2*p_fmt->i_extra_data +1];
577
578             id->i_payload_type = p_sys->i_payload_type++;
579             id->i_clock_rate = p_fmt->i_sample_rate;
580             id->psz_rtpmap = malloc( strlen( "mpeg4-generic/" ) + 12 );
581             sprintf( id->psz_rtpmap, "mpeg4-generic/%d", p_fmt->i_sample_rate );
582             id->pf_packetize = rtp_packetize_mp4a;
583             id->psz_fmtp = malloc( 200 + 2 * p_fmt->i_extra_data );
584             sprintf_hexa( hexa, p_fmt->p_extra_data, p_fmt->i_extra_data );
585             sprintf( id->psz_fmtp,
586                      "streamtype=5; profile-level-id=15; mode=AAC-hbr; config=%s; "
587                      "SizeLength=13; IndexLength=3; IndexDeltaLength=3; Profile=1;", hexa );
588             break;
589         }
590
591         default:
592             msg_Err( p_stream, "cannot add this stream (unsupported codec:%4.4s)", (char*)&p_fmt->i_fourcc );
593             free( id );
594             return NULL;
595     }
596     id->i_cat = p_fmt->i_cat;
597
598     id->ssrc[0] = rand()&0xff;
599     id->ssrc[1] = rand()&0xff;
600     id->ssrc[2] = rand()&0xff;
601     id->ssrc[3] = rand()&0xff;
602     id->i_sequence = rand()&0xffff;
603     id->i_timestamp_start = rand()&0xffffffff;
604
605     id->i_mtu    = config_GetInt( p_stream, "mtu" );  /* XXX beuk */
606     if( id->i_mtu <= 16 )
607     {
608         /* better than nothing */
609         id->i_mtu = 1500;
610     }
611
612     msg_Dbg( p_stream, "access out %s:%s mtu=%d", access, url, id->i_mtu );
613
614     /* Update p_sys context */
615     /* update port used (2 -> 1 rtp, 1 rtcp )*/
616     TAB_APPEND( p_sys->i_es, p_sys->es, id );
617     if( p_sys->p_mux == NULL )
618     {
619         p_sys->i_port += 2;
620         SDPGenerate( p_stream );
621     }
622
623     return id;
624 }
625
626 static int     Del      ( sout_stream_t *p_stream, sout_stream_id_t *id )
627 {
628     sout_stream_sys_t *p_sys = p_stream->p_sys;
629
630     TAB_REMOVE( p_sys->i_es, p_sys->es, id );
631
632     if( id->p_access )
633     {
634         if( id->psz_rtpmap )
635         {
636             free( id->psz_rtpmap );
637         }
638         if( id->psz_fmtp )
639         {
640             free( id->psz_fmtp );
641         }
642         free( id->psz_destination );
643         sout_AccessOutDelete( id->p_access );
644     }
645     else if( id->p_input )
646     {
647         sout_MuxDeleteStream( p_sys->p_mux, id->p_input );
648     }
649     free( id );
650     return VLC_SUCCESS;
651 }
652
653 static int     Send     ( sout_stream_t *p_stream, sout_stream_id_t *id, sout_buffer_t *p_buffer )
654 {
655     sout_buffer_t *p_next;
656
657     if( p_stream->p_sys->p_mux )
658     {
659         sout_MuxSendBuffer( p_stream->p_sys->p_mux, id->p_input, p_buffer );
660     }
661     else
662     {
663         while( p_buffer )
664         {
665             p_next = p_buffer->p_next;
666             if( id->pf_packetize( p_stream, id, p_buffer ) )
667             {
668                 break;
669             }
670             sout_BufferDelete( p_stream->p_sout, p_buffer );
671             p_buffer = p_next;
672         }
673     }
674     return VLC_SUCCESS;
675 }
676
677 static int  HttpCallback( httpd_file_callback_args_t *p_args,
678                           uint8_t *p_request, int i_request,
679                           uint8_t **pp_data, int *pi_data )
680 {
681     sout_stream_sys_t *p_sys = (sout_stream_sys_t*)p_args;
682     vlc_mutex_lock( &p_sys->lock_sdp );
683     if( p_sys->psz_sdp && *p_sys->psz_sdp )
684     {
685         *pi_data = strlen( p_sys->psz_sdp );
686         *pp_data = malloc( *pi_data );
687         memcpy( *pp_data, p_sys->psz_sdp, *pi_data );
688     }
689     else
690     {
691         *pp_data = NULL;
692         *pi_data = 0;
693     }
694     vlc_mutex_unlock( &p_sys->lock_sdp );
695
696     return VLC_SUCCESS;
697 }
698
699 static int AccessOutGrabberWriteBuffer( sout_stream_t *p_stream, sout_buffer_t *p_buffer )
700 {
701     sout_stream_sys_t *p_sys = p_stream->p_sys;
702
703     int64_t  i_dts = p_buffer->i_dts;
704     uint32_t i_timestamp = i_dts * 9 / 100;
705
706     uint8_t         *p_data = p_buffer->p_buffer;
707     unsigned int    i_data  = p_buffer->i_size;
708     unsigned int    i_max   = p_sys->i_mtu - 12;
709
710     int      i_packet = ( p_buffer->i_size + i_max - 1 ) / i_max;
711
712     while( i_data > 0 )
713     {
714         unsigned int i_size;
715
716         /* output complete packet */
717         if( p_sys->packet &&
718             p_sys->packet->i_size + i_data > i_max )
719         {
720             sout_AccessOutWrite( p_sys->p_access, p_sys->packet );
721             p_sys->packet = NULL;
722         }
723
724         if( p_sys->packet == NULL )
725         {
726             /* allocate a new packet */
727             p_sys->packet = sout_BufferNew( p_stream->p_sout, p_sys->i_mtu );
728             p_sys->packet->p_buffer[ 0] = 0x80;
729             p_sys->packet->p_buffer[ 1] = p_sys->i_payload_type;
730             p_sys->packet->p_buffer[ 2] = ( p_sys->i_sequence >> 8)&0xff;
731             p_sys->packet->p_buffer[ 3] = ( p_sys->i_sequence     )&0xff;
732             p_sys->packet->p_buffer[ 4] = ( i_timestamp >> 24 )&0xff;
733             p_sys->packet->p_buffer[ 5] = ( i_timestamp >> 16 )&0xff;
734             p_sys->packet->p_buffer[ 6] = ( i_timestamp >>  8 )&0xff;
735             p_sys->packet->p_buffer[ 7] = ( i_timestamp       )&0xff;
736             p_sys->packet->p_buffer[ 8] = p_sys->ssrc[0];
737             p_sys->packet->p_buffer[ 9] = p_sys->ssrc[1];
738             p_sys->packet->p_buffer[10] = p_sys->ssrc[2];
739             p_sys->packet->p_buffer[11] = p_sys->ssrc[3];
740             p_sys->packet->i_size = 12;
741
742             p_sys->packet->i_dts = i_dts;
743             p_sys->packet->i_length = p_buffer->i_length / i_packet;
744             i_dts += p_sys->packet->i_length;
745
746             p_sys->i_sequence++;
747         }
748
749         i_size = __MIN( i_data, p_sys->i_mtu - p_sys->packet->i_size );
750
751         memcpy( &p_sys->packet->p_buffer[p_sys->packet->i_size],
752                 p_data,
753                 i_size );
754
755         p_sys->packet->i_size += i_size;
756         p_data += i_size;
757         i_data -= i_size;
758     }
759
760     return VLC_SUCCESS;
761 }
762
763 static int AccessOutGrabberWrite( sout_access_out_t *p_access, sout_buffer_t *p_buffer )
764 {
765     sout_stream_t *p_stream = (sout_stream_t*)p_access->p_sys;
766
767     //fprintf( stderr, "received buffer size=%d\n", p_buffer->i_size );
768     //
769     while( p_buffer )
770     {
771         sout_buffer_t *p_next;
772
773         AccessOutGrabberWriteBuffer( p_stream, p_buffer );
774
775         p_next = p_buffer->p_next;
776         sout_BufferDelete( p_access->p_sout, p_buffer );
777         p_buffer = p_next;
778     }
779
780     return VLC_SUCCESS;
781 }
782
783
784 static void rtp_packetize_common( sout_stream_id_t *id, sout_buffer_t *out, int b_marker, int64_t i_pts )
785 {
786     uint32_t i_timestamp = i_pts * (int64_t)id->i_clock_rate / (int64_t)1000000;
787
788     out->p_buffer[0] = 0x80;
789     out->p_buffer[1] = (b_marker?0x80:0x00)|id->i_payload_type;
790     out->p_buffer[2] = ( id->i_sequence >> 8)&0xff;
791     out->p_buffer[3] = ( id->i_sequence     )&0xff;
792     out->p_buffer[4] = ( i_timestamp >> 24 )&0xff;
793     out->p_buffer[5] = ( i_timestamp >> 16 )&0xff;
794     out->p_buffer[6] = ( i_timestamp >>  8 )&0xff;
795     out->p_buffer[7] = ( i_timestamp       )&0xff;
796
797     out->p_buffer[ 8] = id->ssrc[0];
798     out->p_buffer[ 9] = id->ssrc[1];
799     out->p_buffer[10] = id->ssrc[2];
800     out->p_buffer[11] = id->ssrc[3];
801
802     out->i_size = 12;
803     id->i_sequence++;
804 }
805
806 static int rtp_packetize_mpa( sout_stream_t *p_stream, sout_stream_id_t *id, sout_buffer_t *in )
807 {
808     int     i_max   = id->i_mtu - 12 - 4; /* payload max in one packet */
809     int     i_count = ( in->i_size + i_max - 1 ) / i_max;
810
811     uint8_t *p_data = in->p_buffer;
812     int     i_data  = in->i_size;
813     int     i;
814
815     for( i = 0; i < i_count; i++ )
816     {
817         int           i_payload = __MIN( i_max, i_data );
818         sout_buffer_t *out = sout_BufferNew( p_stream->p_sout, 16 + i_payload );
819
820         /* rtp common header */
821         rtp_packetize_common( id, out, (i == i_count - 1)?1:0, in->i_pts );
822         /* mbz set to 0 */
823         out->p_buffer[12] = 0;
824         out->p_buffer[13] = 0;
825         /* fragment offset in the current frame */
826         out->p_buffer[14] = ( (i*i_max) >> 8 )&0xff;
827         out->p_buffer[15] = ( (i*i_max)      )&0xff;
828         memcpy( &out->p_buffer[16], p_data, i_payload );
829
830         out->i_size   = 16 + i_payload;
831         out->i_dts    = in->i_dts + i * in->i_length / i_count;
832         out->i_length = in->i_length / i_count;
833
834         sout_AccessOutWrite( id->p_access, out );
835
836         p_data += i_payload;
837         i_data -= i_payload;
838     }
839
840     return VLC_SUCCESS;
841 }
842
843 /* rfc2250 */
844 static int rtp_packetize_mpv( sout_stream_t *p_stream, sout_stream_id_t *id, sout_buffer_t *in )
845 {
846     int     i_max   = id->i_mtu - 12 - 4; /* payload max in one packet */
847     int     i_count = ( in->i_size + i_max - 1 ) / i_max;
848
849     uint8_t *p_data = in->p_buffer;
850     int     i_data  = in->i_size;
851     int     i;
852     int     b_sequence_start = 0;
853     int     i_temporal_ref = 0;
854     int     i_picture_coding_type = 0;
855     int     i_fbv = 0, i_bfc = 0, i_ffv = 0, i_ffc = 0;
856     int     b_start_slice = 0;
857
858     /* preparse this packet to get some info */
859     if( in->i_size > 4 )
860     {
861         uint8_t *p = p_data;
862         int      i_rest = in->i_size;
863
864         for( ;; )
865         {
866             while( i_rest > 4 &&
867                    ( p[0] != 0x00 || p[1] != 0x00 || p[2] != 0x01 ) )
868             {
869                 p++;
870                 i_rest--;
871             }
872             if( i_rest <= 4 )
873             {
874                 break;
875             }
876             p += 3;
877             i_rest -= 4;
878
879             if( *p == 0xb3 )
880             {
881                 /* sequence start code */
882                 b_sequence_start = 1;
883             }
884             else if( *p == 0x00 && i_rest >= 4 )
885             {
886                 /* picture */
887                 i_temporal_ref = ( p[1] << 2) |((p[2]>>6)&0x03);
888                 i_picture_coding_type = (p[2] >> 3)&0x07;
889
890                 if( i_rest > 4 && ( i_picture_coding_type == 2 || i_picture_coding_type == 3 ) )
891                 {
892                     i_ffc = (p[3] >> 2)&0x01;
893                     i_bfc = ((p[3]&0x03) << 1)|((p[4]>>7)&0x01);
894                     if( i_picture_coding_type == 3 )
895                     {
896                         i_fbv = (p[4]>>6)&0x01;
897                         i_bfc = (p[4]>>3)&0x07;
898                     }
899                 }
900             }
901             else if( *p <= 0xaf )
902             {
903                 b_start_slice = 1;
904             }
905         }
906     }
907
908     for( i = 0; i < i_count; i++ )
909     {
910         int           i_payload = __MIN( i_max, i_data );
911         sout_buffer_t *out = sout_BufferNew( p_stream->p_sout, 16 + i_payload );
912         uint32_t      h = ( i_temporal_ref << 16 )|
913                           ( b_sequence_start << 13 )|
914                           ( b_start_slice << 12 )|
915                           ( i == i_count - 1 ? 1 << 11 : 0 )|
916                           ( i_picture_coding_type << 8 )|
917                           ( i_fbv << 7 )|( i_bfc << 4 )|( i_ffv << 3 )|i_ffc;
918
919         /* rtp common header */
920         rtp_packetize_common( id, out, (i == i_count - 1)?1:0, in->i_pts );
921
922         /* 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 */
923         out->p_buffer[12] = ( h >> 24 )&0xff;
924         out->p_buffer[13] = ( h >> 16 )&0xff;
925         out->p_buffer[14] = ( h >>  8 )&0xff;
926         out->p_buffer[15] = ( h       )&0xff;
927
928         memcpy( &out->p_buffer[16], p_data, i_payload );
929
930         out->i_size   = 16 + i_payload;
931         out->i_dts    = in->i_dts + i * in->i_length / i_count;
932         out->i_length = in->i_length / i_count;
933
934         sout_AccessOutWrite( id->p_access, out );
935
936         p_data += i_payload;
937         i_data -= i_payload;
938     }
939
940     return VLC_SUCCESS;
941 }
942 static int rtp_packetize_ac3( sout_stream_t *p_stream, sout_stream_id_t *id, sout_buffer_t *in )
943 {
944     int     i_max   = id->i_mtu - 12 - 2; /* payload max in one packet */
945     int     i_count = ( in->i_size + i_max - 1 ) / i_max;
946
947     uint8_t *p_data = in->p_buffer;
948     int     i_data  = in->i_size;
949     int     i;
950
951     for( i = 0; i < i_count; i++ )
952     {
953         int           i_payload = __MIN( i_max, i_data );
954         sout_buffer_t *out = sout_BufferNew( p_stream->p_sout, 14 + i_payload );
955
956         /* rtp common header */
957         rtp_packetize_common( id, out, (i == i_count - 1)?1:0, in->i_pts );
958         /* unit count */
959         out->p_buffer[12] = 1;
960         /* unit header */
961         out->p_buffer[13] = 0x00;
962         /* data */
963         memcpy( &out->p_buffer[14], p_data, i_payload );
964
965         out->i_size   = 14 + i_payload;
966         out->i_dts    = in->i_dts + i * in->i_length / i_count;
967         out->i_length = in->i_length / i_count;
968
969         sout_AccessOutWrite( id->p_access, out );
970
971         p_data += i_payload;
972         i_data -= i_payload;
973     }
974
975     return VLC_SUCCESS;
976 }
977
978 static int rtp_packetize_split( sout_stream_t *p_stream, sout_stream_id_t *id, sout_buffer_t *in )
979 {
980     int     i_max   = id->i_mtu - 12; /* payload max in one packet */
981     int     i_count = ( in->i_size + i_max - 1 ) / i_max;
982
983     uint8_t *p_data = in->p_buffer;
984     int     i_data  = in->i_size;
985     int     i;
986
987     for( i = 0; i < i_count; i++ )
988     {
989         int           i_payload = __MIN( i_max, i_data );
990         sout_buffer_t *out = sout_BufferNew( p_stream->p_sout, 12 + i_payload );
991
992         /* rtp common header */
993         rtp_packetize_common( id, out, ((i == i_count - 1)?1:0), (in->i_pts > 0 ? in->i_pts : in->i_dts) );
994         memcpy( &out->p_buffer[12], p_data, i_payload );
995
996         out->i_size   = 12 + i_payload;
997         out->i_dts    = in->i_dts + i * in->i_length / i_count;
998         out->i_length = in->i_length / i_count;
999
1000         sout_AccessOutWrite( id->p_access, out );
1001
1002         p_data += i_payload;
1003         i_data -= i_payload;
1004     }
1005
1006     return VLC_SUCCESS;
1007 }
1008
1009 static int rtp_packetize_l16( sout_stream_t *p_stream, sout_stream_id_t *id, sout_buffer_t *in )
1010 {
1011     int     i_max   = id->i_mtu - 12; /* payload max in one packet */
1012     int     i_count = ( in->i_size + i_max - 1 ) / i_max;
1013
1014     uint8_t *p_data = in->p_buffer;
1015     int     i_data  = in->i_size;
1016     int     i_packet = 0;
1017
1018     while( i_data > 0 )
1019     {
1020         int           i_payload = (__MIN( i_max, i_data )/4)*4;
1021         sout_buffer_t *out = sout_BufferNew( p_stream->p_sout, 12 + i_payload );
1022
1023         /* rtp common header */
1024         rtp_packetize_common( id, out, 0, (in->i_pts > 0 ? in->i_pts : in->i_dts) );
1025         memcpy( &out->p_buffer[12], p_data, i_payload );
1026
1027         out->i_size   = 12 + i_payload;
1028         out->i_dts    = in->i_dts + i_packet * in->i_length / i_count;
1029         out->i_length = in->i_length / i_count;
1030
1031         sout_AccessOutWrite( id->p_access, out );
1032
1033         p_data += i_payload;
1034         i_data -= i_payload;
1035         i_packet++;
1036     }
1037
1038     return VLC_SUCCESS;
1039 }
1040
1041 static int rtp_packetize_l8( sout_stream_t *p_stream, sout_stream_id_t *id, sout_buffer_t *in )
1042 {
1043     int     i_max   = id->i_mtu - 12; /* payload max in one packet */
1044     int     i_count = ( in->i_size + i_max - 1 ) / i_max;
1045
1046     uint8_t *p_data = in->p_buffer;
1047     int     i_data  = in->i_size;
1048     int     i_packet = 0;
1049
1050     while( i_data > 0 )
1051     {
1052         int           i_payload = (__MIN( i_max, i_data )/2)*2;
1053         sout_buffer_t *out = sout_BufferNew( p_stream->p_sout, 12 + i_payload );
1054
1055         /* rtp common header */
1056         rtp_packetize_common( id, out, 0, (in->i_pts > 0 ? in->i_pts : in->i_dts) );
1057         memcpy( &out->p_buffer[12], p_data, i_payload );
1058
1059         out->i_size   = 12 + i_payload;
1060         out->i_dts    = in->i_dts + i_packet * in->i_length / i_count;
1061         out->i_length = in->i_length / i_count;
1062
1063         sout_AccessOutWrite( id->p_access, out );
1064
1065         p_data += i_payload;
1066         i_data -= i_payload;
1067         i_packet++;
1068     }
1069
1070     return VLC_SUCCESS;
1071 }
1072 static int rtp_packetize_mp4a( sout_stream_t *p_stream, sout_stream_id_t *id, sout_buffer_t *in )
1073 {
1074     int     i_max   = id->i_mtu - 16; /* payload max in one packet */
1075     int     i_count = ( in->i_size + i_max - 1 ) / i_max;
1076
1077     uint8_t *p_data = in->p_buffer;
1078     int     i_data  = in->i_size;
1079     int     i;
1080
1081     for( i = 0; i < i_count; i++ )
1082     {
1083         int           i_payload = __MIN( i_max, i_data );
1084         sout_buffer_t *out = sout_BufferNew( p_stream->p_sout, 16 + i_payload );
1085
1086         /* rtp common header */
1087         rtp_packetize_common( id, out, ((i == i_count - 1)?1:0), (in->i_pts > 0 ? in->i_pts : in->i_dts) );
1088         /* AU headers */
1089         /* AU headers length (bits) */
1090         out->p_buffer[12] = 0;
1091         out->p_buffer[13] = 2*8;
1092         /* for each AU length 13 bits + idx 3bits, */
1093         out->p_buffer[14] = ( in->i_size >> 5 )&&0xff;
1094         out->p_buffer[15] = ( (in->i_size&&0xff)<<3 )|0;
1095
1096         memcpy( &out->p_buffer[16], p_data, i_payload );
1097
1098         out->i_size   = 16 + i_payload;
1099         out->i_dts    = in->i_dts + i * in->i_length / i_count;
1100         out->i_length = in->i_length / i_count;
1101
1102         sout_AccessOutWrite( id->p_access, out );
1103
1104         p_data += i_payload;
1105         i_data -= i_payload;
1106     }
1107
1108     return VLC_SUCCESS;
1109 }