📄 rtp.c
字号:
if( val.i_int < 0 ) { msg_Warn( p_stream, "illegal TTL %d, using 1", val.i_int ); val.i_int = -1; } p_sys->i_ttl = val.i_int; var_Get( p_stream, SOUT_CFG_PREFIX "mp4a-latm", &val ); p_sys->b_latm = val.b_bool; p_sys->i_payload_type = 96; p_sys->i_es = 0; p_sys->es = NULL; p_sys->i_rtsp = 0; p_sys->rtsp = NULL; p_sys->psz_sdp = NULL; p_sys->i_sdp_id = mdate(); p_sys->i_sdp_version = 1; p_sys->psz_sdp = NULL; p_sys->b_export_sap = VLC_FALSE; p_sys->b_export_sdp_file = VLC_FALSE; p_sys->p_session = NULL; p_sys->p_httpd_host = NULL; p_sys->p_httpd_file = NULL; p_sys->p_rtsp_host = NULL; p_sys->p_rtsp_url = NULL; p_sys->psz_rtsp_control = NULL; p_sys->psz_rtsp_path = NULL; vlc_mutex_init( p_stream, &p_sys->lock_sdp ); vlc_mutex_init( p_stream, &p_sys->lock_es ); p_stream->pf_add = Add; p_stream->pf_del = Del; p_stream->pf_send = Send; p_stream->p_sys = p_sys; var_Get( p_stream, SOUT_CFG_PREFIX "mux", &val ); if( *val.psz_string ) { sout_access_out_t *p_grab; char *psz_rtpmap, url[NI_MAXHOST + 8], access[17], psz_ttl[5], ipv; if( !p_sys->psz_destination || *p_sys->psz_destination == '\0' ) { msg_Err( p_stream, "rtp needs a destination when muxing" ); free( p_sys ); return VLC_EGENERIC; } /* Check muxer type */ if( !strncasecmp( val.psz_string, "ps", 2 ) || !strncasecmp( val.psz_string, "mpeg1", 5 ) ) { psz_rtpmap = "MP2P/90000"; } else if( !strncasecmp( val.psz_string, "ts", 2 ) ) { psz_rtpmap = "MP2T/90000"; p_sys->i_payload_type = 33; } else { msg_Err( p_stream, "unsupported muxer type with rtp (only ts/ps)" ); free( p_sys ); return VLC_EGENERIC; } /* create the access out */ if( p_sys->i_ttl > 0 ) { sprintf( access, "udp{raw,ttl=%d}", p_sys->i_ttl ); } else { sprintf( access, "udp{raw}" ); } /* IPv6 needs brackets if not already present */ snprintf( url, sizeof( url ), ( ( p_sys->psz_destination[0] != '[' ) && ( strchr( p_sys->psz_destination, ':' ) != NULL ) ) ? "[%s]:%d" : "%s:%d", p_sys->psz_destination, p_sys->i_port ); url[sizeof( url ) - 1] = '\0'; /* FIXME: we should check that url is a numerical address, otherwise * the SDP will be quite broken (regardless of the IP protocol version) * Also it might be IPv6 with no ':' if it is a DNS name. */ ipv = ( strchr( p_sys->psz_destination, ':' ) != NULL ) ? '6' : '4'; if( !( p_sys->p_access = sout_AccessOutNew( p_sout, access, url ) ) ) { msg_Err( p_stream, "cannot create the access out for %s://%s", access, url ); free( p_sys ); return VLC_EGENERIC; } p_sys->i_mtu = config_GetInt( p_stream, "mtu" ); /* XXX beurk */ if( p_sys->i_mtu <= 16 + MTU_REDUCE ) { /* better than nothing */ p_sys->i_mtu = 1500; } p_sys->i_mtu -= MTU_REDUCE; /* the access out grabber TODO export it as sout_AccessOutGrabberNew */ p_grab = p_sys->p_grab = vlc_object_create( p_sout, sizeof( sout_access_out_t ) ); p_grab->p_module = NULL; p_grab->p_sout = p_sout; p_grab->psz_access = strdup( "grab" ); p_grab->p_cfg = NULL; p_grab->psz_name = strdup( "" ); p_grab->p_sys = (sout_access_out_sys_t*)p_stream; p_grab->pf_seek = NULL; p_grab->pf_write = AccessOutGrabberWrite; /* the muxer */ if( !( p_sys->p_mux = sout_MuxNew( p_sout, val.psz_string, p_sys->p_grab ) ) ) { msg_Err( p_stream, "cannot create the muxer (%s)", val.psz_string ); sout_AccessOutDelete( p_sys->p_grab ); sout_AccessOutDelete( p_sys->p_access ); free( p_sys ); return VLC_EGENERIC; } /* create the SDP for a muxed stream (only once) */ /* FIXME http://www.faqs.org/rfcs/rfc4566.html o= - should be local username (no spaces allowed) o= time should be hashed with some other value to garantee uniqueness o= don't use the localhost address. use fully qualified domain name or IP4 address a= source-filter: we need our source address a= x-plgroup: (missing) RTP packets need to get the correct src IP address */ if( (ipv == 4) && net_AddressIsMulticast( (vlc_object_t *)p_stream, p_sys->psz_destination ) ) { snprintf( psz_ttl, sizeof( psz_ttl ), "/%d", p_sys->i_ttl ); psz_ttl[sizeof( psz_ttl ) - 1] = '\0'; } else { psz_ttl[0] = '\0'; } asprintf( &p_sys->psz_sdp, "v=0\r\n" /* FIXME: source address not known :( */ "o=- "I64Fd" %d IN IP%c %s\r\n" "s=%s\r\n" "i=%s\r\n" "u=%s\r\n" "e=%s\r\n" "c=IN IP%c %s%s\r\n" "t=0 0\r\n" /* permanent stream */ /* when scheduled from vlm, we should set this info correctly */ "a=tool:"PACKAGE_STRING"\r\n" "a=recvonly\r\n" "a=type:broadcast\r\n" "m=video %d RTP/AVP %d\r\n" "a=rtpmap:%d %s\r\n", p_sys->i_sdp_id, p_sys->i_sdp_version, ipv, ipv == '6' ? "::1" : "127.0.0.1" /* FIXME */, p_sys->psz_session_name, p_sys->psz_session_description, p_sys->psz_session_url, p_sys->psz_session_email, ipv, p_sys->psz_destination, psz_ttl, p_sys->i_port, p_sys->i_payload_type, p_sys->i_payload_type, psz_rtpmap ); msg_Dbg( p_stream, "sdp=%s", p_sys->psz_sdp ); /* create the rtp context */ p_sys->ssrc[0] = rand()&0xff; p_sys->ssrc[1] = rand()&0xff; p_sys->ssrc[2] = rand()&0xff; p_sys->ssrc[3] = rand()&0xff; p_sys->i_sequence = rand()&0xffff; p_sys->i_timestamp_start = rand()&0xffffffff; p_sys->packet = NULL; } else { p_sys->p_mux = NULL; p_sys->p_access = NULL; p_sys->p_grab = NULL; } free( val.psz_string ); var_Get( p_stream, SOUT_CFG_PREFIX "sdp", &val ); if( *val.psz_string ) { sout_cfg_t *p_cfg; SDPHandleUrl( p_stream, val.psz_string ); for( p_cfg = p_stream->p_cfg; p_cfg != NULL; p_cfg = p_cfg->p_next ) { if( !strcmp( p_cfg->psz_name, "sdp" ) ) { if( p_cfg->psz_value == NULL || *p_cfg->psz_value == '\0' ) continue; if( !strcmp( p_cfg->psz_value, val.psz_string ) ) /* needed both :sout-rtp-sdp= and rtp{sdp=} can be used */ continue; SDPHandleUrl( p_stream, p_cfg->psz_value ); } } } free( val.psz_string ); /* update p_sout->i_out_pace_nocontrol */ p_stream->p_sout->i_out_pace_nocontrol++; return VLC_SUCCESS;}/***************************************************************************** * Close: *****************************************************************************/static void Close( vlc_object_t * p_this ){ sout_stream_t *p_stream = (sout_stream_t*)p_this; sout_stream_sys_t *p_sys = p_stream->p_sys; /* update p_sout->i_out_pace_nocontrol */ p_stream->p_sout->i_out_pace_nocontrol--; if( p_sys->p_mux ) { sout_MuxDelete( p_sys->p_mux ); sout_AccessOutDelete( p_sys->p_access ); sout_AccessOutDelete( p_sys->p_grab ); if( p_sys->packet ) { block_Release( p_sys->packet ); } if( p_sys->b_export_sap ) { p_sys->p_mux = NULL; SapSetup( p_stream ); } } while( p_sys->i_rtsp > 0 ) { RtspClientDel( p_stream, p_sys->rtsp[0] ); } vlc_mutex_destroy( &p_sys->lock_sdp ); if( p_sys->p_httpd_file ) { httpd_FileDelete( p_sys->p_httpd_file ); } if( p_sys->p_httpd_host ) { httpd_HostDelete( p_sys->p_httpd_host ); } if( p_sys->p_rtsp_url ) { httpd_UrlDelete( p_sys->p_rtsp_url ); } if( p_sys->p_rtsp_host ) { httpd_HostDelete( p_sys->p_rtsp_host ); } if( p_sys->psz_session_name ) { free( p_sys->psz_session_name ); p_sys->psz_session_name = NULL; } if( p_sys->psz_session_description ) { free( p_sys->psz_session_description ); p_sys->psz_session_description = NULL; } if( p_sys->psz_session_url ) { free( p_sys->psz_session_url ); p_sys->psz_session_url = NULL; } if( p_sys->psz_session_email ) { free( p_sys->psz_session_email ); p_sys->psz_session_email = NULL; } if( p_sys->psz_sdp ) { free( p_sys->psz_sdp ); p_sys->psz_sdp = NULL; } if( p_sys->b_export_sdp_file ) {#ifdef HAVE_UNISTD_H unlink( p_sys->psz_sdp_file );#endif free( p_sys->psz_sdp_file ); } free( p_sys );}/***************************************************************************** * SDPHandleUrl: *****************************************************************************/static void SDPHandleUrl( sout_stream_t *p_stream, char *psz_url ){ sout_stream_sys_t *p_sys = p_stream->p_sys; vlc_url_t url; vlc_UrlParse( &url, psz_url, 0 ); if( url.psz_protocol && !strcasecmp( url.psz_protocol, "http" ) ) { if( p_sys->p_httpd_file ) { msg_Err( p_stream, "you can use sdp=http:// only once" ); return; } if( HttpSetup( p_stream, &url ) ) { msg_Err( p_stream, "cannot export sdp as http" ); } } else if( url.psz_protocol && !strcasecmp( url.psz_protocol, "rtsp" ) ) { if( p_sys->p_rtsp_url ) { msg_Err( p_stream, "you can use sdp=rtsp:// only once" ); return; } /* FIXME test if destination is multicast or no destination at all FIXME */ if( RtspSetup( p_stream, &url ) ) { msg_Err( p_stream, "cannot export sdp as rtsp" ); } } else if( ( url.psz_protocol && !strcasecmp( url.psz_protocol, "sap" ) ) || ( url.psz_host && !strcasecmp( url.psz_host, "sap" ) ) ) { p_sys->b_export_sap = VLC_TRUE; SapSetup( p_stream ); } else if( url.psz_protocol && !strcasecmp( url.psz_protocol, "file" ) ) { if( p_sys->b_export_sdp_file ) { msg_Err( p_stream, "you can use sdp=file:// only once" ); return; } p_sys->b_export_sdp_file = VLC_TRUE; psz_url = &psz_url[5]; if( psz_url[0] == '/' && psz_url[1] == '/' ) psz_url += 2; p_sys->psz_sdp_file = strdup( psz_url ); } else { msg_Warn( p_stream, "unknown protocol for SDP (%s)", url.psz_protocol ); } vlc_UrlClean( &url );}/***************************************************************************** * SDPGenerate *****************************************************************************/ /* FIXME http://www.faqs.org/rfcs/rfc2327.html All text fields should be UTF-8 encoded. Use global a:charset to announce this. o= - should be local username (no spaces allowed) o= time should be hashed with some other value to garantue uniqueness o= we need IP6 support? o= don't use the localhost address. use fully qualified domain name or IP4 address p= international phone number (pass via vars?) c= IP6 support a= recvonly (missing) a= type:broadcast (missing) a= charset: (normally charset should be UTF-8, this can be used to override s= and i=) a= x-plgroup: (missing)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -