X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Finput%2Finput.c;h=ac7d3908aecba766efe9d25bd7faa663a355718e;hb=a8820e3ef72390eea921d4d421e0f8735d053fa6;hp=c40b9f0f306094585ca80e2a366ce77255fe28a6;hpb=52c18c4dec68158eedd655e0502820b7d7b6128f;p=vlc diff --git a/src/input/input.c b/src/input/input.c index c40b9f0f30..ac7d3908ae 100644 --- a/src/input/input.c +++ b/src/input/input.c @@ -94,7 +94,7 @@ static void InputSourceMeta( input_thread_t *, input_source_t *, vlc_meta_t * ); /* TODO */ //static void InputGetAttachments( input_thread_t *, input_source_t * ); -static void SlaveDemux( input_thread_t *p_input ); +static void SlaveDemux( input_thread_t *p_input, bool *pb_demux_polled ); static void SlaveSeek( input_thread_t *p_input ); static void InputMetaUser( input_thread_t *p_input, vlc_meta_t *p_meta ); @@ -296,7 +296,7 @@ static void ObjectKillChildrens( input_thread_t *p_input, vlc_object_t *p_obj ) i = vlc_internals( p_obj )->i_object_type; if( i == VLC_OBJECT_VOUT ||i == VLC_OBJECT_AOUT || p_obj == VLC_OBJECT(p_input->p->p_sout) || - i == VLC_OBJECT_DECODER || i == VLC_OBJECT_PACKETIZER ) + i == VLC_OBJECT_DECODER ) return; vlc_object_kill( p_obj ); @@ -592,14 +592,15 @@ exit: * MainLoopDemux * It asks the demuxer to demux some data */ -static void MainLoopDemux( input_thread_t *p_input, bool *pb_changed, mtime_t *pi_start_mdate ) +static void MainLoopDemux( input_thread_t *p_input, bool *pb_changed, bool *pb_demux_polled, mtime_t i_start_mdate ) { int i_ret; *pb_changed = false; + *pb_demux_polled = p_input->p->input.p_demux->pf_demux != NULL; if( ( p_input->p->i_stop > 0 && p_input->p->i_time >= p_input->p->i_stop ) || - ( p_input->p->i_run > 0 && *pi_start_mdate+p_input->p->i_run < mdate() ) ) + ( p_input->p->i_run > 0 && i_start_mdate+p_input->p->i_run < mdate() ) ) i_ret = 0; /* EOF */ else i_ret = demux_Demux( p_input->p->input.p_demux ); @@ -629,66 +630,67 @@ static void MainLoopDemux( input_thread_t *p_input, bool *pb_changed, mtime_t *p if( i_ret == 0 ) /* EOF */ { - int i_repeat = var_GetInteger( p_input, "input-repeat" ); - if( i_repeat == 0 ) - { - /* End of file - we do not set b_die because only the - * playlist is allowed to do so. */ - msg_Dbg( p_input, "EOF reached" ); - p_input->p->input.b_eof = true; - } - else - { - vlc_value_t val; + msg_Dbg( p_input, "EOF reached" ); + p_input->p->input.b_eof = true; + } + else if( i_ret < 0 ) + { + input_ChangeState( p_input, ERROR_S ); + } - msg_Dbg( p_input, "repeating the same input (%d)", i_repeat ); - if( i_repeat > 0 ) - { - i_repeat--; - var_SetInteger( p_input, "input-repeat", i_repeat ); - } + if( i_ret > 0 && p_input->p->i_slave > 0 ) + { + bool b_demux_polled; + SlaveDemux( p_input, &b_demux_polled ); - /* Seek to start title/seekpoint */ - val.i_int = p_input->p->input.i_title_start - - p_input->p->input.i_title_offset; - if( val.i_int < 0 || val.i_int >= p_input->p->input.i_title ) - val.i_int = 0; - input_ControlPush( p_input, - INPUT_CONTROL_SET_TITLE, &val ); + *pb_demux_polled |= b_demux_polled; + } +} - val.i_int = p_input->p->input.i_seekpoint_start - - p_input->p->input.i_seekpoint_offset; - if( val.i_int > 0 /* TODO: check upper boundary */ ) - input_ControlPush( p_input, - INPUT_CONTROL_SET_SEEKPOINT, &val ); +static int MainLoopTryRepeat( input_thread_t *p_input, mtime_t *pi_start_mdate ) +{ + int i_repeat = var_GetInteger( p_input, "input-repeat" ); + if( i_repeat == 0 ) + return VLC_EGENERIC; - /* Seek to start position */ - if( p_input->p->i_start > 0 ) - { - val.i_time = p_input->p->i_start; - input_ControlPush( p_input, INPUT_CONTROL_SET_TIME, - &val ); - } - else - { - val.f_float = 0.0; - input_ControlPush( p_input, INPUT_CONTROL_SET_POSITION, - &val ); - } + vlc_value_t val; - /* */ - *pi_start_mdate = mdate(); - } - } - else if( i_ret < 0 ) + msg_Dbg( p_input, "repeating the same input (%d)", i_repeat ); + if( i_repeat > 0 ) { - input_ChangeState( p_input, ERROR_S ); + i_repeat--; + var_SetInteger( p_input, "input-repeat", i_repeat ); } - if( i_ret > 0 && p_input->p->i_slave > 0 ) + /* Seek to start title/seekpoint */ + val.i_int = p_input->p->input.i_title_start - + p_input->p->input.i_title_offset; + if( val.i_int < 0 || val.i_int >= p_input->p->input.i_title ) + val.i_int = 0; + input_ControlPush( p_input, + INPUT_CONTROL_SET_TITLE, &val ); + + val.i_int = p_input->p->input.i_seekpoint_start - + p_input->p->input.i_seekpoint_offset; + if( val.i_int > 0 /* TODO: check upper boundary */ ) + input_ControlPush( p_input, + INPUT_CONTROL_SET_SEEKPOINT, &val ); + + /* Seek to start position */ + if( p_input->p->i_start > 0 ) { - SlaveDemux( p_input ); + val.i_time = p_input->p->i_start; + input_ControlPush( p_input, INPUT_CONTROL_SET_TIME, &val ); } + else + { + val.f_float = 0.0; + input_ControlPush( p_input, INPUT_CONTROL_SET_POSITION, &val ); + } + + /* */ + *pi_start_mdate = mdate(); + return VLC_SUCCESS; } /** @@ -757,6 +759,7 @@ static void MainLoop( input_thread_t *p_input ) mtime_t i_deadline; mtime_t i_wakeup; bool b_paused; + bool b_demux_polled; /* Demux data */ b_force_update = false; @@ -767,11 +770,12 @@ static void MainLoop( input_thread_t *p_input ) b_paused = p_input->p->i_state == PAUSE_S && !es_out_GetBuffering( p_input->p->p_es_out ); + b_demux_polled = true; if( !b_paused ) { if( !p_input->p->input.b_eof ) { - MainLoopDemux( p_input, &b_force_update, &i_start_mdate ); + MainLoopDemux( p_input, &b_force_update, &b_demux_polled, i_start_mdate ); i_wakeup = es_out_GetWakeup( p_input->p->p_es_out ); } @@ -782,14 +786,15 @@ static void MainLoop( input_thread_t *p_input ) } else { - break; + if( MainLoopTryRepeat( p_input, &i_start_mdate ) ) + break; } } /* */ do { i_deadline = i_wakeup; - if( b_paused ) + if( b_paused || !b_demux_polled ) i_deadline = __MIN( i_intf_update, i_statistic_update ); /* Handle control */ @@ -817,13 +822,9 @@ static void MainLoop( input_thread_t *p_input ) i_statistic_update = i_current + INT64_C(1000000); } - /* Check if i_wakeup is still valid */ + /* Update the wakeup time */ if( i_wakeup != 0 ) - { - mtime_t i_new_wakeup = es_out_GetWakeup( p_input->p->p_es_out ); - if( !i_new_wakeup ) - i_wakeup = 0; - } + i_wakeup = es_out_GetWakeup( p_input->p->p_es_out ); } while( i_current < i_wakeup ); } @@ -1138,7 +1139,6 @@ static void InitPrograms( input_thread_t * p_input ) { demux_Control( p_input->p->input.p_demux, DEMUX_SET_GROUP, -1, val.p_list ); - var_FreeList( &val, NULL ); } else { @@ -2337,8 +2337,10 @@ static int InputSourceInit( input_thread_t *p_input, const char *psz_access; const char *psz_demux; char *psz_path; + char *psz_var_demux = NULL; double f_fps; + assert( psz_mrl ); char *psz_dup = strdup( psz_mrl ); if( psz_dup == NULL ) @@ -2347,6 +2349,46 @@ static int InputSourceInit( input_thread_t *p_input, /* Split uri */ input_SplitMRL( &psz_access, &psz_demux, &psz_path, psz_dup ); + /* FIXME: file:// handling plugins do not support URIs properly... + * So we pre-decoded the URI to a path for them. Note that we do not do it + * for non-standard VLC-specific schemes. */ + if( !strcmp( psz_access, "file" ) ) + { + if( psz_path[0] != '/' +#if (DIR_SEP_CHAR != '/') + /* We accept invalid URIs too. */ + && psz_path[0] != DIR_SEP_CHAR +#endif + ) + { /* host specified -> only localhost is supported */ + static const size_t i_localhost = sizeof("localhost")-1; + if( strncmp( psz_path, "localhost/", i_localhost + 1) != 0 ) + { + msg_Err( p_input, "cannot open remote file `%s://%s'", + psz_access, psz_path ); + msg_Info( p_input, "Did you mean `%s:///%s'?", + psz_access, psz_path ); + goto error; + } + psz_path += i_localhost; + } + /* Remove HTML anchor if present (not supported). */ + char *p = strchr( psz_path, '#' ); + if( p ) + *p = '\0'; + /* Then URI-decode the path. */ + decode_URI( psz_path ); +#if defined( WIN32 ) && !defined( UNDER_CE ) + /* Strip leading slash in front of the drive letter */ + psz_path++; +#endif +#if (DIR_SEP_CHAR != '/') + /* Turn slashes into anti-slashes */ + for( char *s = strchr( psz_path, '/' ); s; s = strchr( s + 1, '/' ) ) + *s = DIR_SEP_CHAR; +#endif + } + msg_Dbg( p_input, "`%s' gives access `%s' demux `%s' path `%s'", psz_mrl, psz_access, psz_demux, psz_path ); if( !p_input->b_preparsing ) @@ -2369,7 +2411,7 @@ static int InputSourceInit( input_thread_t *p_input, { /* special hack for forcing a demuxer with --demux=module * (and do nothing with a list) */ - char *psz_var_demux = var_GetNonEmptyString( p_input, "demux" ); + psz_var_demux = var_GetNonEmptyString( p_input, "demux" ); if( psz_var_demux != NULL && !strchr(psz_var_demux, ',' ) && @@ -2416,6 +2458,8 @@ static int InputSourceInit( input_thread_t *p_input, &in->b_can_pace_control ) ) in->b_can_pace_control = false; + assert( in->p_demux->pf_demux != NULL || !in->b_can_pace_control ); + if( !in->b_can_pace_control ) { if( demux_Control( in->p_demux, DEMUX_CAN_CONTROL_RATE, @@ -2446,25 +2490,16 @@ static int InputSourceInit( input_thread_t *p_input, { /* Now try a real access */ in->p_access = access_New( p_input, psz_access, psz_demux, psz_path ); - - /* Access failed, URL encoded ? */ - if( in->p_access == NULL && strchr( psz_path, '%' ) ) - { - decode_URI( psz_path ); - - msg_Dbg( p_input, "retrying with access `%s' demux `%s' path `%s'", - psz_access, psz_demux, psz_path ); - - in->p_access = access_New( p_input, - psz_access, psz_demux, psz_path ); - } if( in->p_access == NULL ) { - msg_Err( p_input, "open of `%s' failed: %s", psz_mrl, - msg_StackMsg() ); - dialog_Fatal( p_input, _("Your input can't be opened"), - _("VLC is unable to open the MRL '%s'." - " Check the log for details."), psz_mrl ); + if( vlc_object_alive( p_input ) ) + { + msg_Err( p_input, "open of `%s' failed: %s", psz_mrl, + msg_StackMsg() ); + dialog_Fatal( p_input, _("Your input can't be opened"), + _("VLC is unable to open the MRL '%s'." + " Check the log for details."), psz_mrl ); + } goto error; } @@ -2591,14 +2626,18 @@ static int InputSourceInit( input_thread_t *p_input, if( in->p_demux == NULL ) { - msg_Err( p_input, "no suitable demux module for `%s/%s://%s'", - psz_access, psz_demux, psz_path ); - dialog_Fatal( VLC_OBJECT( p_input ), - _("VLC can't recognize the input's format"), - _("The format of '%s' cannot be detected. " - "Have a look at the log for details."), psz_mrl ); + if( vlc_object_alive( p_input ) ) + { + msg_Err( p_input, "no suitable demux module for `%s/%s://%s'", + psz_access, psz_demux, psz_path ); + dialog_Fatal( VLC_OBJECT( p_input ), + _("VLC can't recognize the input's format"), + _("The format of '%s' cannot be detected. " + "Have a look at the log for details."), psz_mrl ); + } goto error; } + assert( in->p_demux->pf_demux != NULL ); /* Get title from demux */ if( !p_input->b_preparsing && in->i_title <= 0 ) @@ -2616,6 +2655,7 @@ static int InputSourceInit( input_thread_t *p_input, } } + free( psz_var_demux ); free( psz_dup ); /* Set record capabilities */ @@ -2665,6 +2705,8 @@ error: if( in->p_access ) access_Delete( in->p_access ); + + free( psz_var_demux ); free( psz_dup ); return VLC_EGENERIC; @@ -2746,11 +2788,12 @@ static void InputSourceMeta( input_thread_t *p_input, } -static void SlaveDemux( input_thread_t *p_input ) +static void SlaveDemux( input_thread_t *p_input, bool *pb_demux_polled ) { int64_t i_time; int i; + *pb_demux_polled = false; if( demux_Control( p_input->p->input.p_demux, DEMUX_GET_TIME, &i_time ) ) { msg_Err( p_input, "demux doesn't like DEMUX_GET_TIME" ); @@ -2760,11 +2803,18 @@ static void SlaveDemux( input_thread_t *p_input ) for( i = 0; i < p_input->p->i_slave; i++ ) { input_source_t *in = p_input->p->slave[i]; - int i_ret = 1; + int i_ret; if( in->b_eof ) continue; + const bool b_demux_polled = in->p_demux->pf_demux != NULL; + if( !b_demux_polled ) + continue; + + *pb_demux_polled = true; + + /* Call demux_Demux until we have read enough data */ if( demux_Control( in->p_demux, DEMUX_SET_NEXT_DEMUX_TIME, i_time ) ) { for( ;; ) @@ -2779,7 +2829,10 @@ static void SlaveDemux( input_thread_t *p_input ) } if( i_stime >= i_time ) + { + i_ret = 1; break; + } if( ( i_ret = demux_Demux( in->p_demux ) ) <= 0 ) break; @@ -2993,7 +3046,7 @@ static void InputGetExtraFiles( input_thread_t *p_input, { ".part1.rar", "%s.part%.1d.rar",2, 9 }, { ".part01.rar", "%s.part%.2d.rar",2, 99, }, { ".part001.rar", "%s.part%.3d.rar",2, 999 }, - { ".rar", "%s.r%.2d", 1, 99 }, + { ".rar", "%s.r%.2d", 0, 99 }, { NULL, NULL, 0, 0 } };