/* 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 );
* 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 );
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;
}
/**
mtime_t i_deadline;
mtime_t i_wakeup;
bool b_paused;
+ bool b_demux_polled;
/* Demux data */
b_force_update = false;
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 );
}
}
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 */
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 );
}
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 )
/* 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 )
{
/* 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, ',' ) &&
&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,
{
/* 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;
}
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 )
}
}
+ free( psz_var_demux );
free( psz_dup );
/* Set record capabilities */
if( in->p_access )
access_Delete( in->p_access );
+
+ free( psz_var_demux );
free( psz_dup );
return VLC_EGENERIC;
}
-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" );
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( ;; )
}
if( i_stime >= i_time )
+ {
+ i_ret = 1;
break;
+ }
if( ( i_ret = demux_Demux( in->p_demux ) ) <= 0 )
break;