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