s/sout_stream_id_t/sout_stream_id_sys_t/
[vlc.git] / modules / stream_out / rtpfmt.c
blob6e828f849d1836fe3cea1f69035197b5ec291e20
1 /*****************************************************************************
2 * rtpfmt.c: RTP payload formats
3 *****************************************************************************
4 * Copyright (C) 2003-2004 VLC authors and VideoLAN
5 * Copyright © 2007 Rémi Denis-Courmont
6 * $Id$
8 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2.1 of the License, or
13 * (at your option) any later version.
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 Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
29 #include <vlc_common.h>
30 #include <vlc_sout.h>
31 #include <vlc_block.h>
32 #include <vlc_strings.h>
34 #include "rtp.h"
35 #include "../demux/xiph.h"
37 #include <assert.h>
39 static int rtp_packetize_mpa (sout_stream_id_sys_t *, block_t *);
40 static int rtp_packetize_mpv (sout_stream_id_sys_t *, block_t *);
41 static int rtp_packetize_ac3 (sout_stream_id_sys_t *, block_t *);
42 static int rtp_packetize_split(sout_stream_id_sys_t *, block_t *);
43 static int rtp_packetize_swab (sout_stream_id_sys_t *, block_t *);
44 static int rtp_packetize_mp4a (sout_stream_id_sys_t *, block_t *);
45 static int rtp_packetize_mp4a_latm (sout_stream_id_sys_t *, block_t *);
46 static int rtp_packetize_h263 (sout_stream_id_sys_t *, block_t *);
47 static int rtp_packetize_h264 (sout_stream_id_sys_t *, block_t *);
48 static int rtp_packetize_amr (sout_stream_id_sys_t *, block_t *);
49 static int rtp_packetize_spx (sout_stream_id_sys_t *, block_t *);
50 static int rtp_packetize_t140 (sout_stream_id_sys_t *, block_t *);
51 static int rtp_packetize_g726_16 (sout_stream_id_sys_t *, block_t *);
52 static int rtp_packetize_g726_24 (sout_stream_id_sys_t *, block_t *);
53 static int rtp_packetize_g726_32 (sout_stream_id_sys_t *, block_t *);
54 static int rtp_packetize_g726_40 (sout_stream_id_sys_t *, block_t *);
55 static int rtp_packetize_xiph (sout_stream_id_sys_t *, block_t *);
56 static int rtp_packetize_vp8 (sout_stream_id_sys_t *, block_t *);
57 static int rtp_packetize_jpeg (sout_stream_id_sys_t *, block_t *);
59 #define XIPH_IDENT (0)
61 /* Helpers common to xiph codecs (vorbis and theora) */
63 static int rtp_xiph_pack_headers(size_t room, void *p_extra, size_t i_extra,
64 uint8_t **p_buffer, size_t *i_buffer,
65 uint8_t *theora_pixel_fmt)
67 unsigned packet_size[XIPH_MAX_HEADER_COUNT];
68 void *packet[XIPH_MAX_HEADER_COUNT];
69 unsigned packet_count;
70 if (xiph_SplitHeaders(packet_size, packet, &packet_count,
71 i_extra, p_extra))
72 return VLC_EGENERIC;;
73 if (packet_count < 3)
74 return VLC_EGENERIC;;
76 if (theora_pixel_fmt != NULL)
78 if (packet_size[0] < 42)
79 return VLC_EGENERIC;
80 *theora_pixel_fmt = (((uint8_t *)packet[0])[41] >> 3) & 0x03;
83 unsigned length_size[2] = { 0, 0 };
84 for (int i = 0; i < 2; i++)
86 unsigned size = packet_size[i];
87 while (size > 0)
89 length_size[i]++;
90 size >>= 7;
94 *i_buffer = room + 1 + length_size[0] + length_size[1]
95 + packet_size[0] + packet_size[1] + packet_size[2];
96 *p_buffer = malloc(*i_buffer);
97 if (*p_buffer == NULL)
98 return VLC_ENOMEM;
100 uint8_t *p = *p_buffer + room;
101 /* Number of headers */
102 *p++ = 2;
104 for (int i = 0; i < 2; i++)
106 unsigned size = length_size[i];
107 while (size > 0)
109 *p = (packet_size[i] >> (7 * (size - 1))) & 0x7f;
110 if (--size > 0)
111 *p |= 0x80;
112 p++;
115 for (int i = 0; i < 3; i++)
117 memcpy(p, packet[i], packet_size[i]);
118 p += packet_size[i];
121 return VLC_SUCCESS;
124 static char *rtp_xiph_b64_oob_config(void *p_extra, size_t i_extra,
125 uint8_t *theora_pixel_fmt)
127 uint8_t *p_buffer;
128 size_t i_buffer;
129 if (rtp_xiph_pack_headers(9, p_extra, i_extra, &p_buffer, &i_buffer,
130 theora_pixel_fmt) != VLC_SUCCESS)
131 return NULL;
133 /* Number of packed headers */
134 SetDWBE(p_buffer, 1);
135 /* Ident */
136 uint32_t ident = XIPH_IDENT;
137 SetWBE(p_buffer + 4, ident >> 8);
138 p_buffer[6] = ident & 0xff;
139 /* Length field */
140 SetWBE(p_buffer + 7, i_buffer);
142 char *config = vlc_b64_encode_binary(p_buffer, i_buffer);
143 free(p_buffer);
144 return config;
147 static void sprintf_hexa( char *s, uint8_t *p_data, int i_data )
149 static const char hex[16] = "0123456789abcdef";
151 for( int i = 0; i < i_data; i++ )
153 s[2*i+0] = hex[(p_data[i]>>4)&0xf];
154 s[2*i+1] = hex[(p_data[i] )&0xf];
156 s[2*i_data] = '\0';
159 /* TODO: make this into something more clever than a big switch? */
160 int rtp_get_fmt( vlc_object_t *obj, es_format_t *p_fmt, const char *mux,
161 rtp_format_t *rtp_fmt )
163 assert( p_fmt != NULL || mux != NULL );
165 /* Dynamic payload type. Payload types are scoped to the RTP
166 * session, and we put each ES in its own session, so no risk of
167 * conflict. */
168 rtp_fmt->payload_type = 96;
169 rtp_fmt->cat = mux != NULL ? VIDEO_ES : p_fmt->i_cat;
170 if( rtp_fmt->cat == AUDIO_ES )
172 rtp_fmt->clock_rate = p_fmt->audio.i_rate;
173 rtp_fmt->channels = p_fmt->audio.i_channels;
175 else
176 rtp_fmt->clock_rate = 90000; /* most common case for video */
177 /* Stream bitrate in kbps */
178 rtp_fmt->bitrate = p_fmt != NULL ? p_fmt->i_bitrate/1000 : 0;
179 rtp_fmt->fmtp = NULL;
181 if( mux != NULL )
183 if( strncmp( mux, "ts", 2 ) == 0 )
185 rtp_fmt->payload_type = 33;
186 rtp_fmt->ptname = "MP2T";
188 else
189 rtp_fmt->ptname = "MP2P";
190 return VLC_SUCCESS;
193 switch( p_fmt->i_codec )
195 case VLC_CODEC_MULAW:
196 if( p_fmt->audio.i_channels == 1 && p_fmt->audio.i_rate == 8000 )
197 rtp_fmt->payload_type = 0;
198 rtp_fmt->ptname = "PCMU";
199 rtp_fmt->pf_packetize = rtp_packetize_split;
200 break;
201 case VLC_CODEC_ALAW:
202 if( p_fmt->audio.i_channels == 1 && p_fmt->audio.i_rate == 8000 )
203 rtp_fmt->payload_type = 8;
204 rtp_fmt->ptname = "PCMA";
205 rtp_fmt->pf_packetize = rtp_packetize_split;
206 break;
207 case VLC_CODEC_S16B:
208 case VLC_CODEC_S16L:
209 if( p_fmt->audio.i_channels == 1 && p_fmt->audio.i_rate == 44100 )
211 rtp_fmt->payload_type = 11;
213 else if( p_fmt->audio.i_channels == 2 &&
214 p_fmt->audio.i_rate == 44100 )
216 rtp_fmt->payload_type = 10;
218 rtp_fmt->ptname = "L16";
219 if( p_fmt->i_codec == VLC_CODEC_S16B )
220 rtp_fmt->pf_packetize = rtp_packetize_split;
221 else
222 rtp_fmt->pf_packetize = rtp_packetize_swab;
223 break;
224 case VLC_CODEC_U8:
225 rtp_fmt->ptname = "L8";
226 rtp_fmt->pf_packetize = rtp_packetize_split;
227 break;
228 case VLC_CODEC_S24B:
229 rtp_fmt->ptname = "L24";
230 rtp_fmt->pf_packetize = rtp_packetize_split;
231 break;
232 case VLC_CODEC_MPGA:
233 rtp_fmt->payload_type = 14;
234 rtp_fmt->ptname = "MPA";
235 rtp_fmt->clock_rate = 90000; /* not 44100 */
236 rtp_fmt->pf_packetize = rtp_packetize_mpa;
237 break;
238 case VLC_CODEC_MPGV:
239 rtp_fmt->payload_type = 32;
240 rtp_fmt->ptname = "MPV";
241 rtp_fmt->pf_packetize = rtp_packetize_mpv;
242 break;
243 case VLC_CODEC_ADPCM_G726:
244 switch( p_fmt->i_bitrate / 1000 )
246 case 16:
247 rtp_fmt->ptname = "G726-16";
248 rtp_fmt->pf_packetize = rtp_packetize_g726_16;
249 break;
250 case 24:
251 rtp_fmt->ptname = "G726-24";
252 rtp_fmt->pf_packetize = rtp_packetize_g726_24;
253 break;
254 case 32:
255 rtp_fmt->ptname = "G726-32";
256 rtp_fmt->pf_packetize = rtp_packetize_g726_32;
257 break;
258 case 40:
259 rtp_fmt->ptname = "G726-40";
260 rtp_fmt->pf_packetize = rtp_packetize_g726_40;
261 break;
262 default:
263 msg_Err( obj, "cannot add this stream (unsupported "
264 "G.726 bit rate: %u)", p_fmt->i_bitrate );
265 return VLC_EGENERIC;
267 break;
268 case VLC_CODEC_A52:
269 rtp_fmt->ptname = "ac3";
270 rtp_fmt->pf_packetize = rtp_packetize_ac3;
271 break;
272 case VLC_CODEC_H263:
273 rtp_fmt->ptname = "H263-1998";
274 rtp_fmt->pf_packetize = rtp_packetize_h263;
275 break;
276 case VLC_CODEC_H264:
277 rtp_fmt->ptname = "H264";
278 rtp_fmt->pf_packetize = rtp_packetize_h264;
279 rtp_fmt->fmtp = NULL;
281 if( p_fmt->i_extra > 0 )
283 uint8_t *p_buffer = p_fmt->p_extra;
284 int i_buffer = p_fmt->i_extra;
285 char *p_64_sps = NULL;
286 char *p_64_pps = NULL;
287 char hexa[6+1];
289 while( i_buffer > 4 )
291 int i_offset = 0;
292 int i_size = 0;
294 while( p_buffer[0] != 0 || p_buffer[1] != 0 ||
295 p_buffer[2] != 1 )
297 p_buffer++;
298 i_buffer--;
299 if( i_buffer == 0 ) break;
302 if( i_buffer < 4 || memcmp(p_buffer, "\x00\x00\x01", 3 ) )
304 msg_Dbg( obj, "No startcode found..");
305 break;
307 p_buffer += 3;
308 i_buffer -= 3;
310 const int i_nal_type = p_buffer[0]&0x1f;
312 msg_Dbg( obj, "we found a startcode for NAL with TYPE:%d", i_nal_type );
314 i_size = i_buffer;
315 for( i_offset = 0; i_offset+2 < i_buffer ; i_offset++)
317 if( !memcmp(p_buffer + i_offset, "\x00\x00\x01", 3 ) )
319 /* we found another startcode */
320 while( i_offset > 0 && 0 == p_buffer[ i_offset - 1 ] )
321 i_offset--;
322 i_size = i_offset;
323 break;
327 if( i_size == 0 )
329 msg_Dbg( obj, "No-info found in nal ");
330 continue;
333 if( i_nal_type == 7 )
335 free( p_64_sps );
336 p_64_sps = vlc_b64_encode_binary( p_buffer, i_size );
337 /* XXX: nothing ensures that i_size >= 4 ?? */
338 sprintf_hexa( hexa, &p_buffer[1], 3 );
340 else if( i_nal_type == 8 )
342 free( p_64_pps );
343 p_64_pps = vlc_b64_encode_binary( p_buffer, i_size );
345 i_buffer -= i_size;
346 p_buffer += i_size;
348 /* */
349 if( p_64_sps && p_64_pps &&
350 ( asprintf( &rtp_fmt->fmtp,
351 "packetization-mode=1;profile-level-id=%s;"
352 "sprop-parameter-sets=%s,%s;", hexa, p_64_sps,
353 p_64_pps ) == -1 ) )
354 rtp_fmt->fmtp = NULL;
355 free( p_64_sps );
356 free( p_64_pps );
358 if( rtp_fmt->fmtp == NULL )
359 rtp_fmt->fmtp = strdup( "packetization-mode=1" );
360 break;
362 case VLC_CODEC_MP4V:
364 rtp_fmt->ptname = "MP4V-ES";
365 rtp_fmt->pf_packetize = rtp_packetize_split;
366 if( p_fmt->i_extra > 0 )
368 char hexa[2*p_fmt->i_extra +1];
369 sprintf_hexa( hexa, p_fmt->p_extra, p_fmt->i_extra );
370 if( asprintf( &rtp_fmt->fmtp,
371 "profile-level-id=3; config=%s;", hexa ) == -1 )
372 rtp_fmt->fmtp = NULL;
374 break;
376 case VLC_CODEC_MP4A:
378 if( ! var_InheritBool( obj, "sout-rtp-mp4a-latm" ) )
380 char hexa[2*p_fmt->i_extra +1];
382 rtp_fmt->ptname = "mpeg4-generic";
383 rtp_fmt->pf_packetize = rtp_packetize_mp4a;
384 sprintf_hexa( hexa, p_fmt->p_extra, p_fmt->i_extra );
385 if( asprintf( &rtp_fmt->fmtp,
386 "streamtype=5; profile-level-id=15; "
387 "mode=AAC-hbr; config=%s; SizeLength=13; "
388 "IndexLength=3; IndexDeltaLength=3; Profile=1;",
389 hexa ) == -1 )
390 rtp_fmt->fmtp = NULL;
392 else
394 char hexa[13];
395 int i;
396 unsigned char config[6];
397 unsigned int aacsrates[15] = {
398 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
399 16000, 12000, 11025, 8000, 7350, 0, 0 };
401 for( i = 0; i < 15; i++ )
402 if( p_fmt->audio.i_rate == aacsrates[i] )
403 break;
405 config[0]=0x40;
406 config[1]=0;
407 config[2]=0x20|i;
408 config[3]=p_fmt->audio.i_channels<<4;
409 config[4]=0x3f;
410 config[5]=0xc0;
412 rtp_fmt->ptname = "MP4A-LATM";
413 rtp_fmt->pf_packetize = rtp_packetize_mp4a_latm;
414 sprintf_hexa( hexa, config, 6 );
415 if( asprintf( &rtp_fmt->fmtp, "profile-level-id=15; "
416 "object=2; cpresent=0; config=%s", hexa ) == -1 )
417 rtp_fmt->fmtp = NULL;
419 break;
421 case VLC_CODEC_AMR_NB:
422 rtp_fmt->ptname = "AMR";
423 rtp_fmt->fmtp = strdup( "octet-align=1" );
424 rtp_fmt->pf_packetize = rtp_packetize_amr;
425 break;
426 case VLC_CODEC_AMR_WB:
427 rtp_fmt->ptname = "AMR-WB";
428 rtp_fmt->fmtp = strdup( "octet-align=1" );
429 rtp_fmt->pf_packetize = rtp_packetize_amr;
430 break;
431 case VLC_CODEC_SPEEX:
432 rtp_fmt->ptname = "SPEEX";
433 rtp_fmt->pf_packetize = rtp_packetize_spx;
434 break;
435 case VLC_CODEC_VORBIS:
436 rtp_fmt->ptname = "vorbis";
437 rtp_fmt->pf_packetize = rtp_packetize_xiph;
438 if( p_fmt->i_extra > 0 )
440 rtp_fmt->fmtp = NULL;
441 char *config = rtp_xiph_b64_oob_config(p_fmt->p_extra,
442 p_fmt->i_extra, NULL);
443 if (config == NULL)
444 break;
445 if( asprintf( &rtp_fmt->fmtp,
446 "configuration=%s;", config ) == -1 )
447 rtp_fmt->fmtp = NULL;
448 free(config);
450 break;
451 case VLC_CODEC_THEORA:
452 rtp_fmt->ptname = "theora";
453 rtp_fmt->pf_packetize = rtp_packetize_xiph;
454 if( p_fmt->i_extra > 0 )
456 rtp_fmt->fmtp = NULL;
457 uint8_t pixel_fmt, c1, c2;
458 char *config = rtp_xiph_b64_oob_config(p_fmt->p_extra,
459 p_fmt->i_extra,
460 &pixel_fmt);
461 if (config == NULL)
462 break;
464 if (pixel_fmt == 1)
466 /* reserved */
467 free(config);
468 break;
470 switch (pixel_fmt)
472 case 0:
473 c1 = 2;
474 c2 = 0;
475 break;
476 case 2:
477 c1 = c2 = 2;
478 break;
479 case 3:
480 c1 = c2 = 4;
481 break;
482 default:
483 assert(0);
486 if( asprintf( &rtp_fmt->fmtp,
487 "sampling=YCbCr-4:%d:%d; width=%d; height=%d; "
488 "delivery-method=inline; configuration=%s; "
489 "delivery-method=in_band;", c1, c2,
490 p_fmt->video.i_width, p_fmt->video.i_height,
491 config ) == -1 )
492 rtp_fmt->fmtp = NULL;
493 free(config);
495 break;
496 case VLC_CODEC_ITU_T140:
497 rtp_fmt->ptname = "t140" ;
498 rtp_fmt->clock_rate = 1000;
499 rtp_fmt->pf_packetize = rtp_packetize_t140;
500 break;
501 case VLC_CODEC_GSM:
502 rtp_fmt->payload_type = 3;
503 rtp_fmt->ptname = "GSM";
504 rtp_fmt->pf_packetize = rtp_packetize_split;
505 break;
506 case VLC_CODEC_OPUS:
507 if (p_fmt->audio.i_channels > 2)
509 msg_Err( obj, "Multistream opus not supported in RTP"
510 " (having %d channels input)",
511 p_fmt->audio.i_channels );
512 return VLC_EGENERIC;
514 rtp_fmt->ptname = "opus";
515 rtp_fmt->pf_packetize = rtp_packetize_split;
516 rtp_fmt->clock_rate = 48000;
517 rtp_fmt->channels = 2;
518 if (p_fmt->audio.i_channels == 2)
519 rtp_fmt->fmtp = strdup( "sprop-stereo=1" );
520 break;
521 case VLC_CODEC_VP8:
522 rtp_fmt->ptname = "VP8";
523 rtp_fmt->pf_packetize = rtp_packetize_vp8;
524 break;
525 case VLC_CODEC_MJPG:
526 case VLC_CODEC_JPEG:
527 rtp_fmt->ptname = "JPEG";
528 rtp_fmt->payload_type = 26;
529 rtp_fmt->pf_packetize = rtp_packetize_jpeg;
530 break;
532 default:
533 msg_Err( obj, "cannot add this stream (unsupported "
534 "codec: %4.4s)", (char*)&p_fmt->i_codec );
535 return VLC_EGENERIC;
538 return VLC_SUCCESS;
542 static int
543 rtp_packetize_h264_nal( sout_stream_id_sys_t *id,
544 const uint8_t *p_data, int i_data, int64_t i_pts,
545 int64_t i_dts, bool b_last, int64_t i_length );
547 int rtp_packetize_xiph_config( sout_stream_id_sys_t *id, const char *fmtp,
548 int64_t i_pts )
550 if (fmtp == NULL)
551 return VLC_EGENERIC;
553 /* extract base64 configuration from fmtp */
554 char *start = strstr(fmtp, "configuration=");
555 assert(start != NULL);
556 start += sizeof("configuration=") - 1;
557 char *end = strchr(start, ';');
558 assert(end != NULL);
559 size_t len = end - start;
560 char b64[len + 1];
561 memcpy(b64, start, len);
562 b64[len] = '\0';
564 int i_max = rtp_mtu (id) - 6; /* payload max in one packet */
566 uint8_t *p_orig, *p_data;
567 int i_data;
569 i_data = vlc_b64_decode_binary(&p_orig, b64);
570 if (i_data == 0)
571 return VLC_EGENERIC;
572 assert(i_data > 9);
573 p_data = p_orig + 9;
574 i_data -= 9;
576 int i_count = ( i_data + i_max - 1 ) / i_max;
578 for( int i = 0; i < i_count; i++ )
580 int i_payload = __MIN( i_max, i_data );
581 block_t *out = block_Alloc( 18 + i_payload );
583 unsigned fragtype, numpkts;
584 if (i_count == 1)
586 fragtype = 0;
587 numpkts = 1;
589 else
591 numpkts = 0;
592 if (i == 0)
593 fragtype = 1;
594 else if (i == i_count - 1)
595 fragtype = 3;
596 else
597 fragtype = 2;
599 /* Ident:24, Fragment type:2, Vorbis/Theora Data Type:2, # of pkts:4 */
600 uint32_t header = ((XIPH_IDENT & 0xffffff) << 8) |
601 (fragtype << 6) | (1 << 4) | numpkts;
603 /* rtp common header */
604 rtp_packetize_common( id, out, 0, i_pts );
606 SetDWBE( out->p_buffer + 12, header);
607 SetWBE( out->p_buffer + 16, i_payload);
608 memcpy( &out->p_buffer[18], p_data, i_payload );
610 out->i_buffer = 18 + i_payload;
611 out->i_dts = i_pts;
613 rtp_packetize_send( id, out );
615 p_data += i_payload;
616 i_data -= i_payload;
619 free(p_orig);
621 return VLC_SUCCESS;
624 /* rfc5215 */
625 static int rtp_packetize_xiph( sout_stream_id_sys_t *id, block_t *in )
627 int i_max = rtp_mtu (id) - 6; /* payload max in one packet */
628 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
630 uint8_t *p_data = in->p_buffer;
631 int i_data = in->i_buffer;
633 for( int i = 0; i < i_count; i++ )
635 int i_payload = __MIN( i_max, i_data );
636 block_t *out = block_Alloc( 18 + i_payload );
638 unsigned fragtype, numpkts;
639 if (i_count == 1)
641 /* No fragmentation */
642 fragtype = 0;
643 numpkts = 1;
645 else
647 /* Fragmentation */
648 numpkts = 0;
649 if (i == 0)
650 fragtype = 1;
651 else if (i == i_count - 1)
652 fragtype = 3;
653 else
654 fragtype = 2;
656 /* Ident:24, Fragment type:2, Vorbis/Theora Data Type:2, # of pkts:4 */
657 uint32_t header = ((XIPH_IDENT & 0xffffff) << 8) |
658 (fragtype << 6) | (0 << 4) | numpkts;
660 /* rtp common header */
661 rtp_packetize_common( id, out, 0, in->i_pts);
663 SetDWBE( out->p_buffer + 12, header);
664 SetWBE( out->p_buffer + 16, i_payload);
665 memcpy( &out->p_buffer[18], p_data, i_payload );
667 out->i_buffer = 18 + i_payload;
668 out->i_dts = in->i_dts + i * in->i_length / i_count;
669 out->i_length = in->i_length / i_count;
671 rtp_packetize_send( id, out );
673 p_data += i_payload;
674 i_data -= i_payload;
677 return VLC_SUCCESS;
680 static int rtp_packetize_mpa( sout_stream_id_sys_t *id, block_t *in )
682 int i_max = rtp_mtu (id) - 4; /* payload max in one packet */
683 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
685 uint8_t *p_data = in->p_buffer;
686 int i_data = in->i_buffer;
687 int i;
689 for( i = 0; i < i_count; i++ )
691 int i_payload = __MIN( i_max, i_data );
692 block_t *out = block_Alloc( 16 + i_payload );
694 /* rtp common header */
695 rtp_packetize_common( id, out, (i == i_count - 1)?1:0, in->i_pts );
696 /* mbz set to 0 */
697 SetWBE( out->p_buffer + 12, 0 );
698 /* fragment offset in the current frame */
699 SetWBE( out->p_buffer + 14, i * i_max );
700 memcpy( &out->p_buffer[16], p_data, i_payload );
702 out->i_buffer = 16 + i_payload;
703 out->i_dts = in->i_dts + i * in->i_length / i_count;
704 out->i_length = in->i_length / i_count;
706 rtp_packetize_send( id, out );
708 p_data += i_payload;
709 i_data -= i_payload;
712 return VLC_SUCCESS;
715 /* rfc2250 */
716 static int rtp_packetize_mpv( sout_stream_id_sys_t *id, block_t *in )
718 int i_max = rtp_mtu (id) - 4; /* payload max in one packet */
719 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
721 uint8_t *p_data = in->p_buffer;
722 int i_data = in->i_buffer;
723 int i;
724 int b_sequence_start = 0;
725 int i_temporal_ref = 0;
726 int i_picture_coding_type = 0;
727 int i_fbv = 0, i_bfc = 0, i_ffv = 0, i_ffc = 0;
728 int b_start_slice = 0;
730 /* preparse this packet to get some info */
731 if( in->i_buffer > 4 )
733 uint8_t *p = p_data;
734 int i_rest = in->i_buffer;
736 for( ;; )
738 while( i_rest > 4 &&
739 ( p[0] != 0x00 || p[1] != 0x00 || p[2] != 0x01 ) )
741 p++;
742 i_rest--;
744 if( i_rest <= 4 )
746 break;
748 p += 3;
749 i_rest -= 4;
751 if( *p == 0xb3 )
753 /* sequence start code */
754 b_sequence_start = 1;
756 else if( *p == 0x00 && i_rest >= 4 )
758 /* picture */
759 i_temporal_ref = ( p[1] << 2) |((p[2]>>6)&0x03);
760 i_picture_coding_type = (p[2] >> 3)&0x07;
762 if( i_rest >= 4 && ( i_picture_coding_type == 2 ||
763 i_picture_coding_type == 3 ) )
765 i_ffv = (p[3] >> 2)&0x01;
766 i_ffc = ((p[3]&0x03) << 1)|((p[4]>>7)&0x01);
767 if( i_rest > 4 && i_picture_coding_type == 3 )
769 i_fbv = (p[4]>>6)&0x01;
770 i_bfc = (p[4]>>3)&0x07;
774 else if( *p <= 0xaf )
776 b_start_slice = 1;
781 for( i = 0; i < i_count; i++ )
783 int i_payload = __MIN( i_max, i_data );
784 block_t *out = block_Alloc( 16 + i_payload );
785 /* 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 */
786 uint32_t h = ( i_temporal_ref << 16 )|
787 ( b_sequence_start << 13 )|
788 ( b_start_slice << 12 )|
789 ( i == i_count - 1 ? 1 << 11 : 0 )|
790 ( i_picture_coding_type << 8 )|
791 ( i_fbv << 7 )|( i_bfc << 4 )|( i_ffv << 3 )|i_ffc;
793 /* rtp common header */
794 rtp_packetize_common( id, out, (i == i_count - 1)?1:0,
795 in->i_pts > VLC_TS_INVALID ? in->i_pts : in->i_dts );
797 SetDWBE( out->p_buffer + 12, h );
799 memcpy( &out->p_buffer[16], p_data, i_payload );
801 out->i_buffer = 16 + i_payload;
802 out->i_dts = in->i_dts + i * in->i_length / i_count;
803 out->i_length = in->i_length / i_count;
805 rtp_packetize_send( id, out );
807 p_data += i_payload;
808 i_data -= i_payload;
811 return VLC_SUCCESS;
814 static int rtp_packetize_ac3( sout_stream_id_sys_t *id, block_t *in )
816 int i_max = rtp_mtu (id) - 2; /* payload max in one packet */
817 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
819 uint8_t *p_data = in->p_buffer;
820 int i_data = in->i_buffer;
821 int i;
823 for( i = 0; i < i_count; i++ )
825 int i_payload = __MIN( i_max, i_data );
826 block_t *out = block_Alloc( 14 + i_payload );
828 /* rtp common header */
829 rtp_packetize_common( id, out, (i == i_count - 1)?1:0, in->i_pts );
830 /* unit count */
831 out->p_buffer[12] = 1;
832 /* unit header */
833 out->p_buffer[13] = 0x00;
834 /* data */
835 memcpy( &out->p_buffer[14], p_data, i_payload );
837 out->i_buffer = 14 + i_payload;
838 out->i_dts = in->i_dts + i * in->i_length / i_count;
839 out->i_length = in->i_length / i_count;
841 rtp_packetize_send( id, out );
843 p_data += i_payload;
844 i_data -= i_payload;
847 return VLC_SUCCESS;
850 static int rtp_packetize_split( sout_stream_id_sys_t *id, block_t *in )
852 int i_max = rtp_mtu (id); /* payload max in one packet */
853 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
855 uint8_t *p_data = in->p_buffer;
856 int i_data = in->i_buffer;
857 int i;
859 for( i = 0; i < i_count; i++ )
861 int i_payload = __MIN( i_max, i_data );
862 block_t *out = block_Alloc( 12 + i_payload );
864 /* rtp common header */
865 rtp_packetize_common( id, out, (i == i_count - 1),
866 (in->i_pts > VLC_TS_INVALID ? in->i_pts : in->i_dts) );
867 memcpy( &out->p_buffer[12], p_data, i_payload );
869 out->i_buffer = 12 + i_payload;
870 out->i_dts = in->i_dts + i * in->i_length / i_count;
871 out->i_length = in->i_length / i_count;
873 rtp_packetize_send( id, out );
875 p_data += i_payload;
876 i_data -= i_payload;
879 return VLC_SUCCESS;
882 /* split and convert from little endian to network byte order */
883 static int rtp_packetize_swab( sout_stream_id_sys_t *id, block_t *in )
885 int i_max = rtp_mtu (id); /* payload max in one packet */
886 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
888 uint8_t *p_data = in->p_buffer;
889 int i_data = in->i_buffer;
890 int i;
892 for( i = 0; i < i_count; i++ )
894 int i_payload = __MIN( i_max, i_data );
895 block_t *out = block_Alloc( 12 + i_payload );
897 /* rtp common header */
898 rtp_packetize_common( id, out, (i == i_count - 1),
899 (in->i_pts > VLC_TS_INVALID ? in->i_pts : in->i_dts) );
900 swab( p_data, out->p_buffer + 12, i_payload );
902 out->i_buffer = 12 + i_payload;
903 out->i_dts = in->i_dts + i * in->i_length / i_count;
904 out->i_length = in->i_length / i_count;
906 rtp_packetize_send( id, out );
908 p_data += i_payload;
909 i_data -= i_payload;
912 return VLC_SUCCESS;
915 /* rfc3016 */
916 static int rtp_packetize_mp4a_latm( sout_stream_id_sys_t *id, block_t *in )
918 int i_max = rtp_mtu (id) - 2; /* payload max in one packet */
919 int latmhdrsize = in->i_buffer / 0xff + 1;
920 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
922 uint8_t *p_data = in->p_buffer, *p_header = NULL;
923 int i_data = in->i_buffer;
924 int i;
926 for( i = 0; i < i_count; i++ )
928 int i_payload = __MIN( i_max, i_data );
929 block_t *out;
931 if( i != 0 )
932 latmhdrsize = 0;
933 out = block_Alloc( 12 + latmhdrsize + i_payload );
935 /* rtp common header */
936 rtp_packetize_common( id, out, ((i == i_count - 1) ? 1 : 0),
937 (in->i_pts > VLC_TS_INVALID ? in->i_pts : in->i_dts) );
939 if( i == 0 )
941 int tmp = in->i_buffer;
943 p_header=out->p_buffer+12;
944 while( tmp > 0xfe )
946 *p_header = 0xff;
947 p_header++;
948 tmp -= 0xff;
950 *p_header = tmp;
953 memcpy( &out->p_buffer[12+latmhdrsize], p_data, i_payload );
955 out->i_buffer = 12 + latmhdrsize + i_payload;
956 out->i_dts = in->i_dts + i * in->i_length / i_count;
957 out->i_length = in->i_length / i_count;
959 rtp_packetize_send( id, out );
961 p_data += i_payload;
962 i_data -= i_payload;
965 return VLC_SUCCESS;
968 static int rtp_packetize_mp4a( sout_stream_id_sys_t *id, block_t *in )
970 int i_max = rtp_mtu (id) - 4; /* payload max in one packet */
971 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
973 uint8_t *p_data = in->p_buffer;
974 int i_data = in->i_buffer;
975 int i;
977 for( i = 0; i < i_count; i++ )
979 int i_payload = __MIN( i_max, i_data );
980 block_t *out = block_Alloc( 16 + i_payload );
982 /* rtp common header */
983 rtp_packetize_common( id, out, ((i == i_count - 1)?1:0),
984 (in->i_pts > VLC_TS_INVALID ? in->i_pts : in->i_dts) );
985 /* AU headers */
986 /* AU headers length (bits) */
987 out->p_buffer[12] = 0;
988 out->p_buffer[13] = 2*8;
989 /* for each AU length 13 bits + idx 3bits, */
990 SetWBE( out->p_buffer + 14, (in->i_buffer << 3) | 0 );
992 memcpy( &out->p_buffer[16], p_data, i_payload );
994 out->i_buffer = 16 + i_payload;
995 out->i_dts = in->i_dts + i * in->i_length / i_count;
996 out->i_length = in->i_length / i_count;
998 rtp_packetize_send( id, out );
1000 p_data += i_payload;
1001 i_data -= i_payload;
1004 return VLC_SUCCESS;
1008 /* rfc2429 */
1009 #define RTP_H263_HEADER_SIZE (2) // plen = 0
1010 #define RTP_H263_PAYLOAD_START (14) // plen = 0
1011 static int rtp_packetize_h263( sout_stream_id_sys_t *id, block_t *in )
1013 uint8_t *p_data = in->p_buffer;
1014 int i_data = in->i_buffer;
1015 int i;
1016 int i_max = rtp_mtu (id) - RTP_H263_HEADER_SIZE; /* payload max in one packet */
1017 int i_count;
1018 int b_p_bit;
1019 int b_v_bit = 0; // no pesky error resilience
1020 int i_plen = 0; // normally plen=0 for PSC packet
1021 int i_pebit = 0; // because plen=0
1022 uint16_t h;
1024 if( i_data < 2 )
1026 return VLC_EGENERIC;
1028 if( p_data[0] || p_data[1] )
1030 return VLC_EGENERIC;
1032 /* remove 2 leading 0 bytes */
1033 p_data += 2;
1034 i_data -= 2;
1035 i_count = ( i_data + i_max - 1 ) / i_max;
1037 for( i = 0; i < i_count; i++ )
1039 int i_payload = __MIN( i_max, i_data );
1040 block_t *out = block_Alloc( RTP_H263_PAYLOAD_START + i_payload );
1041 b_p_bit = (i == 0) ? 1 : 0;
1042 h = ( b_p_bit << 10 )|
1043 ( b_v_bit << 9 )|
1044 ( i_plen << 3 )|
1045 i_pebit;
1047 /* rtp common header */
1048 //b_m_bit = 1; // always contains end of frame
1049 rtp_packetize_common( id, out, (i == i_count - 1)?1:0,
1050 in->i_pts > VLC_TS_INVALID ? in->i_pts : in->i_dts );
1052 /* h263 header */
1053 SetWBE( out->p_buffer + 12, h );
1054 memcpy( &out->p_buffer[RTP_H263_PAYLOAD_START], p_data, i_payload );
1056 out->i_buffer = RTP_H263_PAYLOAD_START + i_payload;
1057 out->i_dts = in->i_dts + i * in->i_length / i_count;
1058 out->i_length = in->i_length / i_count;
1060 rtp_packetize_send( id, out );
1062 p_data += i_payload;
1063 i_data -= i_payload;
1066 return VLC_SUCCESS;
1069 /* rfc3984 */
1070 static int
1071 rtp_packetize_h264_nal( sout_stream_id_sys_t *id,
1072 const uint8_t *p_data, int i_data, int64_t i_pts,
1073 int64_t i_dts, bool b_last, int64_t i_length )
1075 const int i_max = rtp_mtu (id); /* payload max in one packet */
1076 int i_nal_hdr;
1077 int i_nal_type;
1079 if( i_data < 5 )
1080 return VLC_SUCCESS;
1082 i_nal_hdr = p_data[3];
1083 i_nal_type = i_nal_hdr&0x1f;
1085 /* Skip start code */
1086 p_data += 3;
1087 i_data -= 3;
1089 /* */
1090 if( i_data <= i_max )
1092 /* Single NAL unit packet */
1093 block_t *out = block_Alloc( 12 + i_data );
1094 out->i_dts = i_dts;
1095 out->i_length = i_length;
1097 /* */
1098 rtp_packetize_common( id, out, b_last, i_pts );
1099 out->i_buffer = 12 + i_data;
1101 memcpy( &out->p_buffer[12], p_data, i_data );
1103 rtp_packetize_send( id, out );
1105 else
1107 /* FU-A Fragmentation Unit without interleaving */
1108 const int i_count = ( i_data-1 + i_max-2 - 1 ) / (i_max-2);
1109 int i;
1111 p_data++;
1112 i_data--;
1114 for( i = 0; i < i_count; i++ )
1116 const int i_payload = __MIN( i_data, i_max-2 );
1117 block_t *out = block_Alloc( 12 + 2 + i_payload );
1118 out->i_dts = i_dts + i * i_length / i_count;
1119 out->i_length = i_length / i_count;
1121 /* */
1122 rtp_packetize_common( id, out, (b_last && i_payload == i_data),
1123 i_pts );
1124 out->i_buffer = 14 + i_payload;
1126 /* FU indicator */
1127 out->p_buffer[12] = 0x00 | (i_nal_hdr & 0x60) | 28;
1128 /* FU header */
1129 out->p_buffer[13] = ( i == 0 ? 0x80 : 0x00 ) | ( (i == i_count-1) ? 0x40 : 0x00 ) | i_nal_type;
1130 memcpy( &out->p_buffer[14], p_data, i_payload );
1132 rtp_packetize_send( id, out );
1134 i_data -= i_payload;
1135 p_data += i_payload;
1138 return VLC_SUCCESS;
1141 static int rtp_packetize_h264( sout_stream_id_sys_t *id, block_t *in )
1143 const uint8_t *p_buffer = in->p_buffer;
1144 int i_buffer = in->i_buffer;
1146 while( i_buffer > 4 && ( p_buffer[0] != 0 || p_buffer[1] != 0 || p_buffer[2] != 1 ) )
1148 i_buffer--;
1149 p_buffer++;
1152 /* Split nal units */
1153 while( i_buffer > 4 )
1155 int i_offset;
1156 int i_size = i_buffer;
1157 int i_skip = i_buffer;
1159 /* search nal end */
1160 for( i_offset = 4; i_offset+2 < i_buffer ; i_offset++)
1162 if( p_buffer[i_offset] == 0 && p_buffer[i_offset+1] == 0 && p_buffer[i_offset+2] == 1 )
1164 /* we found another startcode */
1165 i_size = i_offset - ( p_buffer[i_offset-1] == 0 ? 1 : 0);
1166 i_skip = i_offset;
1167 break;
1170 /* TODO add STAP-A to remove a lot of overhead with small slice/sei/... */
1171 rtp_packetize_h264_nal( id, p_buffer, i_size,
1172 (in->i_pts > VLC_TS_INVALID ? in->i_pts : in->i_dts), in->i_dts,
1173 (i_size >= i_buffer), in->i_length * i_size / in->i_buffer );
1175 i_buffer -= i_skip;
1176 p_buffer += i_skip;
1178 return VLC_SUCCESS;
1181 static int rtp_packetize_amr( sout_stream_id_sys_t *id, block_t *in )
1183 int i_max = rtp_mtu (id) - 2; /* payload max in one packet */
1184 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1186 uint8_t *p_data = in->p_buffer;
1187 int i_data = in->i_buffer;
1188 int i;
1190 /* Only supports octet-aligned mode */
1191 for( i = 0; i < i_count; i++ )
1193 int i_payload = __MIN( i_max, i_data );
1194 block_t *out = block_Alloc( 14 + i_payload );
1196 /* rtp common header */
1197 rtp_packetize_common( id, out, ((i == i_count - 1)?1:0),
1198 (in->i_pts > VLC_TS_INVALID ? in->i_pts : in->i_dts) );
1199 /* Payload header */
1200 out->p_buffer[12] = 0xF0; /* CMR */
1201 out->p_buffer[13] = p_data[0]&0x7C; /* ToC */ /* FIXME: frame type */
1203 /* FIXME: are we fed multiple frames ? */
1204 memcpy( &out->p_buffer[14], p_data+1, i_payload-1 );
1206 out->i_buffer = 14 + i_payload-1;
1207 out->i_dts = in->i_dts + i * in->i_length / i_count;
1208 out->i_length = in->i_length / i_count;
1210 rtp_packetize_send( id, out );
1212 p_data += i_payload;
1213 i_data -= i_payload;
1216 return VLC_SUCCESS;
1219 static int rtp_packetize_t140( sout_stream_id_sys_t *id, block_t *in )
1221 const size_t i_max = rtp_mtu (id);
1222 const uint8_t *p_data = in->p_buffer;
1223 size_t i_data = in->i_buffer;
1225 for( unsigned i_packet = 0; i_data > 0; i_packet++ )
1227 size_t i_payload = i_data;
1229 /* Make sure we stop on an UTF-8 character boundary
1230 * (assuming the input is valid UTF-8) */
1231 if( i_data > i_max )
1233 i_payload = i_max;
1235 while( ( p_data[i_payload] & 0xC0 ) == 0x80 )
1237 if( i_payload == 0 )
1238 return VLC_SUCCESS; /* fishy input! */
1240 i_payload--;
1244 block_t *out = block_Alloc( 12 + i_payload );
1245 if( out == NULL )
1246 return VLC_SUCCESS;
1248 rtp_packetize_common( id, out, 0, in->i_pts + i_packet );
1249 memcpy( out->p_buffer + 12, p_data, i_payload );
1251 out->i_buffer = 12 + i_payload;
1252 out->i_dts = in->i_pts;
1253 out->i_length = 0;
1255 rtp_packetize_send( id, out );
1257 p_data += i_payload;
1258 i_data -= i_payload;
1261 return VLC_SUCCESS;
1265 static int rtp_packetize_spx( sout_stream_id_sys_t *id, block_t *in )
1267 uint8_t *p_buffer = in->p_buffer;
1268 int i_data_size, i_payload_size, i_payload_padding;
1269 i_data_size = i_payload_size = in->i_buffer;
1270 i_payload_padding = 0;
1271 block_t *p_out;
1273 if ( in->i_buffer > rtp_mtu (id) )
1274 return VLC_SUCCESS;
1277 RFC for Speex in RTP says that each packet must end on an octet
1278 boundary. So, we check to see if the number of bytes % 4 is zero.
1279 If not, we have to add some padding.
1281 This MAY be overkill since packetization is handled elsewhere and
1282 appears to ensure the octet boundary. However, better safe than
1283 sorry.
1285 if ( i_payload_size % 4 )
1287 i_payload_padding = 4 - ( i_payload_size % 4 );
1288 i_payload_size += i_payload_padding;
1292 Allocate a new RTP p_output block of the appropriate size.
1293 Allow for 12 extra bytes of RTP header.
1295 p_out = block_Alloc( 12 + i_payload_size );
1297 if ( i_payload_padding )
1300 The padding is required to be a zero followed by all 1s.
1302 char c_first_pad, c_remaining_pad;
1303 c_first_pad = 0x7F;
1304 c_remaining_pad = 0xFF;
1307 Allow for 12 bytes before the i_data_size because
1308 of the expected RTP header added during
1309 rtp_packetize_common.
1311 p_out->p_buffer[12 + i_data_size] = c_first_pad;
1312 switch (i_payload_padding)
1314 case 2:
1315 p_out->p_buffer[12 + i_data_size + 1] = c_remaining_pad;
1316 break;
1317 case 3:
1318 p_out->p_buffer[12 + i_data_size + 1] = c_remaining_pad;
1319 p_out->p_buffer[12 + i_data_size + 2] = c_remaining_pad;
1320 break;
1324 /* Add the RTP header to our p_output buffer. */
1325 rtp_packetize_common( id, p_out, 0,
1326 (in->i_pts > VLC_TS_INVALID ? in->i_pts : in->i_dts) );
1327 /* Copy the Speex payload to the p_output buffer */
1328 memcpy( &p_out->p_buffer[12], p_buffer, i_data_size );
1330 p_out->i_buffer = 12 + i_payload_size;
1331 p_out->i_dts = in->i_dts;
1332 p_out->i_length = in->i_length;
1334 /* Queue the buffer for actual transmission. */
1335 rtp_packetize_send( id, p_out );
1336 return VLC_SUCCESS;
1339 static int rtp_packetize_g726( sout_stream_id_sys_t *id, block_t *in, int i_pad )
1341 int i_max = (rtp_mtu( id )- 12 + i_pad - 1) & ~i_pad;
1342 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1344 uint8_t *p_data = in->p_buffer;
1345 int i_data = in->i_buffer;
1346 int i_packet = 0;
1348 while( i_data > 0 )
1350 int i_payload = __MIN( i_max, i_data );
1351 block_t *out = block_Alloc( 12 + i_payload );
1353 /* rtp common header */
1354 rtp_packetize_common( id, out, 0,
1355 (in->i_pts > VLC_TS_INVALID ? in->i_pts : in->i_dts) );
1357 memcpy( &out->p_buffer[12], p_data, i_payload );
1359 out->i_buffer = 12 + i_payload;
1360 out->i_dts = in->i_dts + i_packet++ * in->i_length / i_count;
1361 out->i_length = in->i_length / i_count;
1363 rtp_packetize_send( id, out );
1365 p_data += i_payload;
1366 i_data -= i_payload;
1368 return VLC_SUCCESS;
1371 static int rtp_packetize_g726_16( sout_stream_id_sys_t *id, block_t *in )
1373 return rtp_packetize_g726( id, in, 4 );
1376 static int rtp_packetize_g726_24( sout_stream_id_sys_t *id, block_t *in )
1378 return rtp_packetize_g726( id, in, 8 );
1381 static int rtp_packetize_g726_32( sout_stream_id_sys_t *id, block_t *in )
1383 return rtp_packetize_g726( id, in, 2 );
1386 static int rtp_packetize_g726_40( sout_stream_id_sys_t *id, block_t *in )
1388 return rtp_packetize_g726( id, in, 8 );
1391 #define RTP_VP8_HEADER_SIZE 1
1392 #define RTP_VP8_PAYLOAD_START (12 + RTP_VP8_HEADER_SIZE)
1394 static int rtp_packetize_vp8( sout_stream_id_sys_t *id, block_t *in )
1396 int i_max = rtp_mtu (id) - RTP_VP8_HEADER_SIZE;
1397 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1399 uint8_t *p_data = in->p_buffer;
1400 int i_data = in->i_buffer;
1402 if ( i_max <= 0 )
1403 return VLC_EGENERIC;
1405 for( int i = 0; i < i_count; i++ )
1407 int i_payload = __MIN( i_max, i_data );
1408 block_t *out = block_Alloc( RTP_VP8_PAYLOAD_START + i_payload );
1409 if ( out == NULL )
1410 return VLC_ENOMEM;
1412 /* VP8 payload header */
1413 /* All frames are marked as reference ones */
1414 if (i == 0)
1415 out->p_buffer[12] = 0x10; // partition start
1416 else
1417 out->p_buffer[12] = 0;
1419 /* rtp common header */
1420 rtp_packetize_common( id, out, (i == i_count - 1),
1421 (in->i_pts > VLC_TS_INVALID ? in->i_pts : in->i_dts) );
1422 memcpy( &out->p_buffer[RTP_VP8_PAYLOAD_START], p_data, i_payload );
1424 out->i_buffer = RTP_VP8_PAYLOAD_START + i_payload;
1425 out->i_dts = in->i_dts + i * in->i_length / i_count;
1426 out->i_length = in->i_length / i_count;
1428 rtp_packetize_send( id, out );
1430 p_data += i_payload;
1431 i_data -= i_payload;
1434 return VLC_SUCCESS;
1437 static int rtp_packetize_jpeg( sout_stream_id_sys_t *id, block_t *in )
1439 uint8_t *p_data = in->p_buffer;
1440 int i_data = in->i_buffer;
1441 uint8_t *bufend = p_data + i_data;
1443 const uint8_t *qtables = NULL;
1444 int nb_qtables = 0;
1445 int off = 0; // fragment offset in frame
1446 int y_sampling_factor;
1447 // type is set by pixel format (determined by y_sampling_factor):
1448 // 0 for yuvj422p
1449 // 1 for yuvj420p
1450 // += 64 if DRI present
1451 int type;
1452 int w = 0; // Width in multiples of 8
1453 int h = 0; // Height in multiples of 8
1454 int restart_interval;
1455 int dri_found = 0;
1457 // Skip SOI
1458 if (GetWBE(p_data) != 0xffd8)
1459 return VLC_EGENERIC;
1460 p_data += 2;
1461 i_data -= 2;
1463 /* parse the header to get necessary info */
1464 int header_finished = 0;
1465 while (!header_finished && p_data + 4 <= bufend) {
1466 uint16_t marker = GetWBE(p_data);
1467 uint8_t *section = p_data + 2;
1468 int section_size = GetWBE(section);
1469 uint8_t *section_body = p_data + 4;
1470 if (section + section_size > bufend)
1471 return VLC_EGENERIC;
1473 assert((marker & 0xff00) == 0xff00);
1474 switch (marker)
1476 case 0xffdb /*DQT*/:
1477 if (section_body[0])
1479 // Only 8-bit precision is supported
1480 return VLC_EGENERIC;
1483 /* a quantization table is 64 bytes long */
1484 nb_qtables = section_size / 65;
1485 qtables = section_body;
1486 break;
1487 case 0xffc0 /*SOF0*/:
1489 int height = GetWBE(&section_body[1]);
1490 int width = GetWBE(&section_body[3]);
1491 if (width > 2040 || height > 2040)
1493 // larger than limit supported by RFC 2435
1494 return VLC_EGENERIC;
1496 // Round up by 8, divide by 8
1497 w = ((width+7)&~7) >> 3;
1498 h = ((height+7)&~7) >> 3;
1500 // Get components sampling to determine type
1501 // Y has component ID 1
1502 // Possible configurations of sampling factors:
1503 // Y - 0x22, Cb - 0x11, Cr - 0x11 => yuvj420p
1504 // Y - 0x21, Cb - 0x11, Cr - 0x11 => yuvj422p
1506 // Only 3 components are supported by RFC 2435
1507 if (section_body[5] != 3) // Number of components
1508 return VLC_EGENERIC;
1509 for (int j = 0; j < 3; j++)
1511 if (section_body[6 + j * 3] == 1 /* Y */)
1513 y_sampling_factor = section_body[6 + j * 3 + 1];
1515 else if (section_body[6 + j * 3 + 1] != 0x11)
1517 // Sampling factor is unsupported by RFC 2435
1518 return VLC_EGENERIC;
1521 break;
1523 case 0xffdd /*DRI*/:
1524 restart_interval = GetWBE(section_body);
1525 dri_found = 1;
1526 break;
1527 case 0xffda /*SOS*/:
1528 /* SOS is last marker in the header */
1529 header_finished = 1;
1530 break;
1532 // Step over marker, 16bit length and section body
1533 p_data += 2 + section_size;
1534 i_data -= 2 + section_size;
1536 if (!header_finished)
1537 return VLC_EGENERIC;
1538 if (!w || !h)
1539 return VLC_EGENERIC;
1541 switch (y_sampling_factor)
1543 case 0x22: // yuvj420p
1544 type = 1;
1545 break;
1546 case 0x21: // yuvj422p
1547 type = 0;
1548 break;
1549 default:
1550 // Sampling format unsupported by RFC 2435
1551 return VLC_EGENERIC;
1554 if (dri_found)
1555 type += 64;
1557 while ( i_data )
1559 int hdr_size = 8 + dri_found * 4;
1560 if (off == 0 && nb_qtables)
1561 hdr_size += 4 + 64 * nb_qtables;
1563 int i_payload = __MIN( i_data, (int)(rtp_mtu (id) - hdr_size) );
1564 if ( i_payload <= 0 )
1565 return VLC_EGENERIC;
1567 block_t *out = block_Alloc( 12 + hdr_size + i_payload );
1568 if( out == NULL )
1569 return VLC_ENOMEM;
1571 uint8_t *p = out->p_buffer + 12;
1572 /* set main header */
1573 /* set type-specific=0, set offset in following 24 bits: */
1574 SetDWBE(p, off & 0x00ffffff);
1575 p += 4;
1576 *p++ = type;
1577 *p++ = 255; // Quant value
1578 *p++ = w;
1579 *p++ = h;
1581 // Write restart_marker_hdr if needed
1582 if (dri_found)
1584 SetWBE(p, restart_interval);
1585 p += 2;
1586 // restart_count. Hardcoded same value as in gstreamer implementation
1587 SetWBE(p, 0xffff);
1588 p += 2;
1591 if (off == 0 && nb_qtables)
1593 /* set quantization tables header */
1594 *p++ = 0;
1595 *p++ = 0;
1596 SetWBE (p, 64 * nb_qtables);
1597 p += 2;
1598 for (int i = 0; i < nb_qtables; i++)
1600 memcpy (p, &qtables[65 * i + 1], 64);
1601 p += 64;
1605 /* rtp common header */
1606 rtp_packetize_common( id, out, (i_payload == i_data),
1607 (in->i_pts > VLC_TS_INVALID ? in->i_pts : in->i_dts) );
1608 memcpy( p, p_data, i_payload );
1610 out->i_buffer = 12 + hdr_size + i_payload;
1611 out->i_dts = in->i_dts;
1612 out->i_length = in->i_length;
1614 rtp_packetize_send( id, out );
1616 p_data += i_payload;
1617 i_data -= i_payload;
1618 off += i_payload;
1621 return VLC_SUCCESS;