📄 rtp.c
字号:
if( ( f = utf8_fopen( p_sys->psz_sdp_file, "wt" ) ) == NULL ) { msg_Err( p_stream, "cannot open file '%s' (%s)", p_sys->psz_sdp_file, strerror(errno) ); return VLC_EGENERIC; } fprintf( f, "%s", p_sys->psz_sdp ); fclose( f ); return VLC_SUCCESS;}/**************************************************************************** * HTTP: ****************************************************************************/static int HttpCallback( httpd_file_sys_t *p_args, httpd_file_t *, uint8_t *p_request, uint8_t **pp_data, int *pi_data );static int HttpSetup( sout_stream_t *p_stream, vlc_url_t *url){ sout_stream_sys_t *p_sys = p_stream->p_sys; p_sys->p_httpd_host = httpd_HostNew( VLC_OBJECT(p_stream), url->psz_host, url->i_port > 0 ? url->i_port : 80 ); if( p_sys->p_httpd_host ) { p_sys->p_httpd_file = httpd_FileNew( p_sys->p_httpd_host, url->psz_path ? url->psz_path : "/", "application/sdp", NULL, NULL, NULL, HttpCallback, (void*)p_sys ); } if( p_sys->p_httpd_file == NULL ) { return VLC_EGENERIC; } return VLC_SUCCESS;}static int HttpCallback( httpd_file_sys_t *p_args, httpd_file_t *f, uint8_t *p_request, uint8_t **pp_data, int *pi_data ){ sout_stream_sys_t *p_sys = (sout_stream_sys_t*)p_args; vlc_mutex_lock( &p_sys->lock_sdp ); if( p_sys->psz_sdp && *p_sys->psz_sdp ) { *pi_data = strlen( p_sys->psz_sdp ); *pp_data = malloc( *pi_data ); memcpy( *pp_data, p_sys->psz_sdp, *pi_data ); } else { *pp_data = NULL; *pi_data = 0; } vlc_mutex_unlock( &p_sys->lock_sdp ); return VLC_SUCCESS;}/**************************************************************************** * RTSP: ****************************************************************************/static rtsp_client_t *RtspClientNew( sout_stream_t *p_stream, char *psz_session ){ rtsp_client_t *rtsp = malloc( sizeof( rtsp_client_t )); rtsp->psz_session = psz_session; rtsp->i_last = 0; rtsp->b_playing = VLC_FALSE; rtsp->i_id = 0; rtsp->id = NULL; rtsp->i_access = 0; rtsp->access = NULL; TAB_APPEND( p_stream->p_sys->i_rtsp, p_stream->p_sys->rtsp, rtsp ); return rtsp;}static rtsp_client_t *RtspClientGet( sout_stream_t *p_stream, char *psz_session ){ int i; if( !psz_session ) return NULL; for( i = 0; i < p_stream->p_sys->i_rtsp; i++ ) { if( !strcmp( p_stream->p_sys->rtsp[i]->psz_session, psz_session ) ) { return p_stream->p_sys->rtsp[i]; } } return NULL;}static void RtspClientDel( sout_stream_t *p_stream, rtsp_client_t *rtsp ){ int i; TAB_REMOVE( p_stream->p_sys->i_rtsp, p_stream->p_sys->rtsp, rtsp ); for( i = 0; i < rtsp->i_access; i++ ) { sout_AccessOutDelete( rtsp->access[i] ); } if( rtsp->id ) free( rtsp->id ); if( rtsp->access ) free( rtsp->access ); free( rtsp->psz_session ); free( rtsp );}static int RtspSetup( sout_stream_t *p_stream, vlc_url_t *url ){ sout_stream_sys_t *p_sys = p_stream->p_sys; msg_Dbg( p_stream, "rtsp setup: %s : %d / %s\n", url->psz_host, url->i_port, url->psz_path ); p_sys->p_rtsp_host = httpd_HostNew( VLC_OBJECT(p_stream), url->psz_host, url->i_port > 0 ? url->i_port : 554 ); if( p_sys->p_rtsp_host == NULL ) { return VLC_EGENERIC; } p_sys->psz_rtsp_path = strdup( url->psz_path ? url->psz_path : "/" ); p_sys->psz_rtsp_control = malloc (strlen( url->psz_host ) + 20 + strlen( p_sys->psz_rtsp_path ) + 1 ); sprintf( p_sys->psz_rtsp_control, "rtsp://%s:%d%s", url->psz_host, url->i_port > 0 ? url->i_port : 554, p_sys->psz_rtsp_path ); p_sys->p_rtsp_url = httpd_UrlNewUnique( p_sys->p_rtsp_host, p_sys->psz_rtsp_path, NULL, NULL, NULL ); if( p_sys->p_rtsp_url == 0 ) { return VLC_EGENERIC; } httpd_UrlCatch( p_sys->p_rtsp_url, HTTPD_MSG_DESCRIBE, RtspCallback, (void*)p_stream ); httpd_UrlCatch( p_sys->p_rtsp_url, HTTPD_MSG_PLAY, RtspCallback, (void*)p_stream ); httpd_UrlCatch( p_sys->p_rtsp_url, HTTPD_MSG_PAUSE, RtspCallback, (void*)p_stream ); httpd_UrlCatch( p_sys->p_rtsp_url, HTTPD_MSG_TEARDOWN, RtspCallback, (void*)p_stream ); return VLC_SUCCESS;}static int RtspCallback( httpd_callback_sys_t *p_args, httpd_client_t *cl, httpd_message_t *answer, httpd_message_t *query ){ sout_stream_t *p_stream = (sout_stream_t*)p_args; sout_stream_sys_t *p_sys = p_stream->p_sys; char *psz_destination = p_sys->psz_destination; char *psz_session = NULL; char *psz_cseq = NULL; int i_cseq = 0; if( answer == NULL || query == NULL ) { return VLC_SUCCESS; } //fprintf( stderr, "RtspCallback query: type=%d\n", query->i_type ); answer->i_proto = HTTPD_PROTO_RTSP; answer->i_version= query->i_version; answer->i_type = HTTPD_MSG_ANSWER; switch( query->i_type ) { case HTTPD_MSG_DESCRIBE: { char *psz_sdp = SDPGenerate( p_stream, psz_destination ? psz_destination : "0.0.0.0", VLC_TRUE ); answer->i_status = 200; answer->psz_status = strdup( "OK" ); httpd_MsgAdd( answer, "Content-type", "%s", "application/sdp" ); answer->p_body = (uint8_t *)psz_sdp; answer->i_body = strlen( psz_sdp ); break; } case HTTPD_MSG_PLAY: { rtsp_client_t *rtsp; /* for now only multicast so easy */ answer->i_status = 200; answer->psz_status = strdup( "OK" ); answer->i_body = 0; answer->p_body = NULL; psz_session = httpd_MsgGet( query, "Session" ); rtsp = RtspClientGet( p_stream, psz_session ); if( rtsp && !rtsp->b_playing ) { int i_id; /* FIXME */ rtsp->b_playing = VLC_TRUE; vlc_mutex_lock( &p_sys->lock_es ); for( i_id = 0; i_id < rtsp->i_id; i_id++ ) { sout_stream_id_t *id = rtsp->id[i_id]; int i; for( i = 0; i < p_sys->i_es; i++ ) { if( id == p_sys->es[i] ) break; } if( i >= p_sys->i_es ) continue; vlc_mutex_lock( &id->lock_rtsp ); TAB_APPEND( id->i_rtsp_access, id->rtsp_access, rtsp->access[i_id] ); vlc_mutex_unlock( &id->lock_rtsp ); } vlc_mutex_unlock( &p_sys->lock_es ); } break; } case HTTPD_MSG_PAUSE: /* FIXME */ return VLC_EGENERIC; case HTTPD_MSG_TEARDOWN: { rtsp_client_t *rtsp; /* for now only multicast so easy again */ answer->i_status = 200; answer->psz_status = strdup( "OK" ); answer->i_body = 0; answer->p_body = NULL; psz_session = httpd_MsgGet( query, "Session" ); rtsp = RtspClientGet( p_stream, psz_session ); if( rtsp ) { int i_id; vlc_mutex_lock( &p_sys->lock_es ); for( i_id = 0; i_id < rtsp->i_id; i_id++ ) { sout_stream_id_t *id = rtsp->id[i_id]; int i; for( i = 0; i < p_sys->i_es; i++ ) { if( id == p_sys->es[i] ) break; } if( i >= p_sys->i_es ) continue; vlc_mutex_lock( &id->lock_rtsp ); TAB_REMOVE( id->i_rtsp_access, id->rtsp_access, rtsp->access[i_id] ); vlc_mutex_unlock( &id->lock_rtsp ); } vlc_mutex_unlock( &p_sys->lock_es ); RtspClientDel( p_stream, rtsp ); } break; } default: return VLC_EGENERIC; } httpd_MsgAdd( answer, "Server", PACKAGE_STRING ); httpd_MsgAdd( answer, "Content-Length", "%d", answer->i_body ); psz_cseq = httpd_MsgGet( query, "Cseq" ); if( psz_cseq ) i_cseq = atoi( psz_cseq ); else i_cseq = 0; httpd_MsgAdd( answer, "Cseq", "%d", i_cseq ); httpd_MsgAdd( answer, "Cache-Control", "%s", "no-cache" ); if( psz_session ) { httpd_MsgAdd( answer, "Session", "%s;timeout=5", psz_session ); } return VLC_SUCCESS;}static int RtspCallbackId( httpd_callback_sys_t *p_args, httpd_client_t *cl, httpd_message_t *answer, httpd_message_t *query ){ sout_stream_id_t *id = (sout_stream_id_t*)p_args; sout_stream_t *p_stream = id->p_stream; sout_stream_sys_t *p_sys = p_stream->p_sys; char *psz_session = NULL; char *psz_cseq = NULL; int i_cseq = 0; if( answer == NULL || query == NULL ) { return VLC_SUCCESS; } //fprintf( stderr, "RtspCallback query: type=%d\n", query->i_type ); answer->i_proto = HTTPD_PROTO_RTSP; answer->i_version= query->i_version; answer->i_type = HTTPD_MSG_ANSWER; switch( query->i_type ) { case HTTPD_MSG_SETUP: { char *psz_transport = httpd_MsgGet( query, "Transport" ); //fprintf( stderr, "HTTPD_MSG_SETUP: transport=%s\n", psz_transport ); if( strstr( psz_transport, "multicast" ) && id->psz_destination ) { //fprintf( stderr, "HTTPD_MSG_SETUP: multicast\n" ); answer->i_status = 200; answer->psz_status = strdup( "OK" ); answer->i_body = 0; answer->p_body = NULL; psz_session = httpd_MsgGet( query, "Session" ); if( !psz_session ) { psz_session = malloc( 100 ); sprintf( psz_session, "%d", rand() ); } httpd_MsgAdd( answer, "Transport", "RTP/AVP/UDP;destination=%s;port=%d-%d;ttl=%d", id->psz_destination, id->i_port,id->i_port+1, p_sys->i_ttl ); } else if( strstr( psz_transport, "unicast" ) && strstr( psz_transport, "client_port=" ) ) { int i_port = atoi( strstr( psz_transport, "client_port=" ) + strlen("client_port=") ); char ip[NI_MAXNUMERICHOST], psz_access[17], psz_url[NI_MAXNUMERICHOST + 8]; sout_access_out_t *p_access; rtsp_client_t *rtsp = NULL; if( httpd_ClientIP( cl, ip ) == NULL ) { answer->i_status = 500; answer->psz_status = strdup( "Internal server error" ); answer->i_body = 0; answer->p_body = NULL; break; } //fprintf( stderr, "HTTPD_MSG_SETUP: unicast ip=%s port=%d\n", ip, i_port ); psz_session = httpd_MsgGet( query, "Session" ); if( !psz_session ) { psz_session = malloc( 100 ); sprintf( psz_session, "%d", rand() ); rtsp = RtspClientNew( p_stream, psz_session ); } else { rtsp = RtspClientGet( p_stream, psz_session ); if( rtsp == NULL ) { answer->i_status = 454; answer->psz_status = strdup( "Unknown session id" ); answer->i_body = 0; answer->p_body = NULL; break; } } /* first try to create the access out */ if( p_sys->i_ttl ) snprintf( psz_access, sizeof( psz_access ), "udp{raw,ttl=%d}", p_sys->i_ttl ); else strlcpy( psz_access, "udp{raw}", sizeof( psz_access ) ); snprintf( psz_url, sizeof( psz_url ), ( strchr( ip, ':' ) != NULL ) ? "[%s]:%d" : "%s:%d", ip, i_port ); if( ( p_access = sout_AccessOutNew( p_stream->p_sout, psz_access, psz_url ) ) == NULL ) { msg_Err(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -