1 /*****************************************************************************
2 * rtp.c: rtp stream output module
3 *****************************************************************************
4 * Copyright (C) 2003-2004 the VideoLAN team
5 * Copyright © 2007 Rémi Denis-Courmont
8 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
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.
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.
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 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
31 #include <vlc_block.h>
33 #include <vlc_httpd.h>
35 #include <vlc_network.h>
36 #include <vlc_charset.h>
37 #include <vlc_strings.h>
42 # include <sys/types.h>
45 # include <sys/stat.h>
47 #ifdef HAVE_LINUX_DCCP_H
48 # include <linux/dccp.h>
51 # define IPPROTO_DCCP 33
53 #ifndef IPPROTO_UDPLITE
54 # define IPPROTO_UDPLITE 136
59 /*****************************************************************************
61 *****************************************************************************/
63 #define DST_TEXT N_("Destination")
64 #define DST_LONGTEXT N_( \
65 "This is the output URL that will be used." )
66 #define SDP_TEXT N_("SDP")
67 #define SDP_LONGTEXT N_( \
68 "This allows you to specify how the SDP (Session Descriptor) for this RTP "\
69 "session will be made available. You must use an url: http://location to " \
70 "access the SDP via HTTP, rtsp://location for RTSP access, and sap:// " \
71 "for the SDP to be announced via SAP." )
72 #define MUX_TEXT N_("Muxer")
73 #define MUX_LONGTEXT N_( \
74 "This allows you to specify the muxer used for the streaming output. " \
75 "Default is to use no muxer (standard RTP stream)." )
77 #define NAME_TEXT N_("Session name")
78 #define NAME_LONGTEXT N_( \
79 "This is the name of the session that will be announced in the SDP " \
80 "(Session Descriptor)." )
81 #define DESC_TEXT N_("Session descriptipn")
82 #define DESC_LONGTEXT N_( \
83 "This allows you to give a short description with details about the stream, " \
84 "that will be announced in the SDP (Session Descriptor)." )
85 #define URL_TEXT N_("Session URL")
86 #define URL_LONGTEXT N_( \
87 "This allows you to give an URL with more details about the stream " \
88 "(often the website of the streaming organization), that will " \
89 "be announced in the SDP (Session Descriptor)." )
90 #define EMAIL_TEXT N_("Session email")
91 #define EMAIL_LONGTEXT N_( \
92 "This allows you to give a contact mail address for the stream, that will " \
93 "be announced in the SDP (Session Descriptor)." )
94 #define PHONE_TEXT N_("Session phone number")
95 #define PHONE_LONGTEXT N_( \
96 "This allows you to give a contact telephone number for the stream, that will " \
97 "be announced in the SDP (Session Descriptor)." )
99 #define PORT_TEXT N_("Port")
100 #define PORT_LONGTEXT N_( \
101 "This allows you to specify the base port for the RTP streaming." )
102 #define PORT_AUDIO_TEXT N_("Audio port")
103 #define PORT_AUDIO_LONGTEXT N_( \
104 "This allows you to specify the default audio port for the RTP streaming." )
105 #define PORT_VIDEO_TEXT N_("Video port")
106 #define PORT_VIDEO_LONGTEXT N_( \
107 "This allows you to specify the default video port for the RTP streaming." )
109 #define TTL_TEXT N_("Hop limit (TTL)")
110 #define TTL_LONGTEXT N_( \
111 "This is the hop limit (also known as \"Time-To-Live\" or TTL) of " \
112 "the multicast packets sent by the stream output (0 = use operating " \
113 "system built-in default).")
115 #define RTCP_MUX_TEXT N_("RTP/RTCP multiplexing")
116 #define RTCP_MUX_LONGTEXT N_( \
117 "This sends and receives RTCP packet multiplexed over the same port " \
120 #define DCCP_TEXT N_("DCCP transport")
121 #define DCCP_LONGTEXT N_( \
122 "This enables DCCP instead of UDP as a transport for RTP." )
123 #define TCP_TEXT N_("TCP transport")
124 #define TCP_LONGTEXT N_( \
125 "This enables TCP instead of UDP as a transport for RTP." )
126 #define UDP_LITE_TEXT N_("UDP-Lite transport")
127 #define UDP_LITE_LONGTEXT N_( \
128 "This enables UDP-Lite instead of UDP as a transport for RTP." )
130 #define RFC3016_TEXT N_("MP4A LATM")
131 #define RFC3016_LONGTEXT N_( \
132 "This allows you to stream MPEG4 LATM audio streams (see RFC3016)." )
134 static int Open ( vlc_object_t * );
135 static void Close( vlc_object_t * );
137 #define SOUT_CFG_PREFIX "sout-rtp-"
138 #define MAX_EMPTY_BLOCKS 200
141 set_shortname( _("RTP"));
142 set_description( _("RTP stream output") );
143 set_capability( "sout stream", 0 );
144 add_shortcut( "rtp" );
145 set_category( CAT_SOUT );
146 set_subcategory( SUBCAT_SOUT_STREAM );
148 add_string( SOUT_CFG_PREFIX "dst", "", NULL, DST_TEXT,
149 DST_LONGTEXT, VLC_TRUE );
150 add_string( SOUT_CFG_PREFIX "sdp", "", NULL, SDP_TEXT,
151 SDP_LONGTEXT, VLC_TRUE );
152 add_string( SOUT_CFG_PREFIX "mux", "", NULL, MUX_TEXT,
153 MUX_LONGTEXT, VLC_TRUE );
155 add_string( SOUT_CFG_PREFIX "name", "", NULL, NAME_TEXT,
156 NAME_LONGTEXT, VLC_TRUE );
157 add_string( SOUT_CFG_PREFIX "description", "", NULL, DESC_TEXT,
158 DESC_LONGTEXT, VLC_TRUE );
159 add_string( SOUT_CFG_PREFIX "url", "", NULL, URL_TEXT,
160 URL_LONGTEXT, VLC_TRUE );
161 add_string( SOUT_CFG_PREFIX "email", "", NULL, EMAIL_TEXT,
162 EMAIL_LONGTEXT, VLC_TRUE );
163 add_string( SOUT_CFG_PREFIX "phone", "", NULL, PHONE_TEXT,
164 PHONE_LONGTEXT, VLC_TRUE );
166 add_integer( SOUT_CFG_PREFIX "port", 1234, NULL, PORT_TEXT,
167 PORT_LONGTEXT, VLC_TRUE );
168 add_integer( SOUT_CFG_PREFIX "port-audio", 1230, NULL, PORT_AUDIO_TEXT,
169 PORT_AUDIO_LONGTEXT, VLC_TRUE );
170 add_integer( SOUT_CFG_PREFIX "port-video", 1232, NULL, PORT_VIDEO_TEXT,
171 PORT_VIDEO_LONGTEXT, VLC_TRUE );
173 add_integer( SOUT_CFG_PREFIX "ttl", 0, NULL, TTL_TEXT,
174 TTL_LONGTEXT, VLC_TRUE );
176 add_bool( SOUT_CFG_PREFIX "rtcp-mux", VLC_FALSE, NULL,
177 RTCP_MUX_TEXT, RTCP_MUX_LONGTEXT, VLC_FALSE );
179 add_bool( SOUT_CFG_PREFIX "dccp", VLC_FALSE, NULL,
180 DCCP_TEXT, DCCP_LONGTEXT, VLC_FALSE );
181 add_bool( SOUT_CFG_PREFIX "tcp", VLC_FALSE, NULL,
182 TCP_TEXT, TCP_LONGTEXT, VLC_FALSE );
183 add_bool( SOUT_CFG_PREFIX "udplite", VLC_FALSE, NULL,
184 UDP_LITE_TEXT, UDP_LITE_LONGTEXT, VLC_FALSE );
186 add_bool( SOUT_CFG_PREFIX "mp4a-latm", 0, NULL, RFC3016_TEXT,
187 RFC3016_LONGTEXT, VLC_FALSE );
189 set_callbacks( Open, Close );
192 /*****************************************************************************
193 * Exported prototypes
194 *****************************************************************************/
195 static const char *ppsz_sout_options[] = {
196 "dst", "name", "port", "port-audio", "port-video", "*sdp", "ttl", "mux",
197 "description", "url", "email", "phone",
198 "rtcp-mux", "dccp", "tcp", "udplite",
202 static sout_stream_id_t *Add ( sout_stream_t *, es_format_t * );
203 static int Del ( sout_stream_t *, sout_stream_id_t * );
204 static int Send( sout_stream_t *, sout_stream_id_t *,
206 static sout_stream_id_t *MuxAdd ( sout_stream_t *, es_format_t * );
207 static int MuxDel ( sout_stream_t *, sout_stream_id_t * );
208 static int MuxSend( sout_stream_t *, sout_stream_id_t *,
211 static sout_access_out_t *GrabberCreate( sout_stream_t *p_sout );
212 static void ThreadSend( vlc_object_t *p_this );
214 static void SDPHandleUrl( sout_stream_t *, char * );
216 static int SapSetup( sout_stream_t *p_stream );
217 static int FileSetup( sout_stream_t *p_stream );
218 static int HttpSetup( sout_stream_t *p_stream, vlc_url_t * );
220 struct sout_stream_sys_t
224 vlc_mutex_t lock_sdp;
227 vlc_bool_t b_export_sdp_file;
231 vlc_bool_t b_export_sap;
232 session_descriptor_t *p_session;
235 httpd_host_t *p_httpd_host;
236 httpd_file_t *p_httpd_file;
242 char *psz_destination;
246 uint16_t i_port_audio;
247 uint16_t i_port_video;
251 /* when need to use a private one or when using muxer */
254 /* in case we do TS/PS over rtp */
256 sout_access_out_t *p_grab;
262 sout_stream_id_t **es;
265 typedef int (*pf_rtp_packetizer_t)( sout_stream_t *, sout_stream_id_t *,
268 typedef struct rtp_sink_t
274 struct sout_stream_id_t
278 sout_stream_t *p_stream;
281 uint8_t i_payload_type;
293 /* Packetizer specific fields */
294 pf_rtp_packetizer_t pf_packetize;
298 vlc_mutex_t lock_sink;
301 rtsp_stream_id_t *rtsp_id;
304 block_fifo_t *p_fifo;
309 /*****************************************************************************
311 *****************************************************************************/
312 static int Open( vlc_object_t *p_this )
314 sout_stream_t *p_stream = (sout_stream_t*)p_this;
315 sout_instance_t *p_sout = p_stream->p_sout;
316 sout_stream_sys_t *p_sys = NULL;
317 config_chain_t *p_cfg = NULL;
319 vlc_bool_t b_rtsp = VLC_FALSE;
321 config_ChainParse( p_stream, SOUT_CFG_PREFIX,
322 ppsz_sout_options, p_stream->p_cfg );
324 p_sys = malloc( sizeof( sout_stream_sys_t ) );
328 p_sys->psz_destination = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "dst" );
330 p_sys->i_port = var_GetInteger( p_stream, SOUT_CFG_PREFIX "port" );
331 p_sys->i_port_audio = var_GetInteger( p_stream, SOUT_CFG_PREFIX "port-audio" );
332 p_sys->i_port_video = var_GetInteger( p_stream, SOUT_CFG_PREFIX "port-video" );
333 p_sys->rtcp_mux = var_GetBool( p_stream, SOUT_CFG_PREFIX "rtcp-mux" );
335 p_sys->psz_sdp_file = NULL;
337 if( p_sys->i_port_audio == p_sys->i_port_video )
339 msg_Err( p_stream, "audio and video port cannot be the same" );
340 p_sys->i_port_audio = 0;
341 p_sys->i_port_video = 0;
344 for( p_cfg = p_stream->p_cfg; p_cfg != NULL; p_cfg = p_cfg->p_next )
346 if( !strcmp( p_cfg->psz_name, "sdp" )
347 && ( p_cfg->psz_value != NULL )
348 && !strncasecmp( p_cfg->psz_value, "rtsp:", 5 ) )
356 psz = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "sdp" );
359 if( !strncasecmp( psz, "rtsp:", 5 ) )
365 /* Transport protocol */
366 p_sys->proto = IPPROTO_UDP;
368 if( var_GetBool( p_stream, SOUT_CFG_PREFIX "dccp" ) )
370 p_sys->proto = IPPROTO_DCCP;
371 p_sys->rtcp_mux = VLC_TRUE; /* Force RTP/RTCP mux */
375 if( var_GetBool( p_stream, SOUT_CFG_PREFIX "tcp" ) )
377 p_sys->proto = IPPROTO_TCP;
378 p_sys->rtcp_mux = VLC_TRUE; /* Force RTP/RTCP mux */
382 if( var_GetBool( p_stream, SOUT_CFG_PREFIX "udplite" ) )
383 p_sys->proto = IPPROTO_UDPLITE;
385 if( ( p_sys->psz_destination == NULL ) && !b_rtsp )
387 msg_Err( p_stream, "missing destination and not in RTSP mode" );
392 p_sys->i_ttl = var_GetInteger( p_stream, SOUT_CFG_PREFIX "ttl" );
393 if( p_sys->i_ttl == 0 )
395 /* Normally, we should let the default hop limit up to the core,
396 * but we have to know it to build our SDP properly, which is why
397 * we ask the core. FIXME: broken when neither sout-rtp-ttl nor
399 p_sys->i_ttl = config_GetInt( p_stream, "ttl" );
402 p_sys->b_latm = var_GetBool( p_stream, SOUT_CFG_PREFIX "mp4a-latm" );
404 p_sys->i_payload_type = 96;
408 p_sys->psz_sdp = NULL;
410 p_sys->b_export_sap = VLC_FALSE;
411 p_sys->b_export_sdp_file = VLC_FALSE;
412 p_sys->p_session = NULL;
414 p_sys->p_httpd_host = NULL;
415 p_sys->p_httpd_file = NULL;
417 p_stream->p_sys = p_sys;
419 vlc_mutex_init( p_stream, &p_sys->lock_sdp );
420 vlc_mutex_init( p_stream, &p_sys->lock_es );
422 psz = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "mux" );
425 sout_stream_id_t *id;
427 /* Check muxer type */
428 if( strncasecmp( psz, "ps", 2 )
429 && strncasecmp( psz, "mpeg1", 5 )
430 && strncasecmp( psz, "ts", 2 ) )
432 msg_Err( p_stream, "unsupported muxer type for RTP (only TS/PS)" );
434 vlc_mutex_destroy( &p_sys->lock_sdp );
435 vlc_mutex_destroy( &p_sys->lock_es );
440 p_sys->p_grab = GrabberCreate( p_stream );
441 p_sys->p_mux = sout_MuxNew( p_sout, psz, p_sys->p_grab );
444 if( p_sys->p_mux == NULL )
446 msg_Err( p_stream, "cannot create muxer" );
447 sout_AccessOutDelete( p_sys->p_grab );
448 vlc_mutex_destroy( &p_sys->lock_sdp );
449 vlc_mutex_destroy( &p_sys->lock_es );
454 id = Add( p_stream, NULL );
457 sout_MuxDelete( p_sys->p_mux );
458 sout_AccessOutDelete( p_sys->p_grab );
459 vlc_mutex_destroy( &p_sys->lock_sdp );
460 vlc_mutex_destroy( &p_sys->lock_es );
465 p_sys->packet = NULL;
467 p_stream->pf_add = MuxAdd;
468 p_stream->pf_del = MuxDel;
469 p_stream->pf_send = MuxSend;
474 p_sys->p_grab = NULL;
476 p_stream->pf_add = Add;
477 p_stream->pf_del = Del;
478 p_stream->pf_send = Send;
481 psz = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "sdp" );
484 config_chain_t *p_cfg;
486 SDPHandleUrl( p_stream, psz );
488 for( p_cfg = p_stream->p_cfg; p_cfg != NULL; p_cfg = p_cfg->p_next )
490 if( !strcmp( p_cfg->psz_name, "sdp" ) )
492 if( p_cfg->psz_value == NULL || *p_cfg->psz_value == '\0' )
495 /* needed both :sout-rtp-sdp= and rtp{sdp=} can be used */
496 if( !strcmp( p_cfg->psz_value, psz ) )
499 SDPHandleUrl( p_stream, p_cfg->psz_value );
505 /* update p_sout->i_out_pace_nocontrol */
506 p_stream->p_sout->i_out_pace_nocontrol++;
511 /*****************************************************************************
513 *****************************************************************************/
514 static void Close( vlc_object_t * p_this )
516 sout_stream_t *p_stream = (sout_stream_t*)p_this;
517 sout_stream_sys_t *p_sys = p_stream->p_sys;
519 /* update p_sout->i_out_pace_nocontrol */
520 p_stream->p_sout->i_out_pace_nocontrol--;
524 assert( p_sys->i_es == 1 );
525 Del( p_stream, p_sys->es[0] );
527 sout_MuxDelete( p_sys->p_mux );
528 sout_AccessOutDelete( p_sys->p_grab );
531 block_Release( p_sys->packet );
533 if( p_sys->b_export_sap )
536 SapSetup( p_stream );
540 if( p_sys->rtsp != NULL )
541 RtspUnsetup( p_sys->rtsp );
543 vlc_mutex_destroy( &p_sys->lock_sdp );
544 vlc_mutex_destroy( &p_sys->lock_es );
546 if( p_sys->p_httpd_file )
547 httpd_FileDelete( p_sys->p_httpd_file );
549 if( p_sys->p_httpd_host )
550 httpd_HostDelete( p_sys->p_httpd_host );
552 free( p_sys->psz_sdp );
554 if( p_sys->b_export_sdp_file )
557 unlink( p_sys->psz_sdp_file );
559 free( p_sys->psz_sdp_file );
561 free( p_sys->psz_destination );
565 /*****************************************************************************
567 *****************************************************************************/
568 static void SDPHandleUrl( sout_stream_t *p_stream, char *psz_url )
570 sout_stream_sys_t *p_sys = p_stream->p_sys;
573 vlc_UrlParse( &url, psz_url, 0 );
574 if( url.psz_protocol && !strcasecmp( url.psz_protocol, "http" ) )
576 if( p_sys->p_httpd_file )
578 msg_Err( p_stream, "you can use sdp=http:// only once" );
582 if( HttpSetup( p_stream, &url ) )
584 msg_Err( p_stream, "cannot export SDP as HTTP" );
587 else if( url.psz_protocol && !strcasecmp( url.psz_protocol, "rtsp" ) )
589 if( p_sys->rtsp != NULL )
591 msg_Err( p_stream, "you can use sdp=rtsp:// only once" );
595 /* FIXME test if destination is multicast or no destination at all */
596 p_sys->rtsp = RtspSetup( p_stream, &url );
597 if( p_sys->rtsp == NULL )
599 msg_Err( p_stream, "cannot export SDP as RTSP" );
602 if( p_sys->p_mux != NULL )
604 sout_stream_id_t *id = p_sys->es[0];
605 id->rtsp_id = RtspAddId( p_sys->rtsp, id, 0, GetDWBE( id->ssrc ),
606 p_sys->psz_destination, p_sys->i_ttl,
607 id->i_port, id->i_port + 1 );
610 else if( ( url.psz_protocol && !strcasecmp( url.psz_protocol, "sap" ) ) ||
611 ( url.psz_host && !strcasecmp( url.psz_host, "sap" ) ) )
613 p_sys->b_export_sap = VLC_TRUE;
614 SapSetup( p_stream );
616 else if( url.psz_protocol && !strcasecmp( url.psz_protocol, "file" ) )
618 if( p_sys->b_export_sdp_file )
620 msg_Err( p_stream, "you can use sdp=file:// only once" );
623 p_sys->b_export_sdp_file = VLC_TRUE;
624 psz_url = &psz_url[5];
625 if( psz_url[0] == '/' && psz_url[1] == '/' )
627 p_sys->psz_sdp_file = strdup( psz_url );
631 msg_Warn( p_stream, "unknown protocol for SDP (%s)",
636 vlc_UrlClean( &url );
639 /*****************************************************************************
641 *****************************************************************************/
643 char *SDPGenerate( const sout_stream_t *p_stream, const char *rtsp_url )
645 const sout_stream_sys_t *p_sys = p_stream->p_sys;
647 struct sockaddr_storage dst;
651 * When we have a fixed destination (typically when we do multicast),
652 * we need to put the actual port numbers in the SDP.
653 * When there is no fixed destination, we only support RTSP unicast
654 * on-demand setup, so we should rather let the clients decide which ports
656 * When there is both a fixed destination and RTSP unicast, we need to
657 * put port numbers used by the fixed destination, otherwise the SDP would
658 * become totally incorrect for multicast use. It should be noted that
659 * port numbers from SDP with RTSP are only "recommendation" from the
660 * server to the clients (per RFC2326), so only broken clients will fail
661 * to handle this properly. There is no solution but to use two differents
662 * output chain with two different RTSP URLs if you need to handle this
667 if( p_sys->psz_destination != NULL )
671 /* Oh boy, this is really ugly! (+ race condition on lock_es) */
672 dstlen = sizeof( dst );
673 if( p_sys->es[0]->listen_fd != NULL )
674 getsockname( p_sys->es[0]->listen_fd[0],
675 (struct sockaddr *)&dst, &dstlen );
677 getpeername( p_sys->es[0]->sinkv[0].rtp_fd,
678 (struct sockaddr *)&dst, &dstlen );
684 /* Dummy destination address for RTSP */
685 memset (&dst, 0, sizeof( struct sockaddr_in ) );
686 dst.ss_family = AF_INET;
690 dstlen = sizeof( struct sockaddr_in );
693 psz_sdp = vlc_sdp_Start( VLC_OBJECT( p_stream ), SOUT_CFG_PREFIX,
694 NULL, 0, (struct sockaddr *)&dst, dstlen );
695 if( psz_sdp == NULL )
698 /* TODO: a=source-filter */
699 if( p_sys->rtcp_mux )
700 sdp_AddAttribute( &psz_sdp, "rtcp-mux", NULL );
702 if( rtsp_url != NULL )
703 sdp_AddAttribute ( &psz_sdp, "control", "%s", rtsp_url );
705 /* FIXME: locking?! */
706 for( i = 0; i < p_sys->i_es; i++ )
708 sout_stream_id_t *id = p_sys->es[i];
709 const char *mime_major; /* major MIME type */
710 const char *proto = "RTP/AVP"; /* protocol */
715 mime_major = "video";
718 mime_major = "audio";
727 if( rtsp_url == NULL )
729 switch( p_sys->proto )
734 proto = "TCP/RTP/AVP";
737 proto = "DCCP/RTP/AVP";
739 case IPPROTO_UDPLITE:
744 sdp_AddMedia( &psz_sdp, mime_major, proto, inclport * id->i_port,
745 id->i_payload_type, VLC_FALSE, id->i_bitrate,
746 id->psz_rtpmap, id->psz_fmtp);
748 if( rtsp_url != NULL )
750 assert( strlen( rtsp_url ) > 0 );
751 vlc_bool_t addslash = ( rtsp_url[strlen( rtsp_url ) - 1] != '/' );
752 sdp_AddAttribute ( &psz_sdp, "control",
753 addslash ? "%s/trackID=%u" : "%strackID=%u",
758 if( id->listen_fd != NULL )
759 sdp_AddAttribute( &psz_sdp, "setup", "passive" );
761 if( p_sys->proto == IPPROTO_DCCP )
762 sdp_AddAttribute( &psz_sdp, "dccp-service-code",
763 "SC:RTP%c", toupper( mime_major[0] ) );
771 /*****************************************************************************
773 *****************************************************************************/
774 static int rtp_packetize_l16 ( sout_stream_t *, sout_stream_id_t *, block_t * );
775 static int rtp_packetize_l8 ( sout_stream_t *, sout_stream_id_t *, block_t * );
776 static int rtp_packetize_mpa ( sout_stream_t *, sout_stream_id_t *, block_t * );
777 static int rtp_packetize_mpv ( sout_stream_t *, sout_stream_id_t *, block_t * );
778 static int rtp_packetize_ac3 ( sout_stream_t *, sout_stream_id_t *, block_t * );
779 static int rtp_packetize_split( sout_stream_t *, sout_stream_id_t *, block_t * );
780 static int rtp_packetize_mp4a ( sout_stream_t *, sout_stream_id_t *, block_t * );
781 static int rtp_packetize_mp4a_latm ( sout_stream_t *, sout_stream_id_t *, block_t * );
782 static int rtp_packetize_h263 ( sout_stream_t *, sout_stream_id_t *, block_t * );
783 static int rtp_packetize_h264 ( sout_stream_t *, sout_stream_id_t *, block_t * );
784 static int rtp_packetize_amr ( sout_stream_t *, sout_stream_id_t *, block_t * );
785 static int rtp_packetize_spx ( sout_stream_t *, sout_stream_id_t *, block_t * );
786 static int rtp_packetize_t140 ( sout_stream_t *, sout_stream_id_t *, block_t * );
788 static void sprintf_hexa( char *s, uint8_t *p_data, int i_data )
790 static const char hex[16] = "0123456789abcdef";
793 for( i = 0; i < i_data; i++ )
795 s[2*i+0] = hex[(p_data[i]>>4)&0xf];
796 s[2*i+1] = hex[(p_data[i] )&0xf];
802 /** Add an ES as a new RTP stream */
803 static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
805 /* NOTE: As a special case, if we use a non-RTP
806 * mux (TS/PS), then p_fmt is NULL. */
807 sout_stream_sys_t *p_sys = p_stream->p_sys;
808 sout_stream_id_t *id;
809 int i_port, cscov = -1;
812 id = vlc_object_create( p_stream, sizeof( sout_stream_id_t ) );
815 vlc_object_attach( id, p_stream );
817 /* Choose the port */
822 if( p_fmt->i_cat == AUDIO_ES && p_sys->i_port_audio > 0 )
824 i_port = p_sys->i_port_audio;
825 p_sys->i_port_audio = 0;
828 if( p_fmt->i_cat == VIDEO_ES && p_sys->i_port_video > 0 )
830 i_port = p_sys->i_port_video;
831 p_sys->i_port_video = 0;
836 if( p_sys->i_port != p_sys->i_port_audio
837 && p_sys->i_port != p_sys->i_port_video )
839 i_port = p_sys->i_port;
846 id->p_stream = p_stream;
848 id->i_sequence = rand()&0xffff;
849 id->i_payload_type = p_sys->i_payload_type;
850 id->ssrc[0] = rand()&0xff;
851 id->ssrc[1] = rand()&0xff;
852 id->ssrc[2] = rand()&0xff;
853 id->ssrc[3] = rand()&0xff;
855 id->psz_rtpmap = NULL;
857 id->i_clock_rate = 90000; /* most common case for video */
862 id->i_cat = p_fmt->i_cat;
863 if( p_fmt->i_cat == AUDIO_ES )
865 id->i_clock_rate = p_fmt->audio.i_rate;
866 id->i_channels = p_fmt->audio.i_channels;
868 id->i_bitrate = p_fmt->i_bitrate/1000; /* Stream bitrate in kbps */
872 id->i_cat = VIDEO_ES;
876 id->pf_packetize = NULL;
877 id->i_mtu = config_GetInt( p_stream, "mtu" );
878 if( id->i_mtu <= 12 + 16 )
879 id->i_mtu = 576 - 20 - 8; /* pessimistic */
881 msg_Dbg( p_stream, "maximum RTP packet size: %d bytes", id->i_mtu );
883 vlc_mutex_init( p_stream, &id->lock_sink );
888 id->listen_fd = NULL;
891 (int64_t)1000 * var_GetInteger( p_stream, SOUT_CFG_PREFIX "caching");
893 if( p_sys->psz_destination != NULL )
894 switch( p_sys->proto )
898 id->listen_fd = net_Listen( VLC_OBJECT(p_stream),
899 p_sys->psz_destination, i_port,
901 if( id->listen_fd == NULL )
903 msg_Err( p_stream, "passive COMEDIA RTP socket failed" );
910 int ttl = (p_sys->i_ttl > 0) ? p_sys->i_ttl : -1;
911 int fd = net_ConnectDgram( p_stream, p_sys->psz_destination,
912 i_port, ttl, p_sys->proto );
915 msg_Err( p_stream, "cannot create RTP socket" );
918 rtp_add_sink( id, fd, p_sys->rtcp_mux );
924 char *psz = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "mux" );
926 if( psz == NULL ) /* Uho! */
929 if( strncmp( psz, "ts", 2 ) == 0 )
931 id->i_payload_type = 33;
932 id->psz_rtpmap = strdup( "MP2T/90000" );
936 id->psz_rtpmap = strdup( "MP2P/90000" );
940 switch( p_fmt->i_codec )
942 case VLC_FOURCC( 'u', 'l', 'a', 'w' ):
943 if( p_fmt->audio.i_channels == 1 && p_fmt->audio.i_rate == 8000 )
944 id->i_payload_type = 0;
945 if( asprintf( &id->psz_rtpmap, "PCMU/%d/%d", p_fmt->audio.i_rate,
946 p_fmt->audio.i_channels ) == -1 )
947 id->psz_rtpmap = NULL;
948 id->pf_packetize = rtp_packetize_l8;
950 case VLC_FOURCC( 'a', 'l', 'a', 'w' ):
951 if( p_fmt->audio.i_channels == 1 && p_fmt->audio.i_rate == 8000 )
952 id->i_payload_type = 8;
953 if( asprintf( &id->psz_rtpmap, "PCMA/%d/%d", p_fmt->audio.i_rate,
954 p_fmt->audio.i_channels ) == -1 )
955 id->psz_rtpmap = NULL;
956 id->pf_packetize = rtp_packetize_l8;
958 case VLC_FOURCC( 's', '1', '6', 'b' ):
959 if( p_fmt->audio.i_channels == 1 && p_fmt->audio.i_rate == 44100 )
961 id->i_payload_type = 11;
963 else if( p_fmt->audio.i_channels == 2 &&
964 p_fmt->audio.i_rate == 44100 )
966 id->i_payload_type = 10;
968 if( asprintf( &id->psz_rtpmap, "L16/%d/%d", p_fmt->audio.i_rate,
969 p_fmt->audio.i_channels ) == -1 )
970 id->psz_rtpmap = NULL;
971 id->pf_packetize = rtp_packetize_l16;
973 case VLC_FOURCC( 'u', '8', ' ', ' ' ):
974 if( asprintf( &id->psz_rtpmap, "L8/%d/%d", p_fmt->audio.i_rate,
975 p_fmt->audio.i_channels ) == -1 )
976 id->psz_rtpmap = NULL;
977 id->pf_packetize = rtp_packetize_l8;
979 case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
980 id->i_payload_type = 14;
981 id->psz_rtpmap = strdup( "MPA/90000" );
982 id->pf_packetize = rtp_packetize_mpa;
984 case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
985 id->i_payload_type = 32;
986 id->psz_rtpmap = strdup( "MPV/90000" );
987 id->pf_packetize = rtp_packetize_mpv;
989 case VLC_FOURCC( 'a', '5', '2', ' ' ):
990 id->psz_rtpmap = strdup( "ac3/90000" );
991 id->pf_packetize = rtp_packetize_ac3;
993 case VLC_FOURCC( 'H', '2', '6', '3' ):
994 id->psz_rtpmap = strdup( "H263-1998/90000" );
995 id->pf_packetize = rtp_packetize_h263;
997 case VLC_FOURCC( 'h', '2', '6', '4' ):
998 id->psz_rtpmap = strdup( "H264/90000" );
999 id->pf_packetize = rtp_packetize_h264;
1000 id->psz_fmtp = NULL;
1002 if( p_fmt->i_extra > 0 )
1004 uint8_t *p_buffer = p_fmt->p_extra;
1005 int i_buffer = p_fmt->i_extra;
1006 char *p_64_sps = NULL;
1007 char *p_64_pps = NULL;
1010 while( i_buffer > 4 &&
1011 p_buffer[0] == 0 && p_buffer[1] == 0 &&
1012 p_buffer[2] == 0 && p_buffer[3] == 1 )
1014 const int i_nal_type = p_buffer[4]&0x1f;
1018 msg_Dbg( p_stream, "we found a startcode for NAL with TYPE:%d", i_nal_type );
1021 for( i_offset = 4; i_offset+3 < i_buffer ; i_offset++)
1023 if( !memcmp (p_buffer + i_offset, "\x00\x00\x00\x01", 4 ) )
1025 /* we found another startcode */
1030 if( i_nal_type == 7 )
1032 p_64_sps = vlc_b64_encode_binary( &p_buffer[4], i_size - 4 );
1033 sprintf_hexa( hexa, &p_buffer[5], 3 );
1035 else if( i_nal_type == 8 )
1037 p_64_pps = vlc_b64_encode_binary( &p_buffer[4], i_size - 4 );
1043 if( p_64_sps && p_64_pps &&
1044 ( asprintf( &id->psz_fmtp,
1045 "packetization-mode=1;profile-level-id=%s;"
1046 "sprop-parameter-sets=%s,%s;", hexa, p_64_sps,
1047 p_64_pps ) == -1 ) )
1048 id->psz_fmtp = NULL;
1053 id->psz_fmtp = strdup( "packetization-mode=1" );
1056 case VLC_FOURCC( 'm', 'p', '4', 'v' ):
1058 char hexa[2*p_fmt->i_extra +1];
1060 id->psz_rtpmap = strdup( "MP4V-ES/90000" );
1061 id->pf_packetize = rtp_packetize_split;
1062 if( p_fmt->i_extra > 0 )
1064 sprintf_hexa( hexa, p_fmt->p_extra, p_fmt->i_extra );
1065 if( asprintf( &id->psz_fmtp,
1066 "profile-level-id=3; config=%s;", hexa ) == -1 )
1067 id->psz_fmtp = NULL;
1071 case VLC_FOURCC( 'm', 'p', '4', 'a' ):
1075 char hexa[2*p_fmt->i_extra +1];
1077 if( asprintf( &id->psz_rtpmap, "mpeg4-generic/%d",
1078 p_fmt->audio.i_rate ) == -1 )
1079 id->psz_rtpmap = NULL;
1080 id->pf_packetize = rtp_packetize_mp4a;
1081 sprintf_hexa( hexa, p_fmt->p_extra, p_fmt->i_extra );
1082 if( asprintf( &id->psz_fmtp,
1083 "streamtype=5; profile-level-id=15; "
1084 "mode=AAC-hbr; config=%s; SizeLength=13; "
1085 "IndexLength=3; IndexDeltaLength=3; Profile=1;",
1087 id->psz_fmtp = NULL;
1093 unsigned char config[6];
1094 unsigned int aacsrates[15] = {
1095 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
1096 16000, 12000, 11025, 8000, 7350, 0, 0 };
1098 for( i = 0; i < 15; i++ )
1099 if( p_fmt->audio.i_rate == aacsrates[i] )
1105 config[3]=p_fmt->audio.i_channels<<4;
1109 if( asprintf( &id->psz_rtpmap, "MP4A-LATM/%d/%d",
1110 p_fmt->audio.i_rate,
1111 p_fmt->audio.i_channels ) == -1)
1112 id->psz_rtpmap = NULL;
1113 id->pf_packetize = rtp_packetize_mp4a_latm;
1114 sprintf_hexa( hexa, config, 6 );
1115 if( asprintf( &id->psz_fmtp, "profile-level-id=15; "
1116 "object=2; cpresent=0; config=%s", hexa ) == -1 )
1117 id->psz_fmtp = NULL;
1121 case VLC_FOURCC( 's', 'a', 'm', 'r' ):
1122 id->psz_rtpmap = strdup( p_fmt->audio.i_channels == 2 ?
1123 "AMR/8000/2" : "AMR/8000" );
1124 id->psz_fmtp = strdup( "octet-align=1" );
1125 id->pf_packetize = rtp_packetize_amr;
1127 case VLC_FOURCC( 's', 'a', 'w', 'b' ):
1128 id->psz_rtpmap = strdup( p_fmt->audio.i_channels == 2 ?
1129 "AMR-WB/16000/2" : "AMR-WB/16000" );
1130 id->psz_fmtp = strdup( "octet-align=1" );
1131 id->pf_packetize = rtp_packetize_amr;
1133 case VLC_FOURCC( 's', 'p', 'x', ' ' ):
1134 id->i_payload_type = p_sys->i_payload_type++;
1135 if( asprintf( &id->psz_rtpmap, "SPEEX/%d",
1136 p_fmt->audio.i_rate ) == -1)
1137 id->psz_rtpmap = NULL;
1138 id->pf_packetize = rtp_packetize_spx;
1140 case VLC_FOURCC( 't', '1', '4', '0' ):
1141 id->psz_rtpmap = strdup( "t140/1000" );
1142 id->i_clock_rate = 1000;
1143 id->pf_packetize = rtp_packetize_t140;
1147 msg_Err( p_stream, "cannot add this stream (unsupported "
1148 "codec:%4.4s)", (char*)&p_fmt->i_codec );
1153 cscov += 8 /* UDP */ + 12 /* RTP */;
1155 net_SetCSCov( id->sinkv[0].rtp_fd, cscov, -1 );
1157 if( id->i_payload_type == p_sys->i_payload_type )
1158 p_sys->i_payload_type++;
1160 if( p_sys->rtsp != NULL )
1161 id->rtsp_id = RtspAddId( p_sys->rtsp, id, p_sys->i_es,
1162 GetDWBE( id->ssrc ),
1163 p_sys->psz_destination,
1164 p_sys->i_ttl, id->i_port, id->i_port + 1 );
1166 id->p_fifo = block_FifoNew( p_stream );
1167 if( vlc_thread_create( id, "RTP send thread", ThreadSend,
1168 VLC_THREAD_PRIORITY_HIGHEST, VLC_FALSE ) )
1171 /* Update p_sys context */
1172 vlc_mutex_lock( &p_sys->lock_es );
1173 TAB_APPEND( p_sys->i_es, p_sys->es, id );
1174 vlc_mutex_unlock( &p_sys->lock_es );
1176 psz_sdp = SDPGenerate( p_stream, NULL );
1178 vlc_mutex_lock( &p_sys->lock_sdp );
1179 free( p_sys->psz_sdp );
1180 p_sys->psz_sdp = psz_sdp;
1181 vlc_mutex_unlock( &p_sys->lock_sdp );
1183 msg_Dbg( p_stream, "sdp=\n%s", p_sys->psz_sdp );
1185 /* Update SDP (sap/file) */
1186 if( p_sys->b_export_sap ) SapSetup( p_stream );
1187 if( p_sys->b_export_sdp_file ) FileSetup( p_stream );
1192 Del( p_stream, id );
1196 static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
1198 sout_stream_sys_t *p_sys = p_stream->p_sys;
1200 if( id->p_fifo != NULL )
1202 vlc_object_kill( id );
1203 block_FifoWake( id->p_fifo );
1204 vlc_thread_join( id );
1205 block_FifoRelease( id->p_fifo );
1208 vlc_mutex_lock( &p_sys->lock_es );
1209 TAB_REMOVE( p_sys->i_es, p_sys->es, id );
1210 vlc_mutex_unlock( &p_sys->lock_es );
1213 if( id->i_port > 0 )
1215 if( id->i_cat == AUDIO_ES && p_sys->i_port_audio == 0 )
1216 p_sys->i_port_audio = id->i_port;
1217 else if( id->i_cat == VIDEO_ES && p_sys->i_port_video == 0 )
1218 p_sys->i_port_video = id->i_port;
1221 free( id->psz_rtpmap );
1222 free( id->psz_fmtp );
1225 RtspDelId( p_sys->rtsp, id->rtsp_id );
1227 rtp_del_sink( id, id->sinkv[0].rtp_fd ); /* sink for explicit dst= */
1228 if( id->listen_fd != NULL )
1229 net_ListenClose( id->listen_fd );
1231 vlc_mutex_destroy( &id->lock_sink );
1233 /* Update SDP (sap/file) */
1234 if( p_sys->b_export_sap && !p_sys->p_mux ) SapSetup( p_stream );
1235 if( p_sys->b_export_sdp_file ) FileSetup( p_stream );
1237 vlc_object_detach( id );
1238 vlc_object_destroy( id );
1242 static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
1247 assert( p_stream->p_sys->p_mux == NULL );
1249 while( p_buffer != NULL )
1251 p_next = p_buffer->p_next;
1252 if( id->pf_packetize( p_stream, id, p_buffer ) )
1255 block_Release( p_buffer );
1261 /****************************************************************************
1263 ****************************************************************************/
1264 static int SapSetup( sout_stream_t *p_stream )
1266 sout_stream_sys_t *p_sys = p_stream->p_sys;
1267 sout_instance_t *p_sout = p_stream->p_sout;
1269 /* Remove the previous session */
1270 if( p_sys->p_session != NULL)
1272 sout_AnnounceUnRegister( p_sout, p_sys->p_session);
1273 p_sys->p_session = NULL;
1276 if( ( p_sys->i_es > 0 || p_sys->p_mux ) && p_sys->psz_sdp && *p_sys->psz_sdp )
1278 announce_method_t *p_method = sout_SAPMethod();
1279 p_sys->p_session = sout_AnnounceRegisterSDP( p_sout, SOUT_CFG_PREFIX,
1281 p_sys->psz_destination,
1283 sout_MethodRelease( p_method );
1289 /****************************************************************************
1291 ****************************************************************************/
1292 static int FileSetup( sout_stream_t *p_stream )
1294 sout_stream_sys_t *p_sys = p_stream->p_sys;
1297 if( ( f = utf8_fopen( p_sys->psz_sdp_file, "wt" ) ) == NULL )
1299 msg_Err( p_stream, "cannot open file '%s' (%m)",
1300 p_sys->psz_sdp_file );
1301 return VLC_EGENERIC;
1304 fputs( p_sys->psz_sdp, f );
1310 /****************************************************************************
1312 ****************************************************************************/
1313 static int HttpCallback( httpd_file_sys_t *p_args,
1314 httpd_file_t *, uint8_t *p_request,
1315 uint8_t **pp_data, int *pi_data );
1317 static int HttpSetup( sout_stream_t *p_stream, vlc_url_t *url)
1319 sout_stream_sys_t *p_sys = p_stream->p_sys;
1321 p_sys->p_httpd_host = httpd_HostNew( VLC_OBJECT(p_stream), url->psz_host,
1322 url->i_port > 0 ? url->i_port : 80 );
1323 if( p_sys->p_httpd_host )
1325 p_sys->p_httpd_file = httpd_FileNew( p_sys->p_httpd_host,
1326 url->psz_path ? url->psz_path : "/",
1329 HttpCallback, (void*)p_sys );
1331 if( p_sys->p_httpd_file == NULL )
1333 return VLC_EGENERIC;
1338 static int HttpCallback( httpd_file_sys_t *p_args,
1339 httpd_file_t *f, uint8_t *p_request,
1340 uint8_t **pp_data, int *pi_data )
1342 sout_stream_sys_t *p_sys = (sout_stream_sys_t*)p_args;
1344 vlc_mutex_lock( &p_sys->lock_sdp );
1345 if( p_sys->psz_sdp && *p_sys->psz_sdp )
1347 *pi_data = strlen( p_sys->psz_sdp );
1348 *pp_data = malloc( *pi_data );
1349 memcpy( *pp_data, p_sys->psz_sdp, *pi_data );
1356 vlc_mutex_unlock( &p_sys->lock_sdp );
1361 /****************************************************************************
1363 ****************************************************************************/
1364 static void ThreadSend( vlc_object_t *p_this )
1366 sout_stream_id_t *id = (sout_stream_id_t *)p_this;
1367 unsigned i_caching = id->i_caching;
1369 int fd[5] = { -1, -1, -1, -1, -1 };
1377 fd[4] = open( "/dev/null", O_WRONLY );
1382 block_t *out = block_FifoGet( id->p_fifo );
1384 continue; /* Forced wakeup */
1386 mtime_t i_date = out->i_dts + i_caching;
1387 ssize_t len = out->i_buffer;
1391 len = write( fd[1], out->p_buffer, len);
1393 continue; /* Uho - should not happen */
1397 vlc_mutex_lock( &id->lock_sink );
1398 unsigned deadc = 0; /* How many dead sockets? */
1399 int deadv[id->sinkc]; /* Dead sockets list */
1401 for( int i = 0; i < id->sinkc; i++ )
1403 SendRTCP( id->sinkv[i].rtcp, out );
1406 tee( fd[0], fd[3], len, 0 );
1407 if( splice( fd[2], NULL, id->sinkv[i].rtp_fd, NULL, len,
1408 SPLICE_F_NONBLOCK ) >= 0 )
1410 if( errno == EAGAIN )
1414 splice( fd[2], NULL, fd[4], NULL, len, 0 );
1416 if( send( id->sinkv[i].rtp_fd, out->p_buffer, len, 0 ) >= 0 )
1419 /* Retry sending to root out soft-errors */
1420 if( send( id->sinkv[i].rtp_fd, out->p_buffer, len, 0 ) >= 0 )
1423 deadv[deadc++] = id->sinkv[i].rtp_fd;
1425 vlc_mutex_unlock( &id->lock_sink );
1427 block_Release( out );
1429 splice( fd[0], NULL, fd[4], NULL, len, 0 );
1432 for( unsigned i = 0; i < deadc; i++ )
1434 msg_Dbg( id, "removing socket %d", deadv[i] );
1435 rtp_del_sink( id, deadv[i] );
1438 /* Hopefully we won't overflow the SO_MAXCONN accept queue */
1439 while( id->listen_fd != NULL )
1441 int fd = net_Accept( id, id->listen_fd, 0 );
1444 msg_Dbg( id, "adding socket %d", fd );
1445 rtp_add_sink( id, fd, VLC_TRUE );
1450 for( unsigned i = 0; i < 5; i++ )
1455 static inline void rtp_packetize_send( sout_stream_id_t *id, block_t *out )
1457 block_FifoPut( id->p_fifo, out );
1460 int rtp_add_sink( sout_stream_id_t *id, int fd, vlc_bool_t rtcp_mux )
1462 rtp_sink_t sink = { fd, NULL };
1463 sink.rtcp = OpenRTCP( VLC_OBJECT( id->p_stream ), fd, IPPROTO_UDP,
1465 if( sink.rtcp == NULL )
1466 msg_Err( id, "RTCP failed!" );
1468 vlc_mutex_lock( &id->lock_sink );
1469 INSERT_ELEM( id->sinkv, id->sinkc, id->sinkc, sink );
1470 vlc_mutex_unlock( &id->lock_sink );
1474 void rtp_del_sink( sout_stream_id_t *id, int fd )
1476 rtp_sink_t sink = { fd, NULL };
1478 /* NOTE: must be safe to use if fd is not included */
1479 vlc_mutex_lock( &id->lock_sink );
1480 for( int i = 0; i < id->sinkc; i++ )
1482 if (id->sinkv[i].rtp_fd == fd)
1484 sink = id->sinkv[i];
1485 REMOVE_ELEM( id->sinkv, id->sinkc, i );
1489 vlc_mutex_unlock( &id->lock_sink );
1491 CloseRTCP( sink.rtcp );
1492 net_Close( sink.rtp_fd );
1495 uint16_t rtp_get_seq( const sout_stream_id_t *id )
1497 /* This will return values for the next packet.
1498 * Accounting for caching would not be totally trivial. */
1499 return id->i_sequence;
1502 /* FIXME: this is pretty bad - if we remove and then insert an ES
1503 * the number will get unsynched from inside RTSP */
1504 unsigned rtp_get_num( const sout_stream_id_t *id )
1506 sout_stream_sys_t *p_sys = id->p_stream->p_sys;
1509 vlc_mutex_lock( &p_sys->lock_es );
1510 for( i = 0; i < p_sys->i_es; i++ )
1512 if( id == p_sys->es[i] )
1515 vlc_mutex_unlock( &p_sys->lock_es );
1521 /****************************************************************************
1523 ****************************************************************************/
1524 static void rtp_packetize_common( sout_stream_id_t *id, block_t *out,
1525 int b_marker, int64_t i_pts )
1527 uint32_t i_timestamp = i_pts * (int64_t)id->i_clock_rate / I64C(1000000);
1529 out->p_buffer[0] = 0x80;
1530 out->p_buffer[1] = (b_marker?0x80:0x00)|id->i_payload_type;
1531 out->p_buffer[2] = ( id->i_sequence >> 8)&0xff;
1532 out->p_buffer[3] = ( id->i_sequence )&0xff;
1533 out->p_buffer[4] = ( i_timestamp >> 24 )&0xff;
1534 out->p_buffer[5] = ( i_timestamp >> 16 )&0xff;
1535 out->p_buffer[6] = ( i_timestamp >> 8 )&0xff;
1536 out->p_buffer[7] = ( i_timestamp )&0xff;
1538 memcpy( out->p_buffer + 8, id->ssrc, 4 );
1544 static int rtp_packetize_mpa( sout_stream_t *p_stream, sout_stream_id_t *id,
1547 int i_max = id->i_mtu - 12 - 4; /* payload max in one packet */
1548 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1550 uint8_t *p_data = in->p_buffer;
1551 int i_data = in->i_buffer;
1554 for( i = 0; i < i_count; i++ )
1556 int i_payload = __MIN( i_max, i_data );
1557 block_t *out = block_New( p_stream, 16 + i_payload );
1559 /* rtp common header */
1560 rtp_packetize_common( id, out, (i == i_count - 1)?1:0, in->i_pts );
1562 out->p_buffer[12] = 0;
1563 out->p_buffer[13] = 0;
1564 /* fragment offset in the current frame */
1565 out->p_buffer[14] = ( (i*i_max) >> 8 )&0xff;
1566 out->p_buffer[15] = ( (i*i_max) )&0xff;
1567 memcpy( &out->p_buffer[16], p_data, i_payload );
1569 out->i_buffer = 16 + i_payload;
1570 out->i_dts = in->i_dts + i * in->i_length / i_count;
1571 out->i_length = in->i_length / i_count;
1573 rtp_packetize_send( id, out );
1575 p_data += i_payload;
1576 i_data -= i_payload;
1583 static int rtp_packetize_mpv( sout_stream_t *p_stream, sout_stream_id_t *id,
1586 int i_max = id->i_mtu - 12 - 4; /* payload max in one packet */
1587 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1589 uint8_t *p_data = in->p_buffer;
1590 int i_data = in->i_buffer;
1592 int b_sequence_start = 0;
1593 int i_temporal_ref = 0;
1594 int i_picture_coding_type = 0;
1595 int i_fbv = 0, i_bfc = 0, i_ffv = 0, i_ffc = 0;
1596 int b_start_slice = 0;
1598 /* preparse this packet to get some info */
1599 if( in->i_buffer > 4 )
1601 uint8_t *p = p_data;
1602 int i_rest = in->i_buffer;
1606 while( i_rest > 4 &&
1607 ( p[0] != 0x00 || p[1] != 0x00 || p[2] != 0x01 ) )
1621 /* sequence start code */
1622 b_sequence_start = 1;
1624 else if( *p == 0x00 && i_rest >= 4 )
1627 i_temporal_ref = ( p[1] << 2) |((p[2]>>6)&0x03);
1628 i_picture_coding_type = (p[2] >> 3)&0x07;
1630 if( i_rest >= 4 && ( i_picture_coding_type == 2 ||
1631 i_picture_coding_type == 3 ) )
1633 i_ffv = (p[3] >> 2)&0x01;
1634 i_ffc = ((p[3]&0x03) << 1)|((p[4]>>7)&0x01);
1635 if( i_rest > 4 && i_picture_coding_type == 3 )
1637 i_fbv = (p[4]>>6)&0x01;
1638 i_bfc = (p[4]>>3)&0x07;
1642 else if( *p <= 0xaf )
1649 for( i = 0; i < i_count; i++ )
1651 int i_payload = __MIN( i_max, i_data );
1652 block_t *out = block_New( p_stream,
1654 uint32_t h = ( i_temporal_ref << 16 )|
1655 ( b_sequence_start << 13 )|
1656 ( b_start_slice << 12 )|
1657 ( i == i_count - 1 ? 1 << 11 : 0 )|
1658 ( i_picture_coding_type << 8 )|
1659 ( i_fbv << 7 )|( i_bfc << 4 )|( i_ffv << 3 )|i_ffc;
1661 /* rtp common header */
1662 rtp_packetize_common( id, out, (i == i_count - 1)?1:0,
1663 in->i_pts > 0 ? in->i_pts : in->i_dts );
1665 /* 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 */
1666 out->p_buffer[12] = ( h >> 24 )&0xff;
1667 out->p_buffer[13] = ( h >> 16 )&0xff;
1668 out->p_buffer[14] = ( h >> 8 )&0xff;
1669 out->p_buffer[15] = ( h )&0xff;
1671 memcpy( &out->p_buffer[16], p_data, i_payload );
1673 out->i_buffer = 16 + i_payload;
1674 out->i_dts = in->i_dts + i * in->i_length / i_count;
1675 out->i_length = in->i_length / i_count;
1677 rtp_packetize_send( id, out );
1679 p_data += i_payload;
1680 i_data -= i_payload;
1686 static int rtp_packetize_ac3( sout_stream_t *p_stream, sout_stream_id_t *id,
1689 int i_max = id->i_mtu - 12 - 2; /* payload max in one packet */
1690 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1692 uint8_t *p_data = in->p_buffer;
1693 int i_data = in->i_buffer;
1696 for( i = 0; i < i_count; i++ )
1698 int i_payload = __MIN( i_max, i_data );
1699 block_t *out = block_New( p_stream, 14 + i_payload );
1701 /* rtp common header */
1702 rtp_packetize_common( id, out, (i == i_count - 1)?1:0, in->i_pts );
1704 out->p_buffer[12] = 1;
1706 out->p_buffer[13] = 0x00;
1708 memcpy( &out->p_buffer[14], p_data, i_payload );
1710 out->i_buffer = 14 + i_payload;
1711 out->i_dts = in->i_dts + i * in->i_length / i_count;
1712 out->i_length = in->i_length / i_count;
1714 rtp_packetize_send( id, out );
1716 p_data += i_payload;
1717 i_data -= i_payload;
1723 static int rtp_packetize_split( sout_stream_t *p_stream, sout_stream_id_t *id,
1726 int i_max = id->i_mtu - 12; /* payload max in one packet */
1727 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1729 uint8_t *p_data = in->p_buffer;
1730 int i_data = in->i_buffer;
1733 for( i = 0; i < i_count; i++ )
1735 int i_payload = __MIN( i_max, i_data );
1736 block_t *out = block_New( p_stream, 12 + i_payload );
1738 /* rtp common header */
1739 rtp_packetize_common( id, out, ((i == i_count - 1)?1:0),
1740 (in->i_pts > 0 ? in->i_pts : in->i_dts) );
1741 memcpy( &out->p_buffer[12], p_data, i_payload );
1743 out->i_buffer = 12 + i_payload;
1744 out->i_dts = in->i_dts + i * in->i_length / i_count;
1745 out->i_length = in->i_length / i_count;
1747 rtp_packetize_send( id, out );
1749 p_data += i_payload;
1750 i_data -= i_payload;
1757 static int rtp_packetize_mp4a_latm( sout_stream_t *p_stream, sout_stream_id_t *id,
1760 int i_max = id->i_mtu - 14; /* payload max in one packet */
1761 int latmhdrsize = in->i_buffer / 0xff + 1;
1762 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1764 uint8_t *p_data = in->p_buffer, *p_header = NULL;
1765 int i_data = in->i_buffer;
1768 for( i = 0; i < i_count; i++ )
1770 int i_payload = __MIN( i_max, i_data );
1775 out = block_New( p_stream, 12 + latmhdrsize + i_payload );
1777 /* rtp common header */
1778 rtp_packetize_common( id, out, ((i == i_count - 1) ? 1 : 0),
1779 (in->i_pts > 0 ? in->i_pts : in->i_dts) );
1783 int tmp = in->i_buffer;
1785 p_header=out->p_buffer+12;
1795 memcpy( &out->p_buffer[12+latmhdrsize], p_data, i_payload );
1797 out->i_buffer = 12 + latmhdrsize + i_payload;
1798 out->i_dts = in->i_dts + i * in->i_length / i_count;
1799 out->i_length = in->i_length / i_count;
1801 rtp_packetize_send( id, out );
1803 p_data += i_payload;
1804 i_data -= i_payload;
1810 static int rtp_packetize_l16( sout_stream_t *p_stream, sout_stream_id_t *id,
1813 int i_max = id->i_mtu - 12; /* payload max in one packet */
1814 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1816 uint8_t *p_data = in->p_buffer;
1817 int i_data = in->i_buffer;
1822 int i_payload = (__MIN( i_max, i_data )/4)*4;
1823 block_t *out = block_New( p_stream, 12 + i_payload );
1825 /* rtp common header */
1826 rtp_packetize_common( id, out, 0,
1827 (in->i_pts > 0 ? in->i_pts : in->i_dts) );
1828 memcpy( &out->p_buffer[12], p_data, i_payload );
1830 out->i_buffer = 12 + i_payload;
1831 out->i_dts = in->i_dts + i_packet * in->i_length / i_count;
1832 out->i_length = in->i_length / i_count;
1834 rtp_packetize_send( id, out );
1836 p_data += i_payload;
1837 i_data -= i_payload;
1844 static int rtp_packetize_l8( sout_stream_t *p_stream, sout_stream_id_t *id,
1847 int i_max = id->i_mtu - 12; /* payload max in one packet */
1848 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1850 uint8_t *p_data = in->p_buffer;
1851 int i_data = in->i_buffer;
1856 int i_payload = (__MIN( i_max, i_data )/2)*2;
1857 block_t *out = block_New( p_stream, 12 + i_payload );
1859 /* rtp common header */
1860 rtp_packetize_common( id, out, 0,
1861 (in->i_pts > 0 ? in->i_pts : in->i_dts) );
1862 memcpy( &out->p_buffer[12], p_data, i_payload );
1864 out->i_buffer = 12 + i_payload;
1865 out->i_dts = in->i_dts + i_packet * in->i_length / i_count;
1866 out->i_length = in->i_length / i_count;
1868 rtp_packetize_send( id, out );
1870 p_data += i_payload;
1871 i_data -= i_payload;
1878 static int rtp_packetize_mp4a( sout_stream_t *p_stream, sout_stream_id_t *id,
1881 int i_max = id->i_mtu - 16; /* payload max in one packet */
1882 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1884 uint8_t *p_data = in->p_buffer;
1885 int i_data = in->i_buffer;
1888 for( i = 0; i < i_count; i++ )
1890 int i_payload = __MIN( i_max, i_data );
1891 block_t *out = block_New( p_stream, 16 + i_payload );
1893 /* rtp common header */
1894 rtp_packetize_common( id, out, ((i == i_count - 1)?1:0),
1895 (in->i_pts > 0 ? in->i_pts : in->i_dts) );
1897 /* AU headers length (bits) */
1898 out->p_buffer[12] = 0;
1899 out->p_buffer[13] = 2*8;
1900 /* for each AU length 13 bits + idx 3bits, */
1901 out->p_buffer[14] = ( in->i_buffer >> 5 )&0xff;
1902 out->p_buffer[15] = ( (in->i_buffer&0xff)<<3 )|0;
1904 memcpy( &out->p_buffer[16], p_data, i_payload );
1906 out->i_buffer = 16 + i_payload;
1907 out->i_dts = in->i_dts + i * in->i_length / i_count;
1908 out->i_length = in->i_length / i_count;
1910 rtp_packetize_send( id, out );
1912 p_data += i_payload;
1913 i_data -= i_payload;
1921 #define RTP_H263_HEADER_SIZE (2) // plen = 0
1922 #define RTP_H263_PAYLOAD_START (14) // plen = 0
1923 static int rtp_packetize_h263( sout_stream_t *p_stream, sout_stream_id_t *id,
1926 uint8_t *p_data = in->p_buffer;
1927 int i_data = in->i_buffer;
1929 int i_max = id->i_mtu - 12 - RTP_H263_HEADER_SIZE; /* payload max in one packet */
1932 int b_v_bit = 0; // no pesky error resilience
1933 int i_plen = 0; // normally plen=0 for PSC packet
1934 int i_pebit = 0; // because plen=0
1939 return VLC_EGENERIC;
1941 if( p_data[0] || p_data[1] )
1943 return VLC_EGENERIC;
1945 /* remove 2 leading 0 bytes */
1948 i_count = ( i_data + i_max - 1 ) / i_max;
1950 for( i = 0; i < i_count; i++ )
1952 int i_payload = __MIN( i_max, i_data );
1953 block_t *out = block_New( p_stream,
1954 RTP_H263_PAYLOAD_START + i_payload );
1955 b_p_bit = (i == 0) ? 1 : 0;
1956 h = ( b_p_bit << 10 )|
1961 /* rtp common header */
1962 //b_m_bit = 1; // always contains end of frame
1963 rtp_packetize_common( id, out, (i == i_count - 1)?1:0,
1964 in->i_pts > 0 ? in->i_pts : in->i_dts );
1967 out->p_buffer[12] = ( h >> 8 )&0xff;
1968 out->p_buffer[13] = ( h )&0xff;
1969 memcpy( &out->p_buffer[RTP_H263_PAYLOAD_START], p_data, i_payload );
1971 out->i_buffer = RTP_H263_PAYLOAD_START + i_payload;
1972 out->i_dts = in->i_dts + i * in->i_length / i_count;
1973 out->i_length = in->i_length / i_count;
1975 rtp_packetize_send( id, out );
1977 p_data += i_payload;
1978 i_data -= i_payload;
1986 rtp_packetize_h264_nal( sout_stream_t *p_stream, sout_stream_id_t *id,
1987 const uint8_t *p_data, int i_data, int64_t i_pts,
1988 int64_t i_dts, vlc_bool_t b_last, int64_t i_length )
1990 const int i_max = id->i_mtu - 12; /* payload max in one packet */
1997 i_nal_hdr = p_data[3];
1998 i_nal_type = i_nal_hdr&0x1f;
2000 /* Skip start code */
2005 if( i_data <= i_max )
2007 /* Single NAL unit packet */
2008 block_t *out = block_New( p_stream, 12 + i_data );
2010 out->i_length = i_length;
2013 rtp_packetize_common( id, out, b_last, i_pts );
2014 out->i_buffer = 12 + i_data;
2016 memcpy( &out->p_buffer[12], p_data, i_data );
2018 rtp_packetize_send( id, out );
2022 /* FU-A Fragmentation Unit without interleaving */
2023 const int i_count = ( i_data-1 + i_max-2 - 1 ) / (i_max-2);
2029 for( i = 0; i < i_count; i++ )
2031 const int i_payload = __MIN( i_data, i_max-2 );
2032 block_t *out = block_New( p_stream, 12 + 2 + i_payload );
2033 out->i_dts = i_dts + i * i_length / i_count;
2034 out->i_length = i_length / i_count;
2037 rtp_packetize_common( id, out, (b_last && i_payload == i_data), i_pts );
2038 out->i_buffer = 14 + i_payload;
2041 out->p_buffer[12] = 0x00 | (i_nal_hdr & 0x60) | 28;
2043 out->p_buffer[13] = ( i == 0 ? 0x80 : 0x00 ) | ( (i == i_count-1) ? 0x40 : 0x00 ) | i_nal_type;
2044 memcpy( &out->p_buffer[14], p_data, i_payload );
2046 rtp_packetize_send( id, out );
2048 i_data -= i_payload;
2049 p_data += i_payload;
2055 static int rtp_packetize_h264( sout_stream_t *p_stream, sout_stream_id_t *id,
2058 const uint8_t *p_buffer = in->p_buffer;
2059 int i_buffer = in->i_buffer;
2061 while( i_buffer > 4 && ( p_buffer[0] != 0 || p_buffer[1] != 0 || p_buffer[2] != 1 ) )
2067 /* Split nal units */
2068 while( i_buffer > 4 )
2071 int i_size = i_buffer;
2072 int i_skip = i_buffer;
2074 /* search nal end */
2075 for( i_offset = 4; i_offset+2 < i_buffer ; i_offset++)
2077 if( p_buffer[i_offset] == 0 && p_buffer[i_offset+1] == 0 && p_buffer[i_offset+2] == 1 )
2079 /* we found another startcode */
2080 i_size = i_offset - ( p_buffer[i_offset-1] == 0 ? 1 : 0);
2085 /* TODO add STAP-A to remove a lot of overhead with small slice/sei/... */
2086 rtp_packetize_h264_nal( p_stream, id, p_buffer, i_size,
2087 (in->i_pts > 0 ? in->i_pts : in->i_dts), in->i_dts,
2088 (i_size >= i_buffer), in->i_length * i_size / in->i_buffer );
2096 static int rtp_packetize_amr( sout_stream_t *p_stream, sout_stream_id_t *id,
2099 int i_max = id->i_mtu - 14; /* payload max in one packet */
2100 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
2102 uint8_t *p_data = in->p_buffer;
2103 int i_data = in->i_buffer;
2106 /* Only supports octet-aligned mode */
2107 for( i = 0; i < i_count; i++ )
2109 int i_payload = __MIN( i_max, i_data );
2110 block_t *out = block_New( p_stream, 14 + i_payload );
2112 /* rtp common header */
2113 rtp_packetize_common( id, out, ((i == i_count - 1)?1:0),
2114 (in->i_pts > 0 ? in->i_pts : in->i_dts) );
2115 /* Payload header */
2116 out->p_buffer[12] = 0xF0; /* CMR */
2117 out->p_buffer[13] = p_data[0]&0x7C; /* ToC */ /* FIXME: frame type */
2119 /* FIXME: are we fed multiple frames ? */
2120 memcpy( &out->p_buffer[14], p_data+1, i_payload-1 );
2122 out->i_buffer = 14 + i_payload-1;
2123 out->i_dts = in->i_dts + i * in->i_length / i_count;
2124 out->i_length = in->i_length / i_count;
2126 rtp_packetize_send( id, out );
2128 p_data += i_payload;
2129 i_data -= i_payload;
2135 static int rtp_packetize_t140( sout_stream_t *p_stream, sout_stream_id_t *id,
2138 const size_t i_max = id->i_mtu - 12;
2139 const uint8_t *p_data = in->p_buffer;
2140 size_t i_data = in->i_buffer;
2142 for( unsigned i_packet = 0; i_data > 0; i_packet++ )
2144 size_t i_payload = i_data;
2146 /* Make sure we stop on an UTF-8 character boundary
2147 * (assuming the input is valid UTF-8) */
2148 if( i_data > i_max )
2152 while( ( p_data[i_payload] & 0xC0 ) == 0x80 )
2154 if( i_payload == 0 )
2155 return VLC_SUCCESS; /* fishy input! */
2161 block_t *out = block_New( p_stream, 12 + i_payload );
2165 rtp_packetize_common( id, out, 0, in->i_pts + i_packet );
2166 memcpy( out->p_buffer + 12, p_data, i_payload );
2168 out->i_buffer = 12 + i_payload;
2169 out->i_dts = out->i_pts;
2172 rtp_packetize_send( id, out );
2174 p_data += i_payload;
2175 i_data -= i_payload;
2181 /*****************************************************************************
2183 *****************************************************************************/
2185 /** Add an ES to a non-RTP muxed stream */
2186 static sout_stream_id_t *MuxAdd( sout_stream_t *p_stream, es_format_t *p_fmt )
2188 sout_input_t *p_input;
2189 sout_mux_t *p_mux = p_stream->p_sys->p_mux;
2190 assert( p_mux != NULL );
2192 p_input = sout_MuxAddStream( p_mux, p_fmt );
2193 if( p_input == NULL )
2195 msg_Err( p_stream, "cannot add this stream to the muxer" );
2199 return (sout_stream_id_t *)p_input;
2203 static int MuxSend( sout_stream_t *p_stream, sout_stream_id_t *id,
2206 sout_mux_t *p_mux = p_stream->p_sys->p_mux;
2207 assert( p_mux != NULL );
2209 sout_MuxSendBuffer( p_mux, (sout_input_t *)id, p_buffer );
2214 /** Remove an ES from a non-RTP muxed stream */
2215 static int MuxDel( sout_stream_t *p_stream, sout_stream_id_t *id )
2217 sout_mux_t *p_mux = p_stream->p_sys->p_mux;
2218 assert( p_mux != NULL );
2220 sout_MuxDeleteStream( p_mux, (sout_input_t *)id );
2225 static int AccessOutGrabberWriteBuffer( sout_stream_t *p_stream,
2226 const block_t *p_buffer )
2228 sout_stream_sys_t *p_sys = p_stream->p_sys;
2229 sout_stream_id_t *id = p_sys->es[0];
2231 int64_t i_dts = p_buffer->i_dts;
2233 uint8_t *p_data = p_buffer->p_buffer;
2234 unsigned int i_data = p_buffer->i_buffer;
2235 unsigned int i_max = id->i_mtu - 12;
2237 unsigned i_packet = ( p_buffer->i_buffer + i_max - 1 ) / i_max;
2241 unsigned int i_size;
2243 /* output complete packet */
2244 if( p_sys->packet &&
2245 p_sys->packet->i_buffer + i_data > i_max )
2247 rtp_packetize_send( id, p_sys->packet );
2248 p_sys->packet = NULL;
2251 if( p_sys->packet == NULL )
2253 /* allocate a new packet */
2254 p_sys->packet = block_New( p_stream, id->i_mtu );
2255 rtp_packetize_common( id, p_sys->packet, 1, i_dts );
2256 p_sys->packet->i_dts = i_dts;
2257 p_sys->packet->i_length = p_buffer->i_length / i_packet;
2258 i_dts += p_sys->packet->i_length;
2261 i_size = __MIN( i_data,
2262 (unsigned)(id->i_mtu - p_sys->packet->i_buffer) );
2264 memcpy( &p_sys->packet->p_buffer[p_sys->packet->i_buffer],
2267 p_sys->packet->i_buffer += i_size;
2276 static int AccessOutGrabberWrite( sout_access_out_t *p_access,
2279 sout_stream_t *p_stream = (sout_stream_t*)p_access->p_sys;
2285 AccessOutGrabberWriteBuffer( p_stream, p_buffer );
2287 p_next = p_buffer->p_next;
2288 block_Release( p_buffer );
2296 static sout_access_out_t *GrabberCreate( sout_stream_t *p_stream )
2298 sout_access_out_t *p_grab;
2300 p_grab = vlc_object_create( p_stream->p_sout, sizeof( *p_grab ) );
2301 if( p_grab == NULL )
2304 p_grab->p_module = NULL;
2305 p_grab->p_sout = p_stream->p_sout;
2306 p_grab->psz_access = strdup( "grab" );
2307 p_grab->p_cfg = NULL;
2308 p_grab->psz_path = strdup( "" );
2309 p_grab->p_sys = (sout_access_out_sys_t *)p_stream;
2310 p_grab->pf_seek = NULL;
2311 p_grab->pf_write = AccessOutGrabberWrite;
2315 static int rtp_packetize_spx( sout_stream_t *p_stream, sout_stream_id_t *id,
2318 uint8_t *p_buffer = in->p_buffer;
2319 int i_data_size, i_payload_size, i_payload_padding;
2320 i_data_size = i_payload_size = in->i_buffer;
2321 i_payload_padding = 0;
2324 if ( in->i_buffer + 12 > id->i_mtu )
2326 msg_Warn( p_stream, "Cannot send packet larger than output MTU" );
2331 RFC for Speex in RTP says that each packet must end on an octet
2332 boundary. So, we check to see if the number of bytes % 4 is zero.
2333 If not, we have to add some padding.
2335 This MAY be overkill since packetization is handled elsewhere and
2336 appears to ensure the octet boundary. However, better safe than
2339 if ( i_payload_size % 4 )
2341 i_payload_padding = 4 - ( i_payload_size % 4 );
2342 i_payload_size += i_payload_padding;
2346 Allocate a new RTP p_output block of the appropriate size.
2347 Allow for 12 extra bytes of RTP header.
2349 p_out = block_New( p_stream, 12 + i_payload_size );
2351 if ( i_payload_padding )
2354 The padding is required to be a zero followed by all 1s.
2356 char c_first_pad, c_remaining_pad;
2358 c_remaining_pad = 0xFF;
2361 Allow for 12 bytes before the i_data_size because
2362 of the expected RTP header added during
2363 rtp_packetize_common.
2365 p_out->p_buffer[12 + i_data_size] = c_first_pad;
2366 switch (i_payload_padding)
2369 p_out->p_buffer[12 + i_data_size + 1] = c_remaining_pad;
2372 p_out->p_buffer[12 + i_data_size + 1] = c_remaining_pad;
2373 p_out->p_buffer[12 + i_data_size + 2] = c_remaining_pad;
2378 /* Add the RTP header to our p_output buffer. */
2379 rtp_packetize_common( id, p_out, 0, (in->i_pts > 0 ? in->i_pts : in->i_dts) );
2380 /* Copy the Speex payload to the p_output buffer */
2381 memcpy( &p_out->p_buffer[12], p_buffer, i_data_size );
2383 p_out->i_buffer = 12 + i_payload_size;
2384 p_out->i_dts = in->i_dts;
2385 p_out->i_length = in->i_length;
2387 /* Queue the buffer for actual transmission. */
2388 rtp_packetize_send( id, p_out );