📄 rtp.c
字号:
char access[100]; char url[p_sys->psz_destination ? strlen( p_sys->psz_destination ) + 1 + 12+1 : 14]; /* 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)" ); 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}" ); } sprintf( url, "%s:%d", p_sys->psz_destination, p_sys->i_port ); 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 ) { /* better than nothing */ p_sys->i_mtu = 1500; } /* 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/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 c= /ttl should only be added in case of multicast 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) RTP packets need to get the correct src IP address */ p_sys->psz_sdp = malloc( 10 + 30 + 10 + strlen( p_sys->psz_session_name ) + 10 + strlen( p_sys->psz_session_description ) + 10 + strlen( p_sys->psz_session_url ) + 10 + strlen( p_sys->psz_session_email ) + 10 + strlen( p_sys->psz_destination ) + 10 + 10 + strlen( PACKAGE_STRING ) + 20 + 10 + 20 + 10 + strlen( psz_rtpmap ) ); sprintf( p_sys->psz_sdp, "v=0\r\n" "o=- "I64Fd" %d IN IP4 127.0.0.1\r\n" "s=%s\r\n" "i=%s\r\n" "u=%s\r\n" "e=%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" "c=IN IP4 %s/%d\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, p_sys->psz_session_name, p_sys->psz_session_description, p_sys->psz_session_url, p_sys->psz_session_email, p_sys->psz_destination, p_sys->i_ttl, p_sys->i_port, p_sys->i_payload_type, p_sys->i_payload_type, psz_rtpmap ); fprintf( stderr, "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 ); } } 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 0 /* why? is this disabled? */ 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; }#endif if( p_sys->psz_sdp ) { free( p_sys->psz_sdp ); } 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 used 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 used 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 used 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 c= /ttl should only be added in case of multicast 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) RTP packets need to get the correct src IP address */static char *SDPGenerate( sout_stream_t *p_stream, char *psz_destination, vlc_bool_t b_rtsp ){ sout_stream_sys_t *p_sys = p_stream->p_sys; int i_size; char *psz_sdp, *p; int i; i_size = strlen( "v=0\r\n" ) + strlen( "o=- * * IN IP4 127.0.0.1\r\n" ) + 10 + 10 + strlen( "s=*\r\n" ) + strlen( p_sys->psz_session_name ) + strlen( "i=*\r\n" ) + strlen( p_sys->psz_session_description ) + strlen( "u=*\r\n" ) + strlen( p_sys->psz_session_url ) + strlen( "e=*\r\n" ) + strlen( p_sys->psz_session_email ) + strlen( "t=0 0\r\n" ) + /* permanent stream */ /* when scheduled from vlm, we should set this info correctly */ strlen( "a=tool:"PACKAGE_STRING"\r\n" ) + strlen( "c=IN IP4 */*\r\n" ) + 20 + 10 + strlen( psz_destination ? psz_destination : "0.0.0.0") ; for( i = 0; i < p_sys->i_es; i++ ) { sout_stream_id_t *id = p_sys->es[i]; i_size += strlen( "m=**d*o * RTP/AVP *\r\n" ) + 10 + 10; if( id->psz_rtpmap ) { i_size += strlen( "a=rtpmap:* *\r\n" ) + strlen( id->psz_rtpmap )+10; } if( id->psz_fmtp ) { i_size += strlen( "a=fmtp:* *\r\n" ) + strlen( id->psz_fmtp ) + 10; } if( b_rtsp ) { i_size += strlen( "a=control:*/trackid=*\r\n" ) + strlen( p_sys->psz_rtsp_control ) + 10; } } p = psz_sdp = malloc( i_size ); p += sprintf( p, "v=0\r\n" ); p += sprintf( p, "o=- "I64Fd" %d IN IP4 127.0.0.1\r\n", p_sys->i_sdp_id, p_sys->i_sdp_version ); if( *p_sys->psz_session_name ) p += sprintf( p, "s=%s\r\n", p_sys->psz_session_name ); if( *p_sys->psz_session_description ) p += sprintf( p, "i=%s\r\n", p_sys->psz_session_description ); if( *p_sys->psz_session_url ) p += sprintf( p, "u=%s\r\n", p_sys->psz_session_url ); if( *p_sys->psz_session_email ) p += sprintf( p, "e=%s\r\n", p_sys->psz_session_email ); p += sprintf( p, "t=0 0\r\n" ); /* permanent stream */ /* when scheduled from vlm, we should set this info correctly */ p += sprintf( p, "a=tool:"PACKAGE_STRING"\r\n" ); p += sprintf( p, "c=IN IP4 %s/%d\r\n", psz_destination ? psz_destination : "0.0.0.0", p_sys->i_ttl ); for( i = 0; i < p_sys->i_es; i++ ) { sout_stream_id_t *id = p_sys->es[i]; if( id->i_cat == AUDIO_ES ) { p += sprintf( p, "m=audio %d RTP/AVP %d\r\n", id->i_port, id->i_payload_type ); } else if( id->i_cat == VIDEO_ES ) { p += sprintf( p, "m=video %d RTP/AVP %d\r\n", id->i_port, id->i_payload_type ); } else { continue; } if( id->psz_rtpmap ) { p += sprintf( p, "a=rtpmap:%d %s\r\n", id->i_payload_type, id->psz_rtpmap ); } if( id->psz_fmtp ) { p += sprintf( p, "a=fmtp:%d %s\r\n", id->i_payload_type, id->psz_fmtp ); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -