X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fdemux%2Flive555.cpp;h=2d9246ae8999989a345e286050e523299170e0e6;hb=0a86a76fec01fe495ace7894c4ecb6be32b4fef7;hp=9e908ac2fc1a8beed70f3441d45c10c271e57786;hpb=7ec013e0c9be7ff431e9823e745c2329a01db64d;p=vlc diff --git a/modules/demux/live555.cpp b/modules/demux/live555.cpp index 9e908ac2fc..2d9246ae89 100644 --- a/modules/demux/live555.cpp +++ b/modules/demux/live555.cpp @@ -1,7 +1,7 @@ /***************************************************************************** * live555.cpp : LIVE555 Streaming Media support. ***************************************************************************** - * Copyright (C) 2003-2007 the VideoLAN team + * Copyright (C) 2003-2007 VLC authors and VideoLAN * $Id$ * * Authors: Laurent Aimar @@ -9,19 +9,19 @@ * Derk-Jan Hartman for M2X * Sébastien Escudier * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ /***************************************************************************** @@ -32,6 +32,7 @@ * Note: config.h may include inttypes.h, so make sure we define this option * early enough. */ #define __STDC_CONSTANT_MACROS 1 +#define __STDC_LIMIT_MACROS 1 #ifdef HAVE_CONFIG_H # include "config.h" @@ -47,7 +48,6 @@ #include #include -#include #include #include @@ -60,6 +60,7 @@ #include #include #include +#include extern "C" { #include "../access/mms/asf.h" /* Who said ugly ? */ @@ -73,18 +74,13 @@ using namespace std; static int Open ( vlc_object_t * ); static void Close( vlc_object_t * ); -#define CACHING_TEXT N_("Caching value (ms)") -#define CACHING_LONGTEXT N_( \ - "Allows you to modify the default caching value for RTSP streams. This " \ - "value should be set in millisecond units." ) - #define KASENNA_TEXT N_( "Kasenna RTSP dialect") #define KASENNA_LONGTEXT N_( "Kasenna servers use an old and nonstandard " \ "dialect of RTSP. With this parameter VLC will try this dialect, but "\ "then it cannot connect to normal RTSP servers." ) #define WMSERVER_TEXT N_("WMServer RTSP dialect") -#define WMSERVER_LONGTEXT N_("WMServer uses an unstandard dialect " \ +#define WMSERVER_LONGTEXT N_("WMServer uses a nonstandard dialect " \ "of RTSP. Selecting this parameter will tell VLC to assume some " \ "options contrary to RFC 2326 guidelines.") @@ -128,9 +124,6 @@ vlc_module_begin () N_("HTTP tunnel port"), N_("Port to use for tunneling the RTSP/RTP over HTTP."), true ) - add_integer("rtsp-caching", 4 * DEFAULT_PTS_DELAY / 1000, - CACHING_TEXT, CACHING_LONGTEXT, true ) - change_safe() add_bool( "rtsp-kasenna", false, KASENNA_TEXT, KASENNA_LONGTEXT, true ) change_safe() @@ -171,7 +164,9 @@ typedef struct bool b_rtcp_sync; char waiting; int64_t i_pts; - float i_npt; + double f_npt; + + bool b_selected; } live_track_t; @@ -197,7 +192,7 @@ struct demux_sys_t /* */ int i_track; - live_track_t **track; /* XXX mallocated */ + live_track_t **track; /* Weird formats */ asf_header_t asfh; @@ -206,9 +201,9 @@ struct demux_sys_t /* */ int64_t i_pcr; /* The clock */ - float i_npt; - float i_npt_length; - float i_npt_start; + double f_npt; + double f_npt_length; + double f_npt_start; /* timeout thread information */ int i_timeout; /* session timeout value in seconds */ @@ -221,7 +216,8 @@ struct demux_sys_t bool b_no_data; /* if we never received any data */ int i_no_data_ti; /* consecutive number of TaskInterrupt */ - char event; + char event_rtsp; + char event_data; bool b_get_param; /* Does the server support GET_PARAMETER */ bool b_paused; /* Are we paused? */ @@ -258,7 +254,8 @@ static int RollOverTcp ( demux_t * ); static void StreamRead ( void *, unsigned int, unsigned int, struct timeval, unsigned int ); static void StreamClose ( void * ); -static void TaskInterrupt( void * ); +static void TaskInterruptData( void * ); +static void TaskInterruptRTSP( void * ); static void* TimeoutPrevention( void * ); @@ -290,39 +287,22 @@ static int Open ( vlc_object_t *p_this ) return VLC_EGENERIC; } } - var_Create( p_demux, "rtsp-caching", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT ); p_demux->pf_demux = Demux; p_demux->pf_control= Control; - p_demux->p_sys = p_sys = (demux_sys_t*)malloc( sizeof( demux_sys_t ) ); + p_demux->p_sys = p_sys = (demux_sys_t*)calloc( 1, sizeof( demux_sys_t ) ); if( !p_sys ) return VLC_ENOMEM; - p_sys->p_sdp = NULL; - p_sys->scheduler = NULL; - p_sys->env = NULL; - p_sys->ms = NULL; - p_sys->rtsp = NULL; - p_sys->i_track = 0; - p_sys->track = NULL; - p_sys->i_pcr = 0; - p_sys->i_npt = 0.; - p_sys->i_npt_start = 0.; - p_sys->i_npt_length = 0.; - p_sys->p_out_asf = NULL; + msg_Dbg( p_demux, "version "LIVEMEDIA_LIBRARY_VERSION_STRING ); + + TAB_INIT( p_sys->i_track, p_sys->track ); + p_sys->f_npt = 0.; + p_sys->f_npt_start = 0.; + p_sys->f_npt_length = 0.; p_sys->b_no_data = true; - p_sys->i_no_data_ti = 0; - p_sys->p_timeout = NULL; - p_sys->i_timeout = 0; - p_sys->b_timeout_call = false; - p_sys->b_multicast = false; - p_sys->b_real = false; p_sys->psz_path = strdup( p_demux->psz_location ); p_sys->b_force_mcast = var_InheritBool( p_demux, "rtsp-mcast" ); - p_sys->b_get_param = false; - p_sys->b_paused = false; p_sys->f_seek_request = -1; - p_sys->b_error = false; - p_sys->i_live555_ret = 0; /* parse URL for rtsp://[user:[passwd]@]serverip:port/options */ vlc_UrlParse( &p_sys->url, p_sys->psz_path, 0 ); @@ -458,8 +438,7 @@ static void Close( vlc_object_t *p_this ) free( tk->p_buffer ); free( tk ); } - - if( p_sys->i_track ) free( p_sys->track ); + TAB_CLEAN( p_sys->i_track, p_sys->track ); if( p_sys->p_out_asf ) stream_Delete( p_sys->p_out_asf ); delete p_sys->scheduler; free( p_sys->p_sdp ); @@ -480,7 +459,7 @@ static void default_live555_callback( RTSPClient* client, int result_code, char* delete []result_string; p_sys->i_live555_ret = result_code; p_sys->b_error = p_sys->i_live555_ret != 0; - p_sys->event = 1; + p_sys->event_rtsp = 1; } /* return true if the RTSP command succeeded */ @@ -488,17 +467,18 @@ static bool wait_Live555_response( demux_t *p_demux, int i_timeout = 0 /* ms */ { TaskToken task; demux_sys_t * p_sys = p_demux->p_sys; - p_sys->event = 0; + p_sys->event_rtsp = 0; if( i_timeout > 0 ) { /* Create a task that will be called if we wait more than timeout ms */ - task = p_sys->scheduler->scheduleDelayedTask( i_timeout*1000, TaskInterrupt, + task = p_sys->scheduler->scheduleDelayedTask( i_timeout*1000, + TaskInterruptRTSP, p_demux ); } - p_sys->event = 0; + p_sys->event_rtsp = 0; p_sys->b_error = true; p_sys->i_live555_ret = 0; - p_sys->scheduler->doEventLoop( &p_sys->event ); + p_sys->scheduler->doEventLoop( &p_sys->event_rtsp ); //here, if b_error is true and i_live555_ret = 0 we didn't receive a response if( i_timeout > 0 ) { @@ -528,7 +508,7 @@ static void continueAfterDESCRIBE( RTSPClient* client, int result_code, else p_sys->b_error = true; delete[] result_string; - p_sys->event = 1; + p_sys->event_rtsp = 1; } static void continueAfterOPTIONS( RTSPClient* client, int result_code, @@ -536,17 +516,14 @@ static void continueAfterOPTIONS( RTSPClient* client, int result_code, { RTSPClientVlc *client_vlc = static_cast (client); demux_sys_t *p_sys = client_vlc->p_sys; - p_sys->i_live555_ret = result_code; - if ( result_code != 0 ) - { - p_sys->b_error = true; - p_sys->event = 1; - } - else - { - p_sys->b_get_param = (bool)strstr( result_string, "GET_PARAMETER" ); - client->sendDescribeCommand( continueAfterDESCRIBE ); - } + p_sys->b_get_param = + // If OPTIONS fails, assume GET_PARAMETER is not supported but + // still continue on with the stream. Some servers (foscam) + // return 501/not implemented for OPTIONS. + result_code != 0 + && result_string != NULL + && strstr( result_string, "GET_PARAMETER" ) != NULL; + client->sendDescribeCommand( continueAfterDESCRIBE ); delete[] result_string; } @@ -560,8 +537,6 @@ static int Connect( demux_t *p_demux ) 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; const int i_timeout = var_InheritInteger( p_demux, "ipv4-timeout" ); @@ -597,7 +572,7 @@ createnew: goto bailout; } - if( var_InheritBool( p_demux, "rtsp-http" ) ) + if( var_CreateGetBool( p_demux, "rtsp-http" ) ) i_http_port = var_InheritInteger( p_demux, "rtsp-http-port" ); p_sys->rtsp = new RTSPClientVlc( *p_sys->env, psz_url, @@ -660,7 +635,12 @@ describe: if( i_code == 0 ) msg_Dbg( p_demux, "connection timeout" ); else + { msg_Dbg( p_demux, "connection error %d", i_code ); + if( i_code == 403 ) + dialog_Fatal( p_demux, _("RTSP connection failed"), + _("Access to the stream is denied by the server configuration.") ); + } if( p_sys->rtsp ) RTSPClient::close( p_sys->rtsp ); p_sys->rtsp = NULL; } @@ -685,14 +665,14 @@ static int SessionsSetup( demux_t *p_demux ) MediaSubsessionIterator *iter = NULL; MediaSubsession *sub = NULL; - bool b_rtsp_tcp = false; + bool b_rtsp_tcp; 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_InheritBool( p_demux, "rtsp-tcp" ) || - var_InheritBool( p_demux, "rtsp-http" ); + b_rtsp_tcp = var_CreateGetBool( p_demux, "rtsp-tcp" ) || + var_GetBool( p_demux, "rtsp-http" ); i_client_port = var_InheritInteger( p_demux, "rtp-client-port" ); /* Create the session from the SDP */ @@ -777,7 +757,7 @@ static int SessionsSetup( demux_t *p_demux ) * use and try again */ if( p_sys->i_live555_ret == 461 ) p_sys->rtsp->sendSetupCommand( *sub, default_live555_callback, False, - toBool( b_rtsp_tcp ), False ); + !toBool( b_rtsp_tcp ), False ); if( p_sys->i_live555_ret != 461 || !wait_Live555_response( p_demux ) ) { msg_Err( p_demux, "SETUP of'%s/%s' failed %s", @@ -785,6 +765,11 @@ static int SessionsSetup( demux_t *p_demux ) p_sys->env->getResultMsg() ); continue; } + else + { + var_SetBool( p_demux, "rtsp-tcp", true ); + b_rtsp_tcp = true; + } } } @@ -815,7 +800,8 @@ static int SessionsSetup( demux_t *p_demux ) tk->waiting = 0; tk->b_rtcp_sync = false; tk->i_pts = VLC_TS_INVALID; - tk->i_npt = 0.; + tk->f_npt = 0.; + tk->b_selected = true; tk->i_buffer = 65536; tk->p_buffer = (uint8_t *)malloc( 65536 ); if( !tk->p_buffer ) @@ -849,6 +835,11 @@ static int SessionsSetup( demux_t *p_demux ) tk->fmt.i_codec = VLC_CODEC_S16B; tk->fmt.audio.i_bitspersample = 16; } + else if( !strcmp( sub->codecName(), "L20" ) ) + { + tk->fmt.i_codec = VLC_CODEC_S20B; + tk->fmt.audio.i_bitspersample = 20; + } else if( !strcmp( sub->codecName(), "L24" ) ) { tk->fmt.i_codec = VLC_CODEC_S24B; @@ -859,6 +850,11 @@ static int SessionsSetup( demux_t *p_demux ) tk->fmt.i_codec = VLC_CODEC_U8; tk->fmt.audio.i_bitspersample = 8; } + else if( !strcmp( sub->codecName(), "DAT12" ) ) + { + tk->fmt.i_codec = VLC_CODEC_DAT12; + tk->fmt.audio.i_bitspersample = 12; + } else if( !strcmp( sub->codecName(), "PCMU" ) ) { tk->fmt.i_codec = VLC_CODEC_MULAW; @@ -908,7 +904,7 @@ static int SessionsSetup( demux_t *p_demux ) } /* Because the "faad" decoder does not handle the LATM * data length field at the start of each returned LATM - * frame, tell the RTP source to omit it. */ + * frame, tell the RTP source to omit. */ ((MPEG4LATMAudioRTPSource*)sub->rtpSource())->omitLATMDataLengthField(); } else if( !strcmp( sub->codecName(), "MPEG4-GENERIC" ) ) @@ -1062,12 +1058,10 @@ static int SessionsSetup( demux_t *p_demux ) sub->rtcpInstance()->setByeHandler( StreamClose, tk ); } - if( tk->p_es || tk->b_quicktime || tk->b_muxed || tk->b_asf ) + if( tk->p_es || tk->b_quicktime || ( tk->b_muxed && tk->p_out_muxed ) || + ( tk->b_asf && p_sys->p_out_asf ) ) { - /* Append */ - p_sys->track = (live_track_t**)xrealloc( p_sys->track, - sizeof( live_track_t ) * ( p_sys->i_track + 1 ) ); - p_sys->track[p_sys->i_track++] = tk; + TAB_APPEND_CAST( (live_track_t **), p_sys->i_track, p_sys->track, tk ); } else { @@ -1082,13 +1076,13 @@ static int SessionsSetup( demux_t *p_demux ) if( p_sys->i_track <= 0 ) i_return = VLC_EGENERIC; /* Retrieve the starttime if possible */ - p_sys->i_npt_start = p_sys->ms->playStartTime(); + p_sys->f_npt_start = p_sys->ms->playStartTime(); /* Retrieve the duration if possible */ - p_sys->i_npt_length = p_sys->ms->playEndTime(); + p_sys->f_npt_length = p_sys->ms->playEndTime(); /* */ - msg_Dbg( p_demux, "setup start: %f stop:%f", p_sys->i_npt_start, p_sys->i_npt_length ); + msg_Dbg( p_demux, "setup start: %f stop:%f", p_sys->f_npt_start, p_sys->f_npt_length ); /* */ p_sys->b_no_data = true; @@ -1107,7 +1101,7 @@ static int Play( demux_t *p_demux ) if( p_sys->rtsp ) { /* The PLAY */ - p_sys->rtsp->sendPlayCommand( *p_sys->ms, default_live555_callback, p_sys->i_npt_start, -1, 1 ); + p_sys->rtsp->sendPlayCommand( *p_sys->ms, default_live555_callback, p_sys->f_npt_start, -1, 1 ); if( !wait_Live555_response(p_demux) ) { @@ -1146,11 +1140,11 @@ static int Play( demux_t *p_demux ) p_sys->i_pcr = 0; /* Retrieve the starttime if possible */ - p_sys->i_npt_start = p_sys->ms->playStartTime(); + p_sys->f_npt_start = p_sys->ms->playStartTime(); if( p_sys->ms->playEndTime() > 0 ) - p_sys->i_npt_length = p_sys->ms->playEndTime(); + p_sys->f_npt_length = p_sys->ms->playEndTime(); - msg_Dbg( p_demux, "play start: %f stop:%f", p_sys->i_npt_start, p_sys->i_npt_length ); + msg_Dbg( p_demux, "play start: %f stop:%f", p_sys->f_npt_start, p_sys->f_npt_length ); return VLC_SUCCESS; } @@ -1179,6 +1173,44 @@ static int Demux( demux_t *p_demux ) { live_track_t *tk = p_sys->track[i]; + if( tk->p_es ) + { + bool b; + es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE, tk->p_es, &b ); + if( !b && tk->b_selected ) + { + tk->b_selected = false; + p_sys->rtsp->sendTeardownCommand( *tk->sub, NULL ); + } + else if( b && !tk->b_selected) + { + bool b_rtsp_tcp = var_GetBool( p_demux, "rtsp-tcp" ) || + var_GetBool( p_demux, "rtsp-http" ); + p_sys->rtsp->sendSetupCommand( *tk->sub, default_live555_callback, False, + toBool( b_rtsp_tcp ), + toBool( p_sys->b_force_mcast && !b_rtsp_tcp ) ); + if( !wait_Live555_response( p_demux ) ) + { + msg_Err( p_demux, "SETUP of'%s/%s' failed %s", + tk->sub->mediumName(), tk->sub->codecName(), + p_sys->env->getResultMsg() ); + } + else + { + p_sys->rtsp->sendPlayCommand( *tk->sub, default_live555_callback, -1, -1, p_sys->ms->scale() ); + if( !wait_Live555_response(p_demux) ) + { + msg_Err( p_demux, "RTSP PLAY failed %s", p_sys->env->getResultMsg() ); + p_sys->rtsp->sendTeardownCommand( *tk->sub, NULL ); + } + else + tk->b_selected = true; + } + if( !tk->b_selected ) + es_out_Control( p_demux->out, ES_OUT_SET_ES_STATE, tk->p_es, false ); + } + } + if( tk->b_asf || tk->b_muxed ) b_send_pcr = false; #if 0 @@ -1199,7 +1231,7 @@ static int Demux( demux_t *p_demux ) } /* First warn we want to read data */ - p_sys->event = 0; + p_sys->event_data = 0; for( i = 0; i < p_sys->i_track; i++ ) { live_track_t *tk = p_sys->track[i]; @@ -1212,10 +1244,10 @@ static int Demux( demux_t *p_demux ) } } /* Create a task that will be called if we wait more than 300ms */ - task = p_sys->scheduler->scheduleDelayedTask( 300000, TaskInterrupt, p_demux ); + task = p_sys->scheduler->scheduleDelayedTask( 300000, TaskInterruptData, p_demux ); /* Do the read */ - p_sys->scheduler->doEventLoop( &p_sys->event ); + p_sys->scheduler->doEventLoop( &p_sys->event_data ); /* remove the task */ p_sys->scheduler->unscheduleDelayedTask( task ); @@ -1234,9 +1266,9 @@ static int Demux( demux_t *p_demux ) tk->b_rtcp_sync = true; /* reset PCR */ tk->i_pts = VLC_TS_INVALID; - tk->i_npt = 0.; + tk->f_npt = 0.; p_sys->i_pcr = 0; - p_sys->i_npt = 0.; + p_sys->f_npt = 0.; i_pcr = 0; } } @@ -1293,49 +1325,53 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) { case DEMUX_GET_TIME: pi64 = (int64_t*)va_arg( args, int64_t * ); - if( p_sys->i_npt > 0 ) + if( p_sys->f_npt > 0 ) { - *pi64 = (int64_t)(p_sys->i_npt * 1000000.); + *pi64 = (int64_t)(p_sys->f_npt * 1000000.); return VLC_SUCCESS; } return VLC_EGENERIC; case DEMUX_GET_LENGTH: pi64 = (int64_t*)va_arg( args, int64_t * ); - if( p_sys->i_npt_length > 0 ) + if( p_sys->f_npt_length > 0 ) { - *pi64 = (int64_t)((double)p_sys->i_npt_length * 1000000.0); + double d_length = p_sys->f_npt_length * 1000000.0; + if( d_length >= INT64_MAX ) + *pi64 = INT64_MAX; + else + *pi64 = (int64_t)d_length; return VLC_SUCCESS; } return VLC_EGENERIC; case DEMUX_GET_POSITION: pf = (double*)va_arg( args, double* ); - if( (p_sys->i_npt_length > 0) && (p_sys->i_npt > 0) ) + if( (p_sys->f_npt_length > 0) && (p_sys->f_npt > 0) ) { - *pf = ( (double)p_sys->i_npt / (double)p_sys->i_npt_length ); + *pf = p_sys->f_npt / p_sys->f_npt_length; return VLC_SUCCESS; } return VLC_EGENERIC; case DEMUX_SET_POSITION: case DEMUX_SET_TIME: - if( p_sys->rtsp && (p_sys->i_npt_length > 0) ) + if( p_sys->rtsp && (p_sys->f_npt_length > 0) ) { int i; float time; - if( (i_query == DEMUX_SET_TIME) && (p_sys->i_npt > 0) ) + if( (i_query == DEMUX_SET_TIME) && (p_sys->f_npt > 0) ) { i64 = (int64_t)va_arg( args, int64_t ); - time = (float)((double)i64 / (double)1000000.0); /* in second */ + time = (float)(i64 / 1000000.0); /* in second */ } else if( i_query == DEMUX_SET_TIME ) return VLC_EGENERIC; else { f = (double)va_arg( args, double ); - time = f * (double)p_sys->i_npt_length; /* in second */ + time = f * p_sys->f_npt_length; /* in second */ } if( p_sys->b_paused ) @@ -1371,13 +1407,13 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) } /* Retrieve the starttime if possible */ - p_sys->i_npt = p_sys->i_npt_start = p_sys->ms->playStartTime(); + p_sys->f_npt = p_sys->f_npt_start = p_sys->ms->playStartTime(); /* Retrieve the duration if possible */ if( p_sys->ms->playEndTime() > 0 ) - p_sys->i_npt_length = p_sys->ms->playEndTime(); + p_sys->f_npt_length = p_sys->ms->playEndTime(); - msg_Dbg( p_demux, "seek start: %f stop:%f", p_sys->i_npt_start, p_sys->i_npt_length ); + msg_Dbg( p_demux, "seek start: %f stop:%f", p_sys->f_npt_start, p_sys->f_npt_length ); return VLC_SUCCESS; } return VLC_EGENERIC; @@ -1386,7 +1422,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) case DEMUX_CAN_PAUSE: case DEMUX_CAN_SEEK: pb = (bool*)va_arg( args, bool * ); - if( p_sys->rtsp && p_sys->i_npt_length > 0 ) + if( p_sys->rtsp && p_sys->f_npt_length > 0 ) /* Not always true, but will be handled in SET_PAUSE_STATE */ *pb = true; else @@ -1409,7 +1445,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) pb2 = (bool*)va_arg( args, bool * ); *pb = (p_sys->rtsp != NULL) && - (p_sys->i_npt_length > 0) && + (p_sys->f_npt_length > 0) && ( !var_GetBool( p_demux, "rtsp-kasenna" ) || !var_GetBool( p_demux, "rtsp-wmserver" ) ); *pb2 = false; @@ -1419,7 +1455,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) { double f_scale, f_old_scale; - if( !p_sys->rtsp || (p_sys->i_npt_length <= 0) || + if( !p_sys->rtsp || (p_sys->f_npt_length <= 0) || var_GetBool( p_demux, "rtsp-kasenna" ) || var_GetBool( p_demux, "rtsp-wmserver" ) ) return VLC_EGENERIC; @@ -1462,9 +1498,9 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) } /* ReSync the stream */ - p_sys->i_npt_start = 0; + p_sys->f_npt_start = 0; p_sys->i_pcr = 0; - p_sys->i_npt = 0.0; + p_sys->f_npt = 0.0; *pi_int = (int)( INPUT_RATE_DEFAULT / p_sys->ms->scale() ); msg_Dbg( p_demux, "PLAY with new Scale %0.2f (%d)", p_sys->ms->scale(), (*pi_int) ); @@ -1522,13 +1558,13 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) p_sys->i_no_data_ti = 0; /* Retrieve the starttime if possible */ - p_sys->i_npt_start = p_sys->ms->playStartTime(); + p_sys->f_npt_start = p_sys->ms->playStartTime(); /* Retrieve the duration if possible */ if( p_sys->ms->playEndTime() ) - p_sys->i_npt_length = p_sys->ms->playEndTime(); + p_sys->f_npt_length = p_sys->ms->playEndTime(); - msg_Dbg( p_demux, "pause start: %f stop:%f", p_sys->i_npt_start, p_sys->i_npt_length ); + msg_Dbg( p_demux, "pause start: %f stop:%f", p_sys->f_npt_start, p_sys->f_npt_length ); return VLC_SUCCESS; } case DEMUX_GET_TITLE_INFO: @@ -1538,7 +1574,8 @@ static int Control( demux_t *p_demux, int i_query, va_list args ) case DEMUX_GET_PTS_DELAY: pi64 = (int64_t*)va_arg( args, int64_t * ); - *pi64 = var_GetInteger( p_demux, "rtsp-caching" ) * 1000; + *pi64 = INT64_C(1000) + * var_InheritInteger( p_demux, "network-caching" ); return VLC_SUCCESS; default: @@ -1559,6 +1596,10 @@ static int RollOverTcp( demux_t *p_demux ) var_SetBool( p_demux, "rtsp-tcp", true ); /* We close the old RTSP session */ + p_sys->rtsp->sendTeardownCommand( *p_sys->ms, NULL ); + Medium::close( p_sys->ms ); + RTSPClient::close( p_sys->rtsp ); + for( i = 0; i < p_sys->i_track; i++ ) { live_track_t *tk = p_sys->track[i]; @@ -1570,17 +1611,11 @@ static int RollOverTcp( demux_t *p_demux ) free( tk->p_buffer ); free( tk ); } - if( p_sys->i_track ) free( p_sys->track ); + TAB_CLEAN( p_sys->i_track, p_sys->track ); if( p_sys->p_out_asf ) stream_Delete( p_sys->p_out_asf ); - p_sys->rtsp->sendTeardownCommand( *p_sys->ms, NULL ); - Medium::close( p_sys->ms ); - RTSPClient::close( p_sys->rtsp ); - p_sys->ms = NULL; p_sys->rtsp = NULL; - p_sys->track = NULL; - p_sys->i_track = 0; p_sys->b_no_data = true; p_sys->i_no_data_ti = 0; p_sys->p_out_asf = NULL; @@ -1631,7 +1666,6 @@ static block_t *StreamParseAsf( demux_t *p_demux, live_track_t *tk, unsigned i_length_offset = (p_data[1] << 16) | (p_data[2] << 8) | (p_data[3] ); - bool b_key = i_flags & 0x80; bool b_length = i_flags & 0x40; bool b_relative_ts = i_flags & 0x20; bool b_duration = i_flags & 0x10; @@ -1667,7 +1701,7 @@ static block_t *StreamParseAsf( demux_t *p_demux, live_track_t *tk, if( !tk->p_asf_block ) { - tk->p_asf_block = block_New( p_demux, i_packet_size ); + tk->p_asf_block = block_Alloc( i_packet_size ); if( !tk->p_asf_block ) break; tk->p_asf_block->i_buffer = 0; @@ -1707,6 +1741,8 @@ static void StreamRead( void *p_private, unsigned int i_size, unsigned int i_truncated_bytes, struct timeval pts, unsigned int duration ) { + VLC_UNUSED( duration ); + live_track_t *tk = (live_track_t*)p_private; demux_t *p_demux = tk->p_demux; demux_sys_t *p_sys = p_demux->p_sys; @@ -1721,7 +1757,7 @@ static void StreamRead( void *p_private, unsigned int i_size, i_pts &= INT64_C(0x00ffffffffffffff); /* Retrieve NPT for this pts */ - tk->i_npt = tk->sub->getNormalPlayTime(pts); + tk->f_npt = tk->sub->getNormalPlayTime(pts); if( tk->b_quicktime && tk->p_es == NULL ) { @@ -1730,11 +1766,13 @@ static void StreamRead( void *p_private, unsigned int i_size, QuickTimeGenericRTPSource::QTState &qtState = qtRTPSource->qtState; uint8_t *sdAtom = (uint8_t*)&qtState.sdAtom[4]; + /* Get codec informations from the quicktime atoms : + * http://developer.apple.com/quicktime/icefloe/dispatch026.html */ if( tk->fmt.i_cat == VIDEO_ES ) { if( qtState.sdAtomSize < 16 + 32 ) { /* invalid */ - p_sys->event = 0xff; + p_sys->event_data = 0xff; tk->waiting = 0; return; } @@ -1770,14 +1808,15 @@ static void StreamRead( void *p_private, unsigned int i_size, } } else { - if( qtState.sdAtomSize < 4 ) + if( qtState.sdAtomSize < 24 ) { /* invalid */ - p_sys->event = 0xff; + p_sys->event_data = 0xff; tk->waiting = 0; return; } tk->fmt.i_codec = VLC_FOURCC(sdAtom[0],sdAtom[1],sdAtom[2],sdAtom[3]); + tk->fmt.audio.i_bitspersample = (sdAtom[22] << 8) | sdAtom[23]; } tk->p_es = es_out_Add( p_demux->out, &tk->fmt ); } @@ -1811,7 +1850,7 @@ static void StreamRead( void *p_private, unsigned int i_size, if( tk->b_discard_trunc ) { - p_sys->event = 0xff; + p_sys->event_data = 0xff; tk->waiting = 0; return; } @@ -1824,7 +1863,7 @@ static void StreamRead( void *p_private, unsigned int i_size, { AMRAudioSource *amrSource = (AMRAudioSource*)tk->sub->readSource(); - p_block = block_New( p_demux, i_size + 1 ); + p_block = block_Alloc( i_size + 1 ); p_block->p_buffer[0] = amrSource->lastFrameHeader(); memcpy( p_block->p_buffer + 1, tk->p_buffer, i_size ); } @@ -1832,7 +1871,7 @@ static void StreamRead( void *p_private, unsigned int i_size, { H261VideoRTPSource *h261Source = (H261VideoRTPSource*)tk->sub->rtpSource(); uint32_t header = h261Source->lastSpecialHeader(); - p_block = block_New( p_demux, i_size + 4 ); + p_block = block_Alloc( i_size + 4 ); memcpy( p_block->p_buffer, &header, 4 ); memcpy( p_block->p_buffer + 4, tk->p_buffer, i_size ); @@ -1845,7 +1884,7 @@ static void StreamRead( void *p_private, unsigned int i_size, msg_Warn( p_demux, "unsupported NAL type for H264" ); /* Normal NAL type */ - p_block = block_New( p_demux, i_size + 4 ); + p_block = block_Alloc( i_size + 4 ); p_block->p_buffer[0] = 0x00; p_block->p_buffer[1] = 0x00; p_block->p_buffer[2] = 0x00; @@ -1860,7 +1899,7 @@ static void StreamRead( void *p_private, unsigned int i_size, } else { - p_block = block_New( p_demux, i_size ); + p_block = block_Alloc( i_size ); memcpy( p_block->p_buffer, tk->p_buffer, i_size ); } @@ -1870,8 +1909,9 @@ static void StreamRead( void *p_private, unsigned int i_size, } /* Update our global npt value */ - if( tk->i_npt > 0 && tk->i_npt > p_sys->i_npt && tk->i_npt < p_sys->i_npt_length) - p_sys->i_npt = tk->i_npt; + if( tk->f_npt > 0 && tk->f_npt > p_sys->f_npt && + ( tk->f_npt < p_sys->f_npt_length || p_sys->f_npt_length <= 0 ) ) + p_sys->f_npt = tk->f_npt; if( p_block ) { @@ -1892,7 +1932,7 @@ static void StreamRead( void *p_private, unsigned int i_size, } /* warn that's ok */ - p_sys->event = 0xff; + p_sys->event_data = 0xff; /* we have read data */ tk->waiting = 0; @@ -1913,30 +1953,50 @@ static void StreamClose( void *p_private ) live_track_t *tk = (live_track_t*)p_private; demux_t *p_demux = tk->p_demux; demux_sys_t *p_sys = p_demux->p_sys; + tk->b_selected = false; + p_sys->event_rtsp = 0xff; + p_sys->event_data = 0xff; - msg_Dbg( p_demux, "StreamClose" ); + if( tk->p_es ) + es_out_Control( p_demux->out, ES_OUT_SET_ES_STATE, tk->p_es, false ); - p_sys->event = 0xff; - p_sys->b_error = true; + int nb_tracks = 0; + for( int i = 0; i < p_sys->i_track; i++ ) + { + if( p_sys->track[i]->b_selected ) + nb_tracks++; + } + msg_Dbg( p_demux, "RTSP track Close, %d track remaining", nb_tracks ); + if( !nb_tracks ) + p_sys->b_error = true; } /***************************************************************************** * *****************************************************************************/ -static void TaskInterrupt( void *p_private ) +static void TaskInterruptRTSP( void *p_private ) +{ + demux_t *p_demux = (demux_t*)p_private; + + /* Avoid lock */ + p_demux->p_sys->event_rtsp = 0xff; +} + +static void TaskInterruptData( void *p_private ) { demux_t *p_demux = (demux_t*)p_private; p_demux->p_sys->i_no_data_ti++; /* Avoid lock */ - p_demux->p_sys->event = 0xff; + p_demux->p_sys->event_data = 0xff; } /***************************************************************************** * *****************************************************************************/ +VLC_NORETURN static void* TimeoutPrevention( void *p_data ) { timeout_thread_t *p_timeout = (timeout_thread_t *)p_data; @@ -1989,7 +2049,7 @@ static int ParseASF( demux_t *p_demux ) } /* Always smaller */ - p_header = block_New( p_demux, psz_end - psz_asf ); + p_header = block_Alloc( psz_end - psz_asf ); p_header->i_buffer = vlc_b64_decode_binary_to_buffer( p_header->p_buffer, p_header->i_buffer, psz_asf ); //msg_Dbg( p_demux, "Size=%d Hdrb64=%s", p_header->i_buffer, psz_asf );