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