Commit c09b621f authored by Laurent Aimar's avatar Laurent Aimar

Added frame by frame support in es out timeshift.

parent 19c98153
...@@ -2152,7 +2152,7 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args ) ...@@ -2152,7 +2152,7 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
/* search program /* search program
* TODO do not use mdate() but proper stream acquisition date */ * TODO do not use mdate() but proper stream acquisition date */
input_clock_Update( p_pgrm->p_clock, VLC_OBJECT(p_sys->p_input), input_clock_Update( p_pgrm->p_clock, VLC_OBJECT(p_sys->p_input),
p_sys->p_input->b_can_pace_control, i_pcr, mdate() ); p_sys->p_input->b_can_pace_control || p_sys->b_buffering, i_pcr, mdate() );
/* Check buffering state on master clock update */ /* Check buffering state on master clock update */
if( p_sys->b_buffering && p_pgrm == p_sys->p_pgrm ) if( p_sys->b_buffering && p_pgrm == p_sys->p_pgrm )
EsOutDecodersStopBuffering( out, false ); EsOutDecodersStopBuffering( out, false );
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* Copyright (C) 2008 Laurent Aimar * Copyright (C) 2008 Laurent Aimar
* $Id$ * $Id$
* *
* Authors: Laurent Aimar < fenrir _AT_ via _DOT_ ecp _DOT_ fr> * Authors: Laurent Aimar < fenrir _AT_ videolan _DOT_ org>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -126,6 +126,9 @@ typedef struct ...@@ -126,6 +126,9 @@ typedef struct
mtime_t i_rate_date; mtime_t i_rate_date;
mtime_t i_rate_delay; mtime_t i_rate_delay;
/* */
mtime_t i_buffering_delay;
/* */ /* */
int i_cmd; int i_cmd;
ts_cmd_t **pp_cmd; ts_cmd_t **pp_cmd;
...@@ -475,7 +478,7 @@ static int ControlLockedSetFrameNext( es_out_t *p_out ) ...@@ -475,7 +478,7 @@ static int ControlLockedSetFrameNext( es_out_t *p_out )
{ {
es_out_sys_t *p_sys = p_out->p_sys; es_out_sys_t *p_sys = p_out->p_sys;
if( !p_sys->b_delayed ) //if( !p_sys->b_delayed )
return es_out_SetFrameNext( p_sys->p_out ); return es_out_SetFrameNext( p_sys->p_out );
/* TODO */ /* TODO */
...@@ -640,6 +643,7 @@ static int TsStart( es_out_t *p_out ) ...@@ -640,6 +643,7 @@ static int TsStart( es_out_t *p_out )
p_ts->i_rate = p_sys->i_input_rate; p_ts->i_rate = p_sys->i_input_rate;
p_ts->i_rate_date = -1; p_ts->i_rate_date = -1;
p_ts->i_rate_delay = 0; p_ts->i_rate_delay = 0;
p_ts->i_buffering_delay = 0;
p_ts->i_cmd_delay = 0; p_ts->i_cmd_delay = 0;
TAB_INIT( p_ts->i_cmd, p_ts->pp_cmd ); TAB_INIT( p_ts->i_cmd, p_ts->pp_cmd );
...@@ -795,18 +799,42 @@ static int TsChangeRate( ts_thread_t *p_ts, int i_src_rate, int i_rate ) ...@@ -795,18 +799,42 @@ static int TsChangeRate( ts_thread_t *p_ts, int i_src_rate, int i_rate )
static void *TsRun( vlc_object_t *p_thread ) static void *TsRun( vlc_object_t *p_thread )
{ {
ts_thread_t *p_ts = (ts_thread_t*)p_thread; ts_thread_t *p_ts = (ts_thread_t*)p_thread;
mtime_t i_buffering_date = -1;
for( ;; ) for( ;; )
{ {
ts_cmd_t cmd; ts_cmd_t cmd;
mtime_t i_deadline; mtime_t i_deadline;
bool b_buffering;
/* Pop a command to execute */ /* Pop a command to execute */
vlc_mutex_lock( &p_ts->lock ); vlc_mutex_lock( &p_ts->lock );
mutex_cleanup_push( &p_ts->lock ); mutex_cleanup_push( &p_ts->lock );
while( p_ts->b_paused || TsPopCmdLocked( p_ts, &cmd ) ) for( ;; )
{
const int canc = vlc_savecancel();
b_buffering = es_out_GetBuffering( p_ts->p_out );
vlc_restorecancel( canc );
if( ( !p_ts->b_paused || b_buffering ) && !TsPopCmdLocked( p_ts, &cmd ) )
break;
vlc_cond_wait( &p_ts->wait, &p_ts->lock ); vlc_cond_wait( &p_ts->wait, &p_ts->lock );
}
if( b_buffering && i_buffering_date < 0 )
{
i_buffering_date = cmd.i_date;
}
else if( i_buffering_date > 0 )
{
p_ts->i_buffering_delay += i_buffering_date - cmd.i_date; /* It is < 0 */
if( b_buffering )
i_buffering_date = cmd.i_date;
else
i_buffering_date = -1;
}
if( p_ts->i_rate_date < 0 ) if( p_ts->i_rate_date < 0 )
p_ts->i_rate_date = cmd.i_date; p_ts->i_rate_date = cmd.i_date;
...@@ -817,7 +845,7 @@ static void *TsRun( vlc_object_t *p_thread ) ...@@ -817,7 +845,7 @@ static void *TsRun( vlc_object_t *p_thread )
const mtime_t i_duration = cmd.i_date - p_ts->i_rate_date; const mtime_t i_duration = cmd.i_date - p_ts->i_rate_date;
p_ts->i_rate_delay = i_duration * p_ts->i_rate / p_ts->i_rate_source - i_duration; p_ts->i_rate_delay = i_duration * p_ts->i_rate / p_ts->i_rate_source - i_duration;
} }
if( p_ts->i_cmd_delay + p_ts->i_rate_delay < 0 ) if( p_ts->i_cmd_delay + p_ts->i_rate_delay + p_ts->i_buffering_delay < 0 && p_ts->i_rate != p_ts->i_rate_source )
{ {
const int canc = vlc_savecancel(); const int canc = vlc_savecancel();
...@@ -825,9 +853,10 @@ static void *TsRun( vlc_object_t *p_thread ) ...@@ -825,9 +853,10 @@ static void *TsRun( vlc_object_t *p_thread )
msg_Warn( p_ts->p_input, "es out timeshift: auto reset rate to %d", p_ts->i_rate_source ); msg_Warn( p_ts->p_input, "es out timeshift: auto reset rate to %d", p_ts->i_rate_source );
p_ts->i_cmd_delay = 0; p_ts->i_cmd_delay = 0;
p_ts->i_buffering_delay = 0;
p_ts->i_rate_date = -1;
p_ts->i_rate_delay = 0; p_ts->i_rate_delay = 0;
p_ts->i_rate_date = -1;
p_ts->i_rate = p_ts->i_rate_source; p_ts->i_rate = p_ts->i_rate_source;
if( !es_out_SetRate( p_ts->p_out, p_ts->i_rate_source, p_ts->i_rate ) ) if( !es_out_SetRate( p_ts->p_out, p_ts->i_rate_source, p_ts->i_rate ) )
...@@ -841,7 +870,7 @@ static void *TsRun( vlc_object_t *p_thread ) ...@@ -841,7 +870,7 @@ static void *TsRun( vlc_object_t *p_thread )
vlc_restorecancel( canc ); vlc_restorecancel( canc );
} }
i_deadline = cmd.i_date + p_ts->i_cmd_delay + p_ts->i_rate_delay; i_deadline = cmd.i_date + p_ts->i_cmd_delay + p_ts->i_rate_delay + p_ts->i_buffering_delay;
vlc_cleanup_run(); vlc_cleanup_run();
......
...@@ -2065,9 +2065,6 @@ static bool Control( input_thread_t *p_input, int i_type, ...@@ -2065,9 +2065,6 @@ static bool Control( input_thread_t *p_input, int i_type,
break; break;
case INPUT_CONTROL_SET_FRAME_NEXT: case INPUT_CONTROL_SET_FRAME_NEXT:
if( !p_input->p->b_can_pause )
break;
if( p_input->i_state == PAUSE_S ) if( p_input->i_state == PAUSE_S )
{ {
es_out_SetFrameNext( p_input->p->p_es_out ); es_out_SetFrameNext( p_input->p->p_es_out );
......
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