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;
292 /* Packetizer specific fields */
293 pf_rtp_packetizer_t pf_packetize;
297 vlc_mutex_t lock_sink;
300 rtsp_stream_id_t *rtsp_id;
303 block_fifo_t *p_fifo;
308 /*****************************************************************************
310 *****************************************************************************/
311 static int Open( vlc_object_t *p_this )
313 sout_stream_t *p_stream = (sout_stream_t*)p_this;
314 sout_instance_t *p_sout = p_stream->p_sout;
315 sout_stream_sys_t *p_sys = NULL;
316 config_chain_t *p_cfg = NULL;
318 vlc_bool_t b_rtsp = VLC_FALSE;
320 config_ChainParse( p_stream, SOUT_CFG_PREFIX,
321 ppsz_sout_options, p_stream->p_cfg );
323 p_sys = malloc( sizeof( sout_stream_sys_t ) );
327 p_sys->psz_destination = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "dst" );
329 p_sys->i_port = var_GetInteger( p_stream, SOUT_CFG_PREFIX "port" );
330 p_sys->i_port_audio = var_GetInteger( p_stream, SOUT_CFG_PREFIX "port-audio" );
331 p_sys->i_port_video = var_GetInteger( p_stream, SOUT_CFG_PREFIX "port-video" );
332 p_sys->rtcp_mux = var_GetBool( p_stream, SOUT_CFG_PREFIX "rtcp-mux" );
334 p_sys->psz_sdp_file = NULL;
336 if( p_sys->i_port_audio == p_sys->i_port_video )
338 msg_Err( p_stream, "audio and video port cannot be the same" );
339 p_sys->i_port_audio = 0;
340 p_sys->i_port_video = 0;
343 for( p_cfg = p_stream->p_cfg; p_cfg != NULL; p_cfg = p_cfg->p_next )
345 if( !strcmp( p_cfg->psz_name, "sdp" )
346 && ( p_cfg->psz_value != NULL )
347 && !strncasecmp( p_cfg->psz_value, "rtsp:", 5 ) )
355 psz = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "sdp" );
358 if( !strncasecmp( psz, "rtsp:", 5 ) )
364 /* Transport protocol */
365 p_sys->proto = IPPROTO_UDP;
367 if( var_GetBool( p_stream, SOUT_CFG_PREFIX "dccp" ) )
369 p_sys->proto = IPPROTO_DCCP;
370 p_sys->rtcp_mux = VLC_TRUE; /* Force RTP/RTCP mux */
374 if( var_GetBool( p_stream, SOUT_CFG_PREFIX "tcp" ) )
376 p_sys->proto = IPPROTO_TCP;
377 p_sys->rtcp_mux = VLC_TRUE; /* Force RTP/RTCP mux */
381 if( var_GetBool( p_stream, SOUT_CFG_PREFIX "udplite" ) )
382 p_sys->proto = IPPROTO_UDPLITE;
384 if( ( p_sys->psz_destination == NULL ) && !b_rtsp )
386 msg_Err( p_stream, "missing destination and not in RTSP mode" );
391 p_sys->i_ttl = var_GetInteger( p_stream, SOUT_CFG_PREFIX "ttl" );
392 if( p_sys->i_ttl == 0 )
394 /* Normally, we should let the default hop limit up to the core,
395 * but we have to know it to build our SDP properly, which is why
396 * we ask the core. FIXME: broken when neither sout-rtp-ttl nor
398 p_sys->i_ttl = config_GetInt( p_stream, "ttl" );
401 p_sys->b_latm = var_GetBool( p_stream, SOUT_CFG_PREFIX "mp4a-latm" );
403 p_sys->i_payload_type = 96;
407 p_sys->psz_sdp = NULL;
409 p_sys->b_export_sap = VLC_FALSE;
410 p_sys->b_export_sdp_file = VLC_FALSE;
411 p_sys->p_session = NULL;
413 p_sys->p_httpd_host = NULL;
414 p_sys->p_httpd_file = NULL;
416 p_stream->p_sys = p_sys;
418 vlc_mutex_init( p_stream, &p_sys->lock_sdp );
419 vlc_mutex_init( p_stream, &p_sys->lock_es );
421 psz = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "mux" );
424 sout_stream_id_t *id;
426 /* Check muxer type */
427 if( strncasecmp( psz, "ps", 2 )
428 && strncasecmp( psz, "mpeg1", 5 )
429 && strncasecmp( psz, "ts", 2 ) )
431 msg_Err( p_stream, "unsupported muxer type for RTP (only TS/PS)" );
433 vlc_mutex_destroy( &p_sys->lock_sdp );
434 vlc_mutex_destroy( &p_sys->lock_es );
439 p_sys->p_grab = GrabberCreate( p_stream );
440 p_sys->p_mux = sout_MuxNew( p_sout, psz, p_sys->p_grab );
443 if( p_sys->p_mux == NULL )
445 msg_Err( p_stream, "cannot create muxer" );
446 sout_AccessOutDelete( p_sys->p_grab );
447 vlc_mutex_destroy( &p_sys->lock_sdp );
448 vlc_mutex_destroy( &p_sys->lock_es );
453 id = Add( p_stream, NULL );
456 sout_MuxDelete( p_sys->p_mux );
457 sout_AccessOutDelete( p_sys->p_grab );
458 vlc_mutex_destroy( &p_sys->lock_sdp );
459 vlc_mutex_destroy( &p_sys->lock_es );
464 p_sys->packet = NULL;
466 p_stream->pf_add = MuxAdd;
467 p_stream->pf_del = MuxDel;
468 p_stream->pf_send = MuxSend;
473 p_sys->p_grab = NULL;
475 p_stream->pf_add = Add;
476 p_stream->pf_del = Del;
477 p_stream->pf_send = Send;
480 psz = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "sdp" );
483 config_chain_t *p_cfg;
485 SDPHandleUrl( p_stream, psz );
487 for( p_cfg = p_stream->p_cfg; p_cfg != NULL; p_cfg = p_cfg->p_next )
489 if( !strcmp( p_cfg->psz_name, "sdp" ) )
491 if( p_cfg->psz_value == NULL || *p_cfg->psz_value == '\0' )
494 /* needed both :sout-rtp-sdp= and rtp{sdp=} can be used */
495 if( !strcmp( p_cfg->psz_value, psz ) )
498 SDPHandleUrl( p_stream, p_cfg->psz_value );
504 /* update p_sout->i_out_pace_nocontrol */
505 p_stream->p_sout->i_out_pace_nocontrol++;
510 /*****************************************************************************
512 *****************************************************************************/
513 static void Close( vlc_object_t * p_this )
515 sout_stream_t *p_stream = (sout_stream_t*)p_this;
516 sout_stream_sys_t *p_sys = p_stream->p_sys;
518 /* update p_sout->i_out_pace_nocontrol */
519 p_stream->p_sout->i_out_pace_nocontrol--;
523 assert( p_sys->i_es == 1 );
524 Del( p_stream, p_sys->es[0] );
526 sout_MuxDelete( p_sys->p_mux );
527 sout_AccessOutDelete( p_sys->p_grab );
530 block_Release( p_sys->packet );
532 if( p_sys->b_export_sap )
535 SapSetup( p_stream );
539 if( p_sys->rtsp != NULL )
540 RtspUnsetup( p_sys->rtsp );
542 vlc_mutex_destroy( &p_sys->lock_sdp );
543 vlc_mutex_destroy( &p_sys->lock_es );
545 if( p_sys->p_httpd_file )
546 httpd_FileDelete( p_sys->p_httpd_file );
548 if( p_sys->p_httpd_host )
549 httpd_HostDelete( p_sys->p_httpd_host );
551 free( p_sys->psz_sdp );
553 if( p_sys->b_export_sdp_file )
556 unlink( p_sys->psz_sdp_file );
558 free( p_sys->psz_sdp_file );
560 free( p_sys->psz_destination );
564 /*****************************************************************************
566 *****************************************************************************/
567 static void SDPHandleUrl( sout_stream_t *p_stream, char *psz_url )
569 sout_stream_sys_t *p_sys = p_stream->p_sys;
572 vlc_UrlParse( &url, psz_url, 0 );
573 if( url.psz_protocol && !strcasecmp( url.psz_protocol, "http" ) )
575 if( p_sys->p_httpd_file )
577 msg_Err( p_stream, "you can use sdp=http:// only once" );
581 if( HttpSetup( p_stream, &url ) )
583 msg_Err( p_stream, "cannot export SDP as HTTP" );
586 else if( url.psz_protocol && !strcasecmp( url.psz_protocol, "rtsp" ) )
588 if( p_sys->rtsp != NULL )
590 msg_Err( p_stream, "you can use sdp=rtsp:// only once" );
594 /* FIXME test if destination is multicast or no destination at all */
595 p_sys->rtsp = RtspSetup( p_stream, &url );
596 if( p_sys->rtsp == NULL )
598 msg_Err( p_stream, "cannot export SDP as RTSP" );
601 if( p_sys->p_mux != NULL )
603 sout_stream_id_t *id = p_sys->es[0];
604 id->rtsp_id = RtspAddId( p_sys->rtsp, id, 0, GetDWBE( id->ssrc ),
605 p_sys->psz_destination, p_sys->i_ttl,
606 id->i_port, id->i_port + 1 );
609 else if( ( url.psz_protocol && !strcasecmp( url.psz_protocol, "sap" ) ) ||
610 ( url.psz_host && !strcasecmp( url.psz_host, "sap" ) ) )
612 p_sys->b_export_sap = VLC_TRUE;
613 SapSetup( p_stream );
615 else if( url.psz_protocol && !strcasecmp( url.psz_protocol, "file" ) )
617 if( p_sys->b_export_sdp_file )
619 msg_Err( p_stream, "you can use sdp=file:// only once" );
622 p_sys->b_export_sdp_file = VLC_TRUE;
623 psz_url = &psz_url[5];
624 if( psz_url[0] == '/' && psz_url[1] == '/' )
626 p_sys->psz_sdp_file = strdup( psz_url );
630 msg_Warn( p_stream, "unknown protocol for SDP (%s)",
635 vlc_UrlClean( &url );
638 /*****************************************************************************
640 *****************************************************************************/
642 char *SDPGenerate( const sout_stream_t *p_stream, const char *rtsp_url )
644 const sout_stream_sys_t *p_sys = p_stream->p_sys;
646 struct sockaddr_storage dst;
650 * When we have a fixed destination (typically when we do multicast),
651 * we need to put the actual port numbers in the SDP.
652 * When there is no fixed destination, we only support RTSP unicast
653 * on-demand setup, so we should rather let the clients decide which ports
655 * When there is both a fixed destination and RTSP unicast, we need to
656 * put port numbers used by the fixed destination, otherwise the SDP would
657 * become totally incorrect for multicast use. It should be noted that
658 * port numbers from SDP with RTSP are only "recommendation" from the
659 * server to the clients (per RFC2326), so only broken clients will fail
660 * to handle this properly. There is no solution but to use two differents
661 * output chain with two different RTSP URLs if you need to handle this
666 if( p_sys->psz_destination != NULL )
670 /* Oh boy, this is really ugly! (+ race condition on lock_es) */
671 dstlen = sizeof( dst );
672 if( p_sys->es[0]->listen_fd != NULL )
673 getsockname( p_sys->es[0]->listen_fd[0],
674 (struct sockaddr *)&dst, &dstlen );
676 getpeername( p_sys->es[0]->sinkv[0].rtp_fd,
677 (struct sockaddr *)&dst, &dstlen );
683 /* Dummy destination address for RTSP */
684 memset (&dst, 0, sizeof( struct sockaddr_in ) );
685 dst.ss_family = AF_INET;
689 dstlen = sizeof( struct sockaddr_in );
692 psz_sdp = vlc_sdp_Start( VLC_OBJECT( p_stream ), SOUT_CFG_PREFIX,
693 NULL, 0, (struct sockaddr *)&dst, dstlen );
694 if( psz_sdp == NULL )
697 /* TODO: a=source-filter */
698 if( p_sys->rtcp_mux )
699 sdp_AddAttribute( &psz_sdp, "rtcp-mux", NULL );
701 if( rtsp_url != NULL )
702 sdp_AddAttribute ( &psz_sdp, "control", "%s", rtsp_url );
704 /* FIXME: locking?! */
705 for( i = 0; i < p_sys->i_es; i++ )
707 sout_stream_id_t *id = p_sys->es[i];
708 const char *mime_major; /* major MIME type */
709 const char *proto = "RTP/AVP"; /* protocol */
714 mime_major = "video";
717 mime_major = "audio";
726 if( rtsp_url == NULL )
728 switch( p_sys->proto )
733 proto = "TCP/RTP/AVP";
736 proto = "DCCP/RTP/AVP";
738 case IPPROTO_UDPLITE:
743 sdp_AddMedia( &psz_sdp, mime_major, proto, inclport * id->i_port,
744 id->i_payload_type, VLC_FALSE, id->i_bitrate,
745 id->psz_rtpmap, id->psz_fmtp);
747 if( rtsp_url != NULL )
749 assert( strlen( rtsp_url ) > 0 );
750 vlc_bool_t addslash = ( rtsp_url[strlen( rtsp_url ) - 1] != '/' );
751 sdp_AddAttribute ( &psz_sdp, "control",
752 addslash ? "%s/trackID=%u" : "%strackID=%u",
757 if( id->listen_fd != NULL )
758 sdp_AddAttribute( &psz_sdp, "setup", "passive" );
760 if( p_sys->proto == IPPROTO_DCCP )
761 sdp_AddAttribute( &psz_sdp, "dccp-service-code",
762 "SC:RTP%c", toupper( mime_major[0] ) );
770 /*****************************************************************************
772 *****************************************************************************/
773 static int rtp_packetize_l16 ( sout_stream_t *, sout_stream_id_t *, block_t * );
774 static int rtp_packetize_l8 ( sout_stream_t *, sout_stream_id_t *, block_t * );
775 static int rtp_packetize_mpa ( sout_stream_t *, sout_stream_id_t *, block_t * );
776 static int rtp_packetize_mpv ( sout_stream_t *, sout_stream_id_t *, block_t * );
777 static int rtp_packetize_ac3 ( sout_stream_t *, sout_stream_id_t *, block_t * );
778 static int rtp_packetize_split( sout_stream_t *, sout_stream_id_t *, block_t * );
779 static int rtp_packetize_mp4a ( sout_stream_t *, sout_stream_id_t *, block_t * );
780 static int rtp_packetize_mp4a_latm ( sout_stream_t *, sout_stream_id_t *, block_t * );
781 static int rtp_packetize_h263 ( sout_stream_t *, sout_stream_id_t *, block_t * );
782 static int rtp_packetize_h264 ( sout_stream_t *, sout_stream_id_t *, block_t * );
783 static int rtp_packetize_amr ( sout_stream_t *, sout_stream_id_t *, block_t * );
784 static int rtp_packetize_spx ( sout_stream_t *, sout_stream_id_t *, block_t * );
785 static int rtp_packetize_t140 ( sout_stream_t *, sout_stream_id_t *, block_t * );
787 static void sprintf_hexa( char *s, uint8_t *p_data, int i_data )
789 static const char hex[16] = "0123456789abcdef";
792 for( i = 0; i < i_data; i++ )
794 s[2*i+0] = hex[(p_data[i]>>4)&0xf];
795 s[2*i+1] = hex[(p_data[i] )&0xf];
801 /** Add an ES as a new RTP stream */
802 static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
804 /* NOTE: As a special case, if we use a non-RTP
805 * mux (TS/PS), then p_fmt is NULL. */
806 sout_stream_sys_t *p_sys = p_stream->p_sys;
807 sout_stream_id_t *id;
808 int i_port, cscov = -1;
811 id = vlc_object_create( p_stream, sizeof( sout_stream_id_t ) );
814 vlc_object_attach( id, p_stream );
816 /* Choose the port */
821 if( p_fmt->i_cat == AUDIO_ES && p_sys->i_port_audio > 0 )
823 i_port = p_sys->i_port_audio;
824 p_sys->i_port_audio = 0;
827 if( p_fmt->i_cat == VIDEO_ES && p_sys->i_port_video > 0 )
829 i_port = p_sys->i_port_video;
830 p_sys->i_port_video = 0;
835 if( p_sys->i_port != p_sys->i_port_audio
836 && p_sys->i_port != p_sys->i_port_video )
838 i_port = p_sys->i_port;
845 id->p_stream = p_stream;
847 id->i_sequence = rand()&0xffff;
848 id->i_payload_type = p_sys->i_payload_type;
849 id->ssrc[0] = rand()&0xff;
850 id->ssrc[1] = rand()&0xff;
851 id->ssrc[2] = rand()&0xff;
852 id->ssrc[3] = rand()&0xff;
854 id->psz_rtpmap = NULL;
856 id->i_clock_rate = 90000; /* most common case */
860 id->i_cat = p_fmt->i_cat;
861 id->i_bitrate = p_fmt->i_bitrate/1000; /* Stream bitrate in kbps */
865 id->i_cat = VIDEO_ES;
869 id->pf_packetize = NULL;
870 id->i_mtu = config_GetInt( p_stream, "mtu" );
871 if( id->i_mtu <= 12 + 16 )
872 id->i_mtu = 576 - 20 - 8; /* pessimistic */
874 msg_Dbg( p_stream, "maximum RTP packet size: %d bytes", id->i_mtu );
876 vlc_mutex_init( p_stream, &id->lock_sink );
881 id->listen_fd = NULL;
884 (int64_t)1000 * var_GetInteger( p_stream, SOUT_CFG_PREFIX "caching");
886 if( p_sys->psz_destination != NULL )
887 switch( p_sys->proto )
891 id->listen_fd = net_Listen( VLC_OBJECT(p_stream),
892 p_sys->psz_destination, i_port,
894 if( id->listen_fd == NULL )
896 msg_Err( p_stream, "passive COMEDIA RTP socket failed" );
903 int ttl = (p_sys->i_ttl > 0) ? p_sys->i_ttl : -1;
904 int fd = net_ConnectDgram( p_stream, p_sys->psz_destination,
905 i_port, ttl, p_sys->proto );
908 msg_Err( p_stream, "cannot create RTP socket" );
911 rtp_add_sink( id, fd, p_sys->rtcp_mux );
917 char *psz = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "mux" );
919 if( psz == NULL ) /* Uho! */
922 if( strncmp( psz, "ts", 2 ) == 0 )
924 id->i_payload_type = 33;
925 id->psz_rtpmap = strdup( "MP2T/90000" );
929 id->psz_rtpmap = strdup( "MP2P/90000" );
933 switch( p_fmt->i_codec )
935 case VLC_FOURCC( 'u', 'l', 'a', 'w' ):
936 if( p_fmt->audio.i_channels == 1 && p_fmt->audio.i_rate == 8000 )
937 id->i_payload_type = 0;
938 id->i_clock_rate = p_fmt->audio.i_rate;
939 if( asprintf( &id->psz_rtpmap, "PCMU/%d/%d", p_fmt->audio.i_rate,
940 p_fmt->audio.i_channels ) == -1 )
941 id->psz_rtpmap = NULL;
942 id->i_clock_rate = p_fmt->audio.i_rate;
943 id->pf_packetize = rtp_packetize_l8;
945 case VLC_FOURCC( 'a', 'l', 'a', 'w' ):
946 if( p_fmt->audio.i_channels == 1 && p_fmt->audio.i_rate == 8000 )
947 id->i_payload_type = 8;
948 id->i_clock_rate = p_fmt->audio.i_rate;
949 if( asprintf( &id->psz_rtpmap, "PCMA/%d/%d", p_fmt->audio.i_rate,
950 p_fmt->audio.i_channels ) == -1 )
951 id->psz_rtpmap = NULL;
952 id->i_clock_rate = p_fmt->audio.i_rate;
953 id->pf_packetize = rtp_packetize_l8;
955 case VLC_FOURCC( 's', '1', '6', 'b' ):
956 if( p_fmt->audio.i_channels == 1 && p_fmt->audio.i_rate == 44100 )
958 id->i_payload_type = 11;
960 else if( p_fmt->audio.i_channels == 2 &&
961 p_fmt->audio.i_rate == 44100 )
963 id->i_payload_type = 10;
965 if( asprintf( &id->psz_rtpmap, "L16/%d/%d", p_fmt->audio.i_rate,
966 p_fmt->audio.i_channels ) == -1 )
967 id->psz_rtpmap = NULL;
968 id->i_clock_rate = p_fmt->audio.i_rate;
969 id->pf_packetize = rtp_packetize_l16;
971 case VLC_FOURCC( 'u', '8', ' ', ' ' ):
972 if( asprintf( &id->psz_rtpmap, "L8/%d/%d", p_fmt->audio.i_rate,
973 p_fmt->audio.i_channels ) == -1 )
974 id->psz_rtpmap = NULL;
975 id->i_clock_rate = p_fmt->audio.i_rate;
976 id->pf_packetize = rtp_packetize_l8;
978 case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
979 id->i_payload_type = 14;
980 id->psz_rtpmap = strdup( "MPA/90000" );
981 id->pf_packetize = rtp_packetize_mpa;
983 case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
984 id->i_payload_type = 32;
985 id->psz_rtpmap = strdup( "MPV/90000" );
986 id->pf_packetize = rtp_packetize_mpv;
988 case VLC_FOURCC( 'a', '5', '2', ' ' ):
989 id->psz_rtpmap = strdup( "ac3/90000" );
990 id->pf_packetize = rtp_packetize_ac3;
992 case VLC_FOURCC( 'H', '2', '6', '3' ):
993 id->psz_rtpmap = strdup( "H263-1998/90000" );
994 id->pf_packetize = rtp_packetize_h263;
996 case VLC_FOURCC( 'h', '2', '6', '4' ):
997 id->psz_rtpmap = strdup( "H264/90000" );
998 id->pf_packetize = rtp_packetize_h264;
1001 if( p_fmt->i_extra > 0 )
1003 uint8_t *p_buffer = p_fmt->p_extra;
1004 int i_buffer = p_fmt->i_extra;
1005 char *p_64_sps = NULL;
1006 char *p_64_pps = NULL;
1009 while( i_buffer > 4 &&
1010 p_buffer[0] == 0 && p_buffer[1] == 0 &&
1011 p_buffer[2] == 0 && p_buffer[3] == 1 )
1013 const int i_nal_type = p_buffer[4]&0x1f;
1017 msg_Dbg( p_stream, "we found a startcode for NAL with TYPE:%d", i_nal_type );
1020 for( i_offset = 4; i_offset+3 < i_buffer ; i_offset++)
1022 if( !memcmp (p_buffer + i_offset, "\x00\x00\x00\x01", 4 ) )
1024 /* we found another startcode */
1029 if( i_nal_type == 7 )
1031 p_64_sps = vlc_b64_encode_binary( &p_buffer[4], i_size - 4 );
1032 sprintf_hexa( hexa, &p_buffer[5], 3 );
1034 else if( i_nal_type == 8 )
1036 p_64_pps = vlc_b64_encode_binary( &p_buffer[4], i_size - 4 );
1042 if( p_64_sps && p_64_pps &&
1043 ( asprintf( &id->psz_fmtp,
1044 "packetization-mode=1;profile-level-id=%s;"
1045 "sprop-parameter-sets=%s,%s;", hexa, p_64_sps,
1046 p_64_pps ) == -1 ) )
1047 id->psz_fmtp = NULL;
1052 id->psz_fmtp = strdup( "packetization-mode=1" );
1055 case VLC_FOURCC( 'm', 'p', '4', 'v' ):
1057 char hexa[2*p_fmt->i_extra +1];
1059 id->psz_rtpmap = strdup( "MP4V-ES/90000" );
1060 id->pf_packetize = rtp_packetize_split;
1061 if( p_fmt->i_extra > 0 )
1063 sprintf_hexa( hexa, p_fmt->p_extra, p_fmt->i_extra );
1064 if( asprintf( &id->psz_fmtp,
1065 "profile-level-id=3; config=%s;", hexa ) == -1 )
1066 id->psz_fmtp = NULL;
1070 case VLC_FOURCC( 'm', 'p', '4', 'a' ):
1072 id->i_clock_rate = p_fmt->audio.i_rate;
1076 char hexa[2*p_fmt->i_extra +1];
1078 if( asprintf( &id->psz_rtpmap, "mpeg4-generic/%d",
1079 p_fmt->audio.i_rate ) == -1 )
1080 id->psz_rtpmap = NULL;
1081 id->pf_packetize = rtp_packetize_mp4a;
1082 sprintf_hexa( hexa, p_fmt->p_extra, p_fmt->i_extra );
1083 if( asprintf( &id->psz_fmtp,
1084 "streamtype=5; profile-level-id=15; "
1085 "mode=AAC-hbr; config=%s; SizeLength=13; "
1086 "IndexLength=3; IndexDeltaLength=3; Profile=1;",
1088 id->psz_fmtp = NULL;
1094 unsigned char config[6];
1095 unsigned int aacsrates[15] = {
1096 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
1097 16000, 12000, 11025, 8000, 7350, 0, 0 };
1099 for( i = 0; i < 15; i++ )
1100 if( p_fmt->audio.i_rate == aacsrates[i] )
1106 config[3]=p_fmt->audio.i_channels<<4;
1110 if( asprintf( &id->psz_rtpmap, "MP4A-LATM/%d/%d",
1111 p_fmt->audio.i_rate,
1112 p_fmt->audio.i_channels ) == -1)
1113 id->psz_rtpmap = NULL;
1114 id->pf_packetize = rtp_packetize_mp4a_latm;
1115 sprintf_hexa( hexa, config, 6 );
1116 if( asprintf( &id->psz_fmtp, "profile-level-id=15; "
1117 "object=2; cpresent=0; config=%s", hexa ) == -1 )
1118 id->psz_fmtp = NULL;
1122 case VLC_FOURCC( 's', 'a', 'm', 'r' ):
1123 id->psz_rtpmap = strdup( p_fmt->audio.i_channels == 2 ?
1124 "AMR/8000/2" : "AMR/8000" );
1125 id->psz_fmtp = strdup( "octet-align=1" );
1126 id->i_clock_rate = p_fmt->audio.i_rate;
1127 id->pf_packetize = rtp_packetize_amr;
1129 case VLC_FOURCC( 's', 'a', 'w', 'b' ):
1130 id->psz_rtpmap = strdup( p_fmt->audio.i_channels == 2 ?
1131 "AMR-WB/16000/2" : "AMR-WB/16000" );
1132 id->psz_fmtp = strdup( "octet-align=1" );
1133 id->i_clock_rate = p_fmt->audio.i_rate;
1134 id->pf_packetize = rtp_packetize_amr;
1136 case VLC_FOURCC( 's', 'p', 'x', ' ' ):
1137 id->i_payload_type = p_sys->i_payload_type++;
1138 if( asprintf( &id->psz_rtpmap, "SPEEX/%d",
1139 p_fmt->audio.i_rate ) == -1)
1140 id->psz_rtpmap = NULL;
1141 id->i_clock_rate = p_fmt->audio.i_rate;
1142 id->pf_packetize = rtp_packetize_spx;
1144 case VLC_FOURCC( 't', '1', '4', '0' ):
1145 id->psz_rtpmap = strdup( "t140/1000" );
1146 id->i_clock_rate = 1000;
1147 id->pf_packetize = rtp_packetize_t140;
1151 msg_Err( p_stream, "cannot add this stream (unsupported "
1152 "codec:%4.4s)", (char*)&p_fmt->i_codec );
1157 cscov += 8 /* UDP */ + 12 /* RTP */;
1159 net_SetCSCov( id->sinkv[0].rtp_fd, cscov, -1 );
1161 if( id->i_payload_type == p_sys->i_payload_type )
1162 p_sys->i_payload_type++;
1164 if( p_sys->rtsp != NULL )
1165 id->rtsp_id = RtspAddId( p_sys->rtsp, id, p_sys->i_es,
1166 GetDWBE( id->ssrc ),
1167 p_sys->psz_destination,
1168 p_sys->i_ttl, id->i_port, id->i_port + 1 );
1170 id->p_fifo = block_FifoNew( p_stream );
1171 if( vlc_thread_create( id, "RTP send thread", ThreadSend,
1172 VLC_THREAD_PRIORITY_HIGHEST, VLC_FALSE ) )
1175 /* Update p_sys context */
1176 vlc_mutex_lock( &p_sys->lock_es );
1177 TAB_APPEND( p_sys->i_es, p_sys->es, id );
1178 vlc_mutex_unlock( &p_sys->lock_es );
1180 psz_sdp = SDPGenerate( p_stream, NULL );
1182 vlc_mutex_lock( &p_sys->lock_sdp );
1183 free( p_sys->psz_sdp );
1184 p_sys->psz_sdp = psz_sdp;
1185 vlc_mutex_unlock( &p_sys->lock_sdp );
1187 msg_Dbg( p_stream, "sdp=\n%s", p_sys->psz_sdp );
1189 /* Update SDP (sap/file) */
1190 if( p_sys->b_export_sap ) SapSetup( p_stream );
1191 if( p_sys->b_export_sdp_file ) FileSetup( p_stream );
1196 Del( p_stream, id );
1200 static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
1202 sout_stream_sys_t *p_sys = p_stream->p_sys;
1204 if( id->p_fifo != NULL )
1206 vlc_object_kill( id );
1207 block_FifoWake( id->p_fifo );
1208 vlc_thread_join( id );
1209 block_FifoRelease( id->p_fifo );
1212 vlc_mutex_lock( &p_sys->lock_es );
1213 TAB_REMOVE( p_sys->i_es, p_sys->es, id );
1214 vlc_mutex_unlock( &p_sys->lock_es );
1217 if( id->i_port > 0 )
1219 if( id->i_cat == AUDIO_ES && p_sys->i_port_audio == 0 )
1220 p_sys->i_port_audio = id->i_port;
1221 else if( id->i_cat == VIDEO_ES && p_sys->i_port_video == 0 )
1222 p_sys->i_port_video = id->i_port;
1225 free( id->psz_rtpmap );
1226 free( id->psz_fmtp );
1229 RtspDelId( p_sys->rtsp, id->rtsp_id );
1231 rtp_del_sink( id, id->sinkv[0].rtp_fd ); /* sink for explicit dst= */
1232 if( id->listen_fd != NULL )
1233 net_ListenClose( id->listen_fd );
1235 vlc_mutex_destroy( &id->lock_sink );
1237 /* Update SDP (sap/file) */
1238 if( p_sys->b_export_sap && !p_sys->p_mux ) SapSetup( p_stream );
1239 if( p_sys->b_export_sdp_file ) FileSetup( p_stream );
1241 vlc_object_detach( id );
1242 vlc_object_destroy( id );
1246 static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
1251 assert( p_stream->p_sys->p_mux == NULL );
1253 while( p_buffer != NULL )
1255 p_next = p_buffer->p_next;
1256 if( id->pf_packetize( p_stream, id, p_buffer ) )
1259 block_Release( p_buffer );
1265 /****************************************************************************
1267 ****************************************************************************/
1268 static int SapSetup( sout_stream_t *p_stream )
1270 sout_stream_sys_t *p_sys = p_stream->p_sys;
1271 sout_instance_t *p_sout = p_stream->p_sout;
1273 /* Remove the previous session */
1274 if( p_sys->p_session != NULL)
1276 sout_AnnounceUnRegister( p_sout, p_sys->p_session);
1277 p_sys->p_session = NULL;
1280 if( ( p_sys->i_es > 0 || p_sys->p_mux ) && p_sys->psz_sdp && *p_sys->psz_sdp )
1282 announce_method_t *p_method = sout_SAPMethod();
1283 p_sys->p_session = sout_AnnounceRegisterSDP( p_sout, SOUT_CFG_PREFIX,
1285 p_sys->psz_destination,
1287 sout_MethodRelease( p_method );
1293 /****************************************************************************
1295 ****************************************************************************/
1296 static int FileSetup( sout_stream_t *p_stream )
1298 sout_stream_sys_t *p_sys = p_stream->p_sys;
1301 if( ( f = utf8_fopen( p_sys->psz_sdp_file, "wt" ) ) == NULL )
1303 msg_Err( p_stream, "cannot open file '%s' (%m)",
1304 p_sys->psz_sdp_file );
1305 return VLC_EGENERIC;
1308 fputs( p_sys->psz_sdp, f );
1314 /****************************************************************************
1316 ****************************************************************************/
1317 static int HttpCallback( httpd_file_sys_t *p_args,
1318 httpd_file_t *, uint8_t *p_request,
1319 uint8_t **pp_data, int *pi_data );
1321 static int HttpSetup( sout_stream_t *p_stream, vlc_url_t *url)
1323 sout_stream_sys_t *p_sys = p_stream->p_sys;
1325 p_sys->p_httpd_host = httpd_HostNew( VLC_OBJECT(p_stream), url->psz_host,
1326 url->i_port > 0 ? url->i_port : 80 );
1327 if( p_sys->p_httpd_host )
1329 p_sys->p_httpd_file = httpd_FileNew( p_sys->p_httpd_host,
1330 url->psz_path ? url->psz_path : "/",
1333 HttpCallback, (void*)p_sys );
1335 if( p_sys->p_httpd_file == NULL )
1337 return VLC_EGENERIC;
1342 static int HttpCallback( httpd_file_sys_t *p_args,
1343 httpd_file_t *f, uint8_t *p_request,
1344 uint8_t **pp_data, int *pi_data )
1346 sout_stream_sys_t *p_sys = (sout_stream_sys_t*)p_args;
1348 vlc_mutex_lock( &p_sys->lock_sdp );
1349 if( p_sys->psz_sdp && *p_sys->psz_sdp )
1351 *pi_data = strlen( p_sys->psz_sdp );
1352 *pp_data = malloc( *pi_data );
1353 memcpy( *pp_data, p_sys->psz_sdp, *pi_data );
1360 vlc_mutex_unlock( &p_sys->lock_sdp );
1365 /****************************************************************************
1367 ****************************************************************************/
1368 static void ThreadSend( vlc_object_t *p_this )
1370 sout_stream_id_t *id = (sout_stream_id_t *)p_this;
1371 unsigned i_caching = id->i_caching;
1373 int fd[5] = { -1, -1, -1, -1, -1 };
1381 fd[4] = open( "/dev/null", O_WRONLY );
1386 block_t *out = block_FifoGet( id->p_fifo );
1388 continue; /* Forced wakeup */
1390 mtime_t i_date = out->i_dts + i_caching;
1391 ssize_t len = out->i_buffer;
1395 len = write( fd[1], out->p_buffer, len);
1397 continue; /* Uho - should not happen */
1401 vlc_mutex_lock( &id->lock_sink );
1402 unsigned deadc = 0; /* How many dead sockets? */
1403 int deadv[id->sinkc]; /* Dead sockets list */
1405 for( int i = 0; i < id->sinkc; i++ )
1407 SendRTCP( id->sinkv[i].rtcp, out );
1410 tee( fd[0], fd[3], len, 0 );
1411 if( splice( fd[2], NULL, id->sinkv[i].rtp_fd, NULL, len,
1412 SPLICE_F_NONBLOCK ) >= 0 )
1414 if( errno == EAGAIN )
1418 splice( fd[2], NULL, fd[4], NULL, len, 0 );
1420 if( send( id->sinkv[i].rtp_fd, out->p_buffer, len, 0 ) >= 0 )
1423 /* Retry sending to root out soft-errors */
1424 if( send( id->sinkv[i].rtp_fd, out->p_buffer, len, 0 ) >= 0 )
1427 deadv[deadc++] = id->sinkv[i].rtp_fd;
1429 vlc_mutex_unlock( &id->lock_sink );
1431 block_Release( out );
1433 splice( fd[0], NULL, fd[4], NULL, len, 0 );
1436 for( unsigned i = 0; i < deadc; i++ )
1438 msg_Dbg( id, "removing socket %d", deadv[i] );
1439 rtp_del_sink( id, deadv[i] );
1442 /* Hopefully we won't overflow the SO_MAXCONN accept queue */
1443 while( id->listen_fd != NULL )
1445 int fd = net_Accept( id, id->listen_fd, 0 );
1448 msg_Dbg( id, "adding socket %d", fd );
1449 rtp_add_sink( id, fd, VLC_TRUE );
1454 for( unsigned i = 0; i < 5; i++ )
1459 static inline void rtp_packetize_send( sout_stream_id_t *id, block_t *out )
1461 block_FifoPut( id->p_fifo, out );
1464 int rtp_add_sink( sout_stream_id_t *id, int fd, vlc_bool_t rtcp_mux )
1466 rtp_sink_t sink = { fd, NULL };
1467 sink.rtcp = OpenRTCP( VLC_OBJECT( id->p_stream ), fd, IPPROTO_UDP,
1469 if( sink.rtcp == NULL )
1470 msg_Err( id, "RTCP failed!" );
1472 vlc_mutex_lock( &id->lock_sink );
1473 INSERT_ELEM( id->sinkv, id->sinkc, id->sinkc, sink );
1474 vlc_mutex_unlock( &id->lock_sink );
1478 void rtp_del_sink( sout_stream_id_t *id, int fd )
1480 rtp_sink_t sink = { fd, NULL };
1482 /* NOTE: must be safe to use if fd is not included */
1483 vlc_mutex_lock( &id->lock_sink );
1484 for( int i = 0; i < id->sinkc; i++ )
1486 if (id->sinkv[i].rtp_fd == fd)
1488 sink = id->sinkv[i];
1489 REMOVE_ELEM( id->sinkv, id->sinkc, i );
1493 vlc_mutex_unlock( &id->lock_sink );
1495 CloseRTCP( sink.rtcp );
1496 net_Close( sink.rtp_fd );
1499 uint16_t rtp_get_seq( const sout_stream_id_t *id )
1501 /* This will return values for the next packet.
1502 * Accounting for caching would not be totally trivial. */
1503 return id->i_sequence;
1506 /* FIXME: this is pretty bad - if we remove and then insert an ES
1507 * the number will get unsynched from inside RTSP */
1508 unsigned rtp_get_num( const sout_stream_id_t *id )
1510 sout_stream_sys_t *p_sys = id->p_stream->p_sys;
1513 vlc_mutex_lock( &p_sys->lock_es );
1514 for( i = 0; i < p_sys->i_es; i++ )
1516 if( id == p_sys->es[i] )
1519 vlc_mutex_unlock( &p_sys->lock_es );
1525 /****************************************************************************
1527 ****************************************************************************/
1528 static void rtp_packetize_common( sout_stream_id_t *id, block_t *out,
1529 int b_marker, int64_t i_pts )
1531 uint32_t i_timestamp = i_pts * (int64_t)id->i_clock_rate / I64C(1000000);
1533 out->p_buffer[0] = 0x80;
1534 out->p_buffer[1] = (b_marker?0x80:0x00)|id->i_payload_type;
1535 out->p_buffer[2] = ( id->i_sequence >> 8)&0xff;
1536 out->p_buffer[3] = ( id->i_sequence )&0xff;
1537 out->p_buffer[4] = ( i_timestamp >> 24 )&0xff;
1538 out->p_buffer[5] = ( i_timestamp >> 16 )&0xff;
1539 out->p_buffer[6] = ( i_timestamp >> 8 )&0xff;
1540 out->p_buffer[7] = ( i_timestamp )&0xff;
1542 memcpy( out->p_buffer + 8, id->ssrc, 4 );
1548 static int rtp_packetize_mpa( sout_stream_t *p_stream, sout_stream_id_t *id,
1551 int i_max = id->i_mtu - 12 - 4; /* payload max in one packet */
1552 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1554 uint8_t *p_data = in->p_buffer;
1555 int i_data = in->i_buffer;
1558 for( i = 0; i < i_count; i++ )
1560 int i_payload = __MIN( i_max, i_data );
1561 block_t *out = block_New( p_stream, 16 + i_payload );
1563 /* rtp common header */
1564 rtp_packetize_common( id, out, (i == i_count - 1)?1:0, in->i_pts );
1566 out->p_buffer[12] = 0;
1567 out->p_buffer[13] = 0;
1568 /* fragment offset in the current frame */
1569 out->p_buffer[14] = ( (i*i_max) >> 8 )&0xff;
1570 out->p_buffer[15] = ( (i*i_max) )&0xff;
1571 memcpy( &out->p_buffer[16], p_data, i_payload );
1573 out->i_buffer = 16 + i_payload;
1574 out->i_dts = in->i_dts + i * in->i_length / i_count;
1575 out->i_length = in->i_length / i_count;
1577 rtp_packetize_send( id, out );
1579 p_data += i_payload;
1580 i_data -= i_payload;
1587 static int rtp_packetize_mpv( sout_stream_t *p_stream, sout_stream_id_t *id,
1590 int i_max = id->i_mtu - 12 - 4; /* payload max in one packet */
1591 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1593 uint8_t *p_data = in->p_buffer;
1594 int i_data = in->i_buffer;
1596 int b_sequence_start = 0;
1597 int i_temporal_ref = 0;
1598 int i_picture_coding_type = 0;
1599 int i_fbv = 0, i_bfc = 0, i_ffv = 0, i_ffc = 0;
1600 int b_start_slice = 0;
1602 /* preparse this packet to get some info */
1603 if( in->i_buffer > 4 )
1605 uint8_t *p = p_data;
1606 int i_rest = in->i_buffer;
1610 while( i_rest > 4 &&
1611 ( p[0] != 0x00 || p[1] != 0x00 || p[2] != 0x01 ) )
1625 /* sequence start code */
1626 b_sequence_start = 1;
1628 else if( *p == 0x00 && i_rest >= 4 )
1631 i_temporal_ref = ( p[1] << 2) |((p[2]>>6)&0x03);
1632 i_picture_coding_type = (p[2] >> 3)&0x07;
1634 if( i_rest >= 4 && ( i_picture_coding_type == 2 ||
1635 i_picture_coding_type == 3 ) )
1637 i_ffv = (p[3] >> 2)&0x01;
1638 i_ffc = ((p[3]&0x03) << 1)|((p[4]>>7)&0x01);
1639 if( i_rest > 4 && i_picture_coding_type == 3 )
1641 i_fbv = (p[4]>>6)&0x01;
1642 i_bfc = (p[4]>>3)&0x07;
1646 else if( *p <= 0xaf )
1653 for( i = 0; i < i_count; i++ )
1655 int i_payload = __MIN( i_max, i_data );
1656 block_t *out = block_New( p_stream,
1658 uint32_t h = ( i_temporal_ref << 16 )|
1659 ( b_sequence_start << 13 )|
1660 ( b_start_slice << 12 )|
1661 ( i == i_count - 1 ? 1 << 11 : 0 )|
1662 ( i_picture_coding_type << 8 )|
1663 ( i_fbv << 7 )|( i_bfc << 4 )|( i_ffv << 3 )|i_ffc;
1665 /* rtp common header */
1666 rtp_packetize_common( id, out, (i == i_count - 1)?1:0,
1667 in->i_pts > 0 ? in->i_pts : in->i_dts );
1669 /* 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 */
1670 out->p_buffer[12] = ( h >> 24 )&0xff;
1671 out->p_buffer[13] = ( h >> 16 )&0xff;
1672 out->p_buffer[14] = ( h >> 8 )&0xff;
1673 out->p_buffer[15] = ( h )&0xff;
1675 memcpy( &out->p_buffer[16], p_data, i_payload );
1677 out->i_buffer = 16 + i_payload;
1678 out->i_dts = in->i_dts + i * in->i_length / i_count;
1679 out->i_length = in->i_length / i_count;
1681 rtp_packetize_send( id, out );
1683 p_data += i_payload;
1684 i_data -= i_payload;
1690 static int rtp_packetize_ac3( sout_stream_t *p_stream, sout_stream_id_t *id,
1693 int i_max = id->i_mtu - 12 - 2; /* payload max in one packet */
1694 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1696 uint8_t *p_data = in->p_buffer;
1697 int i_data = in->i_buffer;
1700 for( i = 0; i < i_count; i++ )
1702 int i_payload = __MIN( i_max, i_data );
1703 block_t *out = block_New( p_stream, 14 + i_payload );
1705 /* rtp common header */
1706 rtp_packetize_common( id, out, (i == i_count - 1)?1:0, in->i_pts );
1708 out->p_buffer[12] = 1;
1710 out->p_buffer[13] = 0x00;
1712 memcpy( &out->p_buffer[14], p_data, i_payload );
1714 out->i_buffer = 14 + i_payload;
1715 out->i_dts = in->i_dts + i * in->i_length / i_count;
1716 out->i_length = in->i_length / i_count;
1718 rtp_packetize_send( id, out );
1720 p_data += i_payload;
1721 i_data -= i_payload;
1727 static int rtp_packetize_split( sout_stream_t *p_stream, sout_stream_id_t *id,
1730 int i_max = id->i_mtu - 12; /* payload max in one packet */
1731 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1733 uint8_t *p_data = in->p_buffer;
1734 int i_data = in->i_buffer;
1737 for( i = 0; i < i_count; i++ )
1739 int i_payload = __MIN( i_max, i_data );
1740 block_t *out = block_New( p_stream, 12 + i_payload );
1742 /* rtp common header */
1743 rtp_packetize_common( id, out, ((i == i_count - 1)?1:0),
1744 (in->i_pts > 0 ? in->i_pts : in->i_dts) );
1745 memcpy( &out->p_buffer[12], p_data, i_payload );
1747 out->i_buffer = 12 + i_payload;
1748 out->i_dts = in->i_dts + i * in->i_length / i_count;
1749 out->i_length = in->i_length / i_count;
1751 rtp_packetize_send( id, out );
1753 p_data += i_payload;
1754 i_data -= i_payload;
1761 static int rtp_packetize_mp4a_latm( sout_stream_t *p_stream, sout_stream_id_t *id,
1764 int i_max = id->i_mtu - 14; /* payload max in one packet */
1765 int latmhdrsize = in->i_buffer / 0xff + 1;
1766 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1768 uint8_t *p_data = in->p_buffer, *p_header = NULL;
1769 int i_data = in->i_buffer;
1772 for( i = 0; i < i_count; i++ )
1774 int i_payload = __MIN( i_max, i_data );
1779 out = block_New( p_stream, 12 + latmhdrsize + i_payload );
1781 /* rtp common header */
1782 rtp_packetize_common( id, out, ((i == i_count - 1) ? 1 : 0),
1783 (in->i_pts > 0 ? in->i_pts : in->i_dts) );
1787 int tmp = in->i_buffer;
1789 p_header=out->p_buffer+12;
1799 memcpy( &out->p_buffer[12+latmhdrsize], p_data, i_payload );
1801 out->i_buffer = 12 + latmhdrsize + i_payload;
1802 out->i_dts = in->i_dts + i * in->i_length / i_count;
1803 out->i_length = in->i_length / i_count;
1805 rtp_packetize_send( id, out );
1807 p_data += i_payload;
1808 i_data -= i_payload;
1814 static int rtp_packetize_l16( sout_stream_t *p_stream, sout_stream_id_t *id,
1817 int i_max = id->i_mtu - 12; /* payload max in one packet */
1818 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1820 uint8_t *p_data = in->p_buffer;
1821 int i_data = in->i_buffer;
1826 int i_payload = (__MIN( i_max, i_data )/4)*4;
1827 block_t *out = block_New( p_stream, 12 + i_payload );
1829 /* rtp common header */
1830 rtp_packetize_common( id, out, 0,
1831 (in->i_pts > 0 ? in->i_pts : in->i_dts) );
1832 memcpy( &out->p_buffer[12], p_data, i_payload );
1834 out->i_buffer = 12 + i_payload;
1835 out->i_dts = in->i_dts + i_packet * in->i_length / i_count;
1836 out->i_length = in->i_length / i_count;
1838 rtp_packetize_send( id, out );
1840 p_data += i_payload;
1841 i_data -= i_payload;
1848 static int rtp_packetize_l8( sout_stream_t *p_stream, sout_stream_id_t *id,
1851 int i_max = id->i_mtu - 12; /* payload max in one packet */
1852 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1854 uint8_t *p_data = in->p_buffer;
1855 int i_data = in->i_buffer;
1860 int i_payload = (__MIN( i_max, i_data )/2)*2;
1861 block_t *out = block_New( p_stream, 12 + i_payload );
1863 /* rtp common header */
1864 rtp_packetize_common( id, out, 0,
1865 (in->i_pts > 0 ? in->i_pts : in->i_dts) );
1866 memcpy( &out->p_buffer[12], p_data, i_payload );
1868 out->i_buffer = 12 + i_payload;
1869 out->i_dts = in->i_dts + i_packet * in->i_length / i_count;
1870 out->i_length = in->i_length / i_count;
1872 rtp_packetize_send( id, out );
1874 p_data += i_payload;
1875 i_data -= i_payload;
1882 static int rtp_packetize_mp4a( sout_stream_t *p_stream, sout_stream_id_t *id,
1885 int i_max = id->i_mtu - 16; /* payload max in one packet */
1886 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1888 uint8_t *p_data = in->p_buffer;
1889 int i_data = in->i_buffer;
1892 for( i = 0; i < i_count; i++ )
1894 int i_payload = __MIN( i_max, i_data );
1895 block_t *out = block_New( p_stream, 16 + i_payload );
1897 /* rtp common header */
1898 rtp_packetize_common( id, out, ((i == i_count - 1)?1:0),
1899 (in->i_pts > 0 ? in->i_pts : in->i_dts) );
1901 /* AU headers length (bits) */
1902 out->p_buffer[12] = 0;
1903 out->p_buffer[13] = 2*8;
1904 /* for each AU length 13 bits + idx 3bits, */
1905 out->p_buffer[14] = ( in->i_buffer >> 5 )&0xff;
1906 out->p_buffer[15] = ( (in->i_buffer&0xff)<<3 )|0;
1908 memcpy( &out->p_buffer[16], p_data, i_payload );
1910 out->i_buffer = 16 + i_payload;
1911 out->i_dts = in->i_dts + i * in->i_length / i_count;
1912 out->i_length = in->i_length / i_count;
1914 rtp_packetize_send( id, out );
1916 p_data += i_payload;
1917 i_data -= i_payload;
1925 #define RTP_H263_HEADER_SIZE (2) // plen = 0
1926 #define RTP_H263_PAYLOAD_START (14) // plen = 0
1927 static int rtp_packetize_h263( sout_stream_t *p_stream, sout_stream_id_t *id,
1930 uint8_t *p_data = in->p_buffer;
1931 int i_data = in->i_buffer;
1933 int i_max = id->i_mtu - 12 - RTP_H263_HEADER_SIZE; /* payload max in one packet */
1936 int b_v_bit = 0; // no pesky error resilience
1937 int i_plen = 0; // normally plen=0 for PSC packet
1938 int i_pebit = 0; // because plen=0
1943 return VLC_EGENERIC;
1945 if( p_data[0] || p_data[1] )
1947 return VLC_EGENERIC;
1949 /* remove 2 leading 0 bytes */
1952 i_count = ( i_data + i_max - 1 ) / i_max;
1954 for( i = 0; i < i_count; i++ )
1956 int i_payload = __MIN( i_max, i_data );
1957 block_t *out = block_New( p_stream,
1958 RTP_H263_PAYLOAD_START + i_payload );
1959 b_p_bit = (i == 0) ? 1 : 0;
1960 h = ( b_p_bit << 10 )|
1965 /* rtp common header */
1966 //b_m_bit = 1; // always contains end of frame
1967 rtp_packetize_common( id, out, (i == i_count - 1)?1:0,
1968 in->i_pts > 0 ? in->i_pts : in->i_dts );
1971 out->p_buffer[12] = ( h >> 8 )&0xff;
1972 out->p_buffer[13] = ( h )&0xff;
1973 memcpy( &out->p_buffer[RTP_H263_PAYLOAD_START], p_data, i_payload );
1975 out->i_buffer = RTP_H263_PAYLOAD_START + i_payload;
1976 out->i_dts = in->i_dts + i * in->i_length / i_count;
1977 out->i_length = in->i_length / i_count;
1979 rtp_packetize_send( id, out );
1981 p_data += i_payload;
1982 i_data -= i_payload;
1990 rtp_packetize_h264_nal( sout_stream_t *p_stream, sout_stream_id_t *id,
1991 const uint8_t *p_data, int i_data, int64_t i_pts,
1992 int64_t i_dts, vlc_bool_t b_last, int64_t i_length )
1994 const int i_max = id->i_mtu - 12; /* payload max in one packet */
2001 i_nal_hdr = p_data[3];
2002 i_nal_type = i_nal_hdr&0x1f;
2004 /* Skip start code */
2009 if( i_data <= i_max )
2011 /* Single NAL unit packet */
2012 block_t *out = block_New( p_stream, 12 + i_data );
2014 out->i_length = i_length;
2017 rtp_packetize_common( id, out, b_last, i_pts );
2018 out->i_buffer = 12 + i_data;
2020 memcpy( &out->p_buffer[12], p_data, i_data );
2022 rtp_packetize_send( id, out );
2026 /* FU-A Fragmentation Unit without interleaving */
2027 const int i_count = ( i_data-1 + i_max-2 - 1 ) / (i_max-2);
2033 for( i = 0; i < i_count; i++ )
2035 const int i_payload = __MIN( i_data, i_max-2 );
2036 block_t *out = block_New( p_stream, 12 + 2 + i_payload );
2037 out->i_dts = i_dts + i * i_length / i_count;
2038 out->i_length = i_length / i_count;
2041 rtp_packetize_common( id, out, (b_last && i_payload == i_data), i_pts );
2042 out->i_buffer = 14 + i_payload;
2045 out->p_buffer[12] = 0x00 | (i_nal_hdr & 0x60) | 28;
2047 out->p_buffer[13] = ( i == 0 ? 0x80 : 0x00 ) | ( (i == i_count-1) ? 0x40 : 0x00 ) | i_nal_type;
2048 memcpy( &out->p_buffer[14], p_data, i_payload );
2050 rtp_packetize_send( id, out );
2052 i_data -= i_payload;
2053 p_data += i_payload;
2059 static int rtp_packetize_h264( sout_stream_t *p_stream, sout_stream_id_t *id,
2062 const uint8_t *p_buffer = in->p_buffer;
2063 int i_buffer = in->i_buffer;
2065 while( i_buffer > 4 && ( p_buffer[0] != 0 || p_buffer[1] != 0 || p_buffer[2] != 1 ) )
2071 /* Split nal units */
2072 while( i_buffer > 4 )
2075 int i_size = i_buffer;
2076 int i_skip = i_buffer;
2078 /* search nal end */
2079 for( i_offset = 4; i_offset+2 < i_buffer ; i_offset++)
2081 if( p_buffer[i_offset] == 0 && p_buffer[i_offset+1] == 0 && p_buffer[i_offset+2] == 1 )
2083 /* we found another startcode */
2084 i_size = i_offset - ( p_buffer[i_offset-1] == 0 ? 1 : 0);
2089 /* TODO add STAP-A to remove a lot of overhead with small slice/sei/... */
2090 rtp_packetize_h264_nal( p_stream, id, p_buffer, i_size,
2091 (in->i_pts > 0 ? in->i_pts : in->i_dts), in->i_dts,
2092 (i_size >= i_buffer), in->i_length * i_size / in->i_buffer );
2100 static int rtp_packetize_amr( sout_stream_t *p_stream, sout_stream_id_t *id,
2103 int i_max = id->i_mtu - 14; /* payload max in one packet */
2104 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
2106 uint8_t *p_data = in->p_buffer;
2107 int i_data = in->i_buffer;
2110 /* Only supports octet-aligned mode */
2111 for( i = 0; i < i_count; i++ )
2113 int i_payload = __MIN( i_max, i_data );
2114 block_t *out = block_New( p_stream, 14 + i_payload );
2116 /* rtp common header */
2117 rtp_packetize_common( id, out, ((i == i_count - 1)?1:0),
2118 (in->i_pts > 0 ? in->i_pts : in->i_dts) );
2119 /* Payload header */
2120 out->p_buffer[12] = 0xF0; /* CMR */
2121 out->p_buffer[13] = p_data[0]&0x7C; /* ToC */ /* FIXME: frame type */
2123 /* FIXME: are we fed multiple frames ? */
2124 memcpy( &out->p_buffer[14], p_data+1, i_payload-1 );
2126 out->i_buffer = 14 + i_payload-1;
2127 out->i_dts = in->i_dts + i * in->i_length / i_count;
2128 out->i_length = in->i_length / i_count;
2130 rtp_packetize_send( id, out );
2132 p_data += i_payload;
2133 i_data -= i_payload;
2139 static int rtp_packetize_t140( sout_stream_t *p_stream, sout_stream_id_t *id,
2142 const size_t i_max = id->i_mtu - 12;
2143 const uint8_t *p_data = in->p_buffer;
2144 size_t i_data = in->i_buffer;
2146 for( unsigned i_packet = 0; i_data > 0; i_packet++ )
2148 size_t i_payload = i_data;
2150 /* Make sure we stop on an UTF-8 character boundary
2151 * (assuming the input is valid UTF-8) */
2152 if( i_data > i_max )
2156 while( ( p_data[i_payload] & 0xC0 ) == 0x80 )
2158 if( i_payload == 0 )
2159 return VLC_SUCCESS; /* fishy input! */
2165 block_t *out = block_New( p_stream, 12 + i_payload );
2169 rtp_packetize_common( id, out, 0, in->i_pts + i_packet );
2170 memcpy( out->p_buffer + 12, p_data, i_payload );
2172 out->i_buffer = 12 + i_payload;
2173 out->i_dts = out->i_pts;
2176 rtp_packetize_send( id, out );
2178 p_data += i_payload;
2179 i_data -= i_payload;
2185 /*****************************************************************************
2187 *****************************************************************************/
2189 /** Add an ES to a non-RTP muxed stream */
2190 static sout_stream_id_t *MuxAdd( sout_stream_t *p_stream, es_format_t *p_fmt )
2192 sout_input_t *p_input;
2193 sout_mux_t *p_mux = p_stream->p_sys->p_mux;
2194 assert( p_mux != NULL );
2196 p_input = sout_MuxAddStream( p_mux, p_fmt );
2197 if( p_input == NULL )
2199 msg_Err( p_stream, "cannot add this stream to the muxer" );
2203 return (sout_stream_id_t *)p_input;
2207 static int MuxSend( sout_stream_t *p_stream, sout_stream_id_t *id,
2210 sout_mux_t *p_mux = p_stream->p_sys->p_mux;
2211 assert( p_mux != NULL );
2213 sout_MuxSendBuffer( p_mux, (sout_input_t *)id, p_buffer );
2218 /** Remove an ES from a non-RTP muxed stream */
2219 static int MuxDel( sout_stream_t *p_stream, sout_stream_id_t *id )
2221 sout_mux_t *p_mux = p_stream->p_sys->p_mux;
2222 assert( p_mux != NULL );
2224 sout_MuxDeleteStream( p_mux, (sout_input_t *)id );
2229 static int AccessOutGrabberWriteBuffer( sout_stream_t *p_stream,
2230 const block_t *p_buffer )
2232 sout_stream_sys_t *p_sys = p_stream->p_sys;
2233 sout_stream_id_t *id = p_sys->es[0];
2235 int64_t i_dts = p_buffer->i_dts;
2237 uint8_t *p_data = p_buffer->p_buffer;
2238 unsigned int i_data = p_buffer->i_buffer;
2239 unsigned int i_max = id->i_mtu - 12;
2241 unsigned i_packet = ( p_buffer->i_buffer + i_max - 1 ) / i_max;
2245 unsigned int i_size;
2247 /* output complete packet */
2248 if( p_sys->packet &&
2249 p_sys->packet->i_buffer + i_data > i_max )
2251 rtp_packetize_send( id, p_sys->packet );
2252 p_sys->packet = NULL;
2255 if( p_sys->packet == NULL )
2257 /* allocate a new packet */
2258 p_sys->packet = block_New( p_stream, id->i_mtu );
2259 rtp_packetize_common( id, p_sys->packet, 1, i_dts );
2260 p_sys->packet->i_dts = i_dts;
2261 p_sys->packet->i_length = p_buffer->i_length / i_packet;
2262 i_dts += p_sys->packet->i_length;
2265 i_size = __MIN( i_data,
2266 (unsigned)(id->i_mtu - p_sys->packet->i_buffer) );
2268 memcpy( &p_sys->packet->p_buffer[p_sys->packet->i_buffer],
2271 p_sys->packet->i_buffer += i_size;
2280 static int AccessOutGrabberWrite( sout_access_out_t *p_access,
2283 sout_stream_t *p_stream = (sout_stream_t*)p_access->p_sys;
2289 AccessOutGrabberWriteBuffer( p_stream, p_buffer );
2291 p_next = p_buffer->p_next;
2292 block_Release( p_buffer );
2300 static sout_access_out_t *GrabberCreate( sout_stream_t *p_stream )
2302 sout_access_out_t *p_grab;
2304 p_grab = vlc_object_create( p_stream->p_sout, sizeof( *p_grab ) );
2305 if( p_grab == NULL )
2308 p_grab->p_module = NULL;
2309 p_grab->p_sout = p_stream->p_sout;
2310 p_grab->psz_access = strdup( "grab" );
2311 p_grab->p_cfg = NULL;
2312 p_grab->psz_path = strdup( "" );
2313 p_grab->p_sys = (sout_access_out_sys_t *)p_stream;
2314 p_grab->pf_seek = NULL;
2315 p_grab->pf_write = AccessOutGrabberWrite;
2319 static int rtp_packetize_spx( sout_stream_t *p_stream, sout_stream_id_t *id,
2322 uint8_t *p_buffer = in->p_buffer;
2323 int i_data_size, i_payload_size, i_payload_padding;
2324 i_data_size = i_payload_size = in->i_buffer;
2325 i_payload_padding = 0;
2328 if ( in->i_buffer + 12 > id->i_mtu )
2330 msg_Warn( p_stream, "Cannot send packet larger than output MTU" );
2335 RFC for Speex in RTP says that each packet must end on an octet
2336 boundary. So, we check to see if the number of bytes % 4 is zero.
2337 If not, we have to add some padding.
2339 This MAY be overkill since packetization is handled elsewhere and
2340 appears to ensure the octet boundary. However, better safe than
2343 if ( i_payload_size % 4 )
2345 i_payload_padding = 4 - ( i_payload_size % 4 );
2346 i_payload_size += i_payload_padding;
2350 Allocate a new RTP p_output block of the appropriate size.
2351 Allow for 12 extra bytes of RTP header.
2353 p_out = block_New( p_stream, 12 + i_payload_size );
2355 if ( i_payload_padding )
2358 The padding is required to be a zero followed by all 1s.
2360 char c_first_pad, c_remaining_pad;
2362 c_remaining_pad = 0xFF;
2365 Allow for 12 bytes before the i_data_size because
2366 of the expected RTP header added during
2367 rtp_packetize_common.
2369 p_out->p_buffer[12 + i_data_size] = c_first_pad;
2370 switch (i_payload_padding)
2373 p_out->p_buffer[12 + i_data_size + 1] = c_remaining_pad;
2376 p_out->p_buffer[12 + i_data_size + 1] = c_remaining_pad;
2377 p_out->p_buffer[12 + i_data_size + 2] = c_remaining_pad;
2382 /* Add the RTP header to our p_output buffer. */
2383 rtp_packetize_common( id, p_out, 0, (in->i_pts > 0 ? in->i_pts : in->i_dts) );
2384 /* Copy the Speex payload to the p_output buffer */
2385 memcpy( &p_out->p_buffer[12], p_buffer, i_data_size );
2387 p_out->i_buffer = 12 + i_payload_size;
2388 p_out->i_dts = in->i_dts;
2389 p_out->i_length = in->i_length;
2391 /* Queue the buffer for actual transmission. */
2392 rtp_packetize_send( id, p_out );