~ubuntu-branches/ubuntu/maverick/vlc/maverick

« back to all changes in this revision

Viewing changes to modules/stream_out/rtpfmt.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2008-09-17 21:56:14 UTC
  • mfrom: (1.1.17 upstream)
  • Revision ID: james.westby@ubuntu.com-20080917215614-tj0vx8xzd57e52t8
Tags: 0.9.2-1ubuntu1
* New Upstream Release, exception granted by
    - dktrkranz, norsetto, Hobbsee (via irc). LP: #270404

Changes done in ubuntu:

* add libxul-dev to build-depends
* make sure that vlc is build against libxul in configure. This doesn't
  change anything in the package, but makes it more robust if building
  in an 'unclean' chroot or when modifying the package.
* debian/control: make Vcs-* fields point to the motumedia branch
* add libx264-dev and libass-dev to build-depends
  LP: #210354, #199870
* actually enable libass support by passing --enable-libass to configure
* enable libdca: add libdca-dev to build depends and --enable-libdca
* install the x264 plugin.

Changes already in the pkg-multimedia branch in debian:

* don't install usr/share/vlc/mozilla in debian/mozilla-plugin-vlc.install  
* new upstream .desktop file now registers flash video mimetype LP: #261567
* add Xb-Npp-Applications to mozilla-plugin-vlc
* remove duplicate entries in debian/vlc-nox.install

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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: a9d0aee6df0b1b9c78afc8a731fed57b9df2cc96 $
 
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
}