Added frame by frame support in es out timeshift.
authorLaurent Aimar <fenrir@videolan.org>
Sun, 16 Nov 2008 12:40:53 +0000 (13:40 +0100)
committerLaurent Aimar <fenrir@videolan.org>
Mon, 17 Nov 2008 19:03:28 +0000 (20:03 +0100)
src/input/es_out.c
src/input/es_out_timeshift.c
src/input/input.c

index b7ad6d8..990e391 100644 (file)
@@ -2152,7 +2152,7 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
             /* search program
              * TODO do not use mdate() but proper stream acquisition date */
             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 */
             if( p_sys->b_buffering && p_pgrm == p_sys->p_pgrm )
                 EsOutDecodersStopBuffering( out, false );
index 7d3aff3..17bcfbf 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (C) 2008 Laurent Aimar
  * $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
  * it under the terms of the GNU General Public License as published by
@@ -126,6 +126,9 @@ typedef struct
     mtime_t        i_rate_date;
     mtime_t        i_rate_delay;
 
+    /* */
+    mtime_t        i_buffering_delay;
+
     /* */
     int            i_cmd;
     ts_cmd_t       **pp_cmd;
@@ -475,7 +478,7 @@ static int ControlLockedSetFrameNext( es_out_t *p_out )
 {
     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 );
 
     /* TODO */
@@ -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_date = -1;
     p_ts->i_rate_delay = 0;
+    p_ts->i_buffering_delay = 0;
     p_ts->i_cmd_delay = 0;
     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 )
 static void *TsRun( vlc_object_t *p_thread )
 {
     ts_thread_t *p_ts = (ts_thread_t*)p_thread;
+    mtime_t i_buffering_date = -1;
 
     for( ;; )
     {
         ts_cmd_t cmd;
         mtime_t  i_deadline;
+        bool b_buffering;
 
         /* Pop a command to execute */
         vlc_mutex_lock( &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 );
+        }
+
+        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 )
             p_ts->i_rate_date = cmd.i_date;
@@ -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;
             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();
 
@@ -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 );
 
             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_date = -1;
             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 ) )
@@ -841,7 +870,7 @@ static void *TsRun( vlc_object_t *p_thread )
 
             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();
 
index 5d90e9a..6f65464 100644 (file)
@@ -2065,9 +2065,6 @@ static bool Control( input_thread_t *p_input, int i_type,
             break;
 
         case INPUT_CONTROL_SET_FRAME_NEXT:
-            if( !p_input->p->b_can_pause )
-                break;
-
             if( p_input->i_state == PAUSE_S )
             {
                 es_out_SetFrameNext( p_input->p->p_es_out );