#include <vlc_network.h>
#include <vlc_charset.h>
#include <vlc_strings.h>
+#include <vlc_rand.h>
#include <srtp.h>
#include "rtp.h"
#define SOUT_CFG_PREFIX "sout-rtp-"
#define MAX_EMPTY_BLOCKS 200
-vlc_module_begin();
- set_shortname( N_("RTP"));
- set_description( N_("RTP stream output") );
- set_capability( "sout stream", 0 );
- add_shortcut( "rtp" );
- set_category( CAT_SOUT );
- set_subcategory( SUBCAT_SOUT_STREAM );
+vlc_module_begin ()
+ set_shortname( N_("RTP"))
+ set_description( N_("RTP stream output") )
+ set_capability( "sout stream", 0 )
+ add_shortcut( "rtp" )
+ set_category( CAT_SOUT )
+ set_subcategory( SUBCAT_SOUT_STREAM )
add_string( SOUT_CFG_PREFIX "dst", "", NULL, DEST_TEXT,
- DEST_LONGTEXT, true );
+ DEST_LONGTEXT, true )
add_string( SOUT_CFG_PREFIX "sdp", "", NULL, SDP_TEXT,
- SDP_LONGTEXT, true );
+ SDP_LONGTEXT, true )
add_string( SOUT_CFG_PREFIX "mux", "", NULL, MUX_TEXT,
- MUX_LONGTEXT, true );
+ MUX_LONGTEXT, true )
add_bool( SOUT_CFG_PREFIX "sap", false, NULL, SAP_TEXT, SAP_LONGTEXT,
- true );
+ true )
add_string( SOUT_CFG_PREFIX "name", "", NULL, NAME_TEXT,
- NAME_LONGTEXT, true );
+ NAME_LONGTEXT, true )
add_string( SOUT_CFG_PREFIX "description", "", NULL, DESC_TEXT,
- DESC_LONGTEXT, true );
+ DESC_LONGTEXT, true )
add_string( SOUT_CFG_PREFIX "url", "", NULL, URL_TEXT,
- URL_LONGTEXT, true );
+ URL_LONGTEXT, true )
add_string( SOUT_CFG_PREFIX "email", "", NULL, EMAIL_TEXT,
- EMAIL_LONGTEXT, true );
+ EMAIL_LONGTEXT, true )
add_string( SOUT_CFG_PREFIX "phone", "", NULL, PHONE_TEXT,
- PHONE_LONGTEXT, true );
+ PHONE_LONGTEXT, true )
add_string( SOUT_CFG_PREFIX "proto", "udp", NULL, PROTO_TEXT,
- PROTO_LONGTEXT, false );
- change_string_list( ppsz_protos, ppsz_protocols, NULL );
- add_integer( SOUT_CFG_PREFIX "port", 50004, NULL, PORT_TEXT,
- PORT_LONGTEXT, true );
- add_integer( SOUT_CFG_PREFIX "port-audio", 50000, NULL, PORT_AUDIO_TEXT,
- PORT_AUDIO_LONGTEXT, true );
- add_integer( SOUT_CFG_PREFIX "port-video", 50002, NULL, PORT_VIDEO_TEXT,
- PORT_VIDEO_LONGTEXT, true );
+ PROTO_LONGTEXT, false )
+ change_string_list( ppsz_protos, ppsz_protocols, NULL )
+ add_integer( SOUT_CFG_PREFIX "port", 5004, NULL, PORT_TEXT,
+ PORT_LONGTEXT, true )
+ add_integer( SOUT_CFG_PREFIX "port-audio", 0, NULL, PORT_AUDIO_TEXT,
+ PORT_AUDIO_LONGTEXT, true )
+ add_integer( SOUT_CFG_PREFIX "port-video", 0, NULL, PORT_VIDEO_TEXT,
+ PORT_VIDEO_LONGTEXT, true )
add_integer( SOUT_CFG_PREFIX "ttl", -1, NULL, TTL_TEXT,
- TTL_LONGTEXT, true );
+ TTL_LONGTEXT, true )
add_bool( SOUT_CFG_PREFIX "rtcp-mux", false, NULL,
- RTCP_MUX_TEXT, RTCP_MUX_LONGTEXT, false );
+ RTCP_MUX_TEXT, RTCP_MUX_LONGTEXT, false )
add_string( SOUT_CFG_PREFIX "key", "", NULL,
- SRTP_KEY_TEXT, SRTP_KEY_LONGTEXT, false );
+ SRTP_KEY_TEXT, SRTP_KEY_LONGTEXT, false )
add_string( SOUT_CFG_PREFIX "salt", "", NULL,
- SRTP_SALT_TEXT, SRTP_SALT_LONGTEXT, false );
+ SRTP_SALT_TEXT, SRTP_SALT_LONGTEXT, false )
add_bool( SOUT_CFG_PREFIX "mp4a-latm", 0, NULL, RFC3016_TEXT,
- RFC3016_LONGTEXT, false );
+ RFC3016_LONGTEXT, false )
- set_callbacks( Open, Close );
-vlc_module_end();
+ set_callbacks( Open, Close )
+vlc_module_end ()
/*****************************************************************************
* Exported prototypes
p_sys->i_port = var_GetInteger( p_stream, SOUT_CFG_PREFIX "port" );
p_sys->i_port_audio = var_GetInteger( p_stream, SOUT_CFG_PREFIX "port-audio" );
p_sys->i_port_video = var_GetInteger( p_stream, SOUT_CFG_PREFIX "port-video" );
- p_sys->rtcp_mux = var_GetBool( p_stream, SOUT_CFG_PREFIX "rtcp-mux" );
+ p_sys->rtcp_mux = var_GetBool( p_stream, SOUT_CFG_PREFIX "rtcp-mux" );
p_sys->psz_sdp_file = NULL;
- if( p_sys->i_port_audio == p_sys->i_port_video )
+ if( p_sys->i_port_audio && p_sys->i_port_video == p_sys->i_port_audio )
{
- msg_Err( p_stream, "audio and video port cannot be the same" );
- p_sys->i_port_audio = 0;
- p_sys->i_port_video = 0;
+ msg_Err( p_stream, "audio and video RTP port must be distinct" );
+ free( p_sys->psz_destination );
+ free( p_sys );
+ return VLC_EGENERIC;
}
for( p_cfg = p_stream->p_cfg; p_cfg != NULL; p_cfg = p_cfg->p_next )
free( psz );
vlc_mutex_destroy( &p_sys->lock_sdp );
vlc_mutex_destroy( &p_sys->lock_es );
+ free( p_sys->psz_destination );
free( p_sys );
return VLC_EGENERIC;
}
sout_AccessOutDelete( p_sys->p_grab );
vlc_mutex_destroy( &p_sys->lock_sdp );
vlc_mutex_destroy( &p_sys->lock_es );
+ free( p_sys->psz_destination );
free( p_sys );
return VLC_EGENERIC;
}
sout_AccessOutDelete( p_sys->p_grab );
vlc_mutex_destroy( &p_sys->lock_sdp );
vlc_mutex_destroy( &p_sys->lock_es );
+ free( p_sys->psz_destination );
free( p_sys );
return VLC_EGENERIC;
}
/* FIXME test if destination is multicast or no destination at all */
p_sys->rtsp = RtspSetup( p_stream, &url );
if( p_sys->rtsp == NULL )
- {
msg_Err( p_stream, "cannot export SDP as RTSP" );
- }
-
+ else
if( p_sys->p_mux != NULL )
{
sout_stream_id_t *id = p_sys->es[0];
id->psz_enc, id->i_clock_rate, id->i_channels,
id->psz_fmtp);
+ if( !p_sys->rtcp_mux && (id->i_port & 1) ) /* cf RFC4566 ยง5.14 */
+ sdp_AddAttribute ( &psz_sdp, "rtcp", "%u", id->i_port + 1 );
+
if( rtsp_url != NULL )
{
assert( strlen( rtsp_url ) > 0 );
sout_stream_id_t *id;
int i_port, cscov = -1;
char *psz_sdp;
+ int i_port_audio_option = var_GetInteger( p_stream, "port-audio" );
+ int i_port_video_option = var_GetInteger( p_stream, "port-video" );
if (0xffffffff == p_sys->payload_bitmap)
{
while( i_port == 0 )
{
- if( p_sys->i_port != p_sys->i_port_audio
- && p_sys->i_port != p_sys->i_port_video )
+ if( p_sys->i_port != i_port_audio_option
+ && p_sys->i_port != i_port_video_option )
{
i_port = p_sys->i_port;
- p_sys->i_port += 2;
- break;
}
p_sys->i_port += 2;
}
id->p_stream = p_stream;
- id->i_sequence = rand()&0xffff;
/* Look for free dymanic payload type */
id->i_payload_type = 96;
while (p_sys->payload_bitmap & (1 << (id->i_payload_type - 96)))
id->i_payload_type++;
assert (id->i_payload_type < 128);
- id->ssrc[0] = rand()&0xff;
- id->ssrc[1] = rand()&0xff;
- id->ssrc[2] = rand()&0xff;
- id->ssrc[3] = rand()&0xff;
+ vlc_rand_bytes (&id->i_sequence, sizeof (id->i_sequence));
+ vlc_rand_bytes (id->ssrc, sizeof (id->ssrc));
id->psz_enc = NULL;
id->psz_fmtp = NULL;
{
case VIDEO_ES: code = "RTPV"; break;
case AUDIO_ES: code = "RTPARTPV"; break;
- case SPU_ES: code = "RTPTRPTV"; break;
+ case SPU_ES: code = "RTPTRTPV"; break;
default: code = "RTPORTPV"; break;
}
var_SetString (p_stream, "dccp-service", code);
else
switch( p_fmt->i_codec )
{
- case VLC_FOURCC( 'u', 'l', 'a', 'w' ):
+ case VLC_CODEC_MULAW:
if( p_fmt->audio.i_channels == 1 && p_fmt->audio.i_rate == 8000 )
id->i_payload_type = 0;
id->psz_enc = "PCMU";
id->pf_packetize = rtp_packetize_split;
rtp_set_ptime (id, 20, 1);
break;
- case VLC_FOURCC( 'a', 'l', 'a', 'w' ):
+ case VLC_CODEC_ALAW:
if( p_fmt->audio.i_channels == 1 && p_fmt->audio.i_rate == 8000 )
id->i_payload_type = 8;
id->psz_enc = "PCMA";
id->pf_packetize = rtp_packetize_split;
rtp_set_ptime (id, 20, 1);
break;
- case VLC_FOURCC( 's', '1', '6', 'b' ):
+ case VLC_CODEC_S16B:
if( p_fmt->audio.i_channels == 1 && p_fmt->audio.i_rate == 44100 )
{
id->i_payload_type = 11;
id->pf_packetize = rtp_packetize_split;
rtp_set_ptime (id, 20, 2);
break;
- case VLC_FOURCC( 'u', '8', ' ', ' ' ):
+ case VLC_CODEC_U8:
id->psz_enc = "L8";
id->pf_packetize = rtp_packetize_split;
rtp_set_ptime (id, 20, 1);
break;
- case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
- case VLC_FOURCC( 'm', 'p', '3', ' ' ):
+ case VLC_CODEC_MPGA:
id->i_payload_type = 14;
id->psz_enc = "MPA";
id->i_clock_rate = 90000; /* not 44100 */
id->pf_packetize = rtp_packetize_mpa;
break;
- case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
+ case VLC_CODEC_MPGV:
id->i_payload_type = 32;
id->psz_enc = "MPV";
id->pf_packetize = rtp_packetize_mpv;
break;
- case VLC_FOURCC( 'G', '7', '2', '6' ):
- case VLC_FOURCC( 'g', '7', '2', '6' ):
+ case VLC_CODEC_ADPCM_G726:
switch( p_fmt->i_bitrate / 1000 )
{
case 16:
break;
}
break;
- case VLC_FOURCC( 'a', '5', '2', ' ' ):
+ case VLC_CODEC_A52:
id->psz_enc = "ac3";
id->pf_packetize = rtp_packetize_ac3;
break;
- case VLC_FOURCC( 'H', '2', '6', '3' ):
+ case VLC_CODEC_H263:
id->psz_enc = "H263-1998";
id->pf_packetize = rtp_packetize_h263;
break;
- case VLC_FOURCC( 'h', '2', '6', '4' ):
+ case VLC_CODEC_H264:
id->psz_enc = "H264";
id->pf_packetize = rtp_packetize_h264;
id->psz_fmtp = NULL;
id->psz_fmtp = strdup( "packetization-mode=1" );
break;
- case VLC_FOURCC( 'm', 'p', '4', 'v' ):
+ case VLC_CODEC_MP4V:
{
char hexa[2*p_fmt->i_extra +1];
}
break;
}
- case VLC_FOURCC( 'm', 'p', '4', 'a' ):
+ case VLC_CODEC_MP4A:
{
if(!p_sys->b_latm)
{
}
break;
}
- case VLC_FOURCC( 's', 'a', 'm', 'r' ):
+ case VLC_CODEC_AMR_NB:
id->psz_enc = "AMR";
id->psz_fmtp = strdup( "octet-align=1" );
id->pf_packetize = rtp_packetize_amr;
break;
- case VLC_FOURCC( 's', 'a', 'w', 'b' ):
+ case VLC_CODEC_AMR_WB:
id->psz_enc = "AMR-WB";
id->psz_fmtp = strdup( "octet-align=1" );
id->pf_packetize = rtp_packetize_amr;
break;
- case VLC_FOURCC( 's', 'p', 'x', ' ' ):
+ case VLC_CODEC_SPEEX:
id->psz_enc = "SPEEX";
id->pf_packetize = rtp_packetize_spx;
break;
- case VLC_FOURCC( 't', '1', '4', '0' ):
+ case VLC_CODEC_ITU_T140:
id->psz_enc = "t140" ;
id->i_clock_rate = 1000;
id->pf_packetize = rtp_packetize_t140;
/* Mark dynamic payload type in use */
p_sys->payload_bitmap |= 1 << (id->i_payload_type - 96);
+#if 0 /* No payload formats sets this at the moment */
if( cscov != -1 )
cscov += 8 /* UDP */ + 12 /* RTP */;
if( id->sinkc > 0 )
net_SetCSCov( id->sinkv[0].rtp_fd, cscov, -1 );
+#endif
if( p_sys->rtsp != NULL )
id->rtsp_id = RtspAddId( p_sys->rtsp, id, p_sys->i_es,
id->p_fifo = block_FifoNew();
if( vlc_thread_create( id, "RTP send thread", ThreadSend,
- VLC_THREAD_PRIORITY_HIGHEST, false ) )
+ VLC_THREAD_PRIORITY_HIGHEST ) )
goto error;
/* Update p_sys context */
****************************************************************************/
static void* ThreadSend( vlc_object_t *p_this )
{
+#ifdef WIN32
+# define ECONNREFUSED WSAECONNREFUSED
+# define ENOPROTOOPT WSAENOPROTOOPT
+# define EHOSTUNREACH WSAEHOSTUNREACH
+# define ENETUNREACH WSAENETUNREACH
+# define ENETDOWN WSAENETDOWN
+# define ENOBUFS WSAENOBUFS
+# define EAGAIN WSAEWOULDBLOCK
+# define EWOULDBLOCK WSAEWOULDBLOCK
+#endif
sout_stream_id_t *id = (sout_stream_id_t *)p_this;
unsigned i_caching = id->i_caching;
if( send( id->sinkv[i].rtp_fd, out->p_buffer, len, 0 ) >= 0 )
continue;
- /* Retry sending to root out soft-errors */
- if( send( id->sinkv[i].rtp_fd, out->p_buffer, len, 0 ) >= 0 )
- continue;
+ switch( net_errno )
+ {
+ /* Soft errors (e.g. ICMP): */
+ case ECONNREFUSED: /* Port unreachable */
+ case ENOPROTOOPT:
+#ifdef EPROTO
+ case EPROTO: /* Protocol unreachable */
+#endif
+ case EHOSTUNREACH: /* Host unreachable */
+ case ENETUNREACH: /* Network unreachable */
+ case ENETDOWN: /* Entire network down */
+ send( id->sinkv[i].rtp_fd, out->p_buffer, len, 0 );
+ /* Transient congestion: */
+ case ENOMEM: /* out of socket buffers */
+ case ENOBUFS:
+ case EAGAIN:
+#if (EAGAIN != EWOULDBLOCK)
+ case EWOULDBLOCK:
+#endif
+ continue;
+ }
deadv[deadc++] = id->sinkv[i].rtp_fd;
}