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 description")
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_enc, id->i_clock_rate, id->i_channels,
749 if( rtsp_url != NULL )
751 assert( strlen( rtsp_url ) > 0 );
752 vlc_bool_t addslash = ( rtsp_url[strlen( rtsp_url ) - 1] != '/' );
753 sdp_AddAttribute ( &psz_sdp, "control",
754 addslash ? "%s/trackID=%u" : "%strackID=%u",
759 if( id->listen_fd != NULL )
760 sdp_AddAttribute( &psz_sdp, "setup", "passive" );
762 if( p_sys->proto == IPPROTO_DCCP )
763 sdp_AddAttribute( &psz_sdp, "dccp-service-code",
764 "SC:RTP%c", toupper( mime_major[0] ) );
772 /*****************************************************************************
774 *****************************************************************************/
775 static int rtp_packetize_l16 ( sout_stream_t *, sout_stream_id_t *, block_t * );
776 static int rtp_packetize_l8 ( sout_stream_t *, sout_stream_id_t *, block_t * );
777 static int rtp_packetize_mpa ( sout_stream_t *, sout_stream_id_t *, block_t * );
778 static int rtp_packetize_mpv ( sout_stream_t *, sout_stream_id_t *, block_t * );
779 static int rtp_packetize_ac3 ( sout_stream_t *, sout_stream_id_t *, block_t * );
780 static int rtp_packetize_split( sout_stream_t *, sout_stream_id_t *, block_t * );
781 static int rtp_packetize_mp4a ( sout_stream_t *, sout_stream_id_t *, block_t * );
782 static int rtp_packetize_mp4a_latm ( sout_stream_t *, sout_stream_id_t *, block_t * );
783 static int rtp_packetize_h263 ( sout_stream_t *, sout_stream_id_t *, block_t * );
784 static int rtp_packetize_h264 ( sout_stream_t *, sout_stream_id_t *, block_t * );
785 static int rtp_packetize_amr ( sout_stream_t *, sout_stream_id_t *, block_t * );
786 static int rtp_packetize_spx ( sout_stream_t *, sout_stream_id_t *, block_t * );
787 static int rtp_packetize_t140 ( sout_stream_t *, sout_stream_id_t *, block_t * );
789 static void sprintf_hexa( char *s, uint8_t *p_data, int i_data )
791 static const char hex[16] = "0123456789abcdef";
794 for( i = 0; i < i_data; i++ )
796 s[2*i+0] = hex[(p_data[i]>>4)&0xf];
797 s[2*i+1] = hex[(p_data[i] )&0xf];
803 /** Add an ES as a new RTP stream */
804 static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
806 /* NOTE: As a special case, if we use a non-RTP
807 * mux (TS/PS), then p_fmt is NULL. */
808 sout_stream_sys_t *p_sys = p_stream->p_sys;
809 sout_stream_id_t *id;
810 int i_port, cscov = -1;
813 id = vlc_object_create( p_stream, sizeof( sout_stream_id_t ) );
816 vlc_object_attach( id, p_stream );
818 /* Choose the port */
823 if( p_fmt->i_cat == AUDIO_ES && p_sys->i_port_audio > 0 )
825 i_port = p_sys->i_port_audio;
826 p_sys->i_port_audio = 0;
829 if( p_fmt->i_cat == VIDEO_ES && p_sys->i_port_video > 0 )
831 i_port = p_sys->i_port_video;
832 p_sys->i_port_video = 0;
837 if( p_sys->i_port != p_sys->i_port_audio
838 && p_sys->i_port != p_sys->i_port_video )
840 i_port = p_sys->i_port;
847 id->p_stream = p_stream;
849 id->i_sequence = rand()&0xffff;
850 id->i_payload_type = p_sys->i_payload_type;
851 id->ssrc[0] = rand()&0xff;
852 id->ssrc[1] = rand()&0xff;
853 id->ssrc[2] = rand()&0xff;
854 id->ssrc[3] = rand()&0xff;
858 id->i_clock_rate = 90000; /* most common case for video */
863 id->i_cat = p_fmt->i_cat;
864 if( p_fmt->i_cat == AUDIO_ES )
866 id->i_clock_rate = p_fmt->audio.i_rate;
867 id->i_channels = p_fmt->audio.i_channels;
869 id->i_bitrate = p_fmt->i_bitrate/1000; /* Stream bitrate in kbps */
873 id->i_cat = VIDEO_ES;
877 id->pf_packetize = NULL;
878 id->i_mtu = config_GetInt( p_stream, "mtu" );
879 if( id->i_mtu <= 12 + 16 )
880 id->i_mtu = 576 - 20 - 8; /* pessimistic */
882 msg_Dbg( p_stream, "maximum RTP packet size: %d bytes", id->i_mtu );
884 vlc_mutex_init( p_stream, &id->lock_sink );
889 id->listen_fd = NULL;
892 (int64_t)1000 * var_GetInteger( p_stream, SOUT_CFG_PREFIX "caching");
894 if( p_sys->psz_destination != NULL )
895 switch( p_sys->proto )
899 id->listen_fd = net_Listen( VLC_OBJECT(p_stream),
900 p_sys->psz_destination, i_port,
902 if( id->listen_fd == NULL )
904 msg_Err( p_stream, "passive COMEDIA RTP socket failed" );
911 int ttl = (p_sys->i_ttl > 0) ? p_sys->i_ttl : -1;
912 int fd = net_ConnectDgram( p_stream, p_sys->psz_destination,
913 i_port, ttl, p_sys->proto );
916 msg_Err( p_stream, "cannot create RTP socket" );
919 rtp_add_sink( id, fd, p_sys->rtcp_mux );
925 char *psz = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "mux" );
927 if( psz == NULL ) /* Uho! */
930 if( strncmp( psz, "ts", 2 ) == 0 )
932 id->i_payload_type = 33;
933 id->psz_enc = "MP2T";
937 id->psz_enc = "MP2P";
941 switch( p_fmt->i_codec )
943 case VLC_FOURCC( 'u', 'l', 'a', 'w' ):
944 if( p_fmt->audio.i_channels == 1 && p_fmt->audio.i_rate == 8000 )
945 id->i_payload_type = 0;
946 id->psz_enc = "PCMU";
947 id->pf_packetize = rtp_packetize_l8;
949 case VLC_FOURCC( 'a', 'l', 'a', 'w' ):
950 if( p_fmt->audio.i_channels == 1 && p_fmt->audio.i_rate == 8000 )
951 id->i_payload_type = 8;
952 id->psz_enc = "PCMA";
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;
966 id->pf_packetize = rtp_packetize_l16;
968 case VLC_FOURCC( 'u', '8', ' ', ' ' ):
970 id->pf_packetize = rtp_packetize_l8;
972 case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
973 id->i_payload_type = 14;
975 id->pf_packetize = rtp_packetize_mpa;
977 case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
978 id->i_payload_type = 32;
980 id->pf_packetize = rtp_packetize_mpv;
982 case VLC_FOURCC( 'a', '5', '2', ' ' ):
984 id->pf_packetize = rtp_packetize_ac3;
986 case VLC_FOURCC( 'H', '2', '6', '3' ):
987 id->psz_enc = "H263-1998";
988 id->pf_packetize = rtp_packetize_h263;
990 case VLC_FOURCC( 'h', '2', '6', '4' ):
991 id->psz_enc = "H264";
992 id->pf_packetize = rtp_packetize_h264;
995 if( p_fmt->i_extra > 0 )
997 uint8_t *p_buffer = p_fmt->p_extra;
998 int i_buffer = p_fmt->i_extra;
999 char *p_64_sps = NULL;
1000 char *p_64_pps = NULL;
1003 while( i_buffer > 4 &&
1004 p_buffer[0] == 0 && p_buffer[1] == 0 &&
1005 p_buffer[2] == 0 && p_buffer[3] == 1 )
1007 const int i_nal_type = p_buffer[4]&0x1f;
1011 msg_Dbg( p_stream, "we found a startcode for NAL with TYPE:%d", i_nal_type );
1014 for( i_offset = 4; i_offset+3 < i_buffer ; i_offset++)
1016 if( !memcmp (p_buffer + i_offset, "\x00\x00\x00\x01", 4 ) )
1018 /* we found another startcode */
1023 if( i_nal_type == 7 )
1025 p_64_sps = vlc_b64_encode_binary( &p_buffer[4], i_size - 4 );
1026 sprintf_hexa( hexa, &p_buffer[5], 3 );
1028 else if( i_nal_type == 8 )
1030 p_64_pps = vlc_b64_encode_binary( &p_buffer[4], i_size - 4 );
1036 if( p_64_sps && p_64_pps &&
1037 ( asprintf( &id->psz_fmtp,
1038 "packetization-mode=1;profile-level-id=%s;"
1039 "sprop-parameter-sets=%s,%s;", hexa, p_64_sps,
1040 p_64_pps ) == -1 ) )
1041 id->psz_fmtp = NULL;
1046 id->psz_fmtp = strdup( "packetization-mode=1" );
1049 case VLC_FOURCC( 'm', 'p', '4', 'v' ):
1051 char hexa[2*p_fmt->i_extra +1];
1053 id->psz_enc = "MP4V-ES";
1054 id->pf_packetize = rtp_packetize_split;
1055 if( p_fmt->i_extra > 0 )
1057 sprintf_hexa( hexa, p_fmt->p_extra, p_fmt->i_extra );
1058 if( asprintf( &id->psz_fmtp,
1059 "profile-level-id=3; config=%s;", hexa ) == -1 )
1060 id->psz_fmtp = NULL;
1064 case VLC_FOURCC( 'm', 'p', '4', 'a' ):
1068 char hexa[2*p_fmt->i_extra +1];
1070 id->psz_enc = "mpeg4-generic";
1071 id->pf_packetize = rtp_packetize_mp4a;
1072 sprintf_hexa( hexa, p_fmt->p_extra, p_fmt->i_extra );
1073 if( asprintf( &id->psz_fmtp,
1074 "streamtype=5; profile-level-id=15; "
1075 "mode=AAC-hbr; config=%s; SizeLength=13; "
1076 "IndexLength=3; IndexDeltaLength=3; Profile=1;",
1078 id->psz_fmtp = NULL;
1084 unsigned char config[6];
1085 unsigned int aacsrates[15] = {
1086 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
1087 16000, 12000, 11025, 8000, 7350, 0, 0 };
1089 for( i = 0; i < 15; i++ )
1090 if( p_fmt->audio.i_rate == aacsrates[i] )
1096 config[3]=p_fmt->audio.i_channels<<4;
1100 id->psz_enc = "MP4A-LATM";
1101 id->pf_packetize = rtp_packetize_mp4a_latm;
1102 sprintf_hexa( hexa, config, 6 );
1103 if( asprintf( &id->psz_fmtp, "profile-level-id=15; "
1104 "object=2; cpresent=0; config=%s", hexa ) == -1 )
1105 id->psz_fmtp = NULL;
1109 case VLC_FOURCC( 's', 'a', 'm', 'r' ):
1110 id->psz_enc = "AMR";
1111 id->psz_fmtp = strdup( "octet-align=1" );
1112 id->pf_packetize = rtp_packetize_amr;
1114 case VLC_FOURCC( 's', 'a', 'w', 'b' ):
1115 id->psz_enc = "AMR-WB";
1116 id->psz_fmtp = strdup( "octet-align=1" );
1117 id->pf_packetize = rtp_packetize_amr;
1119 case VLC_FOURCC( 's', 'p', 'x', ' ' ):
1120 id->i_payload_type = p_sys->i_payload_type++;
1121 id->psz_enc = "SPEEX";
1122 id->pf_packetize = rtp_packetize_spx;
1124 case VLC_FOURCC( 't', '1', '4', '0' ):
1125 id->psz_enc = "t140" ;
1126 id->i_clock_rate = 1000;
1127 id->pf_packetize = rtp_packetize_t140;
1131 msg_Err( p_stream, "cannot add this stream (unsupported "
1132 "codec:%4.4s)", (char*)&p_fmt->i_codec );
1137 cscov += 8 /* UDP */ + 12 /* RTP */;
1139 net_SetCSCov( id->sinkv[0].rtp_fd, cscov, -1 );
1141 if( id->i_payload_type == p_sys->i_payload_type )
1142 p_sys->i_payload_type++;
1144 if( p_sys->rtsp != NULL )
1145 id->rtsp_id = RtspAddId( p_sys->rtsp, id, p_sys->i_es,
1146 GetDWBE( id->ssrc ),
1147 p_sys->psz_destination,
1148 p_sys->i_ttl, id->i_port, id->i_port + 1 );
1150 id->p_fifo = block_FifoNew( p_stream );
1151 if( vlc_thread_create( id, "RTP send thread", ThreadSend,
1152 VLC_THREAD_PRIORITY_HIGHEST, VLC_FALSE ) )
1155 /* Update p_sys context */
1156 vlc_mutex_lock( &p_sys->lock_es );
1157 TAB_APPEND( p_sys->i_es, p_sys->es, id );
1158 vlc_mutex_unlock( &p_sys->lock_es );
1160 psz_sdp = SDPGenerate( p_stream, NULL );
1162 vlc_mutex_lock( &p_sys->lock_sdp );
1163 free( p_sys->psz_sdp );
1164 p_sys->psz_sdp = psz_sdp;
1165 vlc_mutex_unlock( &p_sys->lock_sdp );
1167 msg_Dbg( p_stream, "sdp=\n%s", p_sys->psz_sdp );
1169 /* Update SDP (sap/file) */
1170 if( p_sys->b_export_sap ) SapSetup( p_stream );
1171 if( p_sys->b_export_sdp_file ) FileSetup( p_stream );
1176 Del( p_stream, id );
1180 static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
1182 sout_stream_sys_t *p_sys = p_stream->p_sys;
1184 if( id->p_fifo != NULL )
1186 vlc_object_kill( id );
1187 block_FifoWake( id->p_fifo );
1188 vlc_thread_join( id );
1189 block_FifoRelease( id->p_fifo );
1192 vlc_mutex_lock( &p_sys->lock_es );
1193 TAB_REMOVE( p_sys->i_es, p_sys->es, id );
1194 vlc_mutex_unlock( &p_sys->lock_es );
1197 if( id->i_port > 0 )
1199 if( id->i_cat == AUDIO_ES && p_sys->i_port_audio == 0 )
1200 p_sys->i_port_audio = id->i_port;
1201 else if( id->i_cat == VIDEO_ES && p_sys->i_port_video == 0 )
1202 p_sys->i_port_video = id->i_port;
1205 free( id->psz_fmtp );
1208 RtspDelId( p_sys->rtsp, id->rtsp_id );
1210 rtp_del_sink( id, id->sinkv[0].rtp_fd ); /* sink for explicit dst= */
1211 if( id->listen_fd != NULL )
1212 net_ListenClose( id->listen_fd );
1214 vlc_mutex_destroy( &id->lock_sink );
1216 /* Update SDP (sap/file) */
1217 if( p_sys->b_export_sap && !p_sys->p_mux ) SapSetup( p_stream );
1218 if( p_sys->b_export_sdp_file ) FileSetup( p_stream );
1220 vlc_object_detach( id );
1221 vlc_object_destroy( id );
1225 static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
1230 assert( p_stream->p_sys->p_mux == NULL );
1232 while( p_buffer != NULL )
1234 p_next = p_buffer->p_next;
1235 if( id->pf_packetize( p_stream, id, p_buffer ) )
1238 block_Release( p_buffer );
1244 /****************************************************************************
1246 ****************************************************************************/
1247 static int SapSetup( sout_stream_t *p_stream )
1249 sout_stream_sys_t *p_sys = p_stream->p_sys;
1250 sout_instance_t *p_sout = p_stream->p_sout;
1252 /* Remove the previous session */
1253 if( p_sys->p_session != NULL)
1255 sout_AnnounceUnRegister( p_sout, p_sys->p_session);
1256 p_sys->p_session = NULL;
1259 if( ( p_sys->i_es > 0 || p_sys->p_mux ) && p_sys->psz_sdp && *p_sys->psz_sdp )
1261 announce_method_t *p_method = sout_SAPMethod();
1262 p_sys->p_session = sout_AnnounceRegisterSDP( p_sout, SOUT_CFG_PREFIX,
1264 p_sys->psz_destination,
1266 sout_MethodRelease( p_method );
1272 /****************************************************************************
1274 ****************************************************************************/
1275 static int FileSetup( sout_stream_t *p_stream )
1277 sout_stream_sys_t *p_sys = p_stream->p_sys;
1280 if( ( f = utf8_fopen( p_sys->psz_sdp_file, "wt" ) ) == NULL )
1282 msg_Err( p_stream, "cannot open file '%s' (%m)",
1283 p_sys->psz_sdp_file );
1284 return VLC_EGENERIC;
1287 fputs( p_sys->psz_sdp, f );
1293 /****************************************************************************
1295 ****************************************************************************/
1296 static int HttpCallback( httpd_file_sys_t *p_args,
1297 httpd_file_t *, uint8_t *p_request,
1298 uint8_t **pp_data, int *pi_data );
1300 static int HttpSetup( sout_stream_t *p_stream, vlc_url_t *url)
1302 sout_stream_sys_t *p_sys = p_stream->p_sys;
1304 p_sys->p_httpd_host = httpd_HostNew( VLC_OBJECT(p_stream), url->psz_host,
1305 url->i_port > 0 ? url->i_port : 80 );
1306 if( p_sys->p_httpd_host )
1308 p_sys->p_httpd_file = httpd_FileNew( p_sys->p_httpd_host,
1309 url->psz_path ? url->psz_path : "/",
1312 HttpCallback, (void*)p_sys );
1314 if( p_sys->p_httpd_file == NULL )
1316 return VLC_EGENERIC;
1321 static int HttpCallback( httpd_file_sys_t *p_args,
1322 httpd_file_t *f, uint8_t *p_request,
1323 uint8_t **pp_data, int *pi_data )
1325 sout_stream_sys_t *p_sys = (sout_stream_sys_t*)p_args;
1327 vlc_mutex_lock( &p_sys->lock_sdp );
1328 if( p_sys->psz_sdp && *p_sys->psz_sdp )
1330 *pi_data = strlen( p_sys->psz_sdp );
1331 *pp_data = malloc( *pi_data );
1332 memcpy( *pp_data, p_sys->psz_sdp, *pi_data );
1339 vlc_mutex_unlock( &p_sys->lock_sdp );
1344 /****************************************************************************
1346 ****************************************************************************/
1347 static void ThreadSend( vlc_object_t *p_this )
1349 sout_stream_id_t *id = (sout_stream_id_t *)p_this;
1350 unsigned i_caching = id->i_caching;
1352 int fd[5] = { -1, -1, -1, -1, -1 };
1360 fd[4] = open( "/dev/null", O_WRONLY );
1365 block_t *out = block_FifoGet( id->p_fifo );
1367 continue; /* Forced wakeup */
1369 mtime_t i_date = out->i_dts + i_caching;
1370 ssize_t len = out->i_buffer;
1374 len = write( fd[1], out->p_buffer, len);
1376 continue; /* Uho - should not happen */
1380 vlc_mutex_lock( &id->lock_sink );
1381 unsigned deadc = 0; /* How many dead sockets? */
1382 int deadv[id->sinkc]; /* Dead sockets list */
1384 for( int i = 0; i < id->sinkc; i++ )
1386 SendRTCP( id->sinkv[i].rtcp, out );
1389 tee( fd[0], fd[3], len, 0 );
1390 if( splice( fd[2], NULL, id->sinkv[i].rtp_fd, NULL, len,
1391 SPLICE_F_NONBLOCK ) >= 0 )
1393 if( errno == EAGAIN )
1397 splice( fd[2], NULL, fd[4], NULL, len, 0 );
1399 if( send( id->sinkv[i].rtp_fd, out->p_buffer, len, 0 ) >= 0 )
1402 /* Retry sending to root out soft-errors */
1403 if( send( id->sinkv[i].rtp_fd, out->p_buffer, len, 0 ) >= 0 )
1406 deadv[deadc++] = id->sinkv[i].rtp_fd;
1408 vlc_mutex_unlock( &id->lock_sink );
1410 block_Release( out );
1412 splice( fd[0], NULL, fd[4], NULL, len, 0 );
1415 for( unsigned i = 0; i < deadc; i++ )
1417 msg_Dbg( id, "removing socket %d", deadv[i] );
1418 rtp_del_sink( id, deadv[i] );
1421 /* Hopefully we won't overflow the SO_MAXCONN accept queue */
1422 while( id->listen_fd != NULL )
1424 int fd = net_Accept( id, id->listen_fd, 0 );
1427 msg_Dbg( id, "adding socket %d", fd );
1428 rtp_add_sink( id, fd, VLC_TRUE );
1433 for( unsigned i = 0; i < 5; i++ )
1438 static inline void rtp_packetize_send( sout_stream_id_t *id, block_t *out )
1440 block_FifoPut( id->p_fifo, out );
1443 int rtp_add_sink( sout_stream_id_t *id, int fd, vlc_bool_t rtcp_mux )
1445 rtp_sink_t sink = { fd, NULL };
1446 sink.rtcp = OpenRTCP( VLC_OBJECT( id->p_stream ), fd, IPPROTO_UDP,
1448 if( sink.rtcp == NULL )
1449 msg_Err( id, "RTCP failed!" );
1451 vlc_mutex_lock( &id->lock_sink );
1452 INSERT_ELEM( id->sinkv, id->sinkc, id->sinkc, sink );
1453 vlc_mutex_unlock( &id->lock_sink );
1457 void rtp_del_sink( sout_stream_id_t *id, int fd )
1459 rtp_sink_t sink = { fd, NULL };
1461 /* NOTE: must be safe to use if fd is not included */
1462 vlc_mutex_lock( &id->lock_sink );
1463 for( int i = 0; i < id->sinkc; i++ )
1465 if (id->sinkv[i].rtp_fd == fd)
1467 sink = id->sinkv[i];
1468 REMOVE_ELEM( id->sinkv, id->sinkc, i );
1472 vlc_mutex_unlock( &id->lock_sink );
1474 CloseRTCP( sink.rtcp );
1475 net_Close( sink.rtp_fd );
1478 uint16_t rtp_get_seq( const sout_stream_id_t *id )
1480 /* This will return values for the next packet.
1481 * Accounting for caching would not be totally trivial. */
1482 return id->i_sequence;
1485 /* FIXME: this is pretty bad - if we remove and then insert an ES
1486 * the number will get unsynched from inside RTSP */
1487 unsigned rtp_get_num( const sout_stream_id_t *id )
1489 sout_stream_sys_t *p_sys = id->p_stream->p_sys;
1492 vlc_mutex_lock( &p_sys->lock_es );
1493 for( i = 0; i < p_sys->i_es; i++ )
1495 if( id == p_sys->es[i] )
1498 vlc_mutex_unlock( &p_sys->lock_es );
1504 /****************************************************************************
1506 ****************************************************************************/
1507 static void rtp_packetize_common( sout_stream_id_t *id, block_t *out,
1508 int b_marker, int64_t i_pts )
1510 uint32_t i_timestamp = i_pts * (int64_t)id->i_clock_rate / I64C(1000000);
1512 out->p_buffer[0] = 0x80;
1513 out->p_buffer[1] = (b_marker?0x80:0x00)|id->i_payload_type;
1514 out->p_buffer[2] = ( id->i_sequence >> 8)&0xff;
1515 out->p_buffer[3] = ( id->i_sequence )&0xff;
1516 out->p_buffer[4] = ( i_timestamp >> 24 )&0xff;
1517 out->p_buffer[5] = ( i_timestamp >> 16 )&0xff;
1518 out->p_buffer[6] = ( i_timestamp >> 8 )&0xff;
1519 out->p_buffer[7] = ( i_timestamp )&0xff;
1521 memcpy( out->p_buffer + 8, id->ssrc, 4 );
1527 static int rtp_packetize_mpa( sout_stream_t *p_stream, sout_stream_id_t *id,
1530 int i_max = id->i_mtu - 12 - 4; /* payload max in one packet */
1531 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1533 uint8_t *p_data = in->p_buffer;
1534 int i_data = in->i_buffer;
1537 for( i = 0; i < i_count; i++ )
1539 int i_payload = __MIN( i_max, i_data );
1540 block_t *out = block_New( p_stream, 16 + i_payload );
1542 /* rtp common header */
1543 rtp_packetize_common( id, out, (i == i_count - 1)?1:0, in->i_pts );
1545 out->p_buffer[12] = 0;
1546 out->p_buffer[13] = 0;
1547 /* fragment offset in the current frame */
1548 out->p_buffer[14] = ( (i*i_max) >> 8 )&0xff;
1549 out->p_buffer[15] = ( (i*i_max) )&0xff;
1550 memcpy( &out->p_buffer[16], p_data, i_payload );
1552 out->i_buffer = 16 + i_payload;
1553 out->i_dts = in->i_dts + i * in->i_length / i_count;
1554 out->i_length = in->i_length / i_count;
1556 rtp_packetize_send( id, out );
1558 p_data += i_payload;
1559 i_data -= i_payload;
1566 static int rtp_packetize_mpv( sout_stream_t *p_stream, sout_stream_id_t *id,
1569 int i_max = id->i_mtu - 12 - 4; /* payload max in one packet */
1570 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1572 uint8_t *p_data = in->p_buffer;
1573 int i_data = in->i_buffer;
1575 int b_sequence_start = 0;
1576 int i_temporal_ref = 0;
1577 int i_picture_coding_type = 0;
1578 int i_fbv = 0, i_bfc = 0, i_ffv = 0, i_ffc = 0;
1579 int b_start_slice = 0;
1581 /* preparse this packet to get some info */
1582 if( in->i_buffer > 4 )
1584 uint8_t *p = p_data;
1585 int i_rest = in->i_buffer;
1589 while( i_rest > 4 &&
1590 ( p[0] != 0x00 || p[1] != 0x00 || p[2] != 0x01 ) )
1604 /* sequence start code */
1605 b_sequence_start = 1;
1607 else if( *p == 0x00 && i_rest >= 4 )
1610 i_temporal_ref = ( p[1] << 2) |((p[2]>>6)&0x03);
1611 i_picture_coding_type = (p[2] >> 3)&0x07;
1613 if( i_rest >= 4 && ( i_picture_coding_type == 2 ||
1614 i_picture_coding_type == 3 ) )
1616 i_ffv = (p[3] >> 2)&0x01;
1617 i_ffc = ((p[3]&0x03) << 1)|((p[4]>>7)&0x01);
1618 if( i_rest > 4 && i_picture_coding_type == 3 )
1620 i_fbv = (p[4]>>6)&0x01;
1621 i_bfc = (p[4]>>3)&0x07;
1625 else if( *p <= 0xaf )
1632 for( i = 0; i < i_count; i++ )
1634 int i_payload = __MIN( i_max, i_data );
1635 block_t *out = block_New( p_stream,
1637 uint32_t h = ( i_temporal_ref << 16 )|
1638 ( b_sequence_start << 13 )|
1639 ( b_start_slice << 12 )|
1640 ( i == i_count - 1 ? 1 << 11 : 0 )|
1641 ( i_picture_coding_type << 8 )|
1642 ( i_fbv << 7 )|( i_bfc << 4 )|( i_ffv << 3 )|i_ffc;
1644 /* rtp common header */
1645 rtp_packetize_common( id, out, (i == i_count - 1)?1:0,
1646 in->i_pts > 0 ? in->i_pts : in->i_dts );
1648 /* 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 */
1649 out->p_buffer[12] = ( h >> 24 )&0xff;
1650 out->p_buffer[13] = ( h >> 16 )&0xff;
1651 out->p_buffer[14] = ( h >> 8 )&0xff;
1652 out->p_buffer[15] = ( h )&0xff;
1654 memcpy( &out->p_buffer[16], p_data, i_payload );
1656 out->i_buffer = 16 + i_payload;
1657 out->i_dts = in->i_dts + i * in->i_length / i_count;
1658 out->i_length = in->i_length / i_count;
1660 rtp_packetize_send( id, out );
1662 p_data += i_payload;
1663 i_data -= i_payload;
1669 static int rtp_packetize_ac3( sout_stream_t *p_stream, sout_stream_id_t *id,
1672 int i_max = id->i_mtu - 12 - 2; /* payload max in one packet */
1673 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1675 uint8_t *p_data = in->p_buffer;
1676 int i_data = in->i_buffer;
1679 for( i = 0; i < i_count; i++ )
1681 int i_payload = __MIN( i_max, i_data );
1682 block_t *out = block_New( p_stream, 14 + i_payload );
1684 /* rtp common header */
1685 rtp_packetize_common( id, out, (i == i_count - 1)?1:0, in->i_pts );
1687 out->p_buffer[12] = 1;
1689 out->p_buffer[13] = 0x00;
1691 memcpy( &out->p_buffer[14], p_data, i_payload );
1693 out->i_buffer = 14 + i_payload;
1694 out->i_dts = in->i_dts + i * in->i_length / i_count;
1695 out->i_length = in->i_length / i_count;
1697 rtp_packetize_send( id, out );
1699 p_data += i_payload;
1700 i_data -= i_payload;
1706 static int rtp_packetize_split( sout_stream_t *p_stream, sout_stream_id_t *id,
1709 int i_max = id->i_mtu - 12; /* payload max in one packet */
1710 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1712 uint8_t *p_data = in->p_buffer;
1713 int i_data = in->i_buffer;
1716 for( i = 0; i < i_count; i++ )
1718 int i_payload = __MIN( i_max, i_data );
1719 block_t *out = block_New( p_stream, 12 + i_payload );
1721 /* rtp common header */
1722 rtp_packetize_common( id, out, ((i == i_count - 1)?1:0),
1723 (in->i_pts > 0 ? in->i_pts : in->i_dts) );
1724 memcpy( &out->p_buffer[12], p_data, i_payload );
1726 out->i_buffer = 12 + i_payload;
1727 out->i_dts = in->i_dts + i * in->i_length / i_count;
1728 out->i_length = in->i_length / i_count;
1730 rtp_packetize_send( id, out );
1732 p_data += i_payload;
1733 i_data -= i_payload;
1740 static int rtp_packetize_mp4a_latm( sout_stream_t *p_stream, sout_stream_id_t *id,
1743 int i_max = id->i_mtu - 14; /* payload max in one packet */
1744 int latmhdrsize = in->i_buffer / 0xff + 1;
1745 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1747 uint8_t *p_data = in->p_buffer, *p_header = NULL;
1748 int i_data = in->i_buffer;
1751 for( i = 0; i < i_count; i++ )
1753 int i_payload = __MIN( i_max, i_data );
1758 out = block_New( p_stream, 12 + latmhdrsize + i_payload );
1760 /* rtp common header */
1761 rtp_packetize_common( id, out, ((i == i_count - 1) ? 1 : 0),
1762 (in->i_pts > 0 ? in->i_pts : in->i_dts) );
1766 int tmp = in->i_buffer;
1768 p_header=out->p_buffer+12;
1778 memcpy( &out->p_buffer[12+latmhdrsize], p_data, i_payload );
1780 out->i_buffer = 12 + latmhdrsize + i_payload;
1781 out->i_dts = in->i_dts + i * in->i_length / i_count;
1782 out->i_length = in->i_length / i_count;
1784 rtp_packetize_send( id, out );
1786 p_data += i_payload;
1787 i_data -= i_payload;
1793 static int rtp_packetize_l16( sout_stream_t *p_stream, sout_stream_id_t *id,
1796 const uint8_t *p_data = in->p_buffer;
1797 size_t i_data = in->i_buffer;
1798 /* ptime=20ms -> 50Hz */
1799 size_t i_plen = 2 * id->i_channels * ( ( id->i_clock_rate + 49 ) / 50 );
1801 for( unsigned i_packet = 0; i_data > 0; i_packet++ )
1803 int i_payload = __MIN( i_plen, i_data );
1804 block_t *out = block_New( p_stream, 12 + i_payload );
1806 /* rtp common header */
1807 rtp_packetize_common( id, out, 0,
1808 (in->i_pts > 0 ? in->i_pts : in->i_dts) );
1809 memcpy( &out->p_buffer[12], p_data, i_payload );
1811 out->i_buffer = 12 + i_payload;
1812 out->i_dts = in->i_dts + i_packet * 20000;
1813 out->i_length = i_payload * 20000 / i_plen;
1815 rtp_packetize_send( id, out );
1817 p_data += i_payload;
1818 i_data -= i_payload;
1824 static int rtp_packetize_l8( sout_stream_t *p_stream, sout_stream_id_t *id,
1827 const uint8_t *p_data = in->p_buffer;
1828 size_t i_data = in->i_buffer;
1829 /* ptime=20ms -> 50Hz */
1830 size_t i_plen = id->i_channels * ( ( id->i_clock_rate + 49 ) / 50 );
1832 for( unsigned i_packet = 0; i_data > 0; i_packet++ )
1834 int i_payload = __MIN( i_plen, i_data );
1835 block_t *out = block_New( p_stream, 12 + i_payload );
1837 /* rtp common header */
1838 rtp_packetize_common( id, out, 0,
1839 (in->i_pts > 0 ? in->i_pts : in->i_dts) );
1840 memcpy( &out->p_buffer[12], p_data, i_payload );
1842 out->i_buffer = 12 + i_payload;
1843 out->i_dts = in->i_dts + i_packet * 20000;
1844 out->i_length = i_payload * 20000 / i_plen;
1846 rtp_packetize_send( id, out );
1848 p_data += i_payload;
1849 i_data -= i_payload;
1855 static int rtp_packetize_mp4a( sout_stream_t *p_stream, sout_stream_id_t *id,
1858 int i_max = id->i_mtu - 16; /* payload max in one packet */
1859 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1861 uint8_t *p_data = in->p_buffer;
1862 int i_data = in->i_buffer;
1865 for( i = 0; i < i_count; i++ )
1867 int i_payload = __MIN( i_max, i_data );
1868 block_t *out = block_New( p_stream, 16 + i_payload );
1870 /* rtp common header */
1871 rtp_packetize_common( id, out, ((i == i_count - 1)?1:0),
1872 (in->i_pts > 0 ? in->i_pts : in->i_dts) );
1874 /* AU headers length (bits) */
1875 out->p_buffer[12] = 0;
1876 out->p_buffer[13] = 2*8;
1877 /* for each AU length 13 bits + idx 3bits, */
1878 out->p_buffer[14] = ( in->i_buffer >> 5 )&0xff;
1879 out->p_buffer[15] = ( (in->i_buffer&0xff)<<3 )|0;
1881 memcpy( &out->p_buffer[16], p_data, i_payload );
1883 out->i_buffer = 16 + i_payload;
1884 out->i_dts = in->i_dts + i * in->i_length / i_count;
1885 out->i_length = in->i_length / i_count;
1887 rtp_packetize_send( id, out );
1889 p_data += i_payload;
1890 i_data -= i_payload;
1898 #define RTP_H263_HEADER_SIZE (2) // plen = 0
1899 #define RTP_H263_PAYLOAD_START (14) // plen = 0
1900 static int rtp_packetize_h263( sout_stream_t *p_stream, sout_stream_id_t *id,
1903 uint8_t *p_data = in->p_buffer;
1904 int i_data = in->i_buffer;
1906 int i_max = id->i_mtu - 12 - RTP_H263_HEADER_SIZE; /* payload max in one packet */
1909 int b_v_bit = 0; // no pesky error resilience
1910 int i_plen = 0; // normally plen=0 for PSC packet
1911 int i_pebit = 0; // because plen=0
1916 return VLC_EGENERIC;
1918 if( p_data[0] || p_data[1] )
1920 return VLC_EGENERIC;
1922 /* remove 2 leading 0 bytes */
1925 i_count = ( i_data + i_max - 1 ) / i_max;
1927 for( i = 0; i < i_count; i++ )
1929 int i_payload = __MIN( i_max, i_data );
1930 block_t *out = block_New( p_stream,
1931 RTP_H263_PAYLOAD_START + i_payload );
1932 b_p_bit = (i == 0) ? 1 : 0;
1933 h = ( b_p_bit << 10 )|
1938 /* rtp common header */
1939 //b_m_bit = 1; // always contains end of frame
1940 rtp_packetize_common( id, out, (i == i_count - 1)?1:0,
1941 in->i_pts > 0 ? in->i_pts : in->i_dts );
1944 out->p_buffer[12] = ( h >> 8 )&0xff;
1945 out->p_buffer[13] = ( h )&0xff;
1946 memcpy( &out->p_buffer[RTP_H263_PAYLOAD_START], p_data, i_payload );
1948 out->i_buffer = RTP_H263_PAYLOAD_START + i_payload;
1949 out->i_dts = in->i_dts + i * in->i_length / i_count;
1950 out->i_length = in->i_length / i_count;
1952 rtp_packetize_send( id, out );
1954 p_data += i_payload;
1955 i_data -= i_payload;
1963 rtp_packetize_h264_nal( sout_stream_t *p_stream, sout_stream_id_t *id,
1964 const uint8_t *p_data, int i_data, int64_t i_pts,
1965 int64_t i_dts, vlc_bool_t b_last, int64_t i_length )
1967 const int i_max = id->i_mtu - 12; /* payload max in one packet */
1974 i_nal_hdr = p_data[3];
1975 i_nal_type = i_nal_hdr&0x1f;
1977 /* Skip start code */
1982 if( i_data <= i_max )
1984 /* Single NAL unit packet */
1985 block_t *out = block_New( p_stream, 12 + i_data );
1987 out->i_length = i_length;
1990 rtp_packetize_common( id, out, b_last, i_pts );
1991 out->i_buffer = 12 + i_data;
1993 memcpy( &out->p_buffer[12], p_data, i_data );
1995 rtp_packetize_send( id, out );
1999 /* FU-A Fragmentation Unit without interleaving */
2000 const int i_count = ( i_data-1 + i_max-2 - 1 ) / (i_max-2);
2006 for( i = 0; i < i_count; i++ )
2008 const int i_payload = __MIN( i_data, i_max-2 );
2009 block_t *out = block_New( p_stream, 12 + 2 + i_payload );
2010 out->i_dts = i_dts + i * i_length / i_count;
2011 out->i_length = i_length / i_count;
2014 rtp_packetize_common( id, out, (b_last && i_payload == i_data), i_pts );
2015 out->i_buffer = 14 + i_payload;
2018 out->p_buffer[12] = 0x00 | (i_nal_hdr & 0x60) | 28;
2020 out->p_buffer[13] = ( i == 0 ? 0x80 : 0x00 ) | ( (i == i_count-1) ? 0x40 : 0x00 ) | i_nal_type;
2021 memcpy( &out->p_buffer[14], p_data, i_payload );
2023 rtp_packetize_send( id, out );
2025 i_data -= i_payload;
2026 p_data += i_payload;
2032 static int rtp_packetize_h264( sout_stream_t *p_stream, sout_stream_id_t *id,
2035 const uint8_t *p_buffer = in->p_buffer;
2036 int i_buffer = in->i_buffer;
2038 while( i_buffer > 4 && ( p_buffer[0] != 0 || p_buffer[1] != 0 || p_buffer[2] != 1 ) )
2044 /* Split nal units */
2045 while( i_buffer > 4 )
2048 int i_size = i_buffer;
2049 int i_skip = i_buffer;
2051 /* search nal end */
2052 for( i_offset = 4; i_offset+2 < i_buffer ; i_offset++)
2054 if( p_buffer[i_offset] == 0 && p_buffer[i_offset+1] == 0 && p_buffer[i_offset+2] == 1 )
2056 /* we found another startcode */
2057 i_size = i_offset - ( p_buffer[i_offset-1] == 0 ? 1 : 0);
2062 /* TODO add STAP-A to remove a lot of overhead with small slice/sei/... */
2063 rtp_packetize_h264_nal( p_stream, id, p_buffer, i_size,
2064 (in->i_pts > 0 ? in->i_pts : in->i_dts), in->i_dts,
2065 (i_size >= i_buffer), in->i_length * i_size / in->i_buffer );
2073 static int rtp_packetize_amr( sout_stream_t *p_stream, sout_stream_id_t *id,
2076 int i_max = id->i_mtu - 14; /* payload max in one packet */
2077 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
2079 uint8_t *p_data = in->p_buffer;
2080 int i_data = in->i_buffer;
2083 /* Only supports octet-aligned mode */
2084 for( i = 0; i < i_count; i++ )
2086 int i_payload = __MIN( i_max, i_data );
2087 block_t *out = block_New( p_stream, 14 + i_payload );
2089 /* rtp common header */
2090 rtp_packetize_common( id, out, ((i == i_count - 1)?1:0),
2091 (in->i_pts > 0 ? in->i_pts : in->i_dts) );
2092 /* Payload header */
2093 out->p_buffer[12] = 0xF0; /* CMR */
2094 out->p_buffer[13] = p_data[0]&0x7C; /* ToC */ /* FIXME: frame type */
2096 /* FIXME: are we fed multiple frames ? */
2097 memcpy( &out->p_buffer[14], p_data+1, i_payload-1 );
2099 out->i_buffer = 14 + i_payload-1;
2100 out->i_dts = in->i_dts + i * in->i_length / i_count;
2101 out->i_length = in->i_length / i_count;
2103 rtp_packetize_send( id, out );
2105 p_data += i_payload;
2106 i_data -= i_payload;
2112 static int rtp_packetize_t140( sout_stream_t *p_stream, sout_stream_id_t *id,
2115 const size_t i_max = id->i_mtu - 12;
2116 const uint8_t *p_data = in->p_buffer;
2117 size_t i_data = in->i_buffer;
2119 for( unsigned i_packet = 0; i_data > 0; i_packet++ )
2121 size_t i_payload = i_data;
2123 /* Make sure we stop on an UTF-8 character boundary
2124 * (assuming the input is valid UTF-8) */
2125 if( i_data > i_max )
2129 while( ( p_data[i_payload] & 0xC0 ) == 0x80 )
2131 if( i_payload == 0 )
2132 return VLC_SUCCESS; /* fishy input! */
2138 block_t *out = block_New( p_stream, 12 + i_payload );
2142 rtp_packetize_common( id, out, 0, in->i_pts + i_packet );
2143 memcpy( out->p_buffer + 12, p_data, i_payload );
2145 out->i_buffer = 12 + i_payload;
2146 out->i_dts = out->i_pts;
2149 rtp_packetize_send( id, out );
2151 p_data += i_payload;
2152 i_data -= i_payload;
2158 /*****************************************************************************
2160 *****************************************************************************/
2162 /** Add an ES to a non-RTP muxed stream */
2163 static sout_stream_id_t *MuxAdd( sout_stream_t *p_stream, es_format_t *p_fmt )
2165 sout_input_t *p_input;
2166 sout_mux_t *p_mux = p_stream->p_sys->p_mux;
2167 assert( p_mux != NULL );
2169 p_input = sout_MuxAddStream( p_mux, p_fmt );
2170 if( p_input == NULL )
2172 msg_Err( p_stream, "cannot add this stream to the muxer" );
2176 return (sout_stream_id_t *)p_input;
2180 static int MuxSend( sout_stream_t *p_stream, sout_stream_id_t *id,
2183 sout_mux_t *p_mux = p_stream->p_sys->p_mux;
2184 assert( p_mux != NULL );
2186 sout_MuxSendBuffer( p_mux, (sout_input_t *)id, p_buffer );
2191 /** Remove an ES from a non-RTP muxed stream */
2192 static int MuxDel( sout_stream_t *p_stream, sout_stream_id_t *id )
2194 sout_mux_t *p_mux = p_stream->p_sys->p_mux;
2195 assert( p_mux != NULL );
2197 sout_MuxDeleteStream( p_mux, (sout_input_t *)id );
2202 static int AccessOutGrabberWriteBuffer( sout_stream_t *p_stream,
2203 const block_t *p_buffer )
2205 sout_stream_sys_t *p_sys = p_stream->p_sys;
2206 sout_stream_id_t *id = p_sys->es[0];
2208 int64_t i_dts = p_buffer->i_dts;
2210 uint8_t *p_data = p_buffer->p_buffer;
2211 unsigned int i_data = p_buffer->i_buffer;
2212 unsigned int i_max = id->i_mtu - 12;
2214 unsigned i_packet = ( p_buffer->i_buffer + i_max - 1 ) / i_max;
2218 unsigned int i_size;
2220 /* output complete packet */
2221 if( p_sys->packet &&
2222 p_sys->packet->i_buffer + i_data > i_max )
2224 rtp_packetize_send( id, p_sys->packet );
2225 p_sys->packet = NULL;
2228 if( p_sys->packet == NULL )
2230 /* allocate a new packet */
2231 p_sys->packet = block_New( p_stream, id->i_mtu );
2232 rtp_packetize_common( id, p_sys->packet, 1, i_dts );
2233 p_sys->packet->i_dts = i_dts;
2234 p_sys->packet->i_length = p_buffer->i_length / i_packet;
2235 i_dts += p_sys->packet->i_length;
2238 i_size = __MIN( i_data,
2239 (unsigned)(id->i_mtu - p_sys->packet->i_buffer) );
2241 memcpy( &p_sys->packet->p_buffer[p_sys->packet->i_buffer],
2244 p_sys->packet->i_buffer += i_size;
2253 static int AccessOutGrabberWrite( sout_access_out_t *p_access,
2256 sout_stream_t *p_stream = (sout_stream_t*)p_access->p_sys;
2262 AccessOutGrabberWriteBuffer( p_stream, p_buffer );
2264 p_next = p_buffer->p_next;
2265 block_Release( p_buffer );
2273 static sout_access_out_t *GrabberCreate( sout_stream_t *p_stream )
2275 sout_access_out_t *p_grab;
2277 p_grab = vlc_object_create( p_stream->p_sout, sizeof( *p_grab ) );
2278 if( p_grab == NULL )
2281 p_grab->p_module = NULL;
2282 p_grab->p_sout = p_stream->p_sout;
2283 p_grab->psz_access = strdup( "grab" );
2284 p_grab->p_cfg = NULL;
2285 p_grab->psz_path = strdup( "" );
2286 p_grab->p_sys = (sout_access_out_sys_t *)p_stream;
2287 p_grab->pf_seek = NULL;
2288 p_grab->pf_write = AccessOutGrabberWrite;
2292 static int rtp_packetize_spx( sout_stream_t *p_stream, sout_stream_id_t *id,
2295 uint8_t *p_buffer = in->p_buffer;
2296 int i_data_size, i_payload_size, i_payload_padding;
2297 i_data_size = i_payload_size = in->i_buffer;
2298 i_payload_padding = 0;
2301 if ( in->i_buffer + 12 > id->i_mtu )
2303 msg_Warn( p_stream, "Cannot send packet larger than output MTU" );
2308 RFC for Speex in RTP says that each packet must end on an octet
2309 boundary. So, we check to see if the number of bytes % 4 is zero.
2310 If not, we have to add some padding.
2312 This MAY be overkill since packetization is handled elsewhere and
2313 appears to ensure the octet boundary. However, better safe than
2316 if ( i_payload_size % 4 )
2318 i_payload_padding = 4 - ( i_payload_size % 4 );
2319 i_payload_size += i_payload_padding;
2323 Allocate a new RTP p_output block of the appropriate size.
2324 Allow for 12 extra bytes of RTP header.
2326 p_out = block_New( p_stream, 12 + i_payload_size );
2328 if ( i_payload_padding )
2331 The padding is required to be a zero followed by all 1s.
2333 char c_first_pad, c_remaining_pad;
2335 c_remaining_pad = 0xFF;
2338 Allow for 12 bytes before the i_data_size because
2339 of the expected RTP header added during
2340 rtp_packetize_common.
2342 p_out->p_buffer[12 + i_data_size] = c_first_pad;
2343 switch (i_payload_padding)
2346 p_out->p_buffer[12 + i_data_size + 1] = c_remaining_pad;
2349 p_out->p_buffer[12 + i_data_size + 1] = c_remaining_pad;
2350 p_out->p_buffer[12 + i_data_size + 2] = c_remaining_pad;
2355 /* Add the RTP header to our p_output buffer. */
2356 rtp_packetize_common( id, p_out, 0, (in->i_pts > 0 ? in->i_pts : in->i_dts) );
2357 /* Copy the Speex payload to the p_output buffer */
2358 memcpy( &p_out->p_buffer[12], p_buffer, i_data_size );
2360 p_out->i_buffer = 12 + i_payload_size;
2361 p_out->i_dts = in->i_dts;
2362 p_out->i_length = in->i_length;
2364 /* Queue the buffer for actual transmission. */
2365 rtp_packetize_send( id, p_out );