#endif
#include <vlc_common.h>
+#include <vlc_memory.h>
#include <ctype.h>
#include <limits.h>
static void ObjectKillChildrens( input_thread_t *, vlc_object_t * );
-static inline int ControlPop( input_thread_t *, int *, vlc_value_t *, mtime_t i_deadline );
-static void ControlReduce( input_thread_t * );
+static inline int ControlPop( input_thread_t *, int *, vlc_value_t *, mtime_t i_deadline, bool b_postpone_seek );
static void ControlRelease( int i_type, vlc_value_t val );
+static bool ControlIsSeekRequest( int i_type );
static bool Control( input_thread_t *, int, vlc_value_t );
static int UpdateTitleSeekpointFromAccess( input_thread_t * );
p_input->p->title = NULL;
p_input->p->i_title_offset = p_input->p->i_seekpoint_offset = 0;
p_input->p->i_state = INIT_S;
- p_input->p->i_rate = INPUT_RATE_DEFAULT;
+ p_input->p->i_rate = INPUT_RATE_DEFAULT
+ / var_CreateGetFloat( p_input, "rate" );
+ /* Currently, the input rate variable is an integer. So we need to destroy
+ * the float variable inherited from the configuration. */
+ var_Destroy( p_input, "rate" );
p_input->p->b_recording = false;
memset( &p_input->p->bookmark, 0, sizeof(p_input->p->bookmark) );
TAB_INIT( p_input->p->i_bookmark, p_input->p->pp_bookmark );
mtime_t i_start_mdate = mdate();
mtime_t i_intf_update = 0;
mtime_t i_statistic_update = 0;
+ mtime_t i_last_seek_mdate = 0;
bool b_pause_after_eof = b_interactive &&
var_CreateGetBool( p_input, "play-and-pause" );
while( vlc_object_alive( p_input ) && !p_input->b_error )
{
bool b_force_update;
- int i_type;
vlc_value_t val;
mtime_t i_current;
- mtime_t i_deadline;
mtime_t i_wakeup;
bool b_paused;
bool b_demux_polled;
/* */
do {
- i_deadline = i_wakeup;
+ mtime_t i_deadline = i_wakeup;
if( b_paused || !b_demux_polled )
i_deadline = __MIN( i_intf_update, i_statistic_update );
/* Handle control */
- ControlReduce( p_input );
- while( !ControlPop( p_input, &i_type, &val, i_deadline ) )
+ for( ;; )
{
+ mtime_t i_limit = i_deadline;
+
+ /* We will postpone the execution of a seek until we have
+ * finished the ES bufferisation (postpone is limited to
+ * 125ms) */
+ bool b_buffering = es_out_GetBuffering( p_input->p->p_es_out ) &&
+ !p_input->p->input.b_eof;
+ if( b_buffering )
+ {
+ /* When postpone is in order, check the ES level every 20ms */
+ mtime_t i_current = mdate();
+ if( i_last_seek_mdate + INT64_C(125000) >= i_current )
+ i_limit = __MIN( i_deadline, i_current + INT64_C(20000) );
+ }
+
+ int i_type;
+ if( ControlPop( p_input, &i_type, &val, i_limit, b_buffering ) )
+ {
+ if( b_buffering && i_limit < i_deadline )
+ continue;
+ break;
+ }
msg_Dbg( p_input, "control type=%d", i_type );
if( Control( p_input, i_type, val ) )
+ {
+ if( ControlIsSeekRequest( i_type ) )
+ i_last_seek_mdate = mdate();
b_force_update = true;
+ }
}
/* Update interface and statistics */
vlc_mutex_unlock( &p_input->p->lock_control );
}
+static int ControlGetReducedIndexLocked( input_thread_t *p_input )
+{
+ const int i_lt = p_input->p->control[0].i_type;
+ int i;
+ for( i = 1; i < p_input->p->i_control; i++ )
+ {
+ const int i_ct = p_input->p->control[i].i_type;
+
+ if( i_lt == i_ct &&
+ ( i_ct == INPUT_CONTROL_SET_STATE ||
+ i_ct == INPUT_CONTROL_SET_RATE ||
+ i_ct == INPUT_CONTROL_SET_POSITION ||
+ i_ct == INPUT_CONTROL_SET_TIME ||
+ i_ct == INPUT_CONTROL_SET_PROGRAM ||
+ i_ct == INPUT_CONTROL_SET_TITLE ||
+ i_ct == INPUT_CONTROL_SET_SEEKPOINT ||
+ i_ct == INPUT_CONTROL_SET_BOOKMARK ) )
+ {
+ continue;
+ }
+ else
+ {
+ /* TODO but that's not that important
+ - merge SET_X with SET_X_CMD
+ - ignore SET_SEEKPOINT/SET_POSITION/SET_TIME before a SET_TITLE
+ - ignore SET_SEEKPOINT/SET_POSITION/SET_TIME before another among them
+ - ?
+ */
+ break;
+ }
+ }
+ return i - 1;
+}
+
+
static inline int ControlPop( input_thread_t *p_input,
int *pi_type, vlc_value_t *p_val,
- mtime_t i_deadline )
+ mtime_t i_deadline, bool b_postpone_seek )
{
input_thread_private_t *p_sys = p_input->p;
vlc_mutex_lock( &p_sys->lock_control );
- while( p_sys->i_control <= 0 )
+ while( p_sys->i_control <= 0 ||
+ ( b_postpone_seek && ControlIsSeekRequest( p_sys->control[0].i_type ) ) )
{
if( !vlc_object_alive( p_input ) || i_deadline < 0 )
{
}
/* */
- *pi_type = p_sys->control[0].i_type;
- *p_val = p_sys->control[0].val;
+ const int i_index = ControlGetReducedIndexLocked( p_input );
- p_sys->i_control--;
+ /* */
+ *pi_type = p_sys->control[i_index].i_type;
+ *p_val = p_sys->control[i_index].val;
+
+ p_sys->i_control -= i_index + 1;
if( p_sys->i_control > 0 )
- memmove( &p_sys->control[0], &p_sys->control[1],
+ memmove( &p_sys->control[0], &p_sys->control[i_index+1],
sizeof(*p_sys->control) * p_sys->i_control );
vlc_mutex_unlock( &p_sys->lock_control );
return VLC_SUCCESS;
}
-
-static void ControlReduce( input_thread_t *p_input )
+static bool ControlIsSeekRequest( int i_type )
{
- vlc_mutex_lock( &p_input->p->lock_control );
-
- for( int i = 1; i < p_input->p->i_control; i++ )
+ switch( i_type )
{
- const int i_lt = p_input->p->control[i-1].i_type;
- const int i_ct = p_input->p->control[i].i_type;
-
- /* XXX We can't merge INPUT_CONTROL_SET_ES */
-/* msg_Dbg( p_input, "[%d/%d] l=%d c=%d", i, p_input->p->i_control,
- i_lt, i_ct );
-*/
- if( i_lt == i_ct &&
- ( i_ct == INPUT_CONTROL_SET_STATE ||
- i_ct == INPUT_CONTROL_SET_RATE ||
- i_ct == INPUT_CONTROL_SET_POSITION ||
- i_ct == INPUT_CONTROL_SET_TIME ||
- i_ct == INPUT_CONTROL_SET_PROGRAM ||
- i_ct == INPUT_CONTROL_SET_TITLE ||
- i_ct == INPUT_CONTROL_SET_SEEKPOINT ||
- i_ct == INPUT_CONTROL_SET_BOOKMARK ) )
- {
- int j;
-// msg_Dbg( p_input, "merged at %d", i );
- /* Remove the i-1 */
- for( j = i; j < p_input->p->i_control; j++ )
- p_input->p->control[j-1] = p_input->p->control[j];
- p_input->p->i_control--;
- }
- else
- {
- /* TODO but that's not that important
- - merge SET_X with SET_X_CMD
- - remove SET_SEEKPOINT/SET_POSITION/SET_TIME before a SET_TITLE
- - remove SET_SEEKPOINT/SET_POSITION/SET_TIME before another among them
- - ?
- */
- }
+ case INPUT_CONTROL_SET_POSITION:
+ case INPUT_CONTROL_SET_TIME:
+ case INPUT_CONTROL_SET_TITLE:
+ case INPUT_CONTROL_SET_TITLE_NEXT:
+ case INPUT_CONTROL_SET_TITLE_PREV:
+ case INPUT_CONTROL_SET_SEEKPOINT:
+ case INPUT_CONTROL_SET_SEEKPOINT_NEXT:
+ case INPUT_CONTROL_SET_SEEKPOINT_PREV:
+ case INPUT_CONTROL_SET_BOOKMARK:
+ return true;
+ default:
+ return false;
}
- vlc_mutex_unlock( &p_input->p->lock_control );
}
static void ControlRelease( int i_type, vlc_value_t val )
break;
case INPUT_CONTROL_SET_POSITION:
- case INPUT_CONTROL_SET_POSITION_OFFSET:
{
double f_pos;
}
case INPUT_CONTROL_SET_TIME:
- case INPUT_CONTROL_SET_TIME_OFFSET:
{
int64_t i_time;
int i_ret;
input_attachment_t **attachment = *ppp_attachment;
int i;
- attachment = realloc( attachment,
- sizeof(input_attachment_t**) * ( i_attachment + i_new ) );
+ attachment = realloc_or_free( attachment,
+ sizeof(input_attachment_t**) * ( i_attachment + i_new ) );
+ assert( attachment );
for( i = 0; i < i_new; i++ )
attachment[i_attachment++] = pp_new[i];
free( pp_new );