X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fdemux%2Flive555.cpp;h=6fc5f776f10d7830f66a0dcbb5ebddc23a4923f8;hb=607bbaf11602f6e45d142c8e4a14c96d52931376;hp=2295297791711a02238ee0c6c93d4d98ec38ebb4;hpb=9025fab9931ecc35fe247b0a63d0cea166dee88d;p=vlc diff --git a/modules/demux/live555.cpp b/modules/demux/live555.cpp index 2295297791..6fc5f776f1 100644 --- a/modules/demux/live555.cpp +++ b/modules/demux/live555.cpp @@ -28,12 +28,11 @@ *****************************************************************************/ #include -#include /* malloc(), free() */ -#include #include #include #include +#include #include @@ -41,6 +40,7 @@ # include #endif +#include "UsageEnvironment.hh" #include "BasicUsageEnvironment.hh" #include "GroupsockHelper.hh" #include "liveMedia.hh" @@ -153,6 +153,7 @@ struct demux_sys_t { char *p_sdp; /* XXX mallocated */ char *psz_path; /* URL-encoded path */ + vlc_url_t url; MediaSession *ms; TaskScheduler *scheduler; @@ -222,11 +223,11 @@ static int Open ( vlc_object_t *p_this ) { /* See if it looks like a SDP v, o, s fields are mandatory and in this order */ - uint8_t *p_peek; + const uint8_t *p_peek; if( stream_Peek( p_demux->s, &p_peek, 7 ) < 7 ) return VLC_EGENERIC; - if( memcmp( (char*)p_peek, "v=0\r\n", 5 ) && - memcmp( (char*)p_peek, "v=0\n", 4 ) && + if( memcmp( p_peek, "v=0\r\n", 5 ) && + memcmp( p_peek, "v=0\n", 4 ) && ( p_peek[0] < 'a' || p_peek[0] > 'z' || p_peek[1] != '=' ) ) { return VLC_EGENERIC; @@ -263,6 +264,9 @@ static int Open ( vlc_object_t *p_this ) p_sys->b_real = VLC_FALSE; p_sys->psz_path = strdup( p_demux->psz_path ); + /* parse URL for rtsp://[user:[passwd]@]serverip:port/options */ + vlc_UrlParse( &p_sys->url, p_sys->psz_path, 0 ); + if( ( p_sys->scheduler = BasicTaskScheduler::createNew() ) == NULL ) { msg_Err( p_demux, "BasicTaskScheduler::createNew failed" ); @@ -312,7 +316,8 @@ static int Open ( vlc_object_t *p_this ) } p_sys->p_sdp = (char*)p_sdp; } - else if( p_demux->s == NULL && !strcasecmp( p_demux->psz_access, "sdp" ) ) + else if( ( p_demux->s == NULL ) && + !strcasecmp( p_demux->psz_access, "sdp" ) ) { /* sdp:// link from SAP */ p_sys->p_sdp = strdup( p_sys->psz_path ); @@ -379,6 +384,8 @@ error: if( p_sys->p_sdp ) free( p_sys->p_sdp ); if( p_sys->psz_path ) free( p_sys->psz_path ); + vlc_UrlClean( &p_sys->url ); + free( p_sys ); return VLC_EGENERIC; } @@ -418,6 +425,8 @@ static void Close( vlc_object_t *p_this ) if( p_sys->p_sdp ) free( p_sys->p_sdp ); if( p_sys->psz_path ) free( p_sys->psz_path ); + vlc_UrlClean( &p_sys->url ); + free( p_sys ); } @@ -441,24 +450,42 @@ createnew: 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, 1 /*verbose*/, + if( ( p_sys->rtsp = RTSPClient::createNew( *p_sys->env, + p_demux->p_libvlc->i_verbose > 1, "VLC media player", i_http_port ) ) == NULL ) { 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 ); + if( !psz_url ) return VLC_ENOMEM; - psz_options = p_sys->rtsp->sendOptionsCmd( psz_url ); - if( psz_options ) delete [] psz_options; + if( p_sys->url.psz_username || p_sys->url.psz_password ) + { + sprintf( psz_url, "rtsp://%s%s", p_sys->url.psz_host, + p_sys->url.psz_path ); + + psz_user = strdup( p_sys->url.psz_username ); + psz_pwd = strdup( p_sys->url.psz_password ); + } + else + { + sprintf( psz_url, "rtsp://%s", p_sys->psz_path ); - psz_user = var_CreateGetString( p_demux, "rtsp-user" ); - psz_pwd = var_CreateGetString( p_demux, "rtsp-pwd" ); + 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 ); + 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 ) delete [] psz_options; + p_sdp = p_sys->rtsp->describeURL( psz_url, &authenticator, var_CreateGetBool( p_demux, "rtsp-kasenna" ) ); @@ -472,7 +499,9 @@ describe: 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( var_CreateGetBool( p_demux, "rtsp-http" ) ) + sscanf( psz_error, "%*s %*s HTTP GET %*s HTTP/%*u.%*u %3u %*s", &i_code ); + else sscanf( psz_error, "%*sRTSP/%*s%3u", &i_code ); if( i_code == 401 ) { @@ -493,7 +522,7 @@ describe: if( psz_login ) free( psz_login ); if( psz_password ) free( psz_password ); } - else if( !var_CreateGetBool( p_demux, "rtsp-http" ) ) + else if( !var_GetBool( p_demux, "rtsp-http" ) ) { /* Perhaps a firewall is being annoying. Try HTTP tunneling mode */ vlc_value_t val; @@ -510,6 +539,7 @@ describe: /* malloc-ated copy */ if( p_sys->p_sdp ) free( p_sys->p_sdp ); + p_sys->p_sdp = NULL; if( p_sdp ) p_sys->p_sdp = strdup( (char*)p_sdp ); delete[] p_sdp; @@ -517,7 +547,7 @@ describe: } /***************************************************************************** - * Connect: prepares the subsessions and does the SETUP + * SessionsSetup: prepares the subsessions and does the SETUP *****************************************************************************/ static int SessionsSetup( demux_t *p_demux ) { @@ -531,7 +561,8 @@ static int SessionsSetup( demux_t *p_demux ) 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" ); + 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 */ @@ -675,7 +706,7 @@ static int SessionsSetup( demux_t *p_demux ) } else if( !strncmp( sub->codecName(), "G726", 4 ) ) { - tk->fmt.i_codec = VLC_FOURCC( 'g', '7', '2', '6' ); + tk->fmt.i_codec = VLC_FOURCC( 'g', '7', '2', '6' ); tk->fmt.audio.i_rate = 8000; tk->fmt.audio.i_channels = 1; if( !strcmp( sub->codecName()+5, "40" ) ) @@ -742,6 +773,17 @@ static int SessionsSetup( demux_t *p_demux ) { tk->b_quicktime = VLC_TRUE; } + else if( !strcmp( sub->codecName(), "SPEEX" ) ) + { + tk->fmt.i_codec = VLC_FOURCC( 's', 'p', 'x', 'r' ); + if ( sub->rtpTimestampFrequency() ) + tk->fmt.audio.i_rate = sub->rtpTimestampFrequency(); + else + { + msg_Warn( p_demux,"Using 8kHz as default sample rate." ); + tk->fmt.audio.i_rate = 8000; + } + } } else if( !strcmp( sub->mediumName(), "video" ) ) { @@ -895,7 +937,9 @@ static int Play( demux_t *p_demux ) /* Retrieve the timeout value and set up a timeout prevention thread */ p_sys->i_timeout = p_sys->rtsp->sessionTimeoutParameter(); - if( p_sys->i_timeout > 0 && !p_sys->p_timeout ) + if( p_sys->i_timeout <= 0 ) + p_sys->i_timeout = 60; /* default value from RFC2326 */ + if( !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) ); @@ -912,13 +956,13 @@ static int Play( demux_t *p_demux ) } p_sys->i_pcr = 0; -#if 0 +#if (LIVEMEDIA_LIBRARY_VERSION_INT >= 1195257600) /* TODO */ for( i = 0; i < p_sys->i_track; i++ ) { - //p_sys->track[i]->i_pts = 0; + p_sys->track[i]->i_pts = (int64_t) ( p_sys->track[i]->sub->rtpInfo.timestamp * (double)1000000.0 ); p_sys->track[i]->i_start_seq = (int)p_sys->track[i]->sub->rtpInfo.seqNum; - msg_Dbg( p_demux, "set startseq: %u", p_sys->track[i]->i_start_seq ); + msg_Info( p_demux, "set startseq: %u", p_sys->track[i]->i_start_seq ); } #endif @@ -965,8 +1009,7 @@ static int Demux( demux_t *p_demux ) /* Check if we need to send the server a Keep-A-Live signal */ if( p_sys->b_timeout_call && p_sys->rtsp && p_sys->ms ) { - char *psz_bye = NULL; - p_sys->rtsp->getMediaSessionParameter( *p_sys->ms, NULL, psz_bye ); + p_sys->rtsp->setMediaSessionParameter( *p_sys->ms, "vlc" , "1" ); p_sys->b_timeout_call = VLC_FALSE; } @@ -1028,25 +1071,26 @@ static int Demux( demux_t *p_demux ) es_out_Control( p_demux->out, ES_OUT_RESET_PCR ); tk->b_rtcp_sync = VLC_TRUE; -#if 0 /* reset PCR */ tk->i_pts = 0; p_sys->i_pcr = 0; i_pcr = 0; -#endif } } - if( p_sys->b_multicast && p_sys->b_no_data && p_sys->i_no_data_ti > 120 ) + if( p_sys->b_multicast && p_sys->b_no_data && + ( p_sys->i_no_data_ti > 120 ) ) { /* FIXME Make this configurable msg_Err( p_demux, "no multicast data received in 36s, aborting" ); return 0; */ } - else if( !p_sys->b_multicast && p_sys->b_no_data && p_sys->i_no_data_ti > 34 ) + else if( !p_sys->b_multicast && p_sys->b_no_data && + ( p_sys->i_no_data_ti > 34 ) ) { - vlc_bool_t b_rtsp_tcp = var_GetBool( p_demux, "rtsp-tcp" ); + vlc_bool_t b_rtsp_tcp = var_GetBool( p_demux, "rtsp-tcp" ) || + var_GetBool( p_demux, "rtsp-http" ); if( !b_rtsp_tcp && p_sys->rtsp && p_sys->ms ) { @@ -1128,13 +1172,13 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) } es_out_Control( p_demux->out, ES_OUT_RESET_PCR ); p_sys->i_pcr = 0; -#if 0 +#if (LIVEMEDIA_LIBRARY_VERSION_INT >= 1195257600) /* Retrieve RTP-Info values */ for( i = 0; i < p_sys->i_track; i++ ) { - //p_sys->track[i]->i_pts = 0; + p_sys->track[i]->i_pts = (int64_t) ( p_sys->track[i]->sub->rtpInfo.timestamp * (double)1000000.0 ); p_sys->track[i]->i_start_seq = p_sys->track[i]->sub->rtpInfo.seqNum; - msg_Dbg( p_demux, "set pos startseq: %u", p_sys->track[i]->i_start_seq ); + msg_Info( p_demux, "set pos startseq: %u", p_sys->track[i]->i_start_seq ); } #endif #if (LIVEMEDIA_LIBRARY_VERSION_INT >= 9999999999) @@ -1205,12 +1249,12 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) } es_out_Control( p_demux->out, ES_OUT_RESET_PCR ); p_sys->i_pcr = 0; -#if 0 +#if (LIVEMEDIA_LIBRARY_VERSION_INT >= 1195257600) for( i = 0; i < p_sys->i_track; i++ ) { - //p_sys->track[i]->i_pts = 0; + p_sys->track[i]->i_pts = (int64_t) ( p_sys->track[i]->sub->rtpInfo.timestamp * (double)1000000.0 ); p_sys->track[i]->i_start_seq = p_sys->track[i]->sub->rtpInfo.seqNum; - msg_Dbg( p_demux, "set pause startseq: %u", p_sys->track[i]->i_start_seq ); + msg_Info( p_demux, "set pause startseq: %u", p_sys->track[i]->i_start_seq ); } #endif #if (LIVEMEDIA_LIBRARY_VERSION_INT >= 9999999999) @@ -1288,9 +1332,11 @@ static int RollOverTcp( demux_t *p_demux ) p_sys->i_track = 0; /* Reopen rtsp client */ - if( p_demux->s != NULL && ( i_return = Connect( p_demux ) ) != VLC_SUCCESS ) + if( ( p_demux->s != NULL ) && + ( i_return = Connect( p_demux ) ) != VLC_SUCCESS ) { - msg_Err( p_demux, "Failed to connect with rtsp://%s", p_sys->psz_path ); + msg_Err( p_demux, "Failed to connect with rtsp://%s", + p_sys->psz_path ); goto error; } @@ -1328,7 +1374,7 @@ static void StreamRead( void *p_private, unsigned int i_size, demux_sys_t *p_sys = p_demux->p_sys; block_t *p_block; - msg_Dbg( p_demux, "pts: %d", pts.tv_sec ); + //msg_Dbg( p_demux, "pts: %d", pts.tv_sec ); int64_t i_pts = (uint64_t)pts.tv_sec * UI64C(1000000) + (uint64_t)pts.tv_usec; @@ -1482,13 +1528,13 @@ static void StreamRead( void *p_private, unsigned int i_size, { p_sys->i_npt += __MAX( 0, i_pts - p_sys->i_pcr ); p_sys->i_pcr = i_pts; - msg_Dbg( p_demux, "npt update" ); + //msg_Dbg( p_demux, "npt update" ); } - else if( (tk->fmt.i_cat == VIDEO_ES) && (p_sys->i_pcr < i_pts) ) + else if( /*tk->fmt.i_cat == VIDEO_ES &&*/ p_sys->i_pcr < i_pts ) { p_sys->i_pcr = i_pts; } - msg_Dbg( p_demux, "npt %lld", p_sys->i_npt ); + //msg_Dbg( p_demux, "npt %lld", p_sys->i_npt ); if( (i_pts != tk->i_pts) && (!tk->b_muxed) ) { @@ -1553,7 +1599,7 @@ static void TaskInterrupt( void *p_private ) } /***************************************************************************** - * + * *****************************************************************************/ static void TimeoutPrevention( timeout_thread_t *p_timeout ) {