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;
280 uint32_t i_timestamp_start;
282 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,
606 p_sys->psz_destination, p_sys->i_ttl,
607 id->i_port, id->i_port + 1 );
610 else if( ( url.psz_protocol && !strcasecmp( url.psz_protocol, "sap" ) ) ||
611 ( url.psz_host && !strcasecmp( url.psz_host, "sap" ) ) )
613 p_sys->b_export_sap = VLC_TRUE;
614 SapSetup( p_stream );
616 else if( url.psz_protocol && !strcasecmp( url.psz_protocol, "file" ) )
618 if( p_sys->b_export_sdp_file )
620 msg_Err( p_stream, "you can use sdp=file:// only once" );
623 p_sys->b_export_sdp_file = VLC_TRUE;
624 psz_url = &psz_url[5];
625 if( psz_url[0] == '/' && psz_url[1] == '/' )
627 p_sys->psz_sdp_file = strdup( psz_url );
631 msg_Warn( p_stream, "unknown protocol for SDP (%s)",
636 vlc_UrlClean( &url );
639 /*****************************************************************************
641 *****************************************************************************/
643 char *SDPGenerate( const sout_stream_t *p_stream, const char *rtsp_url )
645 const sout_stream_sys_t *p_sys = p_stream->p_sys;
647 struct sockaddr_storage dst;
651 * When we have a fixed destination (typically when we do multicast),
652 * we need to put the actual port numbers in the SDP.
653 * When there is no fixed destination, we only support RTSP unicast
654 * on-demand setup, so we should rather let the clients decide which ports
656 * When there is both a fixed destination and RTSP unicast, we need to
657 * put port numbers used by the fixed destination, otherwise the SDP would
658 * become totally incorrect for multicast use. It should be noted that
659 * port numbers from SDP with RTSP are only "recommendation" from the
660 * server to the clients (per RFC2326), so only broken clients will fail
661 * to handle this properly. There is no solution but to use two differents
662 * output chain with two different RTSP URLs if you need to handle this
667 if( p_sys->psz_destination != NULL )
671 /* Oh boy, this is really ugly! (+ race condition on lock_es) */
672 dstlen = sizeof( dst );
673 if( p_sys->es[0]->listen_fd != NULL )
674 getsockname( p_sys->es[0]->listen_fd[0],
675 (struct sockaddr *)&dst, &dstlen );
677 getpeername( p_sys->es[0]->sinkv[0].rtp_fd,
678 (struct sockaddr *)&dst, &dstlen );
684 /* Dummy destination address for RTSP */
685 memset (&dst, 0, sizeof( struct sockaddr_in ) );
686 dst.ss_family = AF_INET;
690 dstlen = sizeof( struct sockaddr_in );
693 psz_sdp = vlc_sdp_Start( VLC_OBJECT( p_stream ), SOUT_CFG_PREFIX,
694 NULL, 0, (struct sockaddr *)&dst, dstlen );
695 if( psz_sdp == NULL )
698 /* TODO: a=source-filter */
699 if( p_sys->rtcp_mux )
700 sdp_AddAttribute( &psz_sdp, "rtcp-mux", NULL );
702 if( rtsp_url != NULL )
703 sdp_AddAttribute ( &psz_sdp, "control", "%s", rtsp_url );
705 /* FIXME: locking?! */
706 for( i = 0; i < p_sys->i_es; i++ )
708 sout_stream_id_t *id = p_sys->es[i];
709 const char *mime_major; /* major MIME type */
710 const char *proto = "RTP/AVP"; /* protocol */
715 mime_major = "video";
718 mime_major = "audio";
727 if( rtsp_url == NULL )
729 switch( p_sys->proto )
734 proto = "TCP/RTP/AVP";
737 proto = "DCCP/RTP/AVP";
739 case IPPROTO_UDPLITE:
744 sdp_AddMedia( &psz_sdp, mime_major, proto, inclport * id->i_port,
745 id->i_payload_type, VLC_FALSE, id->i_bitrate,
746 id->psz_rtpmap, id->psz_fmtp);
748 if( rtsp_url != NULL )
750 assert( strlen( rtsp_url ) > 0 );
751 vlc_bool_t addslash = ( rtsp_url[strlen( rtsp_url ) - 1] != '/' );
752 sdp_AddAttribute ( &psz_sdp, "control",
753 addslash ? "%s/trackID=%u" : "%strackID=%u",
758 if( id->listen_fd != NULL )
759 sdp_AddAttribute( &psz_sdp, "setup", "passive" );
761 if( p_sys->proto == IPPROTO_DCCP )
762 sdp_AddAttribute( &psz_sdp, "dccp-service-code",
763 "SC:RTP%c", toupper( mime_major[0] ) );
771 /*****************************************************************************
773 *****************************************************************************/
774 static int rtp_packetize_l16 ( sout_stream_t *, sout_stream_id_t *, block_t * );
775 static int rtp_packetize_l8 ( sout_stream_t *, sout_stream_id_t *, block_t * );
776 static int rtp_packetize_mpa ( sout_stream_t *, sout_stream_id_t *, block_t * );
777 static int rtp_packetize_mpv ( sout_stream_t *, sout_stream_id_t *, block_t * );
778 static int rtp_packetize_ac3 ( sout_stream_t *, sout_stream_id_t *, block_t * );
779 static int rtp_packetize_split( sout_stream_t *, sout_stream_id_t *, block_t * );
780 static int rtp_packetize_mp4a ( sout_stream_t *, sout_stream_id_t *, block_t * );
781 static int rtp_packetize_mp4a_latm ( sout_stream_t *, sout_stream_id_t *, block_t * );
782 static int rtp_packetize_h263 ( sout_stream_t *, sout_stream_id_t *, block_t * );
783 static int rtp_packetize_h264 ( sout_stream_t *, sout_stream_id_t *, block_t * );
784 static int rtp_packetize_amr ( sout_stream_t *, sout_stream_id_t *, block_t * );
785 static int rtp_packetize_spx ( sout_stream_t *, sout_stream_id_t *, block_t * );
786 static int rtp_packetize_t140 ( sout_stream_t *, sout_stream_id_t *, block_t * );
788 static void sprintf_hexa( char *s, uint8_t *p_data, int i_data )
790 static const char hex[16] = "0123456789abcdef";
793 for( i = 0; i < i_data; i++ )
795 s[2*i+0] = hex[(p_data[i]>>4)&0xf];
796 s[2*i+1] = hex[(p_data[i] )&0xf];
802 /** Add an ES as a new RTP stream */
803 static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
805 /* NOTE: As a special case, if we use a non-RTP
806 * mux (TS/PS), then p_fmt is NULL. */
807 sout_stream_sys_t *p_sys = p_stream->p_sys;
808 sout_stream_id_t *id;
809 int i_port, cscov = -1;
812 id = vlc_object_create( p_stream, sizeof( sout_stream_id_t ) );
815 vlc_object_attach( id, p_stream );
817 /* Choose the port */
822 if( p_fmt->i_cat == AUDIO_ES && p_sys->i_port_audio > 0 )
824 i_port = p_sys->i_port_audio;
825 p_sys->i_port_audio = 0;
828 if( p_fmt->i_cat == VIDEO_ES && p_sys->i_port_video > 0 )
830 i_port = p_sys->i_port_video;
831 p_sys->i_port_video = 0;
836 if( p_sys->i_port != p_sys->i_port_audio
837 && p_sys->i_port != p_sys->i_port_video )
839 i_port = p_sys->i_port;
846 id->p_stream = p_stream;
848 id->i_timestamp_start = rand()&0xffffffff;
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;
856 id->psz_rtpmap = NULL;
858 id->i_clock_rate = 90000; /* most common case */
862 id->i_cat = p_fmt->i_cat;
863 id->i_bitrate = p_fmt->i_bitrate/1000; /* Stream bitrate in kbps */
867 id->i_cat = VIDEO_ES;
871 id->pf_packetize = NULL;
872 id->i_mtu = config_GetInt( p_stream, "mtu" );
873 if( id->i_mtu <= 12 + 16 )
874 id->i_mtu = 576 - 20 - 8; /* pessimistic */
876 msg_Dbg( p_stream, "maximum RTP packet size: %d bytes", id->i_mtu );
878 vlc_mutex_init( p_stream, &id->lock_sink );
883 id->listen_fd = NULL;
886 (int64_t)1000 * var_GetInteger( p_stream, SOUT_CFG_PREFIX "caching");
888 if( p_sys->psz_destination != NULL )
889 switch( p_sys->proto )
893 id->listen_fd = net_Listen( VLC_OBJECT(p_stream),
894 p_sys->psz_destination, i_port,
896 if( id->listen_fd == NULL )
898 msg_Err( p_stream, "passive COMEDIA RTP socket failed" );
905 int ttl = (p_sys->i_ttl > 0) ? p_sys->i_ttl : -1;
906 int fd = net_ConnectDgram( p_stream, p_sys->psz_destination,
907 i_port, ttl, p_sys->proto );
910 msg_Err( p_stream, "cannot create RTP socket" );
913 rtp_add_sink( id, fd, p_sys->rtcp_mux );
919 char *psz = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "mux" );
921 if( psz == NULL ) /* Uho! */
924 if( strncmp( psz, "ts", 2 ) == 0 )
926 id->i_payload_type = 33;
927 id->psz_rtpmap = strdup( "MP2T/90000" );
931 id->psz_rtpmap = strdup( "MP2P/90000" );
935 switch( p_fmt->i_codec )
937 case VLC_FOURCC( 's', '1', '6', 'b' ):
938 if( p_fmt->audio.i_channels == 1 && p_fmt->audio.i_rate == 44100 )
940 id->i_payload_type = 11;
942 else if( p_fmt->audio.i_channels == 2 &&
943 p_fmt->audio.i_rate == 44100 )
945 id->i_payload_type = 10;
947 if( asprintf( &id->psz_rtpmap, "L16/%d/%d", p_fmt->audio.i_rate,
948 p_fmt->audio.i_channels ) == -1 )
949 id->psz_rtpmap = NULL;
950 id->i_clock_rate = p_fmt->audio.i_rate;
951 id->pf_packetize = rtp_packetize_l16;
953 case VLC_FOURCC( 'u', '8', ' ', ' ' ):
954 if( asprintf( &id->psz_rtpmap, "L8/%d/%d", p_fmt->audio.i_rate,
955 p_fmt->audio.i_channels ) == -1 )
956 id->psz_rtpmap = NULL;
957 id->i_clock_rate = p_fmt->audio.i_rate;
958 id->pf_packetize = rtp_packetize_l8;
960 case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
961 id->i_payload_type = 14;
962 id->psz_rtpmap = strdup( "MPA/90000" );
963 id->pf_packetize = rtp_packetize_mpa;
965 case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
966 id->i_payload_type = 32;
967 id->psz_rtpmap = strdup( "MPV/90000" );
968 id->pf_packetize = rtp_packetize_mpv;
970 case VLC_FOURCC( 'a', '5', '2', ' ' ):
971 id->psz_rtpmap = strdup( "ac3/90000" );
972 id->pf_packetize = rtp_packetize_ac3;
974 case VLC_FOURCC( 'H', '2', '6', '3' ):
975 id->psz_rtpmap = strdup( "H263-1998/90000" );
976 id->pf_packetize = rtp_packetize_h263;
978 case VLC_FOURCC( 'h', '2', '6', '4' ):
979 id->psz_rtpmap = strdup( "H264/90000" );
980 id->pf_packetize = rtp_packetize_h264;
983 if( p_fmt->i_extra > 0 )
985 uint8_t *p_buffer = p_fmt->p_extra;
986 int i_buffer = p_fmt->i_extra;
987 char *p_64_sps = NULL;
988 char *p_64_pps = NULL;
991 while( i_buffer > 4 &&
992 p_buffer[0] == 0 && p_buffer[1] == 0 &&
993 p_buffer[2] == 0 && p_buffer[3] == 1 )
995 const int i_nal_type = p_buffer[4]&0x1f;
999 msg_Dbg( p_stream, "we found a startcode for NAL with TYPE:%d", i_nal_type );
1002 for( i_offset = 4; i_offset+3 < i_buffer ; i_offset++)
1004 if( !memcmp (p_buffer + i_offset, "\x00\x00\x00\x01", 4 ) )
1006 /* we found another startcode */
1011 if( i_nal_type == 7 )
1013 p_64_sps = vlc_b64_encode_binary( &p_buffer[4], i_size - 4 );
1014 sprintf_hexa( hexa, &p_buffer[5], 3 );
1016 else if( i_nal_type == 8 )
1018 p_64_pps = vlc_b64_encode_binary( &p_buffer[4], i_size - 4 );
1024 if( p_64_sps && p_64_pps &&
1025 ( asprintf( &id->psz_fmtp,
1026 "packetization-mode=1;profile-level-id=%s;"
1027 "sprop-parameter-sets=%s,%s;", hexa, p_64_sps,
1028 p_64_pps ) == -1 ) )
1029 id->psz_fmtp = NULL;
1034 id->psz_fmtp = strdup( "packetization-mode=1" );
1037 case VLC_FOURCC( 'm', 'p', '4', 'v' ):
1039 char hexa[2*p_fmt->i_extra +1];
1041 id->psz_rtpmap = strdup( "MP4V-ES/90000" );
1042 id->pf_packetize = rtp_packetize_split;
1043 if( p_fmt->i_extra > 0 )
1045 sprintf_hexa( hexa, p_fmt->p_extra, p_fmt->i_extra );
1046 if( asprintf( &id->psz_fmtp,
1047 "profile-level-id=3; config=%s;", hexa ) == -1 )
1048 id->psz_fmtp = NULL;
1052 case VLC_FOURCC( 'm', 'p', '4', 'a' ):
1054 id->i_clock_rate = p_fmt->audio.i_rate;
1058 char hexa[2*p_fmt->i_extra +1];
1060 if( asprintf( &id->psz_rtpmap, "mpeg4-generic/%d",
1061 p_fmt->audio.i_rate ) == -1 )
1062 id->psz_rtpmap = NULL;
1063 id->pf_packetize = rtp_packetize_mp4a;
1064 sprintf_hexa( hexa, p_fmt->p_extra, p_fmt->i_extra );
1065 if( asprintf( &id->psz_fmtp,
1066 "streamtype=5; profile-level-id=15; "
1067 "mode=AAC-hbr; config=%s; SizeLength=13; "
1068 "IndexLength=3; IndexDeltaLength=3; Profile=1;",
1070 id->psz_fmtp = NULL;
1076 unsigned char config[6];
1077 unsigned int aacsrates[15] = {
1078 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
1079 16000, 12000, 11025, 8000, 7350, 0, 0 };
1081 for( i = 0; i < 15; i++ )
1082 if( p_fmt->audio.i_rate == aacsrates[i] )
1088 config[3]=p_fmt->audio.i_channels<<4;
1092 if( asprintf( &id->psz_rtpmap, "MP4A-LATM/%d/%d",
1093 p_fmt->audio.i_rate,
1094 p_fmt->audio.i_channels ) == -1)
1095 id->psz_rtpmap = NULL;
1096 id->pf_packetize = rtp_packetize_mp4a_latm;
1097 sprintf_hexa( hexa, config, 6 );
1098 if( asprintf( &id->psz_fmtp, "profile-level-id=15; "
1099 "object=2; cpresent=0; config=%s", hexa ) == -1 )
1100 id->psz_fmtp = NULL;
1104 case VLC_FOURCC( 's', 'a', 'm', 'r' ):
1105 id->psz_rtpmap = strdup( p_fmt->audio.i_channels == 2 ?
1106 "AMR/8000/2" : "AMR/8000" );
1107 id->psz_fmtp = strdup( "octet-align=1" );
1108 id->i_clock_rate = p_fmt->audio.i_rate;
1109 id->pf_packetize = rtp_packetize_amr;
1111 case VLC_FOURCC( 's', 'a', 'w', 'b' ):
1112 id->psz_rtpmap = strdup( p_fmt->audio.i_channels == 2 ?
1113 "AMR-WB/16000/2" : "AMR-WB/16000" );
1114 id->psz_fmtp = strdup( "octet-align=1" );
1115 id->i_clock_rate = p_fmt->audio.i_rate;
1116 id->pf_packetize = rtp_packetize_amr;
1118 case VLC_FOURCC( 's', 'p', 'x', ' ' ):
1119 id->i_payload_type = p_sys->i_payload_type++;
1120 if( asprintf( &id->psz_rtpmap, "SPEEX/%d",
1121 p_fmt->audio.i_rate ) == -1)
1122 id->psz_rtpmap = NULL;
1123 id->i_clock_rate = p_fmt->audio.i_rate;
1124 id->pf_packetize = rtp_packetize_spx;
1126 case VLC_FOURCC( 't', '1', '4', '0' ):
1127 id->psz_rtpmap = strdup( "t140/1000" );
1128 id->i_clock_rate = 1000;
1129 id->pf_packetize = rtp_packetize_t140;
1133 msg_Err( p_stream, "cannot add this stream (unsupported "
1134 "codec:%4.4s)", (char*)&p_fmt->i_codec );
1139 cscov += 8 /* UDP */ + 12 /* RTP */;
1141 net_SetCSCov( id->sinkv[0].rtp_fd, cscov, -1 );
1143 if( id->i_payload_type == p_sys->i_payload_type )
1144 p_sys->i_payload_type++;
1146 if( p_sys->rtsp != NULL )
1147 id->rtsp_id = RtspAddId( p_sys->rtsp, id, p_sys->i_es,
1148 p_sys->psz_destination,
1149 p_sys->i_ttl, id->i_port, id->i_port + 1 );
1151 id->p_fifo = block_FifoNew( p_stream );
1152 if( vlc_thread_create( id, "RTP send thread", ThreadSend,
1153 VLC_THREAD_PRIORITY_HIGHEST, VLC_FALSE ) )
1156 /* Update p_sys context */
1157 vlc_mutex_lock( &p_sys->lock_es );
1158 TAB_APPEND( p_sys->i_es, p_sys->es, id );
1159 vlc_mutex_unlock( &p_sys->lock_es );
1161 psz_sdp = SDPGenerate( p_stream, NULL );
1163 vlc_mutex_lock( &p_sys->lock_sdp );
1164 free( p_sys->psz_sdp );
1165 p_sys->psz_sdp = psz_sdp;
1166 vlc_mutex_unlock( &p_sys->lock_sdp );
1168 msg_Dbg( p_stream, "sdp=\n%s", p_sys->psz_sdp );
1170 /* Update SDP (sap/file) */
1171 if( p_sys->b_export_sap ) SapSetup( p_stream );
1172 if( p_sys->b_export_sdp_file ) FileSetup( p_stream );
1177 Del( p_stream, id );
1181 static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
1183 sout_stream_sys_t *p_sys = p_stream->p_sys;
1185 if( id->p_fifo != NULL )
1187 vlc_object_kill( id );
1188 block_FifoWake( id->p_fifo );
1189 vlc_thread_join( id );
1190 block_FifoRelease( id->p_fifo );
1193 vlc_mutex_lock( &p_sys->lock_es );
1194 TAB_REMOVE( p_sys->i_es, p_sys->es, id );
1195 vlc_mutex_unlock( &p_sys->lock_es );
1198 if( id->i_port > 0 )
1200 if( id->i_cat == AUDIO_ES && p_sys->i_port_audio == 0 )
1201 p_sys->i_port_audio = id->i_port;
1202 else if( id->i_cat == VIDEO_ES && p_sys->i_port_video == 0 )
1203 p_sys->i_port_video = id->i_port;
1206 free( id->psz_rtpmap );
1207 free( id->psz_fmtp );
1210 RtspDelId( p_sys->rtsp, id->rtsp_id );
1212 rtp_del_sink( id, id->sinkv[0].rtp_fd ); /* sink for explicit dst= */
1213 if( id->listen_fd != NULL )
1214 net_ListenClose( id->listen_fd );
1216 vlc_mutex_destroy( &id->lock_sink );
1218 /* Update SDP (sap/file) */
1219 if( p_sys->b_export_sap && !p_sys->p_mux ) SapSetup( p_stream );
1220 if( p_sys->b_export_sdp_file ) FileSetup( p_stream );
1222 vlc_object_detach( id );
1223 vlc_object_destroy( id );
1227 static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
1232 assert( p_stream->p_sys->p_mux == NULL );
1234 while( p_buffer != NULL )
1236 p_next = p_buffer->p_next;
1237 if( id->pf_packetize( p_stream, id, p_buffer ) )
1240 block_Release( p_buffer );
1246 /****************************************************************************
1248 ****************************************************************************/
1249 static int SapSetup( sout_stream_t *p_stream )
1251 sout_stream_sys_t *p_sys = p_stream->p_sys;
1252 sout_instance_t *p_sout = p_stream->p_sout;
1254 /* Remove the previous session */
1255 if( p_sys->p_session != NULL)
1257 sout_AnnounceUnRegister( p_sout, p_sys->p_session);
1258 p_sys->p_session = NULL;
1261 if( ( p_sys->i_es > 0 || p_sys->p_mux ) && p_sys->psz_sdp && *p_sys->psz_sdp )
1263 announce_method_t *p_method = sout_SAPMethod();
1264 p_sys->p_session = sout_AnnounceRegisterSDP( p_sout, SOUT_CFG_PREFIX,
1266 p_sys->psz_destination,
1268 sout_MethodRelease( p_method );
1274 /****************************************************************************
1276 ****************************************************************************/
1277 static int FileSetup( sout_stream_t *p_stream )
1279 sout_stream_sys_t *p_sys = p_stream->p_sys;
1282 if( ( f = utf8_fopen( p_sys->psz_sdp_file, "wt" ) ) == NULL )
1284 msg_Err( p_stream, "cannot open file '%s' (%m)",
1285 p_sys->psz_sdp_file );
1286 return VLC_EGENERIC;
1289 fputs( p_sys->psz_sdp, f );
1295 /****************************************************************************
1297 ****************************************************************************/
1298 static int HttpCallback( httpd_file_sys_t *p_args,
1299 httpd_file_t *, uint8_t *p_request,
1300 uint8_t **pp_data, int *pi_data );
1302 static int HttpSetup( sout_stream_t *p_stream, vlc_url_t *url)
1304 sout_stream_sys_t *p_sys = p_stream->p_sys;
1306 p_sys->p_httpd_host = httpd_HostNew( VLC_OBJECT(p_stream), url->psz_host,
1307 url->i_port > 0 ? url->i_port : 80 );
1308 if( p_sys->p_httpd_host )
1310 p_sys->p_httpd_file = httpd_FileNew( p_sys->p_httpd_host,
1311 url->psz_path ? url->psz_path : "/",
1314 HttpCallback, (void*)p_sys );
1316 if( p_sys->p_httpd_file == NULL )
1318 return VLC_EGENERIC;
1323 static int HttpCallback( httpd_file_sys_t *p_args,
1324 httpd_file_t *f, uint8_t *p_request,
1325 uint8_t **pp_data, int *pi_data )
1327 sout_stream_sys_t *p_sys = (sout_stream_sys_t*)p_args;
1329 vlc_mutex_lock( &p_sys->lock_sdp );
1330 if( p_sys->psz_sdp && *p_sys->psz_sdp )
1332 *pi_data = strlen( p_sys->psz_sdp );
1333 *pp_data = malloc( *pi_data );
1334 memcpy( *pp_data, p_sys->psz_sdp, *pi_data );
1341 vlc_mutex_unlock( &p_sys->lock_sdp );
1346 /****************************************************************************
1348 ****************************************************************************/
1349 static void ThreadSend( vlc_object_t *p_this )
1351 sout_stream_id_t *id = (sout_stream_id_t *)p_this;
1352 unsigned i_caching = id->i_caching;
1354 int fd[5] = { -1, -1, -1, -1, -1 };
1362 fd[4] = open( "/dev/null", O_WRONLY );
1367 block_t *out = block_FifoGet( id->p_fifo );
1369 continue; /* Forced wakeup */
1371 mtime_t i_date = out->i_dts + i_caching;
1372 ssize_t len = out->i_buffer;
1376 len = write( fd[1], out->p_buffer, len);
1378 continue; /* Uho - should not happen */
1382 vlc_mutex_lock( &id->lock_sink );
1384 unsigned deadc = 0; /* How many dead sockets? */
1385 int deadv[id->sinkc]; /* Dead sockets list */
1388 for( int i = 0; i < id->sinkc; i++ )
1390 SendRTCP( id->sinkv[i].rtcp, out );
1393 tee( fd[0], fd[3], len, 0 );
1394 if( splice( fd[2], NULL, id->sinkv[i].rtp_fd, NULL, len,
1395 SPLICE_F_NONBLOCK ) >= 0 )
1399 splice( fd[2], NULL, fd[4], NULL, len, 0 );
1401 if( send( id->sinkv[i].rtp_fd, out->p_buffer, len, 0 ) < 0 )
1402 /*deadv[deadc++] = id->sinkv[i].rtp_fd*/;
1404 vlc_mutex_unlock( &id->lock_sink );
1406 block_Release( out );
1408 splice( fd[0], NULL, fd[4], NULL, len, 0 );
1412 for( unsigned i = 0; i < deadc; i++ )
1414 msg_Dbg( id, "removing socket %d", deadv[i] );
1415 rtp_del_sink( id, deadv[i] );
1419 /* Hopefully we won't overflow the SO_MAXCONN accept queue */
1420 while( id->listen_fd != NULL )
1422 int fd = net_Accept( id, id->listen_fd, 0 );
1425 msg_Dbg( id, "adding socket %d", fd );
1426 rtp_add_sink( id, fd, VLC_TRUE );
1431 for( unsigned i = 0; i < 5; i++ )
1436 static inline void rtp_packetize_send( sout_stream_id_t *id, block_t *out )
1438 block_FifoPut( id->p_fifo, out );
1441 int rtp_add_sink( sout_stream_id_t *id, int fd, vlc_bool_t rtcp_mux )
1443 rtp_sink_t sink = { fd, NULL };
1444 sink.rtcp = OpenRTCP( VLC_OBJECT( id->p_stream ), fd, IPPROTO_UDP,
1446 if( sink.rtcp == NULL )
1447 msg_Err( id, "RTCP failed!" );
1449 vlc_mutex_lock( &id->lock_sink );
1450 INSERT_ELEM( id->sinkv, id->sinkc, id->sinkc, sink );
1451 vlc_mutex_unlock( &id->lock_sink );
1455 void rtp_del_sink( sout_stream_id_t *id, int fd )
1457 rtp_sink_t sink = { fd, NULL };
1459 /* NOTE: must be safe to use if fd is not included */
1460 vlc_mutex_lock( &id->lock_sink );
1461 for( int i = 0; i < id->sinkc; i++ )
1463 if (id->sinkv[i].rtp_fd == fd)
1465 sink = id->sinkv[i];
1466 REMOVE_ELEM( id->sinkv, id->sinkc, i );
1470 vlc_mutex_unlock( &id->lock_sink );
1472 CloseRTCP( sink.rtcp );
1473 net_Close( sink.rtp_fd );
1476 /****************************************************************************
1478 ****************************************************************************/
1479 static void rtp_packetize_common( sout_stream_id_t *id, block_t *out,
1480 int b_marker, int64_t i_pts )
1482 uint32_t i_timestamp = i_pts * (int64_t)id->i_clock_rate / I64C(1000000);
1484 out->p_buffer[0] = 0x80;
1485 out->p_buffer[1] = (b_marker?0x80:0x00)|id->i_payload_type;
1486 out->p_buffer[2] = ( id->i_sequence >> 8)&0xff;
1487 out->p_buffer[3] = ( id->i_sequence )&0xff;
1488 out->p_buffer[4] = ( i_timestamp >> 24 )&0xff;
1489 out->p_buffer[5] = ( i_timestamp >> 16 )&0xff;
1490 out->p_buffer[6] = ( i_timestamp >> 8 )&0xff;
1491 out->p_buffer[7] = ( i_timestamp )&0xff;
1493 memcpy( out->p_buffer + 8, id->ssrc, 4 );
1499 static int rtp_packetize_mpa( sout_stream_t *p_stream, sout_stream_id_t *id,
1502 int i_max = id->i_mtu - 12 - 4; /* payload max in one packet */
1503 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1505 uint8_t *p_data = in->p_buffer;
1506 int i_data = in->i_buffer;
1509 for( i = 0; i < i_count; i++ )
1511 int i_payload = __MIN( i_max, i_data );
1512 block_t *out = block_New( p_stream, 16 + i_payload );
1514 /* rtp common header */
1515 rtp_packetize_common( id, out, (i == i_count - 1)?1:0, in->i_pts );
1517 out->p_buffer[12] = 0;
1518 out->p_buffer[13] = 0;
1519 /* fragment offset in the current frame */
1520 out->p_buffer[14] = ( (i*i_max) >> 8 )&0xff;
1521 out->p_buffer[15] = ( (i*i_max) )&0xff;
1522 memcpy( &out->p_buffer[16], p_data, i_payload );
1524 out->i_buffer = 16 + i_payload;
1525 out->i_dts = in->i_dts + i * in->i_length / i_count;
1526 out->i_length = in->i_length / i_count;
1528 rtp_packetize_send( id, out );
1530 p_data += i_payload;
1531 i_data -= i_payload;
1538 static int rtp_packetize_mpv( sout_stream_t *p_stream, sout_stream_id_t *id,
1541 int i_max = id->i_mtu - 12 - 4; /* payload max in one packet */
1542 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1544 uint8_t *p_data = in->p_buffer;
1545 int i_data = in->i_buffer;
1547 int b_sequence_start = 0;
1548 int i_temporal_ref = 0;
1549 int i_picture_coding_type = 0;
1550 int i_fbv = 0, i_bfc = 0, i_ffv = 0, i_ffc = 0;
1551 int b_start_slice = 0;
1553 /* preparse this packet to get some info */
1554 if( in->i_buffer > 4 )
1556 uint8_t *p = p_data;
1557 int i_rest = in->i_buffer;
1561 while( i_rest > 4 &&
1562 ( p[0] != 0x00 || p[1] != 0x00 || p[2] != 0x01 ) )
1576 /* sequence start code */
1577 b_sequence_start = 1;
1579 else if( *p == 0x00 && i_rest >= 4 )
1582 i_temporal_ref = ( p[1] << 2) |((p[2]>>6)&0x03);
1583 i_picture_coding_type = (p[2] >> 3)&0x07;
1585 if( i_rest >= 4 && ( i_picture_coding_type == 2 ||
1586 i_picture_coding_type == 3 ) )
1588 i_ffv = (p[3] >> 2)&0x01;
1589 i_ffc = ((p[3]&0x03) << 1)|((p[4]>>7)&0x01);
1590 if( i_rest > 4 && i_picture_coding_type == 3 )
1592 i_fbv = (p[4]>>6)&0x01;
1593 i_bfc = (p[4]>>3)&0x07;
1597 else if( *p <= 0xaf )
1604 for( i = 0; i < i_count; i++ )
1606 int i_payload = __MIN( i_max, i_data );
1607 block_t *out = block_New( p_stream,
1609 uint32_t h = ( i_temporal_ref << 16 )|
1610 ( b_sequence_start << 13 )|
1611 ( b_start_slice << 12 )|
1612 ( i == i_count - 1 ? 1 << 11 : 0 )|
1613 ( i_picture_coding_type << 8 )|
1614 ( i_fbv << 7 )|( i_bfc << 4 )|( i_ffv << 3 )|i_ffc;
1616 /* rtp common header */
1617 rtp_packetize_common( id, out, (i == i_count - 1)?1:0,
1618 in->i_pts > 0 ? in->i_pts : in->i_dts );
1620 /* 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 */
1621 out->p_buffer[12] = ( h >> 24 )&0xff;
1622 out->p_buffer[13] = ( h >> 16 )&0xff;
1623 out->p_buffer[14] = ( h >> 8 )&0xff;
1624 out->p_buffer[15] = ( h )&0xff;
1626 memcpy( &out->p_buffer[16], p_data, i_payload );
1628 out->i_buffer = 16 + i_payload;
1629 out->i_dts = in->i_dts + i * in->i_length / i_count;
1630 out->i_length = in->i_length / i_count;
1632 rtp_packetize_send( id, out );
1634 p_data += i_payload;
1635 i_data -= i_payload;
1641 static int rtp_packetize_ac3( sout_stream_t *p_stream, sout_stream_id_t *id,
1644 int i_max = id->i_mtu - 12 - 2; /* payload max in one packet */
1645 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1647 uint8_t *p_data = in->p_buffer;
1648 int i_data = in->i_buffer;
1651 for( i = 0; i < i_count; i++ )
1653 int i_payload = __MIN( i_max, i_data );
1654 block_t *out = block_New( p_stream, 14 + i_payload );
1656 /* rtp common header */
1657 rtp_packetize_common( id, out, (i == i_count - 1)?1:0, in->i_pts );
1659 out->p_buffer[12] = 1;
1661 out->p_buffer[13] = 0x00;
1663 memcpy( &out->p_buffer[14], p_data, i_payload );
1665 out->i_buffer = 14 + i_payload;
1666 out->i_dts = in->i_dts + i * in->i_length / i_count;
1667 out->i_length = in->i_length / i_count;
1669 rtp_packetize_send( id, out );
1671 p_data += i_payload;
1672 i_data -= i_payload;
1678 static int rtp_packetize_split( sout_stream_t *p_stream, sout_stream_id_t *id,
1681 int i_max = id->i_mtu - 12; /* payload max in one packet */
1682 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1684 uint8_t *p_data = in->p_buffer;
1685 int i_data = in->i_buffer;
1688 for( i = 0; i < i_count; i++ )
1690 int i_payload = __MIN( i_max, i_data );
1691 block_t *out = block_New( p_stream, 12 + i_payload );
1693 /* rtp common header */
1694 rtp_packetize_common( id, out, ((i == i_count - 1)?1:0),
1695 (in->i_pts > 0 ? in->i_pts : in->i_dts) );
1696 memcpy( &out->p_buffer[12], p_data, i_payload );
1698 out->i_buffer = 12 + i_payload;
1699 out->i_dts = in->i_dts + i * in->i_length / i_count;
1700 out->i_length = in->i_length / i_count;
1702 rtp_packetize_send( id, out );
1704 p_data += i_payload;
1705 i_data -= i_payload;
1712 static int rtp_packetize_mp4a_latm( sout_stream_t *p_stream, sout_stream_id_t *id,
1715 int i_max = id->i_mtu - 14; /* payload max in one packet */
1716 int latmhdrsize = in->i_buffer / 0xff + 1;
1717 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1719 uint8_t *p_data = in->p_buffer, *p_header = NULL;
1720 int i_data = in->i_buffer;
1723 for( i = 0; i < i_count; i++ )
1725 int i_payload = __MIN( i_max, i_data );
1730 out = block_New( p_stream, 12 + latmhdrsize + i_payload );
1732 /* rtp common header */
1733 rtp_packetize_common( id, out, ((i == i_count - 1) ? 1 : 0),
1734 (in->i_pts > 0 ? in->i_pts : in->i_dts) );
1738 int tmp = in->i_buffer;
1740 p_header=out->p_buffer+12;
1750 memcpy( &out->p_buffer[12+latmhdrsize], p_data, i_payload );
1752 out->i_buffer = 12 + latmhdrsize + i_payload;
1753 out->i_dts = in->i_dts + i * in->i_length / i_count;
1754 out->i_length = in->i_length / i_count;
1756 rtp_packetize_send( id, out );
1758 p_data += i_payload;
1759 i_data -= i_payload;
1765 static int rtp_packetize_l16( sout_stream_t *p_stream, sout_stream_id_t *id,
1768 int i_max = id->i_mtu - 12; /* payload max in one packet */
1769 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1771 uint8_t *p_data = in->p_buffer;
1772 int i_data = in->i_buffer;
1777 int i_payload = (__MIN( i_max, i_data )/4)*4;
1778 block_t *out = block_New( p_stream, 12 + i_payload );
1780 /* rtp common header */
1781 rtp_packetize_common( id, out, 0,
1782 (in->i_pts > 0 ? in->i_pts : in->i_dts) );
1783 memcpy( &out->p_buffer[12], p_data, i_payload );
1785 out->i_buffer = 12 + i_payload;
1786 out->i_dts = in->i_dts + i_packet * in->i_length / i_count;
1787 out->i_length = in->i_length / i_count;
1789 rtp_packetize_send( id, out );
1791 p_data += i_payload;
1792 i_data -= i_payload;
1799 static int rtp_packetize_l8( sout_stream_t *p_stream, sout_stream_id_t *id,
1802 int i_max = id->i_mtu - 12; /* payload max in one packet */
1803 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1805 uint8_t *p_data = in->p_buffer;
1806 int i_data = in->i_buffer;
1811 int i_payload = (__MIN( i_max, i_data )/2)*2;
1812 block_t *out = block_New( p_stream, 12 + i_payload );
1814 /* rtp common header */
1815 rtp_packetize_common( id, out, 0,
1816 (in->i_pts > 0 ? in->i_pts : in->i_dts) );
1817 memcpy( &out->p_buffer[12], p_data, i_payload );
1819 out->i_buffer = 12 + i_payload;
1820 out->i_dts = in->i_dts + i_packet * in->i_length / i_count;
1821 out->i_length = in->i_length / i_count;
1823 rtp_packetize_send( id, out );
1825 p_data += i_payload;
1826 i_data -= i_payload;
1833 static int rtp_packetize_mp4a( sout_stream_t *p_stream, sout_stream_id_t *id,
1836 int i_max = id->i_mtu - 16; /* payload max in one packet */
1837 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1839 uint8_t *p_data = in->p_buffer;
1840 int i_data = in->i_buffer;
1843 for( i = 0; i < i_count; i++ )
1845 int i_payload = __MIN( i_max, i_data );
1846 block_t *out = block_New( p_stream, 16 + i_payload );
1848 /* rtp common header */
1849 rtp_packetize_common( id, out, ((i == i_count - 1)?1:0),
1850 (in->i_pts > 0 ? in->i_pts : in->i_dts) );
1852 /* AU headers length (bits) */
1853 out->p_buffer[12] = 0;
1854 out->p_buffer[13] = 2*8;
1855 /* for each AU length 13 bits + idx 3bits, */
1856 out->p_buffer[14] = ( in->i_buffer >> 5 )&0xff;
1857 out->p_buffer[15] = ( (in->i_buffer&0xff)<<3 )|0;
1859 memcpy( &out->p_buffer[16], p_data, i_payload );
1861 out->i_buffer = 16 + i_payload;
1862 out->i_dts = in->i_dts + i * in->i_length / i_count;
1863 out->i_length = in->i_length / i_count;
1865 rtp_packetize_send( id, out );
1867 p_data += i_payload;
1868 i_data -= i_payload;
1876 #define RTP_H263_HEADER_SIZE (2) // plen = 0
1877 #define RTP_H263_PAYLOAD_START (14) // plen = 0
1878 static int rtp_packetize_h263( sout_stream_t *p_stream, sout_stream_id_t *id,
1881 uint8_t *p_data = in->p_buffer;
1882 int i_data = in->i_buffer;
1884 int i_max = id->i_mtu - 12 - RTP_H263_HEADER_SIZE; /* payload max in one packet */
1887 int b_v_bit = 0; // no pesky error resilience
1888 int i_plen = 0; // normally plen=0 for PSC packet
1889 int i_pebit = 0; // because plen=0
1894 return VLC_EGENERIC;
1896 if( p_data[0] || p_data[1] )
1898 return VLC_EGENERIC;
1900 /* remove 2 leading 0 bytes */
1903 i_count = ( i_data + i_max - 1 ) / i_max;
1905 for( i = 0; i < i_count; i++ )
1907 int i_payload = __MIN( i_max, i_data );
1908 block_t *out = block_New( p_stream,
1909 RTP_H263_PAYLOAD_START + i_payload );
1910 b_p_bit = (i == 0) ? 1 : 0;
1911 h = ( b_p_bit << 10 )|
1916 /* rtp common header */
1917 //b_m_bit = 1; // always contains end of frame
1918 rtp_packetize_common( id, out, (i == i_count - 1)?1:0,
1919 in->i_pts > 0 ? in->i_pts : in->i_dts );
1922 out->p_buffer[12] = ( h >> 8 )&0xff;
1923 out->p_buffer[13] = ( h )&0xff;
1924 memcpy( &out->p_buffer[RTP_H263_PAYLOAD_START], p_data, i_payload );
1926 out->i_buffer = RTP_H263_PAYLOAD_START + i_payload;
1927 out->i_dts = in->i_dts + i * in->i_length / i_count;
1928 out->i_length = in->i_length / i_count;
1930 rtp_packetize_send( id, out );
1932 p_data += i_payload;
1933 i_data -= i_payload;
1941 rtp_packetize_h264_nal( sout_stream_t *p_stream, sout_stream_id_t *id,
1942 const uint8_t *p_data, int i_data, int64_t i_pts,
1943 int64_t i_dts, vlc_bool_t b_last, int64_t i_length )
1945 const int i_max = id->i_mtu - 12; /* payload max in one packet */
1952 i_nal_hdr = p_data[3];
1953 i_nal_type = i_nal_hdr&0x1f;
1955 /* Skip start code */
1960 if( i_data <= i_max )
1962 /* Single NAL unit packet */
1963 block_t *out = block_New( p_stream, 12 + i_data );
1965 out->i_length = i_length;
1968 rtp_packetize_common( id, out, b_last, i_pts );
1969 out->i_buffer = 12 + i_data;
1971 memcpy( &out->p_buffer[12], p_data, i_data );
1973 rtp_packetize_send( id, out );
1977 /* FU-A Fragmentation Unit without interleaving */
1978 const int i_count = ( i_data-1 + i_max-2 - 1 ) / (i_max-2);
1984 for( i = 0; i < i_count; i++ )
1986 const int i_payload = __MIN( i_data, i_max-2 );
1987 block_t *out = block_New( p_stream, 12 + 2 + i_payload );
1988 out->i_dts = i_dts + i * i_length / i_count;
1989 out->i_length = i_length / i_count;
1992 rtp_packetize_common( id, out, (b_last && i_payload == i_data), i_pts );
1993 out->i_buffer = 14 + i_payload;
1996 out->p_buffer[12] = 0x00 | (i_nal_hdr & 0x60) | 28;
1998 out->p_buffer[13] = ( i == 0 ? 0x80 : 0x00 ) | ( (i == i_count-1) ? 0x40 : 0x00 ) | i_nal_type;
1999 memcpy( &out->p_buffer[14], p_data, i_payload );
2001 rtp_packetize_send( id, out );
2003 i_data -= i_payload;
2004 p_data += i_payload;
2010 static int rtp_packetize_h264( sout_stream_t *p_stream, sout_stream_id_t *id,
2013 const uint8_t *p_buffer = in->p_buffer;
2014 int i_buffer = in->i_buffer;
2016 while( i_buffer > 4 && ( p_buffer[0] != 0 || p_buffer[1] != 0 || p_buffer[2] != 1 ) )
2022 /* Split nal units */
2023 while( i_buffer > 4 )
2026 int i_size = i_buffer;
2027 int i_skip = i_buffer;
2029 /* search nal end */
2030 for( i_offset = 4; i_offset+2 < i_buffer ; i_offset++)
2032 if( p_buffer[i_offset] == 0 && p_buffer[i_offset+1] == 0 && p_buffer[i_offset+2] == 1 )
2034 /* we found another startcode */
2035 i_size = i_offset - ( p_buffer[i_offset-1] == 0 ? 1 : 0);
2040 /* TODO add STAP-A to remove a lot of overhead with small slice/sei/... */
2041 rtp_packetize_h264_nal( p_stream, id, p_buffer, i_size,
2042 (in->i_pts > 0 ? in->i_pts : in->i_dts), in->i_dts,
2043 (i_size >= i_buffer), in->i_length * i_size / in->i_buffer );
2051 static int rtp_packetize_amr( sout_stream_t *p_stream, sout_stream_id_t *id,
2054 int i_max = id->i_mtu - 14; /* payload max in one packet */
2055 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
2057 uint8_t *p_data = in->p_buffer;
2058 int i_data = in->i_buffer;
2061 /* Only supports octet-aligned mode */
2062 for( i = 0; i < i_count; i++ )
2064 int i_payload = __MIN( i_max, i_data );
2065 block_t *out = block_New( p_stream, 14 + i_payload );
2067 /* rtp common header */
2068 rtp_packetize_common( id, out, ((i == i_count - 1)?1:0),
2069 (in->i_pts > 0 ? in->i_pts : in->i_dts) );
2070 /* Payload header */
2071 out->p_buffer[12] = 0xF0; /* CMR */
2072 out->p_buffer[13] = p_data[0]&0x7C; /* ToC */ /* FIXME: frame type */
2074 /* FIXME: are we fed multiple frames ? */
2075 memcpy( &out->p_buffer[14], p_data+1, i_payload-1 );
2077 out->i_buffer = 14 + i_payload-1;
2078 out->i_dts = in->i_dts + i * in->i_length / i_count;
2079 out->i_length = in->i_length / i_count;
2081 rtp_packetize_send( id, out );
2083 p_data += i_payload;
2084 i_data -= i_payload;
2090 static int rtp_packetize_t140( sout_stream_t *p_stream, sout_stream_id_t *id,
2093 const size_t i_max = id->i_mtu - 12;
2094 const uint8_t *p_data = in->p_buffer;
2095 size_t i_data = in->i_buffer;
2097 for( unsigned i_packet = 0; i_data > 0; i_packet++ )
2099 size_t i_payload = i_data;
2101 /* Make sure we stop on an UTF-8 character boundary
2102 * (assuming the input is valid UTF-8) */
2103 if( i_data > i_max )
2107 while( ( p_data[i_payload] & 0xC0 ) == 0x80 )
2109 if( i_payload == 0 )
2110 return VLC_SUCCESS; /* fishy input! */
2116 block_t *out = block_New( p_stream, 12 + i_payload );
2120 rtp_packetize_common( id, out, 0, in->i_pts + i_packet );
2121 memcpy( out->p_buffer + 12, p_data, i_payload );
2123 out->i_buffer = 12 + i_payload;
2124 out->i_dts = out->i_pts;
2127 rtp_packetize_send( id, out );
2129 p_data += i_payload;
2130 i_data -= i_payload;
2136 /*****************************************************************************
2138 *****************************************************************************/
2140 /** Add an ES to a non-RTP muxed stream */
2141 static sout_stream_id_t *MuxAdd( sout_stream_t *p_stream, es_format_t *p_fmt )
2143 sout_input_t *p_input;
2144 sout_mux_t *p_mux = p_stream->p_sys->p_mux;
2145 assert( p_mux != NULL );
2147 p_input = sout_MuxAddStream( p_mux, p_fmt );
2148 if( p_input == NULL )
2150 msg_Err( p_stream, "cannot add this stream to the muxer" );
2154 return (sout_stream_id_t *)p_input;
2158 static int MuxSend( sout_stream_t *p_stream, sout_stream_id_t *id,
2161 sout_mux_t *p_mux = p_stream->p_sys->p_mux;
2162 assert( p_mux != NULL );
2164 sout_MuxSendBuffer( p_mux, (sout_input_t *)id, p_buffer );
2169 /** Remove an ES from a non-RTP muxed stream */
2170 static int MuxDel( sout_stream_t *p_stream, sout_stream_id_t *id )
2172 sout_mux_t *p_mux = p_stream->p_sys->p_mux;
2173 assert( p_mux != NULL );
2175 sout_MuxDeleteStream( p_mux, (sout_input_t *)id );
2180 static int AccessOutGrabberWriteBuffer( sout_stream_t *p_stream,
2181 const block_t *p_buffer )
2183 sout_stream_sys_t *p_sys = p_stream->p_sys;
2184 sout_stream_id_t *id = p_sys->es[0];
2186 int64_t i_dts = p_buffer->i_dts;
2188 uint8_t *p_data = p_buffer->p_buffer;
2189 unsigned int i_data = p_buffer->i_buffer;
2190 unsigned int i_max = id->i_mtu - 12;
2192 unsigned i_packet = ( p_buffer->i_buffer + i_max - 1 ) / i_max;
2196 unsigned int i_size;
2198 /* output complete packet */
2199 if( p_sys->packet &&
2200 p_sys->packet->i_buffer + i_data > i_max )
2202 rtp_packetize_send( id, p_sys->packet );
2203 p_sys->packet = NULL;
2206 if( p_sys->packet == NULL )
2208 /* allocate a new packet */
2209 p_sys->packet = block_New( p_stream, id->i_mtu );
2210 rtp_packetize_common( id, p_sys->packet, 1, i_dts );
2211 p_sys->packet->i_dts = i_dts;
2212 p_sys->packet->i_length = p_buffer->i_length / i_packet;
2213 i_dts += p_sys->packet->i_length;
2216 i_size = __MIN( i_data,
2217 (unsigned)(id->i_mtu - p_sys->packet->i_buffer) );
2219 memcpy( &p_sys->packet->p_buffer[p_sys->packet->i_buffer],
2222 p_sys->packet->i_buffer += i_size;
2231 static int AccessOutGrabberWrite( sout_access_out_t *p_access,
2234 sout_stream_t *p_stream = (sout_stream_t*)p_access->p_sys;
2240 AccessOutGrabberWriteBuffer( p_stream, p_buffer );
2242 p_next = p_buffer->p_next;
2243 block_Release( p_buffer );
2251 static sout_access_out_t *GrabberCreate( sout_stream_t *p_stream )
2253 sout_access_out_t *p_grab;
2255 p_grab = vlc_object_create( p_stream->p_sout, sizeof( *p_grab ) );
2256 if( p_grab == NULL )
2259 p_grab->p_module = NULL;
2260 p_grab->p_sout = p_stream->p_sout;
2261 p_grab->psz_access = strdup( "grab" );
2262 p_grab->p_cfg = NULL;
2263 p_grab->psz_path = strdup( "" );
2264 p_grab->p_sys = (sout_access_out_sys_t *)p_stream;
2265 p_grab->pf_seek = NULL;
2266 p_grab->pf_write = AccessOutGrabberWrite;
2270 static int rtp_packetize_spx( sout_stream_t *p_stream, sout_stream_id_t *id,
2273 uint8_t *p_buffer = in->p_buffer;
2274 int i_data_size, i_payload_size, i_payload_padding;
2275 i_data_size = i_payload_size = in->i_buffer;
2276 i_payload_padding = 0;
2279 if ( in->i_buffer + 12 > id->i_mtu )
2281 msg_Warn( p_stream, "Cannot send packet larger than output MTU" );
2286 RFC for Speex in RTP says that each packet must end on an octet
2287 boundary. So, we check to see if the number of bytes % 4 is zero.
2288 If not, we have to add some padding.
2290 This MAY be overkill since packetization is handled elsewhere and
2291 appears to ensure the octet boundary. However, better safe than
2294 if ( i_payload_size % 4 )
2296 i_payload_padding = 4 - ( i_payload_size % 4 );
2297 i_payload_size += i_payload_padding;
2301 Allocate a new RTP p_output block of the appropriate size.
2302 Allow for 12 extra bytes of RTP header.
2304 p_out = block_New( p_stream, 12 + i_payload_size );
2306 if ( i_payload_padding )
2309 The padding is required to be a zero followed by all 1s.
2311 char c_first_pad, c_remaining_pad;
2313 c_remaining_pad = 0xFF;
2316 Allow for 12 bytes before the i_data_size because
2317 of the expected RTP header added during
2318 rtp_packetize_common.
2320 p_out->p_buffer[12 + i_data_size] = c_first_pad;
2321 switch (i_payload_padding)
2324 p_out->p_buffer[12 + i_data_size + 1] = c_remaining_pad;
2327 p_out->p_buffer[12 + i_data_size + 1] = c_remaining_pad;
2328 p_out->p_buffer[12 + i_data_size + 2] = c_remaining_pad;
2333 /* Add the RTP header to our p_output buffer. */
2334 rtp_packetize_common( id, p_out, 0, (in->i_pts > 0 ? in->i_pts : in->i_dts) );
2335 /* Copy the Speex payload to the p_output buffer */
2336 memcpy( &p_out->p_buffer[12], p_buffer, i_data_size );
2338 p_out->i_buffer = 12 + i_payload_size;
2339 p_out->i_dts = in->i_dts;
2340 p_out->i_length = in->i_length;
2342 /* Queue the buffer for actual transmission. */
2343 rtp_packetize_send( id, p_out );