📄 live555.cpp
字号:
} if( p_sys->b_real ) goto error; if( ( i_return = Play( p_demux ) ) != VLC_SUCCESS ) goto error; if( p_sys->p_out_asf && ParseASF( p_demux ) ) { msg_Err( p_demux, "cannot find a usable asf header" ); /* TODO Clean tracks */ goto error; } if( p_sys->i_track <= 0 ) goto error; return VLC_SUCCESS;error: for( i = 0; i < p_sys->i_track; i++ ) { live_track_t *tk = p_sys->track[i]; if( tk->b_muxed ) stream_DemuxDelete( tk->p_out_muxed ); es_format_Clean( &tk->fmt ); free( tk->p_buffer ); free( tk ); } if( p_sys->i_track ) free( p_sys->track ); if( p_sys->p_out_asf ) stream_DemuxDelete( p_sys->p_out_asf ); if( p_sys->rtsp && p_sys->ms ) p_sys->rtsp->teardownMediaSession( *p_sys->ms ); if( p_sys->ms ) Medium::close( p_sys->ms ); if( p_sys->rtsp ) RTSPClient::close( p_sys->rtsp ); if( p_sys->env ) p_sys->env->reclaim(); if( p_sys->p_timeout ) { vlc_object_kill( p_sys->p_timeout ); vlc_thread_join( p_sys->p_timeout ); vlc_object_detach( p_sys->p_timeout ); vlc_object_release( p_sys->p_timeout ); } delete p_sys->scheduler; free( p_sys->p_sdp ); free( p_sys->psz_path ); vlc_UrlClean( &p_sys->url ); free( p_sys ); return i_error;}/***************************************************************************** * DemuxClose: *****************************************************************************/static void Close( vlc_object_t *p_this ){ demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys = p_demux->p_sys; int i; for( i = 0; i < p_sys->i_track; i++ ) { live_track_t *tk = p_sys->track[i]; if( tk->b_muxed ) stream_DemuxDelete( tk->p_out_muxed ); es_format_Clean( &tk->fmt ); free( tk->p_buffer ); free( tk ); } if( p_sys->i_track ) free( p_sys->track ); if( p_sys->p_out_asf ) stream_DemuxDelete( p_sys->p_out_asf ); if( p_sys->rtsp && p_sys->ms ) p_sys->rtsp->teardownMediaSession( *p_sys->ms ); if( p_sys->ms ) Medium::close( p_sys->ms ); if( p_sys->rtsp ) RTSPClient::close( p_sys->rtsp ); if( p_sys->env ) p_sys->env->reclaim(); if( p_sys->p_timeout ) { vlc_object_kill( p_sys->p_timeout ); vlc_thread_join( p_sys->p_timeout ); vlc_object_detach( p_sys->p_timeout ); vlc_object_release( p_sys->p_timeout ); } delete p_sys->scheduler; free( p_sys->p_sdp ); free( p_sys->psz_path ); vlc_UrlClean( &p_sys->url ); free( p_sys );}/***************************************************************************** * Connect: connects to the RTSP server to setup the session DESCRIBE *****************************************************************************/static int Connect( demux_t *p_demux ){ demux_sys_t *p_sys = p_demux->p_sys; Authenticator authenticator; bool b_firstpass = true; char *psz_user = NULL; char *psz_pwd = NULL; char *psz_url = NULL; char *psz_options = NULL; char *p_sdp = NULL; int i_http_port = 0; int i_ret = VLC_SUCCESS; int i_lefttries; if( p_sys->url.i_port == 0 ) p_sys->url.i_port = 554; if( p_sys->url.psz_username || p_sys->url.psz_password ) { int err; err = asprintf( &psz_url, "rtsp://%s:%d%s", p_sys->url.psz_host, p_sys->url.i_port, p_sys->url.psz_path ); if( err == -1 ) return VLC_ENOMEM; psz_user = strdup( p_sys->url.psz_username ); psz_pwd = strdup( p_sys->url.psz_password ); } else { int err; err = asprintf( &psz_url, "rtsp://%s", p_sys->psz_path ); if( err == -1 ) return VLC_ENOMEM; psz_user = var_CreateGetString( p_demux, "rtsp-user" ); psz_pwd = var_CreateGetString( p_demux, "rtsp-pwd" ); } i_lefttries = 3;createnew: i_lefttries--; if( !vlc_object_alive (p_demux) || p_demux->b_error ) { free( psz_user ); free( psz_pwd ); free( psz_url ); return VLC_EGENERIC; } if( var_CreateGetBool( p_demux, "rtsp-http" ) ) i_http_port = var_CreateGetInteger( p_demux, "rtsp-http-port" ); if( ( p_sys->rtsp = RTSPClient::createNew( *p_sys->env, var_CreateGetInteger( p_demux, "verbose" ) > 1, "VLC media player", i_http_port ) ) == NULL ) { msg_Err( p_demux, "RTSPClient::createNew failed (%s)", p_sys->env->getResultMsg() ); free( psz_user ); free( psz_pwd ); free( psz_url ); return VLC_EGENERIC; } /* Kasenna enables KeepAlive by analysing the User-Agent string. * Appending _KA to the string should be enough to enable this feature, * however, there is a bug where the _KA doesn't get parsed from the * default User-Agent as created by VLC/Live555 code. This is probably due * to spaces in the string or the string being too long. Here we override * the default string with a more compact version. */ if( var_CreateGetBool( p_demux, "rtsp-kasenna" )) { p_sys->rtsp->setUserAgentString( "VLC_MEDIA_PLAYER_KA" ); }describe: authenticator.setUsernameAndPassword( (const char*)psz_user, (const char*)psz_pwd ); psz_options = p_sys->rtsp->sendOptionsCmd( psz_url, psz_user, psz_pwd, &authenticator ); if( psz_options ) p_sys->b_get_param = strstr( psz_options, "GET_PARAMETER" ) ? true : false ; delete [] psz_options; p_sdp = p_sys->rtsp->describeURL( psz_url, &authenticator, var_GetBool( p_demux, "rtsp-kasenna" ) ); if( p_sdp == NULL ) { /* failure occurred */ int i_code = 0; const char *psz_error = p_sys->env->getResultMsg(); if( var_GetBool( p_demux, "rtsp-http" ) ) sscanf( psz_error, "%*s %*s HTTP GET %*s HTTP/%*u.%*u %3u %*s", &i_code ); else { const char *psz_tmp = strstr( psz_error, "RTSP" ); if( psz_tmp ) sscanf( psz_tmp, "RTSP/%*s%3u", &i_code ); else i_code = 0; } msg_Dbg( p_demux, "DESCRIBE failed with %d: %s", i_code, psz_error ); if( b_firstpass ) { /* describeURL always returns an "RTSP/1.0 401 Unauthorized" the * first time. This is a workaround to avoid asking for a * user/passwd the first time the code passess here. */ i_code = 0; b_firstpass = false; } if( i_code == 401 ) { int i_result; msg_Dbg( p_demux, "authentication failed" ); free( psz_user ); free( psz_pwd ); psz_user = psz_pwd = NULL; i_result = intf_UserLoginPassword( p_demux, _("RTSP authentication"), _("Please enter a valid login name and a password."), &psz_user, &psz_pwd ); if( i_result == DIALOG_OK_YES ) { msg_Dbg( p_demux, "retrying with user=%s, pwd=%s", psz_user, psz_pwd ); goto describe; } } else if( (i_code != 0) && !var_GetBool( p_demux, "rtsp-http" ) ) { /* Perhaps a firewall is being annoying. Try HTTP tunneling mode */ vlc_value_t val; val.b_bool = true; msg_Dbg( p_demux, "we will now try HTTP tunneling mode" ); var_Set( p_demux, "rtsp-http", val ); if( p_sys->rtsp ) RTSPClient::close( p_sys->rtsp ); p_sys->rtsp = NULL; goto createnew; } else { msg_Dbg( p_demux, "connection timeout, retrying" ); if( p_sys->rtsp ) RTSPClient::close( p_sys->rtsp ); p_sys->rtsp = NULL; if( i_lefttries > 0 ) goto createnew; } i_ret = VLC_EGENERIC; } /* malloc-ated copy */ free( psz_url ); free( psz_user ); free( psz_pwd ); free( p_sys->p_sdp ); p_sys->p_sdp = NULL; if( p_sdp ) p_sys->p_sdp = strdup( (char*)p_sdp ); delete[] p_sdp; return i_ret;}/***************************************************************************** * SessionsSetup: prepares the subsessions and does the SETUP *****************************************************************************/static int SessionsSetup( demux_t *p_demux ){ demux_sys_t *p_sys = p_demux->p_sys; MediaSubsessionIterator *iter = NULL; MediaSubsession *sub = NULL; bool b_rtsp_tcp = false; int i_client_port; int i_return = VLC_SUCCESS; unsigned int i_buffer = 0; unsigned const thresh = 200000; /* RTP reorder threshold .2 second (default .1) */ b_rtsp_tcp = var_CreateGetBool( p_demux, "rtsp-tcp" ) || var_GetBool( p_demux, "rtsp-http" ); i_client_port = var_CreateGetInteger( p_demux, "rtp-client-port" ); /* Create the session from the SDP */ if( !( p_sys->ms = MediaSession::createNew( *p_sys->env, p_sys->p_sdp ) ) ) { msg_Err( p_demux, "Could not create the RTSP Session: %s", p_sys->env->getResultMsg() ); return VLC_EGENERIC; } /* Initialise each media subsession */ iter = new MediaSubsessionIterator( *p_sys->ms ); while( ( sub = iter->next() ) != NULL ) { Boolean bInit; live_track_t *tk; if( !vlc_object_alive (p_demux) || p_demux->b_error ) { delete iter; return VLC_EGENERIC; } /* Value taken from mplayer */ if( !strcmp( sub->mediumName(), "audio" ) ) i_buffer = 100000; else if( !strcmp( sub->mediumName(), "video" ) ) i_buffer = 2000000; else continue; if( i_client_port != -1 ) { sub->setClientPortNum( i_client_port ); i_client_port += 2; } if( strcasestr( sub->codecName(), "REAL" ) ) { msg_Info( p_demux, "real codec detected, using real-RTSP instead" ); p_sys->b_real = true; /* This is a problem, we'll handle it later */ continue; } if( !strcmp( sub->codecName(), "X-ASF-PF" ) ) bInit = sub->initiate( 4 ); /* Constant ? */ else bInit = sub->initiate(); if( !bInit ) { msg_Warn( p_demux, "RTP subsession '%s/%s' failed (%s)", sub->mediumName(), sub->codecName(), p_sys->env->getResultMsg() ); } else { if( sub->rtpSource() != NULL ) { int fd = sub->rtpSource()->RTPgs()->socketNum(); /* Increase the buffer size */ if( i_buffer > 0 ) increaseReceiveBufferTo( *p_sys->env, fd, i_buffer ); /* Increase the RTP reorder timebuffer just a bit */ sub->rtpSource()->setPacketReorderingThresholdTime(thresh); } msg_Dbg( p_demux, "RTP subsession '%s/%s'", sub->mediumName(), sub->codecName() ); /* Issue the SETUP */ if( p_sys->rtsp ) { if( !p_sys->rtsp->setupMediaSubsession( *sub, False, b_rtsp_tcp ? True : False, ( p_sys->b_force_mcast && !b_rtsp_tcp ) ? True : False ) ) { /* if we get an unsupported transport error, toggle TCP use and try again */ if( !strstr(p_sys->env->getResultMsg(), "461 Unsupported Transport") || !p_sys->rtsp->setupMediaSubsession( *sub, False, b_rtsp_tcp ? False : True, False ) ) { msg_Err( p_demux, "SETUP of'%s/%s' failed %s", sub->mediumName(), sub->codecName(), p_sys->env->getResultMsg() ); continue; } } } /* Check if we will receive data from this subsession for this track */ if( sub->readSource() == NULL ) continue; if( !p_sys->b_multicast ) { /* Check, because we need diff. rollover behaviour for multicast */ p_sys->b_multicast = IsMulticastAddress( sub->connectionEndpointAddress() ); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -