]> git.sesse.net Git - vlc/blob - modules/stream_out/rtpfmt.c
7da262a1c6f906f55286ef3ad75c22e540d2d48a
[vlc] / modules / stream_out / rtpfmt.c
1 /*****************************************************************************
2  * rtpfmt.c: RTP payload formats
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 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <vlc/vlc.h>
30 #include <vlc_sout.h>
31 #include <vlc_block.h>
32
33 #include "rtp.h"
34
35 int
36 rtp_packetize_h264_nal( sout_stream_t *p_stream, sout_stream_id_t *id,
37                         const uint8_t *p_data, int i_data, int64_t i_pts,
38                         int64_t i_dts, bool b_last, int64_t i_length );
39
40 int rtp_packetize_mpa( sout_stream_t *p_stream, sout_stream_id_t *id,
41                        block_t *in )
42 {
43     int     i_max   = rtp_mtu (id) - 4; /* payload max in one packet */
44     int     i_count = ( in->i_buffer + i_max - 1 ) / i_max;
45
46     uint8_t *p_data = in->p_buffer;
47     int     i_data  = in->i_buffer;
48     int     i;
49
50     for( i = 0; i < i_count; i++ )
51     {
52         int           i_payload = __MIN( i_max, i_data );
53         block_t *out = block_New( p_stream, 16 + i_payload );
54
55         /* rtp common header */
56         rtp_packetize_common( id, out, (i == i_count - 1)?1:0, in->i_pts );
57         /* mbz set to 0 */
58         out->p_buffer[12] = 0;
59         out->p_buffer[13] = 0;
60         /* fragment offset in the current frame */
61         out->p_buffer[14] = ( (i*i_max) >> 8 )&0xff;
62         out->p_buffer[15] = ( (i*i_max)      )&0xff;
63         memcpy( &out->p_buffer[16], p_data, i_payload );
64
65         out->i_buffer   = 16 + i_payload;
66         out->i_dts    = in->i_dts + i * in->i_length / i_count;
67         out->i_length = in->i_length / i_count;
68
69         rtp_packetize_send( id, out );
70
71         p_data += i_payload;
72         i_data -= i_payload;
73     }
74
75     return VLC_SUCCESS;
76 }
77
78 /* rfc2250 */
79 int rtp_packetize_mpv( sout_stream_t *p_stream, sout_stream_id_t *id,
80                        block_t *in )
81 {
82     int     i_max   = rtp_mtu (id) - 4; /* payload max in one packet */
83     int     i_count = ( in->i_buffer + i_max - 1 ) / i_max;
84
85     uint8_t *p_data = in->p_buffer;
86     int     i_data  = in->i_buffer;
87     int     i;
88     int     b_sequence_start = 0;
89     int     i_temporal_ref = 0;
90     int     i_picture_coding_type = 0;
91     int     i_fbv = 0, i_bfc = 0, i_ffv = 0, i_ffc = 0;
92     int     b_start_slice = 0;
93
94     /* preparse this packet to get some info */
95     if( in->i_buffer > 4 )
96     {
97         uint8_t *p = p_data;
98         int      i_rest = in->i_buffer;
99
100         for( ;; )
101         {
102             while( i_rest > 4 &&
103                    ( p[0] != 0x00 || p[1] != 0x00 || p[2] != 0x01 ) )
104             {
105                 p++;
106                 i_rest--;
107             }
108             if( i_rest <= 4 )
109             {
110                 break;
111             }
112             p += 3;
113             i_rest -= 4;
114
115             if( *p == 0xb3 )
116             {
117                 /* sequence start code */
118                 b_sequence_start = 1;
119             }
120             else if( *p == 0x00 && i_rest >= 4 )
121             {
122                 /* picture */
123                 i_temporal_ref = ( p[1] << 2) |((p[2]>>6)&0x03);
124                 i_picture_coding_type = (p[2] >> 3)&0x07;
125
126                 if( i_rest >= 4 && ( i_picture_coding_type == 2 ||
127                                     i_picture_coding_type == 3 ) )
128                 {
129                     i_ffv = (p[3] >> 2)&0x01;
130                     i_ffc = ((p[3]&0x03) << 1)|((p[4]>>7)&0x01);
131                     if( i_rest > 4 && i_picture_coding_type == 3 )
132                     {
133                         i_fbv = (p[4]>>6)&0x01;
134                         i_bfc = (p[4]>>3)&0x07;
135                     }
136                 }
137             }
138             else if( *p <= 0xaf )
139             {
140                 b_start_slice = 1;
141             }
142         }
143     }
144
145     for( i = 0; i < i_count; i++ )
146     {
147         int           i_payload = __MIN( i_max, i_data );
148         block_t *out = block_New( p_stream,
149                                              16 + i_payload );
150         uint32_t      h = ( i_temporal_ref << 16 )|
151                           ( b_sequence_start << 13 )|
152                           ( b_start_slice << 12 )|
153                           ( i == i_count - 1 ? 1 << 11 : 0 )|
154                           ( i_picture_coding_type << 8 )|
155                           ( i_fbv << 7 )|( i_bfc << 4 )|( i_ffv << 3 )|i_ffc;
156
157         /* rtp common header */
158         rtp_packetize_common( id, out, (i == i_count - 1)?1:0,
159                               in->i_pts > 0 ? in->i_pts : in->i_dts );
160
161         /* 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 */
162         out->p_buffer[12] = ( h >> 24 )&0xff;
163         out->p_buffer[13] = ( h >> 16 )&0xff;
164         out->p_buffer[14] = ( h >>  8 )&0xff;
165         out->p_buffer[15] = ( h       )&0xff;
166
167         memcpy( &out->p_buffer[16], p_data, i_payload );
168
169         out->i_buffer   = 16 + i_payload;
170         out->i_dts    = in->i_dts + i * in->i_length / i_count;
171         out->i_length = in->i_length / i_count;
172
173         rtp_packetize_send( id, out );
174
175         p_data += i_payload;
176         i_data -= i_payload;
177     }
178
179     return VLC_SUCCESS;
180 }
181
182 int rtp_packetize_ac3( sout_stream_t *p_stream, sout_stream_id_t *id,
183                        block_t *in )
184 {
185     int     i_max   = rtp_mtu (id) - 2; /* payload max in one packet */
186     int     i_count = ( in->i_buffer + i_max - 1 ) / i_max;
187
188     uint8_t *p_data = in->p_buffer;
189     int     i_data  = in->i_buffer;
190     int     i;
191
192     for( i = 0; i < i_count; i++ )
193     {
194         int           i_payload = __MIN( i_max, i_data );
195         block_t *out = block_New( p_stream, 14 + i_payload );
196
197         /* rtp common header */
198         rtp_packetize_common( id, out, (i == i_count - 1)?1:0, in->i_pts );
199         /* unit count */
200         out->p_buffer[12] = 1;
201         /* unit header */
202         out->p_buffer[13] = 0x00;
203         /* data */
204         memcpy( &out->p_buffer[14], p_data, i_payload );
205
206         out->i_buffer   = 14 + i_payload;
207         out->i_dts    = in->i_dts + i * in->i_length / i_count;
208         out->i_length = in->i_length / i_count;
209
210         rtp_packetize_send( id, out );
211
212         p_data += i_payload;
213         i_data -= i_payload;
214     }
215
216     return VLC_SUCCESS;
217 }
218
219 int rtp_packetize_split( sout_stream_t *p_stream, sout_stream_id_t *id,
220                          block_t *in )
221 {
222     int     i_max   = rtp_mtu (id); /* payload max in one packet */
223     int     i_count = ( in->i_buffer + i_max - 1 ) / i_max;
224
225     uint8_t *p_data = in->p_buffer;
226     int     i_data  = in->i_buffer;
227     int     i;
228
229     for( i = 0; i < i_count; i++ )
230     {
231         int           i_payload = __MIN( i_max, i_data );
232         block_t *out = block_New( p_stream, 12 + i_payload );
233
234         /* rtp common header */
235         rtp_packetize_common( id, out, (i == i_count - 1),
236                               (in->i_pts > 0 ? in->i_pts : in->i_dts) );
237         memcpy( &out->p_buffer[12], p_data, i_payload );
238
239         out->i_buffer   = 12 + i_payload;
240         out->i_dts    = in->i_dts + i * in->i_length / i_count;
241         out->i_length = in->i_length / i_count;
242
243         rtp_packetize_send( id, out );
244
245         p_data += i_payload;
246         i_data -= i_payload;
247     }
248
249     return VLC_SUCCESS;
250 }
251
252 /* rfc3016 */
253 int rtp_packetize_mp4a_latm( sout_stream_t *p_stream, sout_stream_id_t *id,
254                              block_t *in )
255 {
256     int     i_max   = rtp_mtu (id) - 2;              /* payload max in one packet */
257     int     latmhdrsize = in->i_buffer / 0xff + 1;
258     int     i_count = ( in->i_buffer + i_max - 1 ) / i_max;
259
260     uint8_t *p_data = in->p_buffer, *p_header = NULL;
261     int     i_data  = in->i_buffer;
262     int     i;
263
264     for( i = 0; i < i_count; i++ )
265     {
266         int     i_payload = __MIN( i_max, i_data );
267         block_t *out;
268
269         if( i != 0 )
270             latmhdrsize = 0;
271         out = block_New( p_stream, 12 + latmhdrsize + i_payload );
272
273         /* rtp common header */
274         rtp_packetize_common( id, out, ((i == i_count - 1) ? 1 : 0),
275                               (in->i_pts > 0 ? in->i_pts : in->i_dts) );
276
277         if( i == 0 )
278         {
279             int tmp = in->i_buffer;
280
281             p_header=out->p_buffer+12;
282             while( tmp > 0xfe )
283             {
284                 *p_header = 0xff;
285                 p_header++;
286                 tmp -= 0xff;
287             }
288             *p_header = tmp;
289         }
290
291         memcpy( &out->p_buffer[12+latmhdrsize], p_data, i_payload );
292
293         out->i_buffer   = 12 + latmhdrsize + i_payload;
294         out->i_dts    = in->i_dts + i * in->i_length / i_count;
295         out->i_length = in->i_length / i_count;
296
297         rtp_packetize_send( id, out );
298
299         p_data += i_payload;
300         i_data -= i_payload;
301     }
302
303     return VLC_SUCCESS;
304 }
305
306 int rtp_packetize_l16( sout_stream_t *p_stream, sout_stream_id_t *id,
307                        block_t *in )
308 {
309     const uint8_t *p_data = in->p_buffer;
310     size_t i_data  = in->i_buffer;
311     size_t i_plen = 2 * rtp_plen (id, 20);
312
313     for( unsigned i_packet = 0; i_data > 0; i_packet++ )
314     {
315         int           i_payload = __MIN( i_plen, i_data );
316         block_t *out = block_New( p_stream, 12 + i_payload );
317
318         /* rtp common header */
319         rtp_packetize_common( id, out, 0,
320                               (in->i_pts > 0 ? in->i_pts : in->i_dts) );
321         memcpy( &out->p_buffer[12], p_data, i_payload );
322
323         out->i_buffer = 12 + i_payload;
324         out->i_dts    = in->i_dts + i_packet * 20000;
325         out->i_length = i_payload * 20000 / i_plen;
326
327         rtp_packetize_send( id, out );
328
329         p_data += i_payload;
330         i_data -= i_payload;
331     }
332
333     return VLC_SUCCESS;
334 }
335
336 int rtp_packetize_l8( sout_stream_t *p_stream, sout_stream_id_t *id,
337                       block_t *in )
338 {
339     const uint8_t *p_data = in->p_buffer;
340     size_t i_data  = in->i_buffer;
341     size_t i_plen = rtp_plen (id, 20);
342
343     for( unsigned i_packet = 0; i_data > 0; i_packet++ )
344     {
345         int           i_payload = __MIN( i_plen, i_data );
346         block_t *out = block_New( p_stream, 12 + i_payload );
347
348         /* rtp common header */
349         rtp_packetize_common( id, out, 0,
350                               (in->i_pts > 0 ? in->i_pts : in->i_dts) );
351         memcpy( &out->p_buffer[12], p_data, i_payload );
352
353         out->i_buffer = 12 + i_payload;
354         out->i_dts    = in->i_dts + i_packet * 20000;
355         out->i_length = i_payload * 20000 / i_plen;
356
357         rtp_packetize_send( id, out );
358
359         p_data += i_payload;
360         i_data -= i_payload;
361     }
362
363     return VLC_SUCCESS;
364 }
365
366 int rtp_packetize_mp4a( sout_stream_t *p_stream, sout_stream_id_t *id,
367                         block_t *in )
368 {
369     int     i_max   = rtp_mtu (id) - 4; /* payload max in one packet */
370     int     i_count = ( in->i_buffer + i_max - 1 ) / i_max;
371
372     uint8_t *p_data = in->p_buffer;
373     int     i_data  = in->i_buffer;
374     int     i;
375
376     for( i = 0; i < i_count; i++ )
377     {
378         int           i_payload = __MIN( i_max, i_data );
379         block_t *out = block_New( p_stream, 16 + i_payload );
380
381         /* rtp common header */
382         rtp_packetize_common( id, out, ((i == i_count - 1)?1:0),
383                               (in->i_pts > 0 ? in->i_pts : in->i_dts) );
384         /* AU headers */
385         /* AU headers length (bits) */
386         out->p_buffer[12] = 0;
387         out->p_buffer[13] = 2*8;
388         /* for each AU length 13 bits + idx 3bits, */
389         out->p_buffer[14] = ( in->i_buffer >> 5 )&0xff;
390         out->p_buffer[15] = ( (in->i_buffer&0xff)<<3 )|0;
391
392         memcpy( &out->p_buffer[16], p_data, i_payload );
393
394         out->i_buffer   = 16 + i_payload;
395         out->i_dts    = in->i_dts + i * in->i_length / i_count;
396         out->i_length = in->i_length / i_count;
397
398         rtp_packetize_send( id, out );
399
400         p_data += i_payload;
401         i_data -= i_payload;
402     }
403
404     return VLC_SUCCESS;
405 }
406
407
408 /* rfc2429 */
409 #define RTP_H263_HEADER_SIZE (2)  // plen = 0
410 #define RTP_H263_PAYLOAD_START (14)  // plen = 0
411 int rtp_packetize_h263( sout_stream_t *p_stream, sout_stream_id_t *id,
412                         block_t *in )
413 {
414     uint8_t *p_data = in->p_buffer;
415     int     i_data  = in->i_buffer;
416     int     i;
417     int     i_max   = rtp_mtu (id) - RTP_H263_HEADER_SIZE; /* payload max in one packet */
418     int     i_count;
419     int     b_p_bit;
420     int     b_v_bit = 0; // no pesky error resilience
421     int     i_plen = 0; // normally plen=0 for PSC packet
422     int     i_pebit = 0; // because plen=0
423     uint16_t h;
424
425     if( i_data < 2 )
426     {
427         return VLC_EGENERIC;
428     }
429     if( p_data[0] || p_data[1] )
430     {
431         return VLC_EGENERIC;
432     }
433     /* remove 2 leading 0 bytes */
434     p_data += 2;
435     i_data -= 2;
436     i_count = ( i_data + i_max - 1 ) / i_max;
437
438     for( i = 0; i < i_count; i++ )
439     {
440         int      i_payload = __MIN( i_max, i_data );
441         block_t *out = block_New( p_stream,
442                                   RTP_H263_PAYLOAD_START + i_payload );
443         b_p_bit = (i == 0) ? 1 : 0;
444         h = ( b_p_bit << 10 )|
445             ( b_v_bit << 9  )|
446             ( i_plen  << 3  )|
447               i_pebit;
448
449         /* rtp common header */
450         //b_m_bit = 1; // always contains end of frame
451         rtp_packetize_common( id, out, (i == i_count - 1)?1:0,
452                               in->i_pts > 0 ? in->i_pts : in->i_dts );
453
454         /* h263 header */
455         out->p_buffer[12] = ( h >>  8 )&0xff;
456         out->p_buffer[13] = ( h       )&0xff;
457         memcpy( &out->p_buffer[RTP_H263_PAYLOAD_START], p_data, i_payload );
458
459         out->i_buffer = RTP_H263_PAYLOAD_START + i_payload;
460         out->i_dts    = in->i_dts + i * in->i_length / i_count;
461         out->i_length = in->i_length / i_count;
462
463         rtp_packetize_send( id, out );
464
465         p_data += i_payload;
466         i_data -= i_payload;
467     }
468
469     return VLC_SUCCESS;
470 }
471
472 /* rfc3984 */
473 int
474 rtp_packetize_h264_nal( sout_stream_t *p_stream, sout_stream_id_t *id,
475                         const uint8_t *p_data, int i_data, int64_t i_pts,
476                         int64_t i_dts, bool b_last, int64_t i_length )
477 {
478     const int i_max = rtp_mtu (id); /* payload max in one packet */
479     int i_nal_hdr;
480     int i_nal_type;
481
482     if( i_data < 5 )
483         return VLC_SUCCESS;
484
485     i_nal_hdr = p_data[3];
486     i_nal_type = i_nal_hdr&0x1f;
487
488     /* Skip start code */
489     p_data += 3;
490     i_data -= 3;
491
492     /* */
493     if( i_data <= i_max )
494     {
495         /* Single NAL unit packet */
496         block_t *out = block_New( p_stream, 12 + i_data );
497         out->i_dts    = i_dts;
498         out->i_length = i_length;
499
500         /* */
501         rtp_packetize_common( id, out, b_last, i_pts );
502         out->i_buffer = 12 + i_data;
503
504         memcpy( &out->p_buffer[12], p_data, i_data );
505
506         rtp_packetize_send( id, out );
507     }
508     else
509     {
510         /* FU-A Fragmentation Unit without interleaving */
511         const int i_count = ( i_data-1 + i_max-2 - 1 ) / (i_max-2);
512         int i;
513
514         p_data++;
515         i_data--;
516
517         for( i = 0; i < i_count; i++ )
518         {
519             const int i_payload = __MIN( i_data, i_max-2 );
520             block_t *out = block_New( p_stream, 12 + 2 + i_payload );
521             out->i_dts    = i_dts + i * i_length / i_count;
522             out->i_length = i_length / i_count;
523
524             /* */
525             rtp_packetize_common( id, out, (b_last && i_payload == i_data), i_pts );
526             out->i_buffer = 14 + i_payload;
527
528             /* FU indicator */
529             out->p_buffer[12] = 0x00 | (i_nal_hdr & 0x60) | 28;
530             /* FU header */
531             out->p_buffer[13] = ( i == 0 ? 0x80 : 0x00 ) | ( (i == i_count-1) ? 0x40 : 0x00 )  | i_nal_type;
532             memcpy( &out->p_buffer[14], p_data, i_payload );
533
534             rtp_packetize_send( id, out );
535
536             i_data -= i_payload;
537             p_data += i_payload;
538         }
539     }
540     return VLC_SUCCESS;
541 }
542
543 int rtp_packetize_h264( sout_stream_t *p_stream, sout_stream_id_t *id,
544                         block_t *in )
545 {
546     const uint8_t *p_buffer = in->p_buffer;
547     int i_buffer = in->i_buffer;
548
549     while( i_buffer > 4 && ( p_buffer[0] != 0 || p_buffer[1] != 0 || p_buffer[2] != 1 ) )
550     {
551         i_buffer--;
552         p_buffer++;
553     }
554
555     /* Split nal units */
556     while( i_buffer > 4 )
557     {
558         int i_offset;
559         int i_size = i_buffer;
560         int i_skip = i_buffer;
561
562         /* search nal end */
563         for( i_offset = 4; i_offset+2 < i_buffer ; i_offset++)
564         {
565             if( p_buffer[i_offset] == 0 && p_buffer[i_offset+1] == 0 && p_buffer[i_offset+2] == 1 )
566             {
567                 /* we found another startcode */
568                 i_size = i_offset - ( p_buffer[i_offset-1] == 0 ? 1 : 0);
569                 i_skip = i_offset;
570                 break;
571             }
572         }
573         /* TODO add STAP-A to remove a lot of overhead with small slice/sei/... */
574         rtp_packetize_h264_nal( p_stream, id, p_buffer, i_size,
575                                 (in->i_pts > 0 ? in->i_pts : in->i_dts), in->i_dts,
576                                 (i_size >= i_buffer), in->i_length * i_size / in->i_buffer );
577
578         i_buffer -= i_skip;
579         p_buffer += i_skip;
580     }
581     return VLC_SUCCESS;
582 }
583
584 int rtp_packetize_amr( sout_stream_t *p_stream, sout_stream_id_t *id,
585                        block_t *in )
586 {
587     int     i_max   = rtp_mtu (id) - 2; /* payload max in one packet */
588     int     i_count = ( in->i_buffer + i_max - 1 ) / i_max;
589
590     uint8_t *p_data = in->p_buffer;
591     int     i_data  = in->i_buffer;
592     int     i;
593
594     /* Only supports octet-aligned mode */
595     for( i = 0; i < i_count; i++ )
596     {
597         int           i_payload = __MIN( i_max, i_data );
598         block_t *out = block_New( p_stream, 14 + i_payload );
599
600         /* rtp common header */
601         rtp_packetize_common( id, out, ((i == i_count - 1)?1:0),
602                               (in->i_pts > 0 ? in->i_pts : in->i_dts) );
603         /* Payload header */
604         out->p_buffer[12] = 0xF0; /* CMR */
605         out->p_buffer[13] = p_data[0]&0x7C; /* ToC */ /* FIXME: frame type */
606
607         /* FIXME: are we fed multiple frames ? */
608         memcpy( &out->p_buffer[14], p_data+1, i_payload-1 );
609
610         out->i_buffer   = 14 + i_payload-1;
611         out->i_dts    = in->i_dts + i * in->i_length / i_count;
612         out->i_length = in->i_length / i_count;
613
614         rtp_packetize_send( id, out );
615
616         p_data += i_payload;
617         i_data -= i_payload;
618     }
619
620     return VLC_SUCCESS;
621 }
622
623 int rtp_packetize_t140( sout_stream_t *p_stream, sout_stream_id_t *id,
624                         block_t *in )
625 {
626     const size_t   i_max  = rtp_mtu (id);
627     const uint8_t *p_data = in->p_buffer;
628     size_t         i_data = in->i_buffer;
629
630     for( unsigned i_packet = 0; i_data > 0; i_packet++ )
631     {
632         size_t i_payload = i_data;
633
634         /* Make sure we stop on an UTF-8 character boundary
635          * (assuming the input is valid UTF-8) */
636         if( i_data > i_max )
637         {
638             i_payload = i_max;
639
640             while( ( p_data[i_payload] & 0xC0 ) == 0x80 )
641             {
642                 if( i_payload == 0 )
643                     return VLC_SUCCESS; /* fishy input! */
644
645                 i_payload--;
646             }
647         }
648
649         block_t *out = block_New( p_stream, 12 + i_payload );
650         if( out == NULL )
651             return VLC_SUCCESS;
652
653         rtp_packetize_common( id, out, 0, in->i_pts + i_packet );
654         memcpy( out->p_buffer + 12, p_data, i_payload );
655
656         out->i_buffer = 12 + i_payload;
657         out->i_dts    = out->i_pts;
658         out->i_length = 0;
659
660         rtp_packetize_send( id, out );
661
662         p_data += i_payload;
663         i_data -= i_payload;
664     }
665
666     return VLC_SUCCESS;
667 }
668
669
670 int rtp_packetize_spx( sout_stream_t *p_stream, sout_stream_id_t *id,
671                        block_t *in )
672 {
673     uint8_t *p_buffer = in->p_buffer;
674     int i_data_size, i_payload_size, i_payload_padding;
675     i_data_size = i_payload_size = in->i_buffer;
676     i_payload_padding = 0;
677     block_t *p_out;
678
679     if ( in->i_buffer > rtp_mtu (id) )
680     {
681         msg_Warn( p_stream, "Cannot send packet larger than output MTU" );
682         return VLC_SUCCESS;
683     }
684
685     /*
686       RFC for Speex in RTP says that each packet must end on an octet 
687       boundary. So, we check to see if the number of bytes % 4 is zero.
688       If not, we have to add some padding. 
689
690       This MAY be overkill since packetization is handled elsewhere and 
691       appears to ensure the octet boundary. However, better safe than
692       sorry.
693     */
694     if ( i_payload_size % 4 )
695     {
696         i_payload_padding = 4 - ( i_payload_size % 4 );
697         i_payload_size += i_payload_padding;
698     }
699
700     /*
701       Allocate a new RTP p_output block of the appropriate size. 
702       Allow for 12 extra bytes of RTP header. 
703     */
704     p_out = block_New( p_stream, 12 + i_payload_size );
705
706     if ( i_payload_padding )
707     {
708     /*
709       The padding is required to be a zero followed by all 1s.
710     */
711         char c_first_pad, c_remaining_pad;
712         c_first_pad = 0x7F;
713         c_remaining_pad = 0xFF;
714
715         /*
716           Allow for 12 bytes before the i_data_size because
717           of the expected RTP header added during
718           rtp_packetize_common.
719         */
720         p_out->p_buffer[12 + i_data_size] = c_first_pad; 
721         switch (i_payload_padding)
722         {
723           case 2:
724             p_out->p_buffer[12 + i_data_size + 1] = c_remaining_pad; 
725             break;
726           case 3:
727             p_out->p_buffer[12 + i_data_size + 1] = c_remaining_pad; 
728             p_out->p_buffer[12 + i_data_size + 2] = c_remaining_pad; 
729             break;
730         }
731     }
732
733     /* Add the RTP header to our p_output buffer. */
734     rtp_packetize_common( id, p_out, 0, (in->i_pts > 0 ? in->i_pts : in->i_dts) );
735     /* Copy the Speex payload to the p_output buffer */
736     memcpy( &p_out->p_buffer[12], p_buffer, i_data_size );
737
738     p_out->i_buffer = 12 + i_payload_size;
739     p_out->i_dts = in->i_dts;
740     p_out->i_length = in->i_length;
741
742     /* Queue the buffer for actual transmission. */
743     rtp_packetize_send( id, p_out );
744     return VLC_SUCCESS;
745 }