+/*****************************************************************************
+ * 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;
+
+ 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;
+
+createnew:
+ if( var_CreateGetBool( p_demux, "rtsp-http" ) )
+ i_http_port = var_CreateGetInteger( p_demux, "rtsp-http-port" );
+
+#if LIVEMEDIA_LIBRARY_VERSION_INT > 1130457500
+ if( ( p_sys->rtsp = RTSPClient::createNew(*p_sys->env, 1 /*verbose*/,
+ "VLC media player", i_http_port ) ) == NULL )
+#else
+ if( ( p_sys->rtsp = RTSPClient::createNew(*p_sys->env, 1 /*verbose*/,
+ "VLC media player" ) ) == NULL )
+#endif
+ {
+ msg_Err( p_demux, "RTSPClient::createNew failed (%s)",
+ p_sys->env->getResultMsg() );
+ return VLC_EGENERIC;
+ }
+ psz_url = (char*)malloc( strlen( p_sys->psz_path ) + 8 );
+ sprintf( psz_url, "rtsp://%s", p_sys->psz_path );
+
+ psz_options = p_sys->rtsp->sendOptionsCmd( psz_url );
+ if( psz_options ) delete [] psz_options;
+
+ psz_user = var_CreateGetString( p_demux, "rtsp-user" );
+ psz_pwd = var_CreateGetString( p_demux, "rtsp-pwd" );
+
+describe:
+ authenticator.setUsernameAndPassword( (const char*)psz_user, (const char*)psz_pwd );
+ p_sdp = p_sys->rtsp->describeURL( psz_url,
+ &authenticator, var_CreateGetBool( p_demux, "rtsp-kasenna" ) );
+
+ if( psz_user ) free( psz_user );
+ if( psz_pwd ) free( psz_pwd );
+
+ if( p_sdp == NULL )
+ {
+ /* failure occured */
+ int i_code = 0;
+ const char *psz_error = p_sys->env->getResultMsg();
+
+ msg_Dbg( p_demux, "DESCRIBE failed with %d: %s", i_code, psz_error );
+ sscanf( psz_error, "%*sRTSP/%*s%3u", &i_code );
+
+ if( i_code == 401 )
+ {
+ char *psz_login = NULL; char *psz_password = NULL;
+ msg_Dbg( p_demux, "authentication failed" );
+
+ i_ret = intf_UserLoginPassword( p_demux, _("RTSP authentication"),
+ _("Please enter a valid login name and a password."),
+ &psz_login, &psz_password );
+ if( i_ret == DIALOG_OK_YES )
+ {
+ msg_Dbg( p_demux, "retrying with user=%s, pwd=%s",
+ psz_login, psz_password );
+
+ if( psz_login ) psz_user = psz_login;
+ if( psz_password ) psz_pwd = psz_password;
+ goto describe;
+ }
+ if( psz_login ) free( psz_login );
+ if( psz_password ) free( psz_password );
+ }
+ else if( !var_CreateGetBool( p_demux, "rtsp-http" ) )
+ {
+ /* Perhaps a firewall is being annoying. Try HTTP tunneling mode */
+ vlc_value_t val;
+ val.b_bool = VLC_TRUE;
+ msg_Dbg( p_demux, "we will now try HTTP tunneling mode" );
+ var_Set( p_demux, "rtsp-http", val );
+ if( psz_url ) free( psz_url );
+ if( p_sys->rtsp ) RTSPClient::close( p_sys->rtsp );
+ goto createnew;
+ }
+ i_ret = VLC_EGENERIC;
+ }
+ if( psz_url ) free( psz_url );
+
+ /* malloc-ated copy */
+ if( p_sys->p_sdp ) free( p_sys->p_sdp );
+ p_sys->p_sdp = strdup( (char*)p_sdp );
+ delete[] p_sdp;
+
+ return i_ret;
+}
+
+/*****************************************************************************
+ * Connect: 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;
+
+ vlc_bool_t b_rtsp_tcp = VLC_FALSE;
+ int i_client_port;
+ int i_active_sessions = 0;
+ 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" );
+ i_client_port = var_CreateGetInteger( p_demux, "rtp-client-port" );
+
+ /* Initialise each media subsession */
+ iter = new MediaSubsessionIterator( *p_sys->ms );
+ while( ( sub = iter->next() ) != NULL )
+ {
+ Boolean bInit;
+
+ /* 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" );
+ i_return = VLC_EGENERIC;
+ break;
+ }
+
+ 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 ) ) )
+ {
+ msg_Err( p_demux, "SETUP of'%s/%s' failed %s", sub->mediumName(),
+ sub->codecName(), p_sys->env->getResultMsg() );
+ }
+ else i_active_sessions++;
+ } else i_active_sessions++; /* we don't really know, let's just hope it's there */
+
+ if( !p_sys->b_multicast )
+ {
+ /* Check, because we need diff. rollover behaviour for multicast */
+ p_sys->b_multicast = IsMulticastAddress( sub->connectionEndpointAddress() );
+ }
+ }
+ }
+ delete iter;
+ if( i_active_sessions <= 0 ) i_return = VLC_EGENERIC;
+ return i_return;
+}
+
+/*****************************************************************************
+ * Play: starts the actual playback of the stream
+ *****************************************************************************/
+static int Play( demux_t *p_demux )
+{
+ demux_sys_t *p_sys = p_demux->p_sys;
+
+ if( p_sys->rtsp )
+ {
+ /* The PLAY */
+ if( !p_sys->rtsp->playMediaSession( *p_sys->ms ) )
+ {
+ msg_Err( p_demux, "RTSP PLAY failed %s", p_sys->env->getResultMsg() );
+ return VLC_EGENERIC;
+ }
+
+ /* Retrieve the timeout value and set up a timeout prevention thread */
+#if LIVEMEDIA_LIBRARY_VERSION_INT >= 1138089600
+ p_sys->i_timeout = p_sys->rtsp->sessionTimeoutParameter();
+#endif
+ if( p_sys->i_timeout > 0 && !p_sys->p_timeout )
+ {
+ msg_Dbg( p_demux, "We have a timeout of %d seconds", p_sys->i_timeout );
+ p_sys->p_timeout = (timeout_thread_t *)vlc_object_create( p_demux, sizeof(timeout_thread_t) );
+ p_sys->p_timeout->p_sys = p_demux->p_sys; /* lol, object recursion :D */
+ if( vlc_thread_create( p_sys->p_timeout, "liveMedia-timeout", TimeoutPrevention,
+ VLC_THREAD_PRIORITY_LOW, VLC_TRUE ) )
+ {
+ msg_Err( p_demux, "cannot spawn liveMedia timeout thread" );
+ vlc_object_destroy( p_sys->p_timeout );
+ }
+ msg_Dbg( p_demux, "spawned timeout thread" );
+ vlc_object_attach( p_sys->p_timeout, p_demux );
+ }
+ }
+ return VLC_SUCCESS;
+}
+
+