A little more detail regarding using my github copies of the code with where it's...
[vlc/adversarial.git] / modules / stream_out / rtpfmt.c
blobbaee82aa50ff50eb0702436aae52e1951e5d786b
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 <= 9)
572 free(p_orig);
573 return VLC_EGENERIC;
575 p_data = p_orig + 9;
576 i_data -= 9;
578 int i_count = ( i_data + i_max - 1 ) / i_max;
580 for( int i = 0; i < i_count; i++ )
582 int i_payload = __MIN( i_max, i_data );
583 block_t *out = block_Alloc( 18 + i_payload );
585 unsigned fragtype, numpkts;
586 if (i_count == 1)
588 fragtype = 0;
589 numpkts = 1;
591 else
593 numpkts = 0;
594 if (i == 0)
595 fragtype = 1;
596 else if (i == i_count - 1)
597 fragtype = 3;
598 else
599 fragtype = 2;
601 /* Ident:24, Fragment type:2, Vorbis/Theora Data Type:2, # of pkts:4 */
602 uint32_t header = ((XIPH_IDENT & 0xffffff) << 8) |
603 (fragtype << 6) | (1 << 4) | numpkts;
605 /* rtp common header */
606 rtp_packetize_common( id, out, 0, i_pts );
608 SetDWBE( out->p_buffer + 12, header);
609 SetWBE( out->p_buffer + 16, i_payload);
610 memcpy( &out->p_buffer[18], p_data, i_payload );
612 out->i_buffer = 18 + i_payload;
613 out->i_dts = i_pts;
615 rtp_packetize_send( id, out );
617 p_data += i_payload;
618 i_data -= i_payload;
621 free(p_orig);
623 return VLC_SUCCESS;
626 /* rfc5215 */
627 static int rtp_packetize_xiph( sout_stream_id_sys_t *id, block_t *in )
629 int i_max = rtp_mtu (id) - 6; /* payload max in one packet */
630 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
632 uint8_t *p_data = in->p_buffer;
633 int i_data = in->i_buffer;
635 for( int i = 0; i < i_count; i++ )
637 int i_payload = __MIN( i_max, i_data );
638 block_t *out = block_Alloc( 18 + i_payload );
640 unsigned fragtype, numpkts;
641 if (i_count == 1)
643 /* No fragmentation */
644 fragtype = 0;
645 numpkts = 1;
647 else
649 /* Fragmentation */
650 numpkts = 0;
651 if (i == 0)
652 fragtype = 1;
653 else if (i == i_count - 1)
654 fragtype = 3;
655 else
656 fragtype = 2;
658 /* Ident:24, Fragment type:2, Vorbis/Theora Data Type:2, # of pkts:4 */
659 uint32_t header = ((XIPH_IDENT & 0xffffff) << 8) |
660 (fragtype << 6) | (0 << 4) | numpkts;
662 /* rtp common header */
663 rtp_packetize_common( id, out, 0, in->i_pts);
665 SetDWBE( out->p_buffer + 12, header);
666 SetWBE( out->p_buffer + 16, i_payload);
667 memcpy( &out->p_buffer[18], p_data, i_payload );
669 out->i_buffer = 18 + i_payload;
670 out->i_dts = in->i_dts + i * in->i_length / i_count;
671 out->i_length = in->i_length / i_count;
673 rtp_packetize_send( id, out );
675 p_data += i_payload;
676 i_data -= i_payload;
679 return VLC_SUCCESS;
682 static int rtp_packetize_mpa( sout_stream_id_sys_t *id, block_t *in )
684 int i_max = rtp_mtu (id) - 4; /* payload max in one packet */
685 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
687 uint8_t *p_data = in->p_buffer;
688 int i_data = in->i_buffer;
689 int i;
691 for( i = 0; i < i_count; i++ )
693 int i_payload = __MIN( i_max, i_data );
694 block_t *out = block_Alloc( 16 + i_payload );
696 /* rtp common header */
697 rtp_packetize_common( id, out, (i == i_count - 1)?1:0, in->i_pts );
698 /* mbz set to 0 */
699 SetWBE( out->p_buffer + 12, 0 );
700 /* fragment offset in the current frame */
701 SetWBE( out->p_buffer + 14, i * i_max );
702 memcpy( &out->p_buffer[16], p_data, i_payload );
704 out->i_buffer = 16 + i_payload;
705 out->i_dts = in->i_dts + i * in->i_length / i_count;
706 out->i_length = in->i_length / i_count;
708 rtp_packetize_send( id, out );
710 p_data += i_payload;
711 i_data -= i_payload;
714 return VLC_SUCCESS;
717 /* rfc2250 */
718 static int rtp_packetize_mpv( sout_stream_id_sys_t *id, block_t *in )
720 int i_max = rtp_mtu (id) - 4; /* payload max in one packet */
721 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
723 uint8_t *p_data = in->p_buffer;
724 int i_data = in->i_buffer;
725 int i;
726 int b_sequence_start = 0;
727 int i_temporal_ref = 0;
728 int i_picture_coding_type = 0;
729 int i_fbv = 0, i_bfc = 0, i_ffv = 0, i_ffc = 0;
730 int b_start_slice = 0;
732 /* preparse this packet to get some info */
733 if( in->i_buffer > 4 )
735 uint8_t *p = p_data;
736 int i_rest = in->i_buffer;
738 for( ;; )
740 while( i_rest > 4 &&
741 ( p[0] != 0x00 || p[1] != 0x00 || p[2] != 0x01 ) )
743 p++;
744 i_rest--;
746 if( i_rest <= 4 )
748 break;
750 p += 3;
751 i_rest -= 4;
753 if( *p == 0xb3 )
755 /* sequence start code */
756 b_sequence_start = 1;
758 else if( *p == 0x00 && i_rest >= 4 )
760 /* picture */
761 i_temporal_ref = ( p[1] << 2) |((p[2]>>6)&0x03);
762 i_picture_coding_type = (p[2] >> 3)&0x07;
764 if( i_rest >= 4 && ( i_picture_coding_type == 2 ||
765 i_picture_coding_type == 3 ) )
767 i_ffv = (p[3] >> 2)&0x01;
768 i_ffc = ((p[3]&0x03) << 1)|((p[4]>>7)&0x01);
769 if( i_rest > 4 && i_picture_coding_type == 3 )
771 i_fbv = (p[4]>>6)&0x01;
772 i_bfc = (p[4]>>3)&0x07;
776 else if( *p <= 0xaf )
778 b_start_slice = 1;
783 for( i = 0; i < i_count; i++ )
785 int i_payload = __MIN( i_max, i_data );
786 block_t *out = block_Alloc( 16 + i_payload );
787 /* 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 */
788 uint32_t h = ( i_temporal_ref << 16 )|
789 ( b_sequence_start << 13 )|
790 ( b_start_slice << 12 )|
791 ( i == i_count - 1 ? 1 << 11 : 0 )|
792 ( i_picture_coding_type << 8 )|
793 ( i_fbv << 7 )|( i_bfc << 4 )|( i_ffv << 3 )|i_ffc;
795 /* rtp common header */
796 rtp_packetize_common( id, out, (i == i_count - 1)?1:0,
797 in->i_pts > VLC_TS_INVALID ? in->i_pts : in->i_dts );
799 SetDWBE( out->p_buffer + 12, h );
801 memcpy( &out->p_buffer[16], p_data, i_payload );
803 out->i_buffer = 16 + i_payload;
804 out->i_dts = in->i_dts + i * in->i_length / i_count;
805 out->i_length = in->i_length / i_count;
807 rtp_packetize_send( id, out );
809 p_data += i_payload;
810 i_data -= i_payload;
813 return VLC_SUCCESS;
816 static int rtp_packetize_ac3( sout_stream_id_sys_t *id, block_t *in )
818 int i_max = rtp_mtu (id) - 2; /* payload max in one packet */
819 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
821 uint8_t *p_data = in->p_buffer;
822 int i_data = in->i_buffer;
823 int i;
825 for( i = 0; i < i_count; i++ )
827 int i_payload = __MIN( i_max, i_data );
828 block_t *out = block_Alloc( 14 + i_payload );
830 /* rtp common header */
831 rtp_packetize_common( id, out, (i == i_count - 1)?1:0, in->i_pts );
832 /* unit count */
833 out->p_buffer[12] = 1;
834 /* unit header */
835 out->p_buffer[13] = 0x00;
836 /* data */
837 memcpy( &out->p_buffer[14], p_data, i_payload );
839 out->i_buffer = 14 + i_payload;
840 out->i_dts = in->i_dts + i * in->i_length / i_count;
841 out->i_length = in->i_length / i_count;
843 rtp_packetize_send( id, out );
845 p_data += i_payload;
846 i_data -= i_payload;
849 return VLC_SUCCESS;
852 static int rtp_packetize_split( sout_stream_id_sys_t *id, block_t *in )
854 int i_max = rtp_mtu (id); /* payload max in one packet */
855 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
857 uint8_t *p_data = in->p_buffer;
858 int i_data = in->i_buffer;
859 int i;
861 for( i = 0; i < i_count; i++ )
863 int i_payload = __MIN( i_max, i_data );
864 block_t *out = block_Alloc( 12 + i_payload );
866 /* rtp common header */
867 rtp_packetize_common( id, out, (i == i_count - 1),
868 (in->i_pts > VLC_TS_INVALID ? in->i_pts : in->i_dts) );
869 memcpy( &out->p_buffer[12], p_data, i_payload );
871 out->i_buffer = 12 + i_payload;
872 out->i_dts = in->i_dts + i * in->i_length / i_count;
873 out->i_length = in->i_length / i_count;
875 rtp_packetize_send( id, out );
877 p_data += i_payload;
878 i_data -= i_payload;
881 return VLC_SUCCESS;
884 /* split and convert from little endian to network byte order */
885 static int rtp_packetize_swab( sout_stream_id_sys_t *id, block_t *in )
887 int i_max = rtp_mtu (id); /* payload max in one packet */
888 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
890 uint8_t *p_data = in->p_buffer;
891 int i_data = in->i_buffer;
892 int i;
894 for( i = 0; i < i_count; i++ )
896 int i_payload = __MIN( i_max, i_data );
897 block_t *out = block_Alloc( 12 + i_payload );
899 /* rtp common header */
900 rtp_packetize_common( id, out, (i == i_count - 1),
901 (in->i_pts > VLC_TS_INVALID ? in->i_pts : in->i_dts) );
902 swab( p_data, out->p_buffer + 12, i_payload );
904 out->i_buffer = 12 + i_payload;
905 out->i_dts = in->i_dts + i * in->i_length / i_count;
906 out->i_length = in->i_length / i_count;
908 rtp_packetize_send( id, out );
910 p_data += i_payload;
911 i_data -= i_payload;
914 return VLC_SUCCESS;
917 /* rfc3016 */
918 static int rtp_packetize_mp4a_latm( sout_stream_id_sys_t *id, block_t *in )
920 int i_max = rtp_mtu (id) - 2; /* payload max in one packet */
921 int latmhdrsize = in->i_buffer / 0xff + 1;
922 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
924 uint8_t *p_data = in->p_buffer, *p_header = NULL;
925 int i_data = in->i_buffer;
926 int i;
928 for( i = 0; i < i_count; i++ )
930 int i_payload = __MIN( i_max, i_data );
931 block_t *out;
933 if( i != 0 )
934 latmhdrsize = 0;
935 out = block_Alloc( 12 + latmhdrsize + i_payload );
937 /* rtp common header */
938 rtp_packetize_common( id, out, ((i == i_count - 1) ? 1 : 0),
939 (in->i_pts > VLC_TS_INVALID ? in->i_pts : in->i_dts) );
941 if( i == 0 )
943 int tmp = in->i_buffer;
945 p_header=out->p_buffer+12;
946 while( tmp > 0xfe )
948 *p_header = 0xff;
949 p_header++;
950 tmp -= 0xff;
952 *p_header = tmp;
955 memcpy( &out->p_buffer[12+latmhdrsize], p_data, i_payload );
957 out->i_buffer = 12 + latmhdrsize + i_payload;
958 out->i_dts = in->i_dts + i * in->i_length / i_count;
959 out->i_length = in->i_length / i_count;
961 rtp_packetize_send( id, out );
963 p_data += i_payload;
964 i_data -= i_payload;
967 return VLC_SUCCESS;
970 static int rtp_packetize_mp4a( sout_stream_id_sys_t *id, block_t *in )
972 int i_max = rtp_mtu (id) - 4; /* payload max in one packet */
973 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
975 uint8_t *p_data = in->p_buffer;
976 int i_data = in->i_buffer;
977 int i;
979 for( i = 0; i < i_count; i++ )
981 int i_payload = __MIN( i_max, i_data );
982 block_t *out = block_Alloc( 16 + i_payload );
984 /* rtp common header */
985 rtp_packetize_common( id, out, ((i == i_count - 1)?1:0),
986 (in->i_pts > VLC_TS_INVALID ? in->i_pts : in->i_dts) );
987 /* AU headers */
988 /* AU headers length (bits) */
989 out->p_buffer[12] = 0;
990 out->p_buffer[13] = 2*8;
991 /* for each AU length 13 bits + idx 3bits, */
992 SetWBE( out->p_buffer + 14, (in->i_buffer << 3) | 0 );
994 memcpy( &out->p_buffer[16], p_data, i_payload );
996 out->i_buffer = 16 + i_payload;
997 out->i_dts = in->i_dts + i * in->i_length / i_count;
998 out->i_length = in->i_length / i_count;
1000 rtp_packetize_send( id, out );
1002 p_data += i_payload;
1003 i_data -= i_payload;
1006 return VLC_SUCCESS;
1010 /* rfc2429 */
1011 #define RTP_H263_HEADER_SIZE (2) // plen = 0
1012 #define RTP_H263_PAYLOAD_START (14) // plen = 0
1013 static int rtp_packetize_h263( sout_stream_id_sys_t *id, block_t *in )
1015 uint8_t *p_data = in->p_buffer;
1016 int i_data = in->i_buffer;
1017 int i;
1018 int i_max = rtp_mtu (id) - RTP_H263_HEADER_SIZE; /* payload max in one packet */
1019 int i_count;
1020 int b_p_bit;
1021 int b_v_bit = 0; // no pesky error resilience
1022 int i_plen = 0; // normally plen=0 for PSC packet
1023 int i_pebit = 0; // because plen=0
1024 uint16_t h;
1026 if( i_data < 2 )
1028 return VLC_EGENERIC;
1030 if( p_data[0] || p_data[1] )
1032 return VLC_EGENERIC;
1034 /* remove 2 leading 0 bytes */
1035 p_data += 2;
1036 i_data -= 2;
1037 i_count = ( i_data + i_max - 1 ) / i_max;
1039 for( i = 0; i < i_count; i++ )
1041 int i_payload = __MIN( i_max, i_data );
1042 block_t *out = block_Alloc( RTP_H263_PAYLOAD_START + i_payload );
1043 b_p_bit = (i == 0) ? 1 : 0;
1044 h = ( b_p_bit << 10 )|
1045 ( b_v_bit << 9 )|
1046 ( i_plen << 3 )|
1047 i_pebit;
1049 /* rtp common header */
1050 //b_m_bit = 1; // always contains end of frame
1051 rtp_packetize_common( id, out, (i == i_count - 1)?1:0,
1052 in->i_pts > VLC_TS_INVALID ? in->i_pts : in->i_dts );
1054 /* h263 header */
1055 SetWBE( out->p_buffer + 12, h );
1056 memcpy( &out->p_buffer[RTP_H263_PAYLOAD_START], p_data, i_payload );
1058 out->i_buffer = RTP_H263_PAYLOAD_START + i_payload;
1059 out->i_dts = in->i_dts + i * in->i_length / i_count;
1060 out->i_length = in->i_length / i_count;
1062 rtp_packetize_send( id, out );
1064 p_data += i_payload;
1065 i_data -= i_payload;
1068 return VLC_SUCCESS;
1071 /* rfc3984 */
1072 static int
1073 rtp_packetize_h264_nal( sout_stream_id_sys_t *id,
1074 const uint8_t *p_data, int i_data, int64_t i_pts,
1075 int64_t i_dts, bool b_last, int64_t i_length )
1077 const int i_max = rtp_mtu (id); /* payload max in one packet */
1078 int i_nal_hdr;
1079 int i_nal_type;
1081 if( i_data < 5 )
1082 return VLC_SUCCESS;
1084 i_nal_hdr = p_data[3];
1085 i_nal_type = i_nal_hdr&0x1f;
1087 /* Skip start code */
1088 p_data += 3;
1089 i_data -= 3;
1091 /* */
1092 if( i_data <= i_max )
1094 /* Single NAL unit packet */
1095 block_t *out = block_Alloc( 12 + i_data );
1096 out->i_dts = i_dts;
1097 out->i_length = i_length;
1099 /* */
1100 rtp_packetize_common( id, out, b_last, i_pts );
1101 out->i_buffer = 12 + i_data;
1103 memcpy( &out->p_buffer[12], p_data, i_data );
1105 rtp_packetize_send( id, out );
1107 else
1109 /* FU-A Fragmentation Unit without interleaving */
1110 const int i_count = ( i_data-1 + i_max-2 - 1 ) / (i_max-2);
1111 int i;
1113 p_data++;
1114 i_data--;
1116 for( i = 0; i < i_count; i++ )
1118 const int i_payload = __MIN( i_data, i_max-2 );
1119 block_t *out = block_Alloc( 12 + 2 + i_payload );
1120 out->i_dts = i_dts + i * i_length / i_count;
1121 out->i_length = i_length / i_count;
1123 /* */
1124 rtp_packetize_common( id, out, (b_last && i_payload == i_data),
1125 i_pts );
1126 out->i_buffer = 14 + i_payload;
1128 /* FU indicator */
1129 out->p_buffer[12] = 0x00 | (i_nal_hdr & 0x60) | 28;
1130 /* FU header */
1131 out->p_buffer[13] = ( i == 0 ? 0x80 : 0x00 ) | ( (i == i_count-1) ? 0x40 : 0x00 ) | i_nal_type;
1132 memcpy( &out->p_buffer[14], p_data, i_payload );
1134 rtp_packetize_send( id, out );
1136 i_data -= i_payload;
1137 p_data += i_payload;
1140 return VLC_SUCCESS;
1143 static int rtp_packetize_h264( sout_stream_id_sys_t *id, block_t *in )
1145 const uint8_t *p_buffer = in->p_buffer;
1146 int i_buffer = in->i_buffer;
1148 while( i_buffer > 4 && ( p_buffer[0] != 0 || p_buffer[1] != 0 || p_buffer[2] != 1 ) )
1150 i_buffer--;
1151 p_buffer++;
1154 /* Split nal units */
1155 while( i_buffer > 4 )
1157 int i_offset;
1158 int i_size = i_buffer;
1159 int i_skip = i_buffer;
1161 /* search nal end */
1162 for( i_offset = 4; i_offset+2 < i_buffer ; i_offset++)
1164 if( p_buffer[i_offset] == 0 && p_buffer[i_offset+1] == 0 && p_buffer[i_offset+2] == 1 )
1166 /* we found another startcode */
1167 i_size = i_offset - ( p_buffer[i_offset-1] == 0 ? 1 : 0);
1168 i_skip = i_offset;
1169 break;
1172 /* TODO add STAP-A to remove a lot of overhead with small slice/sei/... */
1173 rtp_packetize_h264_nal( id, p_buffer, i_size,
1174 (in->i_pts > VLC_TS_INVALID ? in->i_pts : in->i_dts), in->i_dts,
1175 (i_size >= i_buffer), in->i_length * i_size / in->i_buffer );
1177 i_buffer -= i_skip;
1178 p_buffer += i_skip;
1180 return VLC_SUCCESS;
1183 static int rtp_packetize_amr( sout_stream_id_sys_t *id, block_t *in )
1185 int i_max = rtp_mtu (id) - 2; /* payload max in one packet */
1186 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1188 uint8_t *p_data = in->p_buffer;
1189 int i_data = in->i_buffer;
1190 int i;
1192 /* Only supports octet-aligned mode */
1193 for( i = 0; i < i_count; i++ )
1195 int i_payload = __MIN( i_max, i_data );
1196 block_t *out = block_Alloc( 14 + i_payload );
1198 /* rtp common header */
1199 rtp_packetize_common( id, out, ((i == i_count - 1)?1:0),
1200 (in->i_pts > VLC_TS_INVALID ? in->i_pts : in->i_dts) );
1201 /* Payload header */
1202 out->p_buffer[12] = 0xF0; /* CMR */
1203 out->p_buffer[13] = p_data[0]&0x7C; /* ToC */ /* FIXME: frame type */
1205 /* FIXME: are we fed multiple frames ? */
1206 memcpy( &out->p_buffer[14], p_data+1, i_payload-1 );
1208 out->i_buffer = 14 + i_payload-1;
1209 out->i_dts = in->i_dts + i * in->i_length / i_count;
1210 out->i_length = in->i_length / i_count;
1212 rtp_packetize_send( id, out );
1214 p_data += i_payload;
1215 i_data -= i_payload;
1218 return VLC_SUCCESS;
1221 static int rtp_packetize_t140( sout_stream_id_sys_t *id, block_t *in )
1223 const size_t i_max = rtp_mtu (id);
1224 const uint8_t *p_data = in->p_buffer;
1225 size_t i_data = in->i_buffer;
1227 for( unsigned i_packet = 0; i_data > 0; i_packet++ )
1229 size_t i_payload = i_data;
1231 /* Make sure we stop on an UTF-8 character boundary
1232 * (assuming the input is valid UTF-8) */
1233 if( i_data > i_max )
1235 i_payload = i_max;
1237 while( ( p_data[i_payload] & 0xC0 ) == 0x80 )
1239 if( i_payload == 0 )
1240 return VLC_SUCCESS; /* fishy input! */
1242 i_payload--;
1246 block_t *out = block_Alloc( 12 + i_payload );
1247 if( out == NULL )
1248 return VLC_SUCCESS;
1250 rtp_packetize_common( id, out, 0, in->i_pts + i_packet );
1251 memcpy( out->p_buffer + 12, p_data, i_payload );
1253 out->i_buffer = 12 + i_payload;
1254 out->i_dts = in->i_pts;
1255 out->i_length = 0;
1257 rtp_packetize_send( id, out );
1259 p_data += i_payload;
1260 i_data -= i_payload;
1263 return VLC_SUCCESS;
1267 static int rtp_packetize_spx( sout_stream_id_sys_t *id, block_t *in )
1269 uint8_t *p_buffer = in->p_buffer;
1270 int i_data_size, i_payload_size, i_payload_padding;
1271 i_data_size = i_payload_size = in->i_buffer;
1272 i_payload_padding = 0;
1273 block_t *p_out;
1275 if ( in->i_buffer > rtp_mtu (id) )
1276 return VLC_SUCCESS;
1279 RFC for Speex in RTP says that each packet must end on an octet
1280 boundary. So, we check to see if the number of bytes % 4 is zero.
1281 If not, we have to add some padding.
1283 This MAY be overkill since packetization is handled elsewhere and
1284 appears to ensure the octet boundary. However, better safe than
1285 sorry.
1287 if ( i_payload_size % 4 )
1289 i_payload_padding = 4 - ( i_payload_size % 4 );
1290 i_payload_size += i_payload_padding;
1294 Allocate a new RTP p_output block of the appropriate size.
1295 Allow for 12 extra bytes of RTP header.
1297 p_out = block_Alloc( 12 + i_payload_size );
1299 if ( i_payload_padding )
1302 The padding is required to be a zero followed by all 1s.
1304 char c_first_pad, c_remaining_pad;
1305 c_first_pad = 0x7F;
1306 c_remaining_pad = 0xFF;
1309 Allow for 12 bytes before the i_data_size because
1310 of the expected RTP header added during
1311 rtp_packetize_common.
1313 p_out->p_buffer[12 + i_data_size] = c_first_pad;
1314 switch (i_payload_padding)
1316 case 2:
1317 p_out->p_buffer[12 + i_data_size + 1] = c_remaining_pad;
1318 break;
1319 case 3:
1320 p_out->p_buffer[12 + i_data_size + 1] = c_remaining_pad;
1321 p_out->p_buffer[12 + i_data_size + 2] = c_remaining_pad;
1322 break;
1326 /* Add the RTP header to our p_output buffer. */
1327 rtp_packetize_common( id, p_out, 0,
1328 (in->i_pts > VLC_TS_INVALID ? in->i_pts : in->i_dts) );
1329 /* Copy the Speex payload to the p_output buffer */
1330 memcpy( &p_out->p_buffer[12], p_buffer, i_data_size );
1332 p_out->i_buffer = 12 + i_payload_size;
1333 p_out->i_dts = in->i_dts;
1334 p_out->i_length = in->i_length;
1336 /* Queue the buffer for actual transmission. */
1337 rtp_packetize_send( id, p_out );
1338 return VLC_SUCCESS;
1341 static int rtp_packetize_g726( sout_stream_id_sys_t *id, block_t *in, int i_pad )
1343 int i_max = (rtp_mtu( id )- 12 + i_pad - 1) & ~i_pad;
1344 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1346 uint8_t *p_data = in->p_buffer;
1347 int i_data = in->i_buffer;
1348 int i_packet = 0;
1350 while( i_data > 0 )
1352 int i_payload = __MIN( i_max, i_data );
1353 block_t *out = block_Alloc( 12 + i_payload );
1355 /* rtp common header */
1356 rtp_packetize_common( id, out, 0,
1357 (in->i_pts > VLC_TS_INVALID ? in->i_pts : in->i_dts) );
1359 memcpy( &out->p_buffer[12], p_data, i_payload );
1361 out->i_buffer = 12 + i_payload;
1362 out->i_dts = in->i_dts + i_packet++ * in->i_length / i_count;
1363 out->i_length = in->i_length / i_count;
1365 rtp_packetize_send( id, out );
1367 p_data += i_payload;
1368 i_data -= i_payload;
1370 return VLC_SUCCESS;
1373 static int rtp_packetize_g726_16( sout_stream_id_sys_t *id, block_t *in )
1375 return rtp_packetize_g726( id, in, 4 );
1378 static int rtp_packetize_g726_24( sout_stream_id_sys_t *id, block_t *in )
1380 return rtp_packetize_g726( id, in, 8 );
1383 static int rtp_packetize_g726_32( sout_stream_id_sys_t *id, block_t *in )
1385 return rtp_packetize_g726( id, in, 2 );
1388 static int rtp_packetize_g726_40( sout_stream_id_sys_t *id, block_t *in )
1390 return rtp_packetize_g726( id, in, 8 );
1393 #define RTP_VP8_HEADER_SIZE 1
1394 #define RTP_VP8_PAYLOAD_START (12 + RTP_VP8_HEADER_SIZE)
1396 static int rtp_packetize_vp8( sout_stream_id_sys_t *id, block_t *in )
1398 int i_max = rtp_mtu (id) - RTP_VP8_HEADER_SIZE;
1399 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1401 uint8_t *p_data = in->p_buffer;
1402 int i_data = in->i_buffer;
1404 if ( i_max <= 0 )
1405 return VLC_EGENERIC;
1407 for( int i = 0; i < i_count; i++ )
1409 int i_payload = __MIN( i_max, i_data );
1410 block_t *out = block_Alloc( RTP_VP8_PAYLOAD_START + i_payload );
1411 if ( out == NULL )
1412 return VLC_ENOMEM;
1414 /* VP8 payload header */
1415 /* All frames are marked as reference ones */
1416 if (i == 0)
1417 out->p_buffer[12] = 0x10; // partition start
1418 else
1419 out->p_buffer[12] = 0;
1421 /* rtp common header */
1422 rtp_packetize_common( id, out, (i == i_count - 1),
1423 (in->i_pts > VLC_TS_INVALID ? in->i_pts : in->i_dts) );
1424 memcpy( &out->p_buffer[RTP_VP8_PAYLOAD_START], p_data, i_payload );
1426 out->i_buffer = RTP_VP8_PAYLOAD_START + i_payload;
1427 out->i_dts = in->i_dts + i * in->i_length / i_count;
1428 out->i_length = in->i_length / i_count;
1430 rtp_packetize_send( id, out );
1432 p_data += i_payload;
1433 i_data -= i_payload;
1436 return VLC_SUCCESS;
1439 static int rtp_packetize_jpeg( sout_stream_id_sys_t *id, block_t *in )
1441 uint8_t *p_data = in->p_buffer;
1442 int i_data = in->i_buffer;
1443 uint8_t *bufend = p_data + i_data;
1445 const uint8_t *qtables = NULL;
1446 int nb_qtables = 0;
1447 int off = 0; // fragment offset in frame
1448 int y_sampling_factor;
1449 // type is set by pixel format (determined by y_sampling_factor):
1450 // 0 for yuvj422p
1451 // 1 for yuvj420p
1452 // += 64 if DRI present
1453 int type;
1454 int w = 0; // Width in multiples of 8
1455 int h = 0; // Height in multiples of 8
1456 int restart_interval;
1457 int dri_found = 0;
1459 // Skip SOI
1460 if (GetWBE(p_data) != 0xffd8)
1461 return VLC_EGENERIC;
1462 p_data += 2;
1463 i_data -= 2;
1465 /* parse the header to get necessary info */
1466 int header_finished = 0;
1467 while (!header_finished && p_data + 4 <= bufend) {
1468 uint16_t marker = GetWBE(p_data);
1469 uint8_t *section = p_data + 2;
1470 int section_size = GetWBE(section);
1471 uint8_t *section_body = p_data + 4;
1472 if (section + section_size > bufend)
1473 return VLC_EGENERIC;
1475 assert((marker & 0xff00) == 0xff00);
1476 switch (marker)
1478 case 0xffdb /*DQT*/:
1479 if (section_body[0])
1481 // Only 8-bit precision is supported
1482 return VLC_EGENERIC;
1485 /* a quantization table is 64 bytes long */
1486 nb_qtables = section_size / 65;
1487 qtables = section_body;
1488 break;
1489 case 0xffc0 /*SOF0*/:
1491 int height = GetWBE(&section_body[1]);
1492 int width = GetWBE(&section_body[3]);
1493 if (width > 2040 || height > 2040)
1495 // larger than limit supported by RFC 2435
1496 return VLC_EGENERIC;
1498 // Round up by 8, divide by 8
1499 w = ((width+7)&~7) >> 3;
1500 h = ((height+7)&~7) >> 3;
1502 // Get components sampling to determine type
1503 // Y has component ID 1
1504 // Possible configurations of sampling factors:
1505 // Y - 0x22, Cb - 0x11, Cr - 0x11 => yuvj420p
1506 // Y - 0x21, Cb - 0x11, Cr - 0x11 => yuvj422p
1508 // Only 3 components are supported by RFC 2435
1509 if (section_body[5] != 3) // Number of components
1510 return VLC_EGENERIC;
1511 for (int j = 0; j < 3; j++)
1513 if (section_body[6 + j * 3] == 1 /* Y */)
1515 y_sampling_factor = section_body[6 + j * 3 + 1];
1517 else if (section_body[6 + j * 3 + 1] != 0x11)
1519 // Sampling factor is unsupported by RFC 2435
1520 return VLC_EGENERIC;
1523 break;
1525 case 0xffdd /*DRI*/:
1526 restart_interval = GetWBE(section_body);
1527 dri_found = 1;
1528 break;
1529 case 0xffda /*SOS*/:
1530 /* SOS is last marker in the header */
1531 header_finished = 1;
1532 break;
1534 // Step over marker, 16bit length and section body
1535 p_data += 2 + section_size;
1536 i_data -= 2 + section_size;
1538 if (!header_finished)
1539 return VLC_EGENERIC;
1540 if (!w || !h)
1541 return VLC_EGENERIC;
1543 switch (y_sampling_factor)
1545 case 0x22: // yuvj420p
1546 type = 1;
1547 break;
1548 case 0x21: // yuvj422p
1549 type = 0;
1550 break;
1551 default:
1552 // Sampling format unsupported by RFC 2435
1553 return VLC_EGENERIC;
1556 if (dri_found)
1557 type += 64;
1559 while ( i_data )
1561 int hdr_size = 8 + dri_found * 4;
1562 if (off == 0 && nb_qtables)
1563 hdr_size += 4 + 64 * nb_qtables;
1565 int i_payload = __MIN( i_data, (int)(rtp_mtu (id) - hdr_size) );
1566 if ( i_payload <= 0 )
1567 return VLC_EGENERIC;
1569 block_t *out = block_Alloc( 12 + hdr_size + i_payload );
1570 if( out == NULL )
1571 return VLC_ENOMEM;
1573 uint8_t *p = out->p_buffer + 12;
1574 /* set main header */
1575 /* set type-specific=0, set offset in following 24 bits: */
1576 SetDWBE(p, off & 0x00ffffff);
1577 p += 4;
1578 *p++ = type;
1579 *p++ = 255; // Quant value
1580 *p++ = w;
1581 *p++ = h;
1583 // Write restart_marker_hdr if needed
1584 if (dri_found)
1586 SetWBE(p, restart_interval);
1587 p += 2;
1588 // restart_count. Hardcoded same value as in gstreamer implementation
1589 SetWBE(p, 0xffff);
1590 p += 2;
1593 if (off == 0 && nb_qtables)
1595 /* set quantization tables header */
1596 *p++ = 0;
1597 *p++ = 0;
1598 SetWBE (p, 64 * nb_qtables);
1599 p += 2;
1600 for (int i = 0; i < nb_qtables; i++)
1602 memcpy (p, &qtables[65 * i + 1], 64);
1603 p += 64;
1607 /* rtp common header */
1608 rtp_packetize_common( id, out, (i_payload == i_data),
1609 (in->i_pts > VLC_TS_INVALID ? in->i_pts : in->i_dts) );
1610 memcpy( p, p_data, i_payload );
1612 out->i_buffer = 12 + hdr_size + i_payload;
1613 out->i_dts = in->i_dts;
1614 out->i_length = in->i_length;
1616 rtp_packetize_send( id, out );
1618 p_data += i_payload;
1619 i_data -= i_payload;
1620 off += i_payload;
1623 return VLC_SUCCESS;