X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fstream_out%2Frtp.c;h=c0ec1977c2bedcb1d7546fc9b2702fae61074c5e;hb=d2e7edbdb2edf1afde6e67bef8161025dcbcad4a;hp=5c611ca116dd22a022e0ebcb20ede63cc1536ffa;hpb=c32cb1d118ba028be1df6b98a11811a27b04d782;p=vlc diff --git a/modules/stream_out/rtp.c b/modules/stream_out/rtp.c index 5c611ca116..c0ec1977c2 100644 --- a/modules/stream_out/rtp.c +++ b/modules/stream_out/rtp.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include "rtp.h" @@ -118,7 +119,7 @@ #define TTL_TEXT N_("Hop limit (TTL)") #define TTL_LONGTEXT N_( \ "This is the hop limit (also known as \"Time-To-Live\" or TTL) of " \ - "the multicast packets sent by the stream output (0 = use operating " \ + "the multicast packets sent by the stream output (-1 = use operating " \ "system built-in default).") #define RTCP_MUX_TEXT N_("RTP/RTCP multiplexing") @@ -157,60 +158,59 @@ static void Close( vlc_object_t * ); #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 ); - change_unsafe(); + 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 ); - - add_integer( SOUT_CFG_PREFIX "ttl", 0, NULL, TTL_TEXT, - TTL_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 ) 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 @@ -263,16 +263,14 @@ struct sout_stream_sys_t /* */ char *psz_destination; - uint8_t proto; - uint8_t i_ttl; + uint32_t payload_bitmap; uint16_t i_port; uint16_t i_port_audio; uint16_t i_port_video; - bool b_latm; - bool rtcp_mux; - - /* when need to use a private one or when using muxer */ - int i_payload_type; + uint8_t proto; + bool rtcp_mux; + int i_ttl:9; + bool b_latm; /* in case we do TS/PS over rtp */ sout_mux_t *p_mux; @@ -352,15 +350,16 @@ static int Open( vlc_object_t *p_this ) 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 ) @@ -429,7 +428,7 @@ static int Open( vlc_object_t *p_this ) } p_sys->i_ttl = var_GetInteger( p_stream, SOUT_CFG_PREFIX "ttl" ); - if( p_sys->i_ttl == 0 ) + if( p_sys->i_ttl == -1 ) { /* Normally, we should let the default hop limit up to the core, * but we have to know it to build our SDP properly, which is why @@ -440,7 +439,7 @@ static int Open( vlc_object_t *p_this ) p_sys->b_latm = var_GetBool( p_stream, SOUT_CFG_PREFIX "mp4a-latm" ); - p_sys->i_payload_type = 96; + p_sys->payload_bitmap = 0; p_sys->i_es = 0; p_sys->es = NULL; p_sys->rtsp = NULL; @@ -472,6 +471,7 @@ static int Open( vlc_object_t *p_this ) 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; } @@ -486,6 +486,7 @@ static int Open( vlc_object_t *p_this ) 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; } @@ -497,6 +498,7 @@ static int Open( vlc_object_t *p_this ) 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; } @@ -637,10 +639,8 @@ static void SDPHandleUrl( sout_stream_t *p_stream, const char *psz_url ) /* 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]; @@ -788,6 +788,9 @@ char *SDPGenerate( const sout_stream_t *p_stream, const char *rtsp_url ) 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 ); @@ -801,7 +804,7 @@ char *SDPGenerate( const sout_stream_t *p_stream, const char *rtsp_url ) if( id->listen_fd != NULL ) sdp_AddAttribute( &psz_sdp, "setup", "passive" ); if( p_sys->proto == IPPROTO_DCCP ) - sdp_AddAttribute( &psz_sdp, "dccp-service-code", + sdp_AddAttribute( &psz_sdp, "dccp-service-code", "SC:RTP%c", toupper( mime_major[0] ) ); } } @@ -852,6 +855,14 @@ static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt ) 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) + { + msg_Err (p_stream, "too many RTP elementary streams"); + return NULL; + } id = vlc_object_create( p_stream, sizeof( sout_stream_id_t ) ); if( id == NULL ) @@ -877,24 +888,24 @@ static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt ) 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; - id->i_payload_type = p_sys->i_payload_type; - id->ssrc[0] = rand()&0xff; - id->ssrc[1] = rand()&0xff; - id->ssrc[2] = rand()&0xff; - id->ssrc[3] = rand()&0xff; + /* 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); + + 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; @@ -968,7 +979,7 @@ static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt ) { 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); @@ -986,7 +997,7 @@ static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt ) default: { - int ttl = (p_sys->i_ttl > 0) ? p_sys->i_ttl : -1; + int ttl = (p_sys->i_ttl >= 0) ? p_sys->i_ttl : -1; int fd = net_ConnectDgram( p_stream, p_sys->psz_destination, i_port, ttl, p_sys->proto ); if( fd == -1 ) @@ -1224,7 +1235,6 @@ static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt ) id->pf_packetize = rtp_packetize_amr; break; case VLC_FOURCC( 's', 'p', 'x', ' ' ): - id->i_payload_type = p_sys->i_payload_type++; id->psz_enc = "SPEEX"; id->pf_packetize = rtp_packetize_spx; break; @@ -1239,14 +1249,16 @@ static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt ) "codec:%4.4s)", (char*)&p_fmt->i_codec ); goto error; } + if (id->i_payload_type >= 96) + /* 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 ); - - if( id->i_payload_type == p_sys->i_payload_type ) - p_sys->i_payload_type++; +#endif if( p_sys->rtsp != NULL ) id->rtsp_id = RtspAddId( p_sys->rtsp, id, p_sys->i_es, @@ -1256,7 +1268,7 @@ static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt ) 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 */ @@ -1304,6 +1316,9 @@ static int Del( sout_stream_t *p_stream, sout_stream_id_t *id ) p_sys->i_port_audio = id->i_port; if( id->i_port == var_GetInteger( p_stream, "port-video" ) ) p_sys->i_port_video = id->i_port; + /* Release dynamic payload type */ + if (id->i_payload_type >= 96) + p_sys->payload_bitmap &= ~(1 << (id->i_payload_type - 96)); free( id->psz_fmtp );