]> git.sesse.net Git - vlc/blob - modules/stream_out/rtpfmt.c
RTP out: convert s16l to s16b on the fly
[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 > 0 ? 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 > 0 ? 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 > 0 ? 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 > 0 ? 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 > 0 ? 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 > 0 ? 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), i_pts );
484             out->i_buffer = 14 + i_payload;
485
486             /* FU indicator */
487             out->p_buffer[12] = 0x00 | (i_nal_hdr & 0x60) | 28;
488             /* FU header */
489             out->p_buffer[13] = ( i == 0 ? 0x80 : 0x00 ) | ( (i == i_count-1) ? 0x40 : 0x00 )  | i_nal_type;
490             memcpy( &out->p_buffer[14], p_data, i_payload );
491
492             rtp_packetize_send( id, out );
493
494             i_data -= i_payload;
495             p_data += i_payload;
496         }
497     }
498     return VLC_SUCCESS;
499 }
500
501 int rtp_packetize_h264( sout_stream_id_t *id, block_t *in )
502 {
503     const uint8_t *p_buffer = in->p_buffer;
504     int i_buffer = in->i_buffer;
505
506     while( i_buffer > 4 && ( p_buffer[0] != 0 || p_buffer[1] != 0 || p_buffer[2] != 1 ) )
507     {
508         i_buffer--;
509         p_buffer++;
510     }
511
512     /* Split nal units */
513     while( i_buffer > 4 )
514     {
515         int i_offset;
516         int i_size = i_buffer;
517         int i_skip = i_buffer;
518
519         /* search nal end */
520         for( i_offset = 4; i_offset+2 < i_buffer ; i_offset++)
521         {
522             if( p_buffer[i_offset] == 0 && p_buffer[i_offset+1] == 0 && p_buffer[i_offset+2] == 1 )
523             {
524                 /* we found another startcode */
525                 i_size = i_offset - ( p_buffer[i_offset-1] == 0 ? 1 : 0);
526                 i_skip = i_offset;
527                 break;
528             }
529         }
530         /* TODO add STAP-A to remove a lot of overhead with small slice/sei/... */
531         rtp_packetize_h264_nal( id, p_buffer, i_size,
532                                 (in->i_pts > 0 ? in->i_pts : in->i_dts), in->i_dts,
533                                 (i_size >= i_buffer), in->i_length * i_size / in->i_buffer );
534
535         i_buffer -= i_skip;
536         p_buffer += i_skip;
537     }
538     return VLC_SUCCESS;
539 }
540
541 int rtp_packetize_amr( sout_stream_id_t *id, block_t *in )
542 {
543     int     i_max   = rtp_mtu (id) - 2; /* payload max in one packet */
544     int     i_count = ( in->i_buffer + i_max - 1 ) / i_max;
545
546     uint8_t *p_data = in->p_buffer;
547     int     i_data  = in->i_buffer;
548     int     i;
549
550     /* Only supports octet-aligned mode */
551     for( i = 0; i < i_count; i++ )
552     {
553         int           i_payload = __MIN( i_max, i_data );
554         block_t *out = block_Alloc( 14 + i_payload );
555
556         /* rtp common header */
557         rtp_packetize_common( id, out, ((i == i_count - 1)?1:0),
558                               (in->i_pts > 0 ? in->i_pts : in->i_dts) );
559         /* Payload header */
560         out->p_buffer[12] = 0xF0; /* CMR */
561         out->p_buffer[13] = p_data[0]&0x7C; /* ToC */ /* FIXME: frame type */
562
563         /* FIXME: are we fed multiple frames ? */
564         memcpy( &out->p_buffer[14], p_data+1, i_payload-1 );
565
566         out->i_buffer   = 14 + i_payload-1;
567         out->i_dts    = in->i_dts + i * in->i_length / i_count;
568         out->i_length = in->i_length / i_count;
569
570         rtp_packetize_send( id, out );
571
572         p_data += i_payload;
573         i_data -= i_payload;
574     }
575
576     return VLC_SUCCESS;
577 }
578
579 int rtp_packetize_t140( sout_stream_id_t *id, block_t *in )
580 {
581     const size_t   i_max  = rtp_mtu (id);
582     const uint8_t *p_data = in->p_buffer;
583     size_t         i_data = in->i_buffer;
584
585     for( unsigned i_packet = 0; i_data > 0; i_packet++ )
586     {
587         size_t i_payload = i_data;
588
589         /* Make sure we stop on an UTF-8 character boundary
590          * (assuming the input is valid UTF-8) */
591         if( i_data > i_max )
592         {
593             i_payload = i_max;
594
595             while( ( p_data[i_payload] & 0xC0 ) == 0x80 )
596             {
597                 if( i_payload == 0 )
598                     return VLC_SUCCESS; /* fishy input! */
599
600                 i_payload--;
601             }
602         }
603
604         block_t *out = block_Alloc( 12 + i_payload );
605         if( out == NULL )
606             return VLC_SUCCESS;
607
608         rtp_packetize_common( id, out, 0, in->i_pts + i_packet );
609         memcpy( out->p_buffer + 12, p_data, i_payload );
610
611         out->i_buffer = 12 + i_payload;
612         out->i_dts    = out->i_pts;
613         out->i_length = 0;
614
615         rtp_packetize_send( id, out );
616
617         p_data += i_payload;
618         i_data -= i_payload;
619     }
620
621     return VLC_SUCCESS;
622 }
623
624
625 int rtp_packetize_spx( sout_stream_id_t *id, block_t *in )
626 {
627     uint8_t *p_buffer = in->p_buffer;
628     int i_data_size, i_payload_size, i_payload_padding;
629     i_data_size = i_payload_size = in->i_buffer;
630     i_payload_padding = 0;
631     block_t *p_out;
632
633     if ( in->i_buffer > rtp_mtu (id) )
634         return VLC_SUCCESS;
635
636     /*
637       RFC for Speex in RTP says that each packet must end on an octet 
638       boundary. So, we check to see if the number of bytes % 4 is zero.
639       If not, we have to add some padding. 
640
641       This MAY be overkill since packetization is handled elsewhere and 
642       appears to ensure the octet boundary. However, better safe than
643       sorry.
644     */
645     if ( i_payload_size % 4 )
646     {
647         i_payload_padding = 4 - ( i_payload_size % 4 );
648         i_payload_size += i_payload_padding;
649     }
650
651     /*
652       Allocate a new RTP p_output block of the appropriate size. 
653       Allow for 12 extra bytes of RTP header. 
654     */
655     p_out = block_Alloc( 12 + i_payload_size );
656
657     if ( i_payload_padding )
658     {
659     /*
660       The padding is required to be a zero followed by all 1s.
661     */
662         char c_first_pad, c_remaining_pad;
663         c_first_pad = 0x7F;
664         c_remaining_pad = 0xFF;
665
666         /*
667           Allow for 12 bytes before the i_data_size because
668           of the expected RTP header added during
669           rtp_packetize_common.
670         */
671         p_out->p_buffer[12 + i_data_size] = c_first_pad; 
672         switch (i_payload_padding)
673         {
674           case 2:
675             p_out->p_buffer[12 + i_data_size + 1] = c_remaining_pad; 
676             break;
677           case 3:
678             p_out->p_buffer[12 + i_data_size + 1] = c_remaining_pad; 
679             p_out->p_buffer[12 + i_data_size + 2] = c_remaining_pad; 
680             break;
681         }
682     }
683
684     /* Add the RTP header to our p_output buffer. */
685     rtp_packetize_common( id, p_out, 0, (in->i_pts > 0 ? in->i_pts : in->i_dts) );
686     /* Copy the Speex payload to the p_output buffer */
687     memcpy( &p_out->p_buffer[12], p_buffer, i_data_size );
688
689     p_out->i_buffer = 12 + i_payload_size;
690     p_out->i_dts = in->i_dts;
691     p_out->i_length = in->i_length;
692
693     /* Queue the buffer for actual transmission. */
694     rtp_packetize_send( id, p_out );
695     return VLC_SUCCESS;
696 }
697
698 static int rtp_packetize_g726( sout_stream_id_t *id, block_t *in, int i_pad )
699 {
700     int     i_max   = (rtp_mtu( id )- 12 + i_pad - 1) & ~i_pad;
701     int     i_count = ( in->i_buffer + i_max - 1 ) / i_max;
702
703     uint8_t *p_data = in->p_buffer;
704     int     i_data  = in->i_buffer;
705     int     i_packet = 0;
706
707     while( i_data > 0 )
708     {
709         int           i_payload = __MIN( i_max, i_data );
710         block_t *out = block_New( p_stream, 12 + i_payload );
711
712         /* rtp common header */
713         rtp_packetize_common( id, out, 0,
714                               (in->i_pts > 0 ? in->i_pts : in->i_dts) );
715
716         memcpy( &out->p_buffer[12], p_data, i_payload );
717
718         out->i_buffer   = 12 + i_payload;
719         out->i_dts    = in->i_dts + i_packet++ * in->i_length / i_count;
720         out->i_length = in->i_length / i_count;
721
722         rtp_packetize_send( id, out );
723
724         p_data += i_payload;
725         i_data -= i_payload;
726     }
727     return VLC_SUCCESS;
728 }
729
730 int rtp_packetize_g726_16( sout_stream_id_t *id, block_t *in )
731 {
732     return rtp_packetize_g726( id, in, 4 );
733 }
734
735 int rtp_packetize_g726_24( sout_stream_id_t *id, block_t *in )
736 {
737     return rtp_packetize_g726( id, in, 8 );
738 }
739
740 int rtp_packetize_g726_32( sout_stream_id_t *id, block_t *in )
741 {
742     return rtp_packetize_g726( id, in, 2 );
743 }
744
745 int rtp_packetize_g726_40( sout_stream_id_t *id, block_t *in )
746 {
747     return rtp_packetize_g726( id, in, 8 );
748 }