Commit fc75017b authored by Laurent Aimar's avatar Laurent Aimar

Added rate change support to es_out_timeshift.

parent 1c01003b
...@@ -123,6 +123,11 @@ struct es_out_sys_t ...@@ -123,6 +123,11 @@ struct es_out_sys_t
bool b_paused; bool b_paused;
mtime_t i_pause_date; mtime_t i_pause_date;
int i_rate;
int i_rate_source;
mtime_t i_rate_date;
mtime_t i_rate_delay;
/* */ /* */
int i_es; int i_es;
es_out_id_t **pp_es; es_out_id_t **pp_es;
...@@ -168,7 +173,7 @@ static FILE *GetTmpFile( const char *psz_path ); ...@@ -168,7 +173,7 @@ static FILE *GetTmpFile( const char *psz_path );
/***************************************************************************** /*****************************************************************************
* input_EsOutTimeshiftNew: * input_EsOutTimeshiftNew:
*****************************************************************************/ *****************************************************************************/
es_out_t *input_EsOutTimeshiftNew( input_thread_t *p_input, es_out_t *p_next_out ) es_out_t *input_EsOutTimeshiftNew( input_thread_t *p_input, es_out_t *p_next_out, int i_rate )
{ {
es_out_t *p_out = malloc( sizeof(*p_out) ); es_out_t *p_out = malloc( sizeof(*p_out) );
if( !p_out ) if( !p_out )
...@@ -200,6 +205,10 @@ es_out_t *input_EsOutTimeshiftNew( input_thread_t *p_input, es_out_t *p_next_out ...@@ -200,6 +205,10 @@ es_out_t *input_EsOutTimeshiftNew( input_thread_t *p_input, es_out_t *p_next_out
p_sys->p_thread = NULL; p_sys->p_thread = NULL;
p_sys->b_paused = false; p_sys->b_paused = false;
p_sys->i_pause_date = -1; p_sys->i_pause_date = -1;
p_sys->i_rate_source =
p_sys->i_rate = i_rate;
p_sys->i_rate_date = -1;
p_sys->i_rate_delay = 0;
p_sys->i_cmd_delay = 0; p_sys->i_cmd_delay = 0;
TAB_INIT( p_sys->i_es, p_sys->pp_es ); TAB_INIT( p_sys->i_es, p_sys->pp_es );
...@@ -350,7 +359,6 @@ static int ControlLockedSetPauseState( es_out_t *p_out, bool b_source_paused, bo ...@@ -350,7 +359,6 @@ static int ControlLockedSetPauseState( es_out_t *p_out, bool b_source_paused, bo
{ {
return es_out_SetPauseState( p_sys->p_out, b_source_paused, b_paused, i_date ); return es_out_SetPauseState( p_sys->p_out, b_source_paused, b_paused, i_date );
} }
if( p_sys->p_input->b_can_pace_control ) if( p_sys->p_input->b_can_pace_control )
{ {
/* XXX we may do it BUT it would be better to finish the clock clean up+improvments /* XXX we may do it BUT it would be better to finish the clock clean up+improvments
...@@ -400,9 +408,26 @@ static int ControlLockedSetRate( es_out_t *p_out, int i_src_rate, int i_rate ) ...@@ -400,9 +408,26 @@ static int ControlLockedSetRate( es_out_t *p_out, int i_src_rate, int i_rate )
{ {
return es_out_SetRate( p_sys->p_out, i_src_rate, i_rate ); return es_out_SetRate( p_sys->p_out, i_src_rate, i_rate );
} }
/* TODO */ if( p_sys->p_input->b_can_pace_control )
msg_Err( p_sys->p_input, "EsOutTimeshift does not yet support rate change" ); {
return VLC_EGENERIC; /* XXX we may do it BUT it would be better to finish the clock clean up+improvments
* and so be able to advertize correctly pace control property in access
* module */
msg_Err( p_sys->p_input, "EsOutTimeshift does not work with streams that have space control" );
return VLC_EGENERIC;
}
p_sys->i_cmd_delay += p_sys->i_rate_delay;
p_sys->i_rate_date = -1;
p_sys->i_rate_delay = 0;
p_sys->i_rate = i_rate;
p_sys->i_rate_source = i_src_rate;
if( !p_sys->b_delayed )
TsStart( p_out );
return es_out_SetRate( p_sys->p_out, i_rate, i_rate );
} }
static int ControlLockedSetTime( es_out_t *p_out, mtime_t i_date ) static int ControlLockedSetTime( es_out_t *p_out, mtime_t i_date )
{ {
...@@ -595,6 +620,7 @@ static void *TsRun( vlc_object_t *p_thread ) ...@@ -595,6 +620,7 @@ static void *TsRun( vlc_object_t *p_thread )
for( ;; ) for( ;; )
{ {
ts_cmd_t cmd; ts_cmd_t cmd;
mtime_t i_deadline;
/* Pop a command to execute */ /* Pop a command to execute */
vlc_mutex_lock( &p_sys->lock ); vlc_mutex_lock( &p_sys->lock );
...@@ -603,15 +629,32 @@ static void *TsRun( vlc_object_t *p_thread ) ...@@ -603,15 +629,32 @@ static void *TsRun( vlc_object_t *p_thread )
while( p_sys->b_paused || CmdPop( p_out, &cmd ) ) while( p_sys->b_paused || CmdPop( p_out, &cmd ) )
vlc_cond_wait( &p_sys->wait, &p_sys->lock ); vlc_cond_wait( &p_sys->wait, &p_sys->lock );
vlc_cleanup_pop(); if( p_sys->i_rate_date < 0 )
vlc_mutex_unlock( &p_sys->lock ); p_sys->i_rate_date = cmd.i_date;
p_sys->i_rate_delay = 0;
if( p_sys->i_rate_source != p_sys->i_rate )
{
const mtime_t i_duration = cmd.i_date - p_sys->i_rate_date;
p_sys->i_rate_delay = i_duration * p_sys->i_rate / p_sys->i_rate_source - i_duration;
}
i_deadline = cmd.i_date + p_sys->i_cmd_delay + p_sys->i_rate_delay;
if( p_sys->i_cmd_delay + p_sys->i_rate_delay < 0 )
{
/* TODO handle when we cannot go faster anymore */
msg_Err( p_sys->p_input, "FIXME rate underflow" );
}
vlc_cleanup_run();
/* Regulate the speed of command processing to the same one than /* Regulate the speed of command processing to the same one than
* reading */ * reading */
//fprintf( stderr, "d=%d - %d\n", (int)(p_sys->i_cmd_delay/1000), (int)( (mdate() - cmd.i_date - p_sys->i_cmd_delay)/1000) ); //fprintf( stderr, "d=%d - %d\n", (int)(p_sys->i_cmd_delay/1000), (int)( (mdate() - cmd.i_date - p_sys->i_cmd_delay)/1000) );
vlc_cleanup_push( cmd_cleanup_routine, &cmd ); vlc_cleanup_push( cmd_cleanup_routine, &cmd );
mwait( cmd.i_date + p_sys->i_cmd_delay ); mwait( i_deadline );
vlc_cleanup_pop(); vlc_cleanup_pop();
......
...@@ -31,6 +31,6 @@ ...@@ -31,6 +31,6 @@
#include <vlc_common.h> #include <vlc_common.h>
es_out_t *input_EsOutTimeshiftNew( input_thread_t *, es_out_t * ); es_out_t *input_EsOutTimeshiftNew( input_thread_t *, es_out_t *, int i_rate );
#endif #endif
...@@ -1185,7 +1185,7 @@ static int Init( input_thread_t * p_input ) ...@@ -1185,7 +1185,7 @@ static int Init( input_thread_t * p_input )
/* Create es out */ /* Create es out */
p_input->p->p_es_out_display = input_EsOutNew( p_input, p_input->p->i_rate ); p_input->p->p_es_out_display = input_EsOutNew( p_input, p_input->p->i_rate );
p_input->p->p_es_out = input_EsOutTimeshiftNew( p_input, p_input->p->p_es_out_display ); p_input->p->p_es_out = input_EsOutTimeshiftNew( p_input, p_input->p->p_es_out_display, p_input->p->i_rate );
es_out_Control( p_input->p->p_es_out, ES_OUT_SET_ACTIVE, false ); es_out_Control( p_input->p->p_es_out, ES_OUT_SET_ACTIVE, false );
es_out_Control( p_input->p->p_es_out, ES_OUT_SET_MODE, ES_OUT_MODE_NONE ); es_out_Control( p_input->p->p_es_out, ES_OUT_SET_MODE, ES_OUT_MODE_NONE );
...@@ -1517,12 +1517,20 @@ static void ControlPause( input_thread_t *p_input, mtime_t i_control_date ) ...@@ -1517,12 +1517,20 @@ static void ControlPause( input_thread_t *p_input, mtime_t i_control_date )
} }
} }
/* */
if( !i_ret )
{
i_ret = es_out_SetPauseState( p_input->p->p_es_out, p_input->p->b_can_pause, true, i_control_date );
if( i_ret )
{
msg_Warn( p_input, "cannot set pause state at es_out level" );
i_state = p_input->i_state;
}
}
/* Switch to new state */ /* Switch to new state */
input_ChangeStateWithVarCallback( p_input, i_state, false ); input_ChangeStateWithVarCallback( p_input, i_state, false );
/* */
if( !i_ret )
es_out_SetPauseState( p_input->p->p_es_out, p_input->p->b_can_pause, true, i_control_date );
} }
static void ControlUnpause( input_thread_t *p_input, mtime_t i_control_date ) static void ControlUnpause( input_thread_t *p_input, mtime_t i_control_date )
{ {
...@@ -1766,7 +1774,8 @@ static bool Control( input_thread_t *p_input, int i_type, ...@@ -1766,7 +1774,8 @@ static bool Control( input_thread_t *p_input, int i_type,
i_rate = INPUT_RATE_MAX; i_rate = INPUT_RATE_MAX;
} }
if( i_rate != INPUT_RATE_DEFAULT && if( i_rate != INPUT_RATE_DEFAULT &&
( ( !p_input->b_can_pace_control && !p_input->p->b_can_rate_control ) || ( /*( !p_input->b_can_pace_control && !p_input->p->b_can_rate_control ) ||*/
( !p_input->p->b_can_rate_control && !p_input->p->input.b_rescale_ts ) ||
( p_input->p->p_sout && !p_input->p->b_out_pace_control ) ) ) ( p_input->p->p_sout && !p_input->p->b_out_pace_control ) ) )
{ {
msg_Dbg( p_input, "cannot change rate" ); msg_Dbg( p_input, "cannot change rate" );
...@@ -1799,7 +1808,10 @@ static bool Control( input_thread_t *p_input, int i_type, ...@@ -1799,7 +1808,10 @@ static bool Control( input_thread_t *p_input, int i_type,
/* FIXME do we need a RESET_PCR when !p_input->p->input.b_rescale_ts ? */ /* FIXME do we need a RESET_PCR when !p_input->p->input.b_rescale_ts ? */
if( p_input->p->input.b_rescale_ts ) if( p_input->p->input.b_rescale_ts )
es_out_SetRate( p_input->p->p_es_out, i_rate, i_rate ); {
const int i_rate_source = (p_input->b_can_pace_control || p_input->p->b_can_rate_control ) ? i_rate : INPUT_RATE_DEFAULT;
es_out_SetRate( p_input->p->p_es_out, i_rate_source, i_rate );
}
b_force_update = true; b_force_update = true;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment