#include <assert.h>
#include "input_internal.h"
+#include "es_out.h"
+#include "access.h"
+#include "demux.h"
+#include "stream.h"
#include <vlc_sout.h>
#include "../stream_output/stream_output.h"
* - intf-change
* - intf-change-vout for when a vout is created or destroyed
* - rate-change for when playback rate changes
+ * - stats-change for when statistics are updated
* TODO explain when Callback is called
* TODO complete this list (?)
*****************************************************************************/
stats_TimerStart( p_input, psz_timer_name,
STATS_TIMER_INPUT_LAUNCHING );
- MALLOC_NULL( p_input->p, input_thread_private_t );
- memset( p_input->p, 0, sizeof( input_thread_private_t ) );
+ p_input->p = calloc( 1, sizeof( input_thread_private_t ) );
+ if( !p_input->p )
+ return NULL;
/* One "randomly" selected input thread is responsible for computing
* the global stats. Check if there is already someone doing this */
psz_parser = val.psz_string;
while( (psz_start = strchr( psz_parser, '{' ) ) )
{
- seekpoint_t *p_seekpoint = vlc_seekpoint_New();
+ seekpoint_t *p_seekpoint;
char backup;
psz_start++;
psz_end = strchr( psz_start, '}' );
backup = *psz_parser;
*psz_parser = 0;
*psz_end = ',';
+
+ p_seekpoint = vlc_seekpoint_New();
while( (psz_end = strchr( psz_start, ',' ) ) )
{
*psz_end = 0;
sout_instance_t * input_DetachSout( input_thread_t *p_input )
{
+ assert( p_input->b_dead );
sout_instance_t *p_sout = p_input->p->p_sout;
vlc_object_detach( p_sout );
p_input->p->p_sout = NULL;
stats_ComputeGlobalStats( p_input->p_libvlc,
p_input->p_libvlc->p_stats );
}
+ var_SetBool( p_input, "stats-change", true );
}
/**
mtime_t i_current;
mtime_t i_deadline;
mtime_t i_wakeup;
+ bool b_paused;
/* Demux data */
b_force_update = false;
i_wakeup = 0;
- if( p_input->i_state != PAUSE_S )
+ /* FIXME if p_input->i_state == PAUSE_S the access/access_demux
+ * is paused -> this may cause problem with some of them
+ * The same problem can be seen when seeking while paused */
+ input_EsOutLock( p_input->p->p_es_out );
+ b_paused = p_input->i_state == PAUSE_S &&
+ !input_EsOutIsBuffering( p_input->p->p_es_out );
+ input_EsOutUnlock( p_input->p->p_es_out );
+
+ if( !b_paused )
{
MainLoopDemux( p_input, &b_force_update, &i_start_mdate );
- i_wakeup = input_EsOutGetWakeup( p_input->p->p_es_out );
+
+ i_wakeup = es_out_GetWakeup( p_input->p->p_es_out );
}
/* */
do {
i_deadline = i_wakeup;
- if( p_input->i_state == PAUSE_S )
+ if( b_paused )
i_deadline = __MIN( i_intf_update, i_statistic_update );
/* Handle control */
while( !ControlPopNoLock( p_input, &i_type, &val, i_deadline ) )
{
msg_Dbg( p_input, "control type=%d", i_type );
+
if( Control( p_input, i_type, val ) )
b_force_update = true;
}
/* Check if i_wakeup is still valid */
if( i_wakeup != 0 )
{
- mtime_t i_new_wakeup = input_EsOutGetWakeup( p_input->p->p_es_out );
+ mtime_t i_new_wakeup = es_out_GetWakeup( p_input->p->p_es_out );
if( !i_new_wakeup )
i_wakeup = 0;
}
/* We have finish to demux data but not to play them */
while( vlc_object_alive( p_input ) )
{
- if( input_EsOutDecodersEmpty( p_input->p->p_es_out ) )
+ input_EsOutLock( p_input->p->p_es_out );
+ bool b_empty = input_EsOutDecodersIsEmpty( p_input->p->p_es_out );
+ input_EsOutUnlock( p_input->p->p_es_out );
+
+ if( b_empty )
break;
msg_Dbg( p_input, "waiting decoder fifos to empty" );
input_ChangeState( p_input, ERROR_S );
if( p_input->p->p_es_out )
- input_EsOutDelete( p_input->p->p_es_out );
+ es_out_Delete( p_input->p->p_es_out );
#ifdef ENABLE_SOUT
if( p_input->p->p_sout )
{
/* Unload all modules */
if( p_input->p->p_es_out )
- input_EsOutDelete( p_input->p->p_es_out );
+ es_out_Delete( p_input->p->p_es_out );
if( !p_input->b_preparsing )
{
}
}
}
+/* Pause input */
+static void ControlPause( input_thread_t *p_input, mtime_t i_control_date )
+{
+ int i_ret;
+ int i_state;
+ if( p_input->p->input.p_access )
+ i_ret = access_Control( p_input->p->input.p_access,
+ ACCESS_SET_PAUSE_STATE, true );
+ else
+ i_ret = demux_Control( p_input->p->input.p_demux,
+ DEMUX_SET_PAUSE_STATE, true );
+
+ i_state = PAUSE_S;
+ if( i_ret )
+ {
+ msg_Warn( p_input, "cannot set pause state" );
+ i_state = p_input->i_state;
+ }
+
+ /* Switch to new state */
+ input_ChangeStateWithVarCallback( p_input, i_state, false );
+
+ /* */
+ if( !i_ret )
+ input_EsOutChangePause( p_input->p->p_es_out, true, i_control_date );
+}
+static void ControlUnpause( input_thread_t *p_input, mtime_t i_control_date )
+{
+ int i_ret;
+ if( p_input->p->input.p_access )
+ i_ret = access_Control( p_input->p->input.p_access,
+ ACCESS_SET_PAUSE_STATE, false );
+ else
+ i_ret = demux_Control( p_input->p->input.p_demux,
+ DEMUX_SET_PAUSE_STATE, false );
+
+ if( i_ret )
+ {
+ /* FIXME What to do ? */
+ msg_Warn( p_input, "cannot unset pause -> EOF" );
+ vlc_mutex_unlock( &p_input->p->lock_control );
+ input_ControlPush( p_input, INPUT_CONTROL_SET_DIE, NULL );
+ vlc_mutex_lock( &p_input->p->lock_control );
+ }
+
+ /* Switch to play */
+ input_ChangeStateWithVarCallback( p_input, PLAYING_S, false );
+
+ /* */
+ if( !i_ret )
+ input_EsOutChangePause( p_input->p->p_es_out, false, i_control_date );
+}
static bool Control( input_thread_t *p_input, int i_type,
vlc_value_t val )
if( !p_input )
return b_force_update;
+ input_EsOutLock( p_input->p->p_es_out );
+
switch( i_type )
{
case INPUT_CONTROL_SET_DIE:
if( ( val.i_int == PLAYING_S && p_input->i_state == PAUSE_S ) ||
( val.i_int == PAUSE_S && p_input->i_state == PAUSE_S ) )
{
- int i_ret;
- if( p_input->p->input.p_access )
- i_ret = access_Control( p_input->p->input.p_access,
- ACCESS_SET_PAUSE_STATE, false );
- else
- i_ret = demux_Control( p_input->p->input.p_demux,
- DEMUX_SET_PAUSE_STATE, false );
-
- if( i_ret )
- {
- /* FIXME What to do ? */
- msg_Warn( p_input, "cannot unset pause -> EOF" );
- vlc_mutex_unlock( &p_input->p->lock_control );
- input_ControlPush( p_input, INPUT_CONTROL_SET_DIE, NULL );
- vlc_mutex_lock( &p_input->p->lock_control );
- }
+ ControlUnpause( p_input, i_control_date );
b_force_update = true;
-
- /* Switch to play */
- input_ChangeStateWithVarCallback( p_input, PLAYING_S, false );
-
- /* */
- if( !i_ret )
- input_EsOutChangePause( p_input->p->p_es_out, false, i_control_date );
}
else if( val.i_int == PAUSE_S && p_input->i_state == PLAYING_S &&
p_input->p->b_can_pause )
{
- int i_ret, state;
- if( p_input->p->input.p_access )
- i_ret = access_Control( p_input->p->input.p_access,
- ACCESS_SET_PAUSE_STATE, true );
- else
- i_ret = demux_Control( p_input->p->input.p_demux,
- DEMUX_SET_PAUSE_STATE, true );
+ ControlPause( p_input, i_control_date );
b_force_update = true;
-
- if( i_ret )
- {
- msg_Warn( p_input, "cannot set pause state" );
- state = p_input->i_state;
- }
- else
- {
- state = PAUSE_S;
- }
-
- /* Switch to new state */
- input_ChangeStateWithVarCallback( p_input, state, false );
-
- /* */
- if( !i_ret )
- input_EsOutChangePause( p_input->p->p_es_out, true, i_control_date );
}
else if( val.i_int == PAUSE_S && !p_input->p->b_can_pause )
{
}
break;
+ case INPUT_CONTROL_SET_FRAME_NEXT:
+ if( !p_input->p->b_can_pause )
+ break;
+
+ if( p_input->i_state == PAUSE_S )
+ {
+ input_EsOutFrameNext( p_input->p->p_es_out );
+ }
+ else if( p_input->i_state == PLAYING_S )
+ {
+ ControlPause( p_input, i_control_date );
+ }
+ else
+ {
+ msg_Err( p_input, "invalid state for frame next" );
+ }
+ b_force_update = true;
+ break;
+
case INPUT_CONTROL_SET_BOOKMARK:
default:
msg_Err( p_input, "not yet implemented" );
break;
}
+ input_EsOutUnlock( p_input->p->p_es_out );
+
return b_force_update;
}
if( count.i_int < list.p_list->i_count )
{
int i_id = list.p_list->p_values[count.i_int].i_int;
+
+ input_EsOutLock( p_input->p->p_es_out );
es_out_id_t *p_es = input_EsOutGetFromID( p_input->p->p_es_out, i_id );
- es_out_Control( p_input->p->p_es_out, ES_OUT_SET_DEFAULT, p_es );
+ es_out_Control( p_input->p->p_es_out, ES_OUT_SET_ES_DEFAULT, p_es );
es_out_Control( p_input->p->p_es_out, ES_OUT_SET_ES, p_es );
+ input_EsOutUnlock( p_input->p->p_es_out );
}
var_Change( p_input, "spu-es", VLC_VAR_FREELIST, &list, NULL );
}