1 /*****************************************************************************
2 * rtp.c: rtp stream output module
3 *****************************************************************************
4 * Copyright (C) 2003-2004 the VideoLAN team
5 * Copyright © 2007 Rémi Denis-Courmont
8 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
31 #include <vlc_block.h>
33 #include <vlc_httpd.h>
35 #include <vlc_network.h>
36 #include <vlc_charset.h>
37 #include <vlc_strings.h>
42 # include <sys/types.h>
45 # include <sys/stat.h>
47 #ifdef HAVE_LINUX_DCCP_H
48 # include <linux/dccp.h>
51 # define IPPROTO_DCCP 33
53 #ifndef IPPROTO_UDPLITE
54 # define IPPROTO_UDPLITE 136
59 /*****************************************************************************
61 *****************************************************************************/
63 #define DST_TEXT N_("Destination")
64 #define DST_LONGTEXT N_( \
65 "This is the output URL that will be used." )
66 #define SDP_TEXT N_("SDP")
67 #define SDP_LONGTEXT N_( \
68 "This allows you to specify how the SDP (Session Descriptor) for this RTP "\
69 "session will be made available. You must use an url: http://location to " \
70 "access the SDP via HTTP, rtsp://location for RTSP access, and sap:// " \
71 "for the SDP to be announced via SAP." )
72 #define MUX_TEXT N_("Muxer")
73 #define MUX_LONGTEXT N_( \
74 "This allows you to specify the muxer used for the streaming output. " \
75 "Default is to use no muxer (standard RTP stream)." )
77 #define NAME_TEXT N_("Session name")
78 #define NAME_LONGTEXT N_( \
79 "This is the name of the session that will be announced in the SDP " \
80 "(Session Descriptor)." )
81 #define DESC_TEXT N_("Session descriptipn")
82 #define DESC_LONGTEXT N_( \
83 "This allows you to give a short description with details about the stream, " \
84 "that will be announced in the SDP (Session Descriptor)." )
85 #define URL_TEXT N_("Session URL")
86 #define URL_LONGTEXT N_( \
87 "This allows you to give an URL with more details about the stream " \
88 "(often the website of the streaming organization), that will " \
89 "be announced in the SDP (Session Descriptor)." )
90 #define EMAIL_TEXT N_("Session email")
91 #define EMAIL_LONGTEXT N_( \
92 "This allows you to give a contact mail address for the stream, that will " \
93 "be announced in the SDP (Session Descriptor)." )
94 #define PHONE_TEXT N_("Session phone number")
95 #define PHONE_LONGTEXT N_( \
96 "This allows you to give a contact telephone number for the stream, that will " \
97 "be announced in the SDP (Session Descriptor)." )
99 #define PORT_TEXT N_("Port")
100 #define PORT_LONGTEXT N_( \
101 "This allows you to specify the base port for the RTP streaming." )
102 #define PORT_AUDIO_TEXT N_("Audio port")
103 #define PORT_AUDIO_LONGTEXT N_( \
104 "This allows you to specify the default audio port for the RTP streaming." )
105 #define PORT_VIDEO_TEXT N_("Video port")
106 #define PORT_VIDEO_LONGTEXT N_( \
107 "This allows you to specify the default video port for the RTP streaming." )
109 #define TTL_TEXT N_("Hop limit (TTL)")
110 #define TTL_LONGTEXT N_( \
111 "This is the hop limit (also known as \"Time-To-Live\" or TTL) of " \
112 "the multicast packets sent by the stream output (0 = use operating " \
113 "system built-in default).")
115 #define RTCP_MUX_TEXT N_("RTP/RTCP multiplexing")
116 #define RTCP_MUX_LONGTEXT N_( \
117 "This sends and receives RTCP packet multiplexed over the same port " \
120 #define DCCP_TEXT N_("DCCP transport")
121 #define DCCP_LONGTEXT N_( \
122 "This enables DCCP instead of UDP as a transport for RTP." )
123 #define TCP_TEXT N_("TCP transport")
124 #define TCP_LONGTEXT N_( \
125 "This enables TCP instead of UDP as a transport for RTP." )
126 #define UDP_LITE_TEXT N_("UDP-Lite transport")
127 #define UDP_LITE_LONGTEXT N_( \
128 "This enables UDP-Lite instead of UDP as a transport for RTP." )
130 #define RFC3016_TEXT N_("MP4A LATM")
131 #define RFC3016_LONGTEXT N_( \
132 "This allows you to stream MPEG4 LATM audio streams (see RFC3016)." )
134 static int Open ( vlc_object_t * );
135 static void Close( vlc_object_t * );
137 #define SOUT_CFG_PREFIX "sout-rtp-"
138 #define MAX_EMPTY_BLOCKS 200
141 set_shortname( _("RTP"));
142 set_description( _("RTP stream output") );
143 set_capability( "sout stream", 0 );
144 add_shortcut( "rtp" );
145 set_category( CAT_SOUT );
146 set_subcategory( SUBCAT_SOUT_STREAM );
148 add_string( SOUT_CFG_PREFIX "dst", "", NULL, DST_TEXT,
149 DST_LONGTEXT, VLC_TRUE );
150 add_string( SOUT_CFG_PREFIX "sdp", "", NULL, SDP_TEXT,
151 SDP_LONGTEXT, VLC_TRUE );
152 add_string( SOUT_CFG_PREFIX "mux", "", NULL, MUX_TEXT,
153 MUX_LONGTEXT, VLC_TRUE );
155 add_string( SOUT_CFG_PREFIX "name", "", NULL, NAME_TEXT,
156 NAME_LONGTEXT, VLC_TRUE );
157 add_string( SOUT_CFG_PREFIX "description", "", NULL, DESC_TEXT,
158 DESC_LONGTEXT, VLC_TRUE );
159 add_string( SOUT_CFG_PREFIX "url", "", NULL, URL_TEXT,
160 URL_LONGTEXT, VLC_TRUE );
161 add_string( SOUT_CFG_PREFIX "email", "", NULL, EMAIL_TEXT,
162 EMAIL_LONGTEXT, VLC_TRUE );
163 add_string( SOUT_CFG_PREFIX "phone", "", NULL, PHONE_TEXT,
164 PHONE_LONGTEXT, VLC_TRUE );
166 add_integer( SOUT_CFG_PREFIX "port", 1234, NULL, PORT_TEXT,
167 PORT_LONGTEXT, VLC_TRUE );
168 add_integer( SOUT_CFG_PREFIX "port-audio", 1230, NULL, PORT_AUDIO_TEXT,
169 PORT_AUDIO_LONGTEXT, VLC_TRUE );
170 add_integer( SOUT_CFG_PREFIX "port-video", 1232, NULL, PORT_VIDEO_TEXT,
171 PORT_VIDEO_LONGTEXT, VLC_TRUE );
173 add_integer( SOUT_CFG_PREFIX "ttl", 0, NULL, TTL_TEXT,
174 TTL_LONGTEXT, VLC_TRUE );
176 add_bool( SOUT_CFG_PREFIX "rtcp-mux", VLC_FALSE, NULL,
177 RTCP_MUX_TEXT, RTCP_MUX_LONGTEXT, VLC_FALSE );
179 add_bool( SOUT_CFG_PREFIX "dccp", VLC_FALSE, NULL,
180 DCCP_TEXT, DCCP_LONGTEXT, VLC_FALSE );
181 add_bool( SOUT_CFG_PREFIX "tcp", VLC_FALSE, NULL,
182 TCP_TEXT, TCP_LONGTEXT, VLC_FALSE );
183 add_bool( SOUT_CFG_PREFIX "udplite", VLC_FALSE, NULL,
184 UDP_LITE_TEXT, UDP_LITE_LONGTEXT, VLC_FALSE );
186 add_bool( SOUT_CFG_PREFIX "mp4a-latm", 0, NULL, RFC3016_TEXT,
187 RFC3016_LONGTEXT, VLC_FALSE );
189 set_callbacks( Open, Close );
192 /*****************************************************************************
193 * Exported prototypes
194 *****************************************************************************/
195 static const char *ppsz_sout_options[] = {
196 "dst", "name", "port", "port-audio", "port-video", "*sdp", "ttl", "mux",
197 "description", "url", "email", "phone",
198 "rtcp-mux", "dccp", "tcp", "udplite",
202 static sout_stream_id_t *Add ( sout_stream_t *, es_format_t * );
203 static int Del ( sout_stream_t *, sout_stream_id_t * );
204 static int Send( sout_stream_t *, sout_stream_id_t *,
206 static sout_stream_id_t *MuxAdd ( sout_stream_t *, es_format_t * );
207 static int MuxDel ( sout_stream_t *, sout_stream_id_t * );
208 static int MuxSend( sout_stream_t *, sout_stream_id_t *,
211 static sout_access_out_t *GrabberCreate( sout_stream_t *p_sout );
212 static void ThreadSend( vlc_object_t *p_this );
214 static void SDPHandleUrl( sout_stream_t *, char * );
216 static int SapSetup( sout_stream_t *p_stream );
217 static int FileSetup( sout_stream_t *p_stream );
218 static int HttpSetup( sout_stream_t *p_stream, vlc_url_t * );
220 struct sout_stream_sys_t
224 vlc_mutex_t lock_sdp;
227 vlc_bool_t b_export_sdp_file;
231 vlc_bool_t b_export_sap;
232 session_descriptor_t *p_session;
235 httpd_host_t *p_httpd_host;
236 httpd_file_t *p_httpd_file;
242 char *psz_destination;
246 uint16_t i_port_audio;
247 uint16_t i_port_video;
251 /* when need to use a private one or when using muxer */
254 /* in case we do TS/PS over rtp */
256 sout_access_out_t *p_grab;
262 sout_stream_id_t **es;
265 typedef int (*pf_rtp_packetizer_t)( sout_stream_t *, sout_stream_id_t *,
268 typedef struct rtp_sink_t
274 struct sout_stream_id_t
278 sout_stream_t *p_stream;
281 uint8_t i_payload_type;
292 /* Packetizer specific fields */
293 pf_rtp_packetizer_t pf_packetize;
297 vlc_mutex_t lock_sink;
300 rtsp_stream_id_t *rtsp_id;
303 block_fifo_t *p_fifo;
308 /*****************************************************************************
310 *****************************************************************************/
311 static int Open( vlc_object_t *p_this )
313 sout_stream_t *p_stream = (sout_stream_t*)p_this;
314 sout_instance_t *p_sout = p_stream->p_sout;
315 sout_stream_sys_t *p_sys = NULL;
316 config_chain_t *p_cfg = NULL;
318 vlc_bool_t b_rtsp = VLC_FALSE;
320 config_ChainParse( p_stream, SOUT_CFG_PREFIX,
321 ppsz_sout_options, p_stream->p_cfg );
323 p_sys = malloc( sizeof( sout_stream_sys_t ) );
327 p_sys->psz_destination = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "dst" );
329 p_sys->i_port = var_GetInteger( p_stream, SOUT_CFG_PREFIX "port" );
330 p_sys->i_port_audio = var_GetInteger( p_stream, SOUT_CFG_PREFIX "port-audio" );
331 p_sys->i_port_video = var_GetInteger( p_stream, SOUT_CFG_PREFIX "port-video" );
332 p_sys->rtcp_mux = var_GetBool( p_stream, SOUT_CFG_PREFIX "rtcp-mux" );
334 p_sys->psz_sdp_file = NULL;
336 if( p_sys->i_port_audio == p_sys->i_port_video )
338 msg_Err( p_stream, "audio and video port cannot be the same" );
339 p_sys->i_port_audio = 0;
340 p_sys->i_port_video = 0;
343 for( p_cfg = p_stream->p_cfg; p_cfg != NULL; p_cfg = p_cfg->p_next )
345 if( !strcmp( p_cfg->psz_name, "sdp" )
346 && ( p_cfg->psz_value != NULL )
347 && !strncasecmp( p_cfg->psz_value, "rtsp:", 5 ) )
355 psz = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "sdp" );
358 if( !strncasecmp( psz, "rtsp:", 5 ) )
364 /* Transport protocol */
365 p_sys->proto = IPPROTO_UDP;
367 if( var_GetBool( p_stream, SOUT_CFG_PREFIX "dccp" ) )
369 p_sys->proto = IPPROTO_DCCP;
370 p_sys->rtcp_mux = VLC_TRUE; /* Force RTP/RTCP mux */
374 if( var_GetBool( p_stream, SOUT_CFG_PREFIX "tcp" ) )
376 p_sys->proto = IPPROTO_TCP;
377 p_sys->rtcp_mux = VLC_TRUE; /* Force RTP/RTCP mux */
381 if( var_GetBool( p_stream, SOUT_CFG_PREFIX "udplite" ) )
382 p_sys->proto = IPPROTO_UDPLITE;
384 if( ( p_sys->psz_destination == NULL ) && !b_rtsp )
386 msg_Err( p_stream, "missing destination and not in RTSP mode" );
391 p_sys->i_ttl = var_GetInteger( p_stream, SOUT_CFG_PREFIX "ttl" );
392 if( p_sys->i_ttl == 0 )
394 /* Normally, we should let the default hop limit up to the core,
395 * but we have to know it to build our SDP properly, which is why
396 * we ask the core. FIXME: broken when neither sout-rtp-ttl nor
398 p_sys->i_ttl = config_GetInt( p_stream, "ttl" );
401 p_sys->b_latm = var_GetBool( p_stream, SOUT_CFG_PREFIX "mp4a-latm" );
403 p_sys->i_payload_type = 96;
407 p_sys->psz_sdp = NULL;
409 p_sys->b_export_sap = VLC_FALSE;
410 p_sys->b_export_sdp_file = VLC_FALSE;
411 p_sys->p_session = NULL;
413 p_sys->p_httpd_host = NULL;
414 p_sys->p_httpd_file = NULL;
416 p_stream->p_sys = p_sys;
418 vlc_mutex_init( p_stream, &p_sys->lock_sdp );
419 vlc_mutex_init( p_stream, &p_sys->lock_es );
421 psz = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "mux" );
424 sout_stream_id_t *id;
426 /* Check muxer type */
427 if( strncasecmp( psz, "ps", 2 )
428 && strncasecmp( psz, "mpeg1", 5 )
429 && strncasecmp( psz, "ts", 2 ) )
431 msg_Err( p_stream, "unsupported muxer type for RTP (only TS/PS)" );
433 vlc_mutex_destroy( &p_sys->lock_sdp );
434 vlc_mutex_destroy( &p_sys->lock_es );
439 p_sys->p_grab = GrabberCreate( p_stream );
440 p_sys->p_mux = sout_MuxNew( p_sout, psz, p_sys->p_grab );
443 if( p_sys->p_mux == NULL )
445 msg_Err( p_stream, "cannot create muxer" );
446 sout_AccessOutDelete( p_sys->p_grab );
447 vlc_mutex_destroy( &p_sys->lock_sdp );
448 vlc_mutex_destroy( &p_sys->lock_es );
453 id = Add( p_stream, NULL );
456 sout_MuxDelete( p_sys->p_mux );
457 sout_AccessOutDelete( p_sys->p_grab );
458 vlc_mutex_destroy( &p_sys->lock_sdp );
459 vlc_mutex_destroy( &p_sys->lock_es );
464 p_sys->packet = NULL;
466 p_stream->pf_add = MuxAdd;
467 p_stream->pf_del = MuxDel;
468 p_stream->pf_send = MuxSend;
473 p_sys->p_grab = NULL;
475 p_stream->pf_add = Add;
476 p_stream->pf_del = Del;
477 p_stream->pf_send = Send;
480 psz = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "sdp" );
483 config_chain_t *p_cfg;
485 SDPHandleUrl( p_stream, psz );
487 for( p_cfg = p_stream->p_cfg; p_cfg != NULL; p_cfg = p_cfg->p_next )
489 if( !strcmp( p_cfg->psz_name, "sdp" ) )
491 if( p_cfg->psz_value == NULL || *p_cfg->psz_value == '\0' )
494 /* needed both :sout-rtp-sdp= and rtp{sdp=} can be used */
495 if( !strcmp( p_cfg->psz_value, psz ) )
498 SDPHandleUrl( p_stream, p_cfg->psz_value );
504 /* update p_sout->i_out_pace_nocontrol */
505 p_stream->p_sout->i_out_pace_nocontrol++;
510 /*****************************************************************************
512 *****************************************************************************/
513 static void Close( vlc_object_t * p_this )
515 sout_stream_t *p_stream = (sout_stream_t*)p_this;
516 sout_stream_sys_t *p_sys = p_stream->p_sys;
518 /* update p_sout->i_out_pace_nocontrol */
519 p_stream->p_sout->i_out_pace_nocontrol--;
523 assert( p_sys->i_es == 1 );
524 Del( p_stream, p_sys->es[0] );
526 sout_MuxDelete( p_sys->p_mux );
527 sout_AccessOutDelete( p_sys->p_grab );
530 block_Release( p_sys->packet );
532 if( p_sys->b_export_sap )
535 SapSetup( p_stream );
539 if( p_sys->rtsp != NULL )
540 RtspUnsetup( p_sys->rtsp );
542 vlc_mutex_destroy( &p_sys->lock_sdp );
543 vlc_mutex_destroy( &p_sys->lock_es );
545 if( p_sys->p_httpd_file )
546 httpd_FileDelete( p_sys->p_httpd_file );
548 if( p_sys->p_httpd_host )
549 httpd_HostDelete( p_sys->p_httpd_host );
551 free( p_sys->psz_sdp );
553 if( p_sys->b_export_sdp_file )
556 unlink( p_sys->psz_sdp_file );
558 free( p_sys->psz_sdp_file );
560 free( p_sys->psz_destination );
564 /*****************************************************************************
566 *****************************************************************************/
567 static void SDPHandleUrl( sout_stream_t *p_stream, char *psz_url )
569 sout_stream_sys_t *p_sys = p_stream->p_sys;
572 vlc_UrlParse( &url, psz_url, 0 );
573 if( url.psz_protocol && !strcasecmp( url.psz_protocol, "http" ) )
575 if( p_sys->p_httpd_file )
577 msg_Err( p_stream, "you can use sdp=http:// only once" );
581 if( HttpSetup( p_stream, &url ) )
583 msg_Err( p_stream, "cannot export SDP as HTTP" );
586 else if( url.psz_protocol && !strcasecmp( url.psz_protocol, "rtsp" ) )
588 if( p_sys->rtsp != NULL )
590 msg_Err( p_stream, "you can use sdp=rtsp:// only once" );
594 /* FIXME test if destination is multicast or no destination at all */
595 p_sys->rtsp = RtspSetup( p_stream, &url );
596 if( p_sys->rtsp == NULL )
598 msg_Err( p_stream, "cannot export SDP as RTSP" );
601 if( p_sys->p_mux != NULL )
603 sout_stream_id_t *id = p_sys->es[0];
604 id->rtsp_id = RtspAddId( p_sys->rtsp, id, 0,
605 p_sys->psz_destination, p_sys->i_ttl,
606 id->i_port, id->i_port + 1 );
609 else if( ( url.psz_protocol && !strcasecmp( url.psz_protocol, "sap" ) ) ||
610 ( url.psz_host && !strcasecmp( url.psz_host, "sap" ) ) )
612 p_sys->b_export_sap = VLC_TRUE;
613 SapSetup( p_stream );
615 else if( url.psz_protocol && !strcasecmp( url.psz_protocol, "file" ) )
617 if( p_sys->b_export_sdp_file )
619 msg_Err( p_stream, "you can use sdp=file:// only once" );
622 p_sys->b_export_sdp_file = VLC_TRUE;
623 psz_url = &psz_url[5];
624 if( psz_url[0] == '/' && psz_url[1] == '/' )
626 p_sys->psz_sdp_file = strdup( psz_url );
630 msg_Warn( p_stream, "unknown protocol for SDP (%s)",
635 vlc_UrlClean( &url );
638 /*****************************************************************************
640 *****************************************************************************/
642 char *SDPGenerate( const sout_stream_t *p_stream, const char *rtsp_url )
644 const sout_stream_sys_t *p_sys = p_stream->p_sys;
646 struct sockaddr_storage dst;
650 * When we have a fixed destination (typically when we do multicast),
651 * we need to put the actual port numbers in the SDP.
652 * When there is no fixed destination, we only support RTSP unicast
653 * on-demand setup, so we should rather let the clients decide which ports
655 * When there is both a fixed destination and RTSP unicast, we need to
656 * put port numbers used by the fixed destination, otherwise the SDP would
657 * become totally incorrect for multicast use. It should be noted that
658 * port numbers from SDP with RTSP are only "recommendation" from the
659 * server to the clients (per RFC2326), so only broken clients will fail
660 * to handle this properly. There is no solution but to use two differents
661 * output chain with two different RTSP URLs if you need to handle this
666 if( p_sys->psz_destination != NULL )
670 /* Oh boy, this is really ugly! (+ race condition on lock_es) */
671 dstlen = sizeof( dst );
672 if( p_sys->es[0]->listen_fd != NULL )
673 getsockname( p_sys->es[0]->listen_fd[0],
674 (struct sockaddr *)&dst, &dstlen );
676 getpeername( p_sys->es[0]->sinkv[0].rtp_fd,
677 (struct sockaddr *)&dst, &dstlen );
683 /* Dummy destination address for RTSP */
684 memset (&dst, 0, sizeof( struct sockaddr_in ) );
685 dst.ss_family = AF_INET;
689 dstlen = sizeof( struct sockaddr_in );
692 psz_sdp = vlc_sdp_Start( VLC_OBJECT( p_stream ), SOUT_CFG_PREFIX,
693 NULL, 0, (struct sockaddr *)&dst, dstlen );
694 if( psz_sdp == NULL )
697 /* TODO: a=source-filter */
698 if( p_sys->rtcp_mux )
699 sdp_AddAttribute( &psz_sdp, "rtcp-mux", NULL );
701 if( rtsp_url != NULL )
702 sdp_AddAttribute ( &psz_sdp, "control", "%s", rtsp_url );
704 /* FIXME: locking?! */
705 for( i = 0; i < p_sys->i_es; i++ )
707 sout_stream_id_t *id = p_sys->es[i];
708 const char *mime_major; /* major MIME type */
709 const char *proto = "RTP/AVP"; /* protocol */
714 mime_major = "video";
717 mime_major = "audio";
726 if( rtsp_url == NULL )
728 switch( p_sys->proto )
733 proto = "TCP/RTP/AVP";
736 proto = "DCCP/RTP/AVP";
738 case IPPROTO_UDPLITE:
743 sdp_AddMedia( &psz_sdp, mime_major, proto, inclport * id->i_port,
744 id->i_payload_type, VLC_FALSE, id->i_bitrate,
745 id->psz_rtpmap, id->psz_fmtp);
747 if( rtsp_url != NULL )
749 assert( strlen( rtsp_url ) > 0 );
750 vlc_bool_t addslash = ( rtsp_url[strlen( rtsp_url ) - 1] != '/' );
751 sdp_AddAttribute ( &psz_sdp, "control",
752 addslash ? "%s/trackID=%u" : "%strackID=%u",
757 if( id->listen_fd != NULL )
758 sdp_AddAttribute( &psz_sdp, "setup", "passive" );
760 if( p_sys->proto == IPPROTO_DCCP )
761 sdp_AddAttribute( &psz_sdp, "dccp-service-code",
762 "SC:RTP%c", toupper( mime_major[0] ) );
770 /*****************************************************************************
772 *****************************************************************************/
773 static int rtp_packetize_l16 ( sout_stream_t *, sout_stream_id_t *, block_t * );
774 static int rtp_packetize_l8 ( sout_stream_t *, sout_stream_id_t *, block_t * );
775 static int rtp_packetize_mpa ( sout_stream_t *, sout_stream_id_t *, block_t * );
776 static int rtp_packetize_mpv ( sout_stream_t *, sout_stream_id_t *, block_t * );
777 static int rtp_packetize_ac3 ( sout_stream_t *, sout_stream_id_t *, block_t * );
778 static int rtp_packetize_split( sout_stream_t *, sout_stream_id_t *, block_t * );
779 static int rtp_packetize_mp4a ( sout_stream_t *, sout_stream_id_t *, block_t * );
780 static int rtp_packetize_mp4a_latm ( sout_stream_t *, sout_stream_id_t *, block_t * );
781 static int rtp_packetize_h263 ( sout_stream_t *, sout_stream_id_t *, block_t * );
782 static int rtp_packetize_h264 ( sout_stream_t *, sout_stream_id_t *, block_t * );
783 static int rtp_packetize_amr ( sout_stream_t *, sout_stream_id_t *, block_t * );
784 static int rtp_packetize_spx ( sout_stream_t *, sout_stream_id_t *, block_t * );
785 static int rtp_packetize_t140 ( sout_stream_t *, sout_stream_id_t *, block_t * );
787 static void sprintf_hexa( char *s, uint8_t *p_data, int i_data )
789 static const char hex[16] = "0123456789abcdef";
792 for( i = 0; i < i_data; i++ )
794 s[2*i+0] = hex[(p_data[i]>>4)&0xf];
795 s[2*i+1] = hex[(p_data[i] )&0xf];
801 /** Add an ES as a new RTP stream */
802 static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
804 /* NOTE: As a special case, if we use a non-RTP
805 * mux (TS/PS), then p_fmt is NULL. */
806 sout_stream_sys_t *p_sys = p_stream->p_sys;
807 sout_stream_id_t *id;
808 int i_port, cscov = -1;
811 id = vlc_object_create( p_stream, sizeof( sout_stream_id_t ) );
814 vlc_object_attach( id, p_stream );
816 /* Choose the port */
821 if( p_fmt->i_cat == AUDIO_ES && p_sys->i_port_audio > 0 )
823 i_port = p_sys->i_port_audio;
824 p_sys->i_port_audio = 0;
827 if( p_fmt->i_cat == VIDEO_ES && p_sys->i_port_video > 0 )
829 i_port = p_sys->i_port_video;
830 p_sys->i_port_video = 0;
835 if( p_sys->i_port != p_sys->i_port_audio
836 && p_sys->i_port != p_sys->i_port_video )
838 i_port = p_sys->i_port;
845 id->p_stream = p_stream;
847 id->i_sequence = rand()&0xffff;
848 id->i_payload_type = p_sys->i_payload_type;
849 id->ssrc[0] = rand()&0xff;
850 id->ssrc[1] = rand()&0xff;
851 id->ssrc[2] = rand()&0xff;
852 id->ssrc[3] = rand()&0xff;
854 id->psz_rtpmap = NULL;
856 id->i_clock_rate = 90000; /* most common case */
860 id->i_cat = p_fmt->i_cat;
861 id->i_bitrate = p_fmt->i_bitrate/1000; /* Stream bitrate in kbps */
865 id->i_cat = VIDEO_ES;
869 id->pf_packetize = NULL;
870 id->i_mtu = config_GetInt( p_stream, "mtu" );
871 if( id->i_mtu <= 12 + 16 )
872 id->i_mtu = 576 - 20 - 8; /* pessimistic */
874 msg_Dbg( p_stream, "maximum RTP packet size: %d bytes", id->i_mtu );
876 vlc_mutex_init( p_stream, &id->lock_sink );
881 id->listen_fd = NULL;
884 (int64_t)1000 * var_GetInteger( p_stream, SOUT_CFG_PREFIX "caching");
886 if( p_sys->psz_destination != NULL )
887 switch( p_sys->proto )
891 id->listen_fd = net_Listen( VLC_OBJECT(p_stream),
892 p_sys->psz_destination, i_port,
894 if( id->listen_fd == NULL )
896 msg_Err( p_stream, "passive COMEDIA RTP socket failed" );
903 int ttl = (p_sys->i_ttl > 0) ? p_sys->i_ttl : -1;
904 int fd = net_ConnectDgram( p_stream, p_sys->psz_destination,
905 i_port, ttl, p_sys->proto );
908 msg_Err( p_stream, "cannot create RTP socket" );
911 rtp_add_sink( id, fd, p_sys->rtcp_mux );
917 char *psz = var_GetNonEmptyString( p_stream, SOUT_CFG_PREFIX "mux" );
919 if( psz == NULL ) /* Uho! */
922 if( strncmp( psz, "ts", 2 ) == 0 )
924 id->i_payload_type = 33;
925 id->psz_rtpmap = strdup( "MP2T/90000" );
929 id->psz_rtpmap = strdup( "MP2P/90000" );
933 switch( p_fmt->i_codec )
935 case VLC_FOURCC( 's', '1', '6', 'b' ):
936 if( p_fmt->audio.i_channels == 1 && p_fmt->audio.i_rate == 44100 )
938 id->i_payload_type = 11;
940 else if( p_fmt->audio.i_channels == 2 &&
941 p_fmt->audio.i_rate == 44100 )
943 id->i_payload_type = 10;
945 if( asprintf( &id->psz_rtpmap, "L16/%d/%d", p_fmt->audio.i_rate,
946 p_fmt->audio.i_channels ) == -1 )
947 id->psz_rtpmap = NULL;
948 id->i_clock_rate = p_fmt->audio.i_rate;
949 id->pf_packetize = rtp_packetize_l16;
951 case VLC_FOURCC( 'u', '8', ' ', ' ' ):
952 if( asprintf( &id->psz_rtpmap, "L8/%d/%d", p_fmt->audio.i_rate,
953 p_fmt->audio.i_channels ) == -1 )
954 id->psz_rtpmap = NULL;
955 id->i_clock_rate = p_fmt->audio.i_rate;
956 id->pf_packetize = rtp_packetize_l8;
958 case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
959 id->i_payload_type = 14;
960 id->psz_rtpmap = strdup( "MPA/90000" );
961 id->pf_packetize = rtp_packetize_mpa;
963 case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
964 id->i_payload_type = 32;
965 id->psz_rtpmap = strdup( "MPV/90000" );
966 id->pf_packetize = rtp_packetize_mpv;
968 case VLC_FOURCC( 'a', '5', '2', ' ' ):
969 id->psz_rtpmap = strdup( "ac3/90000" );
970 id->pf_packetize = rtp_packetize_ac3;
972 case VLC_FOURCC( 'H', '2', '6', '3' ):
973 id->psz_rtpmap = strdup( "H263-1998/90000" );
974 id->pf_packetize = rtp_packetize_h263;
976 case VLC_FOURCC( 'h', '2', '6', '4' ):
977 id->psz_rtpmap = strdup( "H264/90000" );
978 id->pf_packetize = rtp_packetize_h264;
981 if( p_fmt->i_extra > 0 )
983 uint8_t *p_buffer = p_fmt->p_extra;
984 int i_buffer = p_fmt->i_extra;
985 char *p_64_sps = NULL;
986 char *p_64_pps = NULL;
989 while( i_buffer > 4 &&
990 p_buffer[0] == 0 && p_buffer[1] == 0 &&
991 p_buffer[2] == 0 && p_buffer[3] == 1 )
993 const int i_nal_type = p_buffer[4]&0x1f;
997 msg_Dbg( p_stream, "we found a startcode for NAL with TYPE:%d", i_nal_type );
1000 for( i_offset = 4; i_offset+3 < i_buffer ; i_offset++)
1002 if( !memcmp (p_buffer + i_offset, "\x00\x00\x00\x01", 4 ) )
1004 /* we found another startcode */
1009 if( i_nal_type == 7 )
1011 p_64_sps = vlc_b64_encode_binary( &p_buffer[4], i_size - 4 );
1012 sprintf_hexa( hexa, &p_buffer[5], 3 );
1014 else if( i_nal_type == 8 )
1016 p_64_pps = vlc_b64_encode_binary( &p_buffer[4], i_size - 4 );
1022 if( p_64_sps && p_64_pps &&
1023 ( asprintf( &id->psz_fmtp,
1024 "packetization-mode=1;profile-level-id=%s;"
1025 "sprop-parameter-sets=%s,%s;", hexa, p_64_sps,
1026 p_64_pps ) == -1 ) )
1027 id->psz_fmtp = NULL;
1032 id->psz_fmtp = strdup( "packetization-mode=1" );
1035 case VLC_FOURCC( 'm', 'p', '4', 'v' ):
1037 char hexa[2*p_fmt->i_extra +1];
1039 id->psz_rtpmap = strdup( "MP4V-ES/90000" );
1040 id->pf_packetize = rtp_packetize_split;
1041 if( p_fmt->i_extra > 0 )
1043 sprintf_hexa( hexa, p_fmt->p_extra, p_fmt->i_extra );
1044 if( asprintf( &id->psz_fmtp,
1045 "profile-level-id=3; config=%s;", hexa ) == -1 )
1046 id->psz_fmtp = NULL;
1050 case VLC_FOURCC( 'm', 'p', '4', 'a' ):
1052 id->i_clock_rate = p_fmt->audio.i_rate;
1056 char hexa[2*p_fmt->i_extra +1];
1058 if( asprintf( &id->psz_rtpmap, "mpeg4-generic/%d",
1059 p_fmt->audio.i_rate ) == -1 )
1060 id->psz_rtpmap = NULL;
1061 id->pf_packetize = rtp_packetize_mp4a;
1062 sprintf_hexa( hexa, p_fmt->p_extra, p_fmt->i_extra );
1063 if( asprintf( &id->psz_fmtp,
1064 "streamtype=5; profile-level-id=15; "
1065 "mode=AAC-hbr; config=%s; SizeLength=13; "
1066 "IndexLength=3; IndexDeltaLength=3; Profile=1;",
1068 id->psz_fmtp = NULL;
1074 unsigned char config[6];
1075 unsigned int aacsrates[15] = {
1076 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
1077 16000, 12000, 11025, 8000, 7350, 0, 0 };
1079 for( i = 0; i < 15; i++ )
1080 if( p_fmt->audio.i_rate == aacsrates[i] )
1086 config[3]=p_fmt->audio.i_channels<<4;
1090 if( asprintf( &id->psz_rtpmap, "MP4A-LATM/%d/%d",
1091 p_fmt->audio.i_rate,
1092 p_fmt->audio.i_channels ) == -1)
1093 id->psz_rtpmap = NULL;
1094 id->pf_packetize = rtp_packetize_mp4a_latm;
1095 sprintf_hexa( hexa, config, 6 );
1096 if( asprintf( &id->psz_fmtp, "profile-level-id=15; "
1097 "object=2; cpresent=0; config=%s", hexa ) == -1 )
1098 id->psz_fmtp = NULL;
1102 case VLC_FOURCC( 's', 'a', 'm', 'r' ):
1103 id->psz_rtpmap = strdup( p_fmt->audio.i_channels == 2 ?
1104 "AMR/8000/2" : "AMR/8000" );
1105 id->psz_fmtp = strdup( "octet-align=1" );
1106 id->i_clock_rate = p_fmt->audio.i_rate;
1107 id->pf_packetize = rtp_packetize_amr;
1109 case VLC_FOURCC( 's', 'a', 'w', 'b' ):
1110 id->psz_rtpmap = strdup( p_fmt->audio.i_channels == 2 ?
1111 "AMR-WB/16000/2" : "AMR-WB/16000" );
1112 id->psz_fmtp = strdup( "octet-align=1" );
1113 id->i_clock_rate = p_fmt->audio.i_rate;
1114 id->pf_packetize = rtp_packetize_amr;
1116 case VLC_FOURCC( 's', 'p', 'x', ' ' ):
1117 id->i_payload_type = p_sys->i_payload_type++;
1118 if( asprintf( &id->psz_rtpmap, "SPEEX/%d",
1119 p_fmt->audio.i_rate ) == -1)
1120 id->psz_rtpmap = NULL;
1121 id->i_clock_rate = p_fmt->audio.i_rate;
1122 id->pf_packetize = rtp_packetize_spx;
1124 case VLC_FOURCC( 't', '1', '4', '0' ):
1125 id->psz_rtpmap = strdup( "t140/1000" );
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 p_sys->psz_destination,
1147 p_sys->i_ttl, id->i_port, id->i_port + 1 );
1149 id->p_fifo = block_FifoNew( p_stream );
1150 if( vlc_thread_create( id, "RTP send thread", ThreadSend,
1151 VLC_THREAD_PRIORITY_HIGHEST, VLC_FALSE ) )
1154 /* Update p_sys context */
1155 vlc_mutex_lock( &p_sys->lock_es );
1156 TAB_APPEND( p_sys->i_es, p_sys->es, id );
1157 vlc_mutex_unlock( &p_sys->lock_es );
1159 psz_sdp = SDPGenerate( p_stream, NULL );
1161 vlc_mutex_lock( &p_sys->lock_sdp );
1162 free( p_sys->psz_sdp );
1163 p_sys->psz_sdp = psz_sdp;
1164 vlc_mutex_unlock( &p_sys->lock_sdp );
1166 msg_Dbg( p_stream, "sdp=\n%s", p_sys->psz_sdp );
1168 /* Update SDP (sap/file) */
1169 if( p_sys->b_export_sap ) SapSetup( p_stream );
1170 if( p_sys->b_export_sdp_file ) FileSetup( p_stream );
1175 Del( p_stream, id );
1179 static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
1181 sout_stream_sys_t *p_sys = p_stream->p_sys;
1183 if( id->p_fifo != NULL )
1185 vlc_object_kill( id );
1186 block_FifoWake( id->p_fifo );
1187 vlc_thread_join( id );
1188 block_FifoRelease( id->p_fifo );
1191 vlc_mutex_lock( &p_sys->lock_es );
1192 TAB_REMOVE( p_sys->i_es, p_sys->es, id );
1193 vlc_mutex_unlock( &p_sys->lock_es );
1196 if( id->i_port > 0 )
1198 if( id->i_cat == AUDIO_ES && p_sys->i_port_audio == 0 )
1199 p_sys->i_port_audio = id->i_port;
1200 else if( id->i_cat == VIDEO_ES && p_sys->i_port_video == 0 )
1201 p_sys->i_port_video = id->i_port;
1204 free( id->psz_rtpmap );
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 )
1395 splice( fd[2], NULL, fd[4], NULL, len, 0 );
1397 if( ( send( id->sinkv[i].rtp_fd, out->p_buffer, len, 0 ) < 0 )
1398 && ( errno != EAGAIN ) )
1399 deadv[deadc++] = id->sinkv[i].rtp_fd;
1401 vlc_mutex_unlock( &id->lock_sink );
1403 block_Release( out );
1405 splice( fd[0], NULL, fd[4], NULL, len, 0 );
1408 for( unsigned i = 0; i < deadc; i++ )
1410 msg_Dbg( id, "removing socket %d", deadv[i] );
1411 rtp_del_sink( id, deadv[i] );
1414 /* Hopefully we won't overflow the SO_MAXCONN accept queue */
1415 while( id->listen_fd != NULL )
1417 int fd = net_Accept( id, id->listen_fd, 0 );
1420 msg_Dbg( id, "adding socket %d", fd );
1421 rtp_add_sink( id, fd, VLC_TRUE );
1426 for( unsigned i = 0; i < 5; i++ )
1431 static inline void rtp_packetize_send( sout_stream_id_t *id, block_t *out )
1433 block_FifoPut( id->p_fifo, out );
1436 int rtp_add_sink( sout_stream_id_t *id, int fd, vlc_bool_t rtcp_mux )
1438 rtp_sink_t sink = { fd, NULL };
1439 sink.rtcp = OpenRTCP( VLC_OBJECT( id->p_stream ), fd, IPPROTO_UDP,
1441 if( sink.rtcp == NULL )
1442 msg_Err( id, "RTCP failed!" );
1444 vlc_mutex_lock( &id->lock_sink );
1445 INSERT_ELEM( id->sinkv, id->sinkc, id->sinkc, sink );
1446 vlc_mutex_unlock( &id->lock_sink );
1450 void rtp_del_sink( sout_stream_id_t *id, int fd )
1452 rtp_sink_t sink = { fd, NULL };
1454 /* NOTE: must be safe to use if fd is not included */
1455 vlc_mutex_lock( &id->lock_sink );
1456 for( int i = 0; i < id->sinkc; i++ )
1458 if (id->sinkv[i].rtp_fd == fd)
1460 sink = id->sinkv[i];
1461 REMOVE_ELEM( id->sinkv, id->sinkc, i );
1465 vlc_mutex_unlock( &id->lock_sink );
1467 CloseRTCP( sink.rtcp );
1468 net_Close( sink.rtp_fd );
1471 uint16_t rtp_get_seq( const sout_stream_id_t *id )
1473 /* This will return values for the next packet.
1474 * Accounting for caching would not be totally trivial. */
1475 return id->i_sequence;
1478 /* FIXME: this is pretty bad - if we remove and then insert an ES
1479 * the number will get unsynched from inside RTSP */
1480 unsigned rtp_get_num( const sout_stream_id_t *id )
1482 sout_stream_sys_t *p_sys = id->p_stream->p_sys;
1485 vlc_mutex_lock( &p_sys->lock_es );
1486 for( i = 0; i < p_sys->i_es; i++ )
1488 if( id == p_sys->es[i] )
1491 vlc_mutex_unlock( &p_sys->lock_es );
1497 /****************************************************************************
1499 ****************************************************************************/
1500 static void rtp_packetize_common( sout_stream_id_t *id, block_t *out,
1501 int b_marker, int64_t i_pts )
1503 uint32_t i_timestamp = i_pts * (int64_t)id->i_clock_rate / I64C(1000000);
1505 out->p_buffer[0] = 0x80;
1506 out->p_buffer[1] = (b_marker?0x80:0x00)|id->i_payload_type;
1507 out->p_buffer[2] = ( id->i_sequence >> 8)&0xff;
1508 out->p_buffer[3] = ( id->i_sequence )&0xff;
1509 out->p_buffer[4] = ( i_timestamp >> 24 )&0xff;
1510 out->p_buffer[5] = ( i_timestamp >> 16 )&0xff;
1511 out->p_buffer[6] = ( i_timestamp >> 8 )&0xff;
1512 out->p_buffer[7] = ( i_timestamp )&0xff;
1514 memcpy( out->p_buffer + 8, id->ssrc, 4 );
1520 static int rtp_packetize_mpa( sout_stream_t *p_stream, sout_stream_id_t *id,
1523 int i_max = id->i_mtu - 12 - 4; /* payload max in one packet */
1524 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1526 uint8_t *p_data = in->p_buffer;
1527 int i_data = in->i_buffer;
1530 for( i = 0; i < i_count; i++ )
1532 int i_payload = __MIN( i_max, i_data );
1533 block_t *out = block_New( p_stream, 16 + i_payload );
1535 /* rtp common header */
1536 rtp_packetize_common( id, out, (i == i_count - 1)?1:0, in->i_pts );
1538 out->p_buffer[12] = 0;
1539 out->p_buffer[13] = 0;
1540 /* fragment offset in the current frame */
1541 out->p_buffer[14] = ( (i*i_max) >> 8 )&0xff;
1542 out->p_buffer[15] = ( (i*i_max) )&0xff;
1543 memcpy( &out->p_buffer[16], p_data, i_payload );
1545 out->i_buffer = 16 + i_payload;
1546 out->i_dts = in->i_dts + i * in->i_length / i_count;
1547 out->i_length = in->i_length / i_count;
1549 rtp_packetize_send( id, out );
1551 p_data += i_payload;
1552 i_data -= i_payload;
1559 static int rtp_packetize_mpv( sout_stream_t *p_stream, sout_stream_id_t *id,
1562 int i_max = id->i_mtu - 12 - 4; /* payload max in one packet */
1563 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1565 uint8_t *p_data = in->p_buffer;
1566 int i_data = in->i_buffer;
1568 int b_sequence_start = 0;
1569 int i_temporal_ref = 0;
1570 int i_picture_coding_type = 0;
1571 int i_fbv = 0, i_bfc = 0, i_ffv = 0, i_ffc = 0;
1572 int b_start_slice = 0;
1574 /* preparse this packet to get some info */
1575 if( in->i_buffer > 4 )
1577 uint8_t *p = p_data;
1578 int i_rest = in->i_buffer;
1582 while( i_rest > 4 &&
1583 ( p[0] != 0x00 || p[1] != 0x00 || p[2] != 0x01 ) )
1597 /* sequence start code */
1598 b_sequence_start = 1;
1600 else if( *p == 0x00 && i_rest >= 4 )
1603 i_temporal_ref = ( p[1] << 2) |((p[2]>>6)&0x03);
1604 i_picture_coding_type = (p[2] >> 3)&0x07;
1606 if( i_rest >= 4 && ( i_picture_coding_type == 2 ||
1607 i_picture_coding_type == 3 ) )
1609 i_ffv = (p[3] >> 2)&0x01;
1610 i_ffc = ((p[3]&0x03) << 1)|((p[4]>>7)&0x01);
1611 if( i_rest > 4 && i_picture_coding_type == 3 )
1613 i_fbv = (p[4]>>6)&0x01;
1614 i_bfc = (p[4]>>3)&0x07;
1618 else if( *p <= 0xaf )
1625 for( i = 0; i < i_count; i++ )
1627 int i_payload = __MIN( i_max, i_data );
1628 block_t *out = block_New( p_stream,
1630 uint32_t h = ( i_temporal_ref << 16 )|
1631 ( b_sequence_start << 13 )|
1632 ( b_start_slice << 12 )|
1633 ( i == i_count - 1 ? 1 << 11 : 0 )|
1634 ( i_picture_coding_type << 8 )|
1635 ( i_fbv << 7 )|( i_bfc << 4 )|( i_ffv << 3 )|i_ffc;
1637 /* rtp common header */
1638 rtp_packetize_common( id, out, (i == i_count - 1)?1:0,
1639 in->i_pts > 0 ? in->i_pts : in->i_dts );
1641 /* 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 */
1642 out->p_buffer[12] = ( h >> 24 )&0xff;
1643 out->p_buffer[13] = ( h >> 16 )&0xff;
1644 out->p_buffer[14] = ( h >> 8 )&0xff;
1645 out->p_buffer[15] = ( h )&0xff;
1647 memcpy( &out->p_buffer[16], p_data, i_payload );
1649 out->i_buffer = 16 + i_payload;
1650 out->i_dts = in->i_dts + i * in->i_length / i_count;
1651 out->i_length = in->i_length / i_count;
1653 rtp_packetize_send( id, out );
1655 p_data += i_payload;
1656 i_data -= i_payload;
1662 static int rtp_packetize_ac3( sout_stream_t *p_stream, sout_stream_id_t *id,
1665 int i_max = id->i_mtu - 12 - 2; /* payload max in one packet */
1666 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1668 uint8_t *p_data = in->p_buffer;
1669 int i_data = in->i_buffer;
1672 for( i = 0; i < i_count; i++ )
1674 int i_payload = __MIN( i_max, i_data );
1675 block_t *out = block_New( p_stream, 14 + i_payload );
1677 /* rtp common header */
1678 rtp_packetize_common( id, out, (i == i_count - 1)?1:0, in->i_pts );
1680 out->p_buffer[12] = 1;
1682 out->p_buffer[13] = 0x00;
1684 memcpy( &out->p_buffer[14], p_data, i_payload );
1686 out->i_buffer = 14 + i_payload;
1687 out->i_dts = in->i_dts + i * in->i_length / i_count;
1688 out->i_length = in->i_length / i_count;
1690 rtp_packetize_send( id, out );
1692 p_data += i_payload;
1693 i_data -= i_payload;
1699 static int rtp_packetize_split( sout_stream_t *p_stream, sout_stream_id_t *id,
1702 int i_max = id->i_mtu - 12; /* payload max in one packet */
1703 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1705 uint8_t *p_data = in->p_buffer;
1706 int i_data = in->i_buffer;
1709 for( i = 0; i < i_count; i++ )
1711 int i_payload = __MIN( i_max, i_data );
1712 block_t *out = block_New( p_stream, 12 + i_payload );
1714 /* rtp common header */
1715 rtp_packetize_common( id, out, ((i == i_count - 1)?1:0),
1716 (in->i_pts > 0 ? in->i_pts : in->i_dts) );
1717 memcpy( &out->p_buffer[12], p_data, i_payload );
1719 out->i_buffer = 12 + i_payload;
1720 out->i_dts = in->i_dts + i * in->i_length / i_count;
1721 out->i_length = in->i_length / i_count;
1723 rtp_packetize_send( id, out );
1725 p_data += i_payload;
1726 i_data -= i_payload;
1733 static int rtp_packetize_mp4a_latm( sout_stream_t *p_stream, sout_stream_id_t *id,
1736 int i_max = id->i_mtu - 14; /* payload max in one packet */
1737 int latmhdrsize = in->i_buffer / 0xff + 1;
1738 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1740 uint8_t *p_data = in->p_buffer, *p_header = NULL;
1741 int i_data = in->i_buffer;
1744 for( i = 0; i < i_count; i++ )
1746 int i_payload = __MIN( i_max, i_data );
1751 out = block_New( p_stream, 12 + latmhdrsize + i_payload );
1753 /* rtp common header */
1754 rtp_packetize_common( id, out, ((i == i_count - 1) ? 1 : 0),
1755 (in->i_pts > 0 ? in->i_pts : in->i_dts) );
1759 int tmp = in->i_buffer;
1761 p_header=out->p_buffer+12;
1771 memcpy( &out->p_buffer[12+latmhdrsize], p_data, i_payload );
1773 out->i_buffer = 12 + latmhdrsize + i_payload;
1774 out->i_dts = in->i_dts + i * in->i_length / i_count;
1775 out->i_length = in->i_length / i_count;
1777 rtp_packetize_send( id, out );
1779 p_data += i_payload;
1780 i_data -= i_payload;
1786 static int rtp_packetize_l16( sout_stream_t *p_stream, sout_stream_id_t *id,
1789 int i_max = id->i_mtu - 12; /* payload max in one packet */
1790 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1792 uint8_t *p_data = in->p_buffer;
1793 int i_data = in->i_buffer;
1798 int i_payload = (__MIN( i_max, i_data )/4)*4;
1799 block_t *out = block_New( p_stream, 12 + i_payload );
1801 /* rtp common header */
1802 rtp_packetize_common( id, out, 0,
1803 (in->i_pts > 0 ? in->i_pts : in->i_dts) );
1804 memcpy( &out->p_buffer[12], p_data, i_payload );
1806 out->i_buffer = 12 + i_payload;
1807 out->i_dts = in->i_dts + i_packet * in->i_length / i_count;
1808 out->i_length = in->i_length / i_count;
1810 rtp_packetize_send( id, out );
1812 p_data += i_payload;
1813 i_data -= i_payload;
1820 static int rtp_packetize_l8( sout_stream_t *p_stream, sout_stream_id_t *id,
1823 int i_max = id->i_mtu - 12; /* payload max in one packet */
1824 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1826 uint8_t *p_data = in->p_buffer;
1827 int i_data = in->i_buffer;
1832 int i_payload = (__MIN( i_max, i_data )/2)*2;
1833 block_t *out = block_New( p_stream, 12 + i_payload );
1835 /* rtp common header */
1836 rtp_packetize_common( id, out, 0,
1837 (in->i_pts > 0 ? in->i_pts : in->i_dts) );
1838 memcpy( &out->p_buffer[12], p_data, i_payload );
1840 out->i_buffer = 12 + i_payload;
1841 out->i_dts = in->i_dts + i_packet * in->i_length / i_count;
1842 out->i_length = in->i_length / i_count;
1844 rtp_packetize_send( id, out );
1846 p_data += i_payload;
1847 i_data -= i_payload;
1854 static int rtp_packetize_mp4a( sout_stream_t *p_stream, sout_stream_id_t *id,
1857 int i_max = id->i_mtu - 16; /* payload max in one packet */
1858 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
1860 uint8_t *p_data = in->p_buffer;
1861 int i_data = in->i_buffer;
1864 for( i = 0; i < i_count; i++ )
1866 int i_payload = __MIN( i_max, i_data );
1867 block_t *out = block_New( p_stream, 16 + i_payload );
1869 /* rtp common header */
1870 rtp_packetize_common( id, out, ((i == i_count - 1)?1:0),
1871 (in->i_pts > 0 ? in->i_pts : in->i_dts) );
1873 /* AU headers length (bits) */
1874 out->p_buffer[12] = 0;
1875 out->p_buffer[13] = 2*8;
1876 /* for each AU length 13 bits + idx 3bits, */
1877 out->p_buffer[14] = ( in->i_buffer >> 5 )&0xff;
1878 out->p_buffer[15] = ( (in->i_buffer&0xff)<<3 )|0;
1880 memcpy( &out->p_buffer[16], p_data, i_payload );
1882 out->i_buffer = 16 + i_payload;
1883 out->i_dts = in->i_dts + i * in->i_length / i_count;
1884 out->i_length = in->i_length / i_count;
1886 rtp_packetize_send( id, out );
1888 p_data += i_payload;
1889 i_data -= i_payload;
1897 #define RTP_H263_HEADER_SIZE (2) // plen = 0
1898 #define RTP_H263_PAYLOAD_START (14) // plen = 0
1899 static int rtp_packetize_h263( sout_stream_t *p_stream, sout_stream_id_t *id,
1902 uint8_t *p_data = in->p_buffer;
1903 int i_data = in->i_buffer;
1905 int i_max = id->i_mtu - 12 - RTP_H263_HEADER_SIZE; /* payload max in one packet */
1908 int b_v_bit = 0; // no pesky error resilience
1909 int i_plen = 0; // normally plen=0 for PSC packet
1910 int i_pebit = 0; // because plen=0
1915 return VLC_EGENERIC;
1917 if( p_data[0] || p_data[1] )
1919 return VLC_EGENERIC;
1921 /* remove 2 leading 0 bytes */
1924 i_count = ( i_data + i_max - 1 ) / i_max;
1926 for( i = 0; i < i_count; i++ )
1928 int i_payload = __MIN( i_max, i_data );
1929 block_t *out = block_New( p_stream,
1930 RTP_H263_PAYLOAD_START + i_payload );
1931 b_p_bit = (i == 0) ? 1 : 0;
1932 h = ( b_p_bit << 10 )|
1937 /* rtp common header */
1938 //b_m_bit = 1; // always contains end of frame
1939 rtp_packetize_common( id, out, (i == i_count - 1)?1:0,
1940 in->i_pts > 0 ? in->i_pts : in->i_dts );
1943 out->p_buffer[12] = ( h >> 8 )&0xff;
1944 out->p_buffer[13] = ( h )&0xff;
1945 memcpy( &out->p_buffer[RTP_H263_PAYLOAD_START], p_data, i_payload );
1947 out->i_buffer = RTP_H263_PAYLOAD_START + i_payload;
1948 out->i_dts = in->i_dts + i * in->i_length / i_count;
1949 out->i_length = in->i_length / i_count;
1951 rtp_packetize_send( id, out );
1953 p_data += i_payload;
1954 i_data -= i_payload;
1962 rtp_packetize_h264_nal( sout_stream_t *p_stream, sout_stream_id_t *id,
1963 const uint8_t *p_data, int i_data, int64_t i_pts,
1964 int64_t i_dts, vlc_bool_t b_last, int64_t i_length )
1966 const int i_max = id->i_mtu - 12; /* payload max in one packet */
1973 i_nal_hdr = p_data[3];
1974 i_nal_type = i_nal_hdr&0x1f;
1976 /* Skip start code */
1981 if( i_data <= i_max )
1983 /* Single NAL unit packet */
1984 block_t *out = block_New( p_stream, 12 + i_data );
1986 out->i_length = i_length;
1989 rtp_packetize_common( id, out, b_last, i_pts );
1990 out->i_buffer = 12 + i_data;
1992 memcpy( &out->p_buffer[12], p_data, i_data );
1994 rtp_packetize_send( id, out );
1998 /* FU-A Fragmentation Unit without interleaving */
1999 const int i_count = ( i_data-1 + i_max-2 - 1 ) / (i_max-2);
2005 for( i = 0; i < i_count; i++ )
2007 const int i_payload = __MIN( i_data, i_max-2 );
2008 block_t *out = block_New( p_stream, 12 + 2 + i_payload );
2009 out->i_dts = i_dts + i * i_length / i_count;
2010 out->i_length = i_length / i_count;
2013 rtp_packetize_common( id, out, (b_last && i_payload == i_data), i_pts );
2014 out->i_buffer = 14 + i_payload;
2017 out->p_buffer[12] = 0x00 | (i_nal_hdr & 0x60) | 28;
2019 out->p_buffer[13] = ( i == 0 ? 0x80 : 0x00 ) | ( (i == i_count-1) ? 0x40 : 0x00 ) | i_nal_type;
2020 memcpy( &out->p_buffer[14], p_data, i_payload );
2022 rtp_packetize_send( id, out );
2024 i_data -= i_payload;
2025 p_data += i_payload;
2031 static int rtp_packetize_h264( sout_stream_t *p_stream, sout_stream_id_t *id,
2034 const uint8_t *p_buffer = in->p_buffer;
2035 int i_buffer = in->i_buffer;
2037 while( i_buffer > 4 && ( p_buffer[0] != 0 || p_buffer[1] != 0 || p_buffer[2] != 1 ) )
2043 /* Split nal units */
2044 while( i_buffer > 4 )
2047 int i_size = i_buffer;
2048 int i_skip = i_buffer;
2050 /* search nal end */
2051 for( i_offset = 4; i_offset+2 < i_buffer ; i_offset++)
2053 if( p_buffer[i_offset] == 0 && p_buffer[i_offset+1] == 0 && p_buffer[i_offset+2] == 1 )
2055 /* we found another startcode */
2056 i_size = i_offset - ( p_buffer[i_offset-1] == 0 ? 1 : 0);
2061 /* TODO add STAP-A to remove a lot of overhead with small slice/sei/... */
2062 rtp_packetize_h264_nal( p_stream, id, p_buffer, i_size,
2063 (in->i_pts > 0 ? in->i_pts : in->i_dts), in->i_dts,
2064 (i_size >= i_buffer), in->i_length * i_size / in->i_buffer );
2072 static int rtp_packetize_amr( sout_stream_t *p_stream, sout_stream_id_t *id,
2075 int i_max = id->i_mtu - 14; /* payload max in one packet */
2076 int i_count = ( in->i_buffer + i_max - 1 ) / i_max;
2078 uint8_t *p_data = in->p_buffer;
2079 int i_data = in->i_buffer;
2082 /* Only supports octet-aligned mode */
2083 for( i = 0; i < i_count; i++ )
2085 int i_payload = __MIN( i_max, i_data );
2086 block_t *out = block_New( p_stream, 14 + i_payload );
2088 /* rtp common header */
2089 rtp_packetize_common( id, out, ((i == i_count - 1)?1:0),
2090 (in->i_pts > 0 ? in->i_pts : in->i_dts) );
2091 /* Payload header */
2092 out->p_buffer[12] = 0xF0; /* CMR */
2093 out->p_buffer[13] = p_data[0]&0x7C; /* ToC */ /* FIXME: frame type */
2095 /* FIXME: are we fed multiple frames ? */
2096 memcpy( &out->p_buffer[14], p_data+1, i_payload-1 );
2098 out->i_buffer = 14 + i_payload-1;
2099 out->i_dts = in->i_dts + i * in->i_length / i_count;
2100 out->i_length = in->i_length / i_count;
2102 rtp_packetize_send( id, out );
2104 p_data += i_payload;
2105 i_data -= i_payload;
2111 static int rtp_packetize_t140( sout_stream_t *p_stream, sout_stream_id_t *id,
2114 const size_t i_max = id->i_mtu - 12;
2115 const uint8_t *p_data = in->p_buffer;
2116 size_t i_data = in->i_buffer;
2118 for( unsigned i_packet = 0; i_data > 0; i_packet++ )
2120 size_t i_payload = i_data;
2122 /* Make sure we stop on an UTF-8 character boundary
2123 * (assuming the input is valid UTF-8) */
2124 if( i_data > i_max )
2128 while( ( p_data[i_payload] & 0xC0 ) == 0x80 )
2130 if( i_payload == 0 )
2131 return VLC_SUCCESS; /* fishy input! */
2137 block_t *out = block_New( p_stream, 12 + i_payload );
2141 rtp_packetize_common( id, out, 0, in->i_pts + i_packet );
2142 memcpy( out->p_buffer + 12, p_data, i_payload );
2144 out->i_buffer = 12 + i_payload;
2145 out->i_dts = out->i_pts;
2148 rtp_packetize_send( id, out );
2150 p_data += i_payload;
2151 i_data -= i_payload;
2157 /*****************************************************************************
2159 *****************************************************************************/
2161 /** Add an ES to a non-RTP muxed stream */
2162 static sout_stream_id_t *MuxAdd( sout_stream_t *p_stream, es_format_t *p_fmt )
2164 sout_input_t *p_input;
2165 sout_mux_t *p_mux = p_stream->p_sys->p_mux;
2166 assert( p_mux != NULL );
2168 p_input = sout_MuxAddStream( p_mux, p_fmt );
2169 if( p_input == NULL )
2171 msg_Err( p_stream, "cannot add this stream to the muxer" );
2175 return (sout_stream_id_t *)p_input;
2179 static int MuxSend( sout_stream_t *p_stream, sout_stream_id_t *id,
2182 sout_mux_t *p_mux = p_stream->p_sys->p_mux;
2183 assert( p_mux != NULL );
2185 sout_MuxSendBuffer( p_mux, (sout_input_t *)id, p_buffer );
2190 /** Remove an ES from a non-RTP muxed stream */
2191 static int MuxDel( sout_stream_t *p_stream, sout_stream_id_t *id )
2193 sout_mux_t *p_mux = p_stream->p_sys->p_mux;
2194 assert( p_mux != NULL );
2196 sout_MuxDeleteStream( p_mux, (sout_input_t *)id );
2201 static int AccessOutGrabberWriteBuffer( sout_stream_t *p_stream,
2202 const block_t *p_buffer )
2204 sout_stream_sys_t *p_sys = p_stream->p_sys;
2205 sout_stream_id_t *id = p_sys->es[0];
2207 int64_t i_dts = p_buffer->i_dts;
2209 uint8_t *p_data = p_buffer->p_buffer;
2210 unsigned int i_data = p_buffer->i_buffer;
2211 unsigned int i_max = id->i_mtu - 12;
2213 unsigned i_packet = ( p_buffer->i_buffer + i_max - 1 ) / i_max;
2217 unsigned int i_size;
2219 /* output complete packet */
2220 if( p_sys->packet &&
2221 p_sys->packet->i_buffer + i_data > i_max )
2223 rtp_packetize_send( id, p_sys->packet );
2224 p_sys->packet = NULL;
2227 if( p_sys->packet == NULL )
2229 /* allocate a new packet */
2230 p_sys->packet = block_New( p_stream, id->i_mtu );
2231 rtp_packetize_common( id, p_sys->packet, 1, i_dts );
2232 p_sys->packet->i_dts = i_dts;
2233 p_sys->packet->i_length = p_buffer->i_length / i_packet;
2234 i_dts += p_sys->packet->i_length;
2237 i_size = __MIN( i_data,
2238 (unsigned)(id->i_mtu - p_sys->packet->i_buffer) );
2240 memcpy( &p_sys->packet->p_buffer[p_sys->packet->i_buffer],
2243 p_sys->packet->i_buffer += i_size;
2252 static int AccessOutGrabberWrite( sout_access_out_t *p_access,
2255 sout_stream_t *p_stream = (sout_stream_t*)p_access->p_sys;
2261 AccessOutGrabberWriteBuffer( p_stream, p_buffer );
2263 p_next = p_buffer->p_next;
2264 block_Release( p_buffer );
2272 static sout_access_out_t *GrabberCreate( sout_stream_t *p_stream )
2274 sout_access_out_t *p_grab;
2276 p_grab = vlc_object_create( p_stream->p_sout, sizeof( *p_grab ) );
2277 if( p_grab == NULL )
2280 p_grab->p_module = NULL;
2281 p_grab->p_sout = p_stream->p_sout;
2282 p_grab->psz_access = strdup( "grab" );
2283 p_grab->p_cfg = NULL;
2284 p_grab->psz_path = strdup( "" );
2285 p_grab->p_sys = (sout_access_out_sys_t *)p_stream;
2286 p_grab->pf_seek = NULL;
2287 p_grab->pf_write = AccessOutGrabberWrite;
2291 static int rtp_packetize_spx( sout_stream_t *p_stream, sout_stream_id_t *id,
2294 uint8_t *p_buffer = in->p_buffer;
2295 int i_data_size, i_payload_size, i_payload_padding;
2296 i_data_size = i_payload_size = in->i_buffer;
2297 i_payload_padding = 0;
2300 if ( in->i_buffer + 12 > id->i_mtu )
2302 msg_Warn( p_stream, "Cannot send packet larger than output MTU" );
2307 RFC for Speex in RTP says that each packet must end on an octet
2308 boundary. So, we check to see if the number of bytes % 4 is zero.
2309 If not, we have to add some padding.
2311 This MAY be overkill since packetization is handled elsewhere and
2312 appears to ensure the octet boundary. However, better safe than
2315 if ( i_payload_size % 4 )
2317 i_payload_padding = 4 - ( i_payload_size % 4 );
2318 i_payload_size += i_payload_padding;
2322 Allocate a new RTP p_output block of the appropriate size.
2323 Allow for 12 extra bytes of RTP header.
2325 p_out = block_New( p_stream, 12 + i_payload_size );
2327 if ( i_payload_padding )
2330 The padding is required to be a zero followed by all 1s.
2332 char c_first_pad, c_remaining_pad;
2334 c_remaining_pad = 0xFF;
2337 Allow for 12 bytes before the i_data_size because
2338 of the expected RTP header added during
2339 rtp_packetize_common.
2341 p_out->p_buffer[12 + i_data_size] = c_first_pad;
2342 switch (i_payload_padding)
2345 p_out->p_buffer[12 + i_data_size + 1] = c_remaining_pad;
2348 p_out->p_buffer[12 + i_data_size + 1] = c_remaining_pad;
2349 p_out->p_buffer[12 + i_data_size + 2] = c_remaining_pad;
2354 /* Add the RTP header to our p_output buffer. */
2355 rtp_packetize_common( id, p_out, 0, (in->i_pts > 0 ? in->i_pts : in->i_dts) );
2356 /* Copy the Speex payload to the p_output buffer */
2357 memcpy( &p_out->p_buffer[12], p_buffer, i_data_size );
2359 p_out->i_buffer = 12 + i_payload_size;
2360 p_out->i_dts = in->i_dts;
2361 p_out->i_length = in->i_length;
2363 /* Queue the buffer for actual transmission. */
2364 rtp_packetize_send( id, p_out );