[vlc-devel] Re: ff / rew based on time ...

John Michael Zorko j.zorko at att.net
Tue May 27 01:03:38 CEST 2003


DJ,

My friends' server is down, so here is the diff so far.  Some things I  
still want to work on are:

1. SetDemuxOptions() is a bit too specific to MP3 or MPEG I think (time  
offset, frame offset) but maybe not so bad ...
2. none of the frame-seeking code is in yet (just stubbed out if's, but  
i'm working on it)
3. how to seek backwards n frames, when a frame could be:
     a.) be spread across more than 1 pack
     b.) could have it's start code spread across more than 1 pack
     c.) variable length i.e. MP3 VBR

Thoughts?




? diffstuff
? stoneseggs.mp3
Index: include/input_ext-intf.h
===================================================================
RCS file: /var/cvs/videolan/vlc/include/input_ext-intf.h,v
retrieving revision 1.90
diff -u -r1.90 input_ext-intf.h
--- include/input_ext-intf.h	17 May 2003 22:00:00 -0000	1.90
+++ include/input_ext-intf.h	26 May 2003 22:28:32 -0000
@@ -316,6 +316,10 @@
      /* Demux module */
      module_t *       p_demux;
      int           (* pf_demux )  ( input_thread_t * );
+    int           (* pf_setdemuxoptions ) ( input_thread_t *p_input,
+                                      int i_offsettime,    /* -:  
rewind, +: ff */
+                                      int i_offsetframe,   /* -:  
rewind, +: ff */
+                                      int i_drop );       /* packets  
to drop b4 playing */
      int           (* pf_rewind ) ( input_thread_t * );
                                             /* NULL if we don't support  
going *
                                              * backwards (it's gonna be  
fun)  */
@@ -365,6 +369,14 @@
  #define INPUT_STATUS_PAUSE          2
  #define INPUT_STATUS_FASTER         3
  #define INPUT_STATUS_SLOWER         4
+#define INPUT_STATUS_FASTFORWARD_TS 5  // fast-forward by skipping time
+#define INPUT_STATUS_REWIND_TS      6  // rewind       "      "       "
+#define INPUT_STATUS_FASTFORWARD_FS 7  // fast-forward by skipping  
frames
+#define INPUT_STATUS_REWIND_FS      8  // rewind       "      "       "
+
+/* maximum seconds to skip when doing ff / rew using time-based  
skipping (PS) */
+
+#define MAX_FF_REW_SKIP  10

  /* Seek modes */
  #define INPUT_SEEK_SET       0x00
@@ -373,6 +385,8 @@
  #define INPUT_SEEK_BYTES     0x00
  #define INPUT_SEEK_SECONDS   0x10
  #define INPUT_SEEK_PERCENT   0x20
+#define INPUT_SEEK_SPECIAL   0x30
+

   
/ 
************************************************************************ 
*****
   * Prototypes
Index: include/stream_control.h
===================================================================
RCS file: /var/cvs/videolan/vlc/include/stream_control.h,v
retrieving revision 1.10
diff -u -r1.10 stream_control.h
--- include/stream_control.h	31 Jul 2002 20:56:50 -0000	1.10
+++ include/stream_control.h	26 May 2003 22:28:33 -0000
@@ -41,6 +41,12 @@
      /* if i_status == FORWARD_S or BACKWARD_S */
      int                     i_rate;

+    /* for packet-skipping fast-forward / rewind implementation */
+    int                     i_packet_skip_rate;
+
+    /* for frame-skipping fast-forward / rewind implementation */
+    int                     i_frame_skip_rate;
+
      vlc_bool_t              b_mute;
      vlc_bool_t              b_grayscale;           /* use color or  
grayscale */
  };
Index: modules/control/rc/rc.c
===================================================================
RCS file: /var/cvs/videolan/vlc/modules/control/rc/rc.c,v
retrieving revision 1.34
diff -u -r1.34 rc.c
--- modules/control/rc/rc.c	15 May 2003 22:27:37 -0000	1.34
+++ modules/control/rc/rc.c	26 May 2003 22:28:41 -0000
@@ -196,6 +196,15 @@
      var_Create( p_intf, "achan", VLC_VAR_STRING | VLC_VAR_ISCOMMAND );
      var_AddCallback( p_intf, "achan", AudioConfig, NULL );

+    var_Create( p_intf, "ff_ts", VLC_VAR_VOID | VLC_VAR_ISCOMMAND );
+    var_AddCallback( p_intf, "ff_ts", Input, NULL );
+    var_Create( p_intf, "rew_ts", VLC_VAR_VOID | VLC_VAR_ISCOMMAND );
+    var_AddCallback( p_intf, "rew_ts", Input, NULL );
+    var_Create( p_intf, "ff_fs", VLC_VAR_VOID | VLC_VAR_ISCOMMAND );
+    var_AddCallback( p_intf, "ff_fs", Input, NULL );
+    var_Create( p_intf, "rew_fs", VLC_VAR_VOID | VLC_VAR_ISCOMMAND );
+    var_AddCallback( p_intf, "rew_fs", Input, NULL );
+
  #ifdef WIN32
      /* Get the file descriptor of the console input */
      hConsoleIn = GetStdHandle(STD_INPUT_HANDLE);
@@ -472,6 +481,13 @@
                  printf("| f  . . . . . . . . . . . . . . toggle  
fullscreen\n");
                  printf("| info . . .  information about the current  
stream\n");
                  printf("| \n");
+                printf("| ff_ts  . . . .  fast-forward using time  
skipping\n");
+                printf("|               (enter command again to go  
faster)\n");
+                printf("| rew_ts . . . . . . .  rewind using time  
skipping\n");
+                printf("|               (enter command again to go  
faster)\n");
+                printf("| ff_fs  . . . . fast-forward using frame  
skipping\n");
+                printf("| rew_fs . . . . . . . rewind using frame  
skipping\n");
+                printf("| \n");
                  printf("| volume [X] . . . . . . . .  set/get audio  
volume\n");
                  printf("| volup [X]  . . . . .  raise audio volume X  
steps\n");
                  printf("| voldown [X]  . . . .  lower audio volume X  
steps\n");
@@ -529,6 +545,22 @@
      {
          input_Seek( p_input, atoi( newval.psz_string ),
                      INPUT_SEEK_SECONDS | INPUT_SEEK_SET );
+    }
+    else if ( !strcmp( psz_cmd, "ff_ts" ) )
+    {
+        input_SetStatus( p_input, INPUT_STATUS_FASTFORWARD_TS );
+    }
+    else if ( !strcmp( psz_cmd, "rew_ts" ) )
+    {
+        input_SetStatus( p_input, INPUT_STATUS_REWIND_TS );
+    }
+    else if ( !strcmp( psz_cmd, "ff_ts" ) )
+    {
+        input_SetStatus( p_input, INPUT_STATUS_FASTFORWARD_FS );
+    }
+    else if ( !strcmp( psz_cmd, "rew_fs" ) )
+    {
+        input_SetStatus( p_input, INPUT_STATUS_REWIND_FS );
      }
      else if( !strcmp( psz_cmd, "chapter" ) ||
               !strcmp( psz_cmd, "chapter_n" ) ||
Index: modules/demux/mpeg/audio.c
===================================================================
RCS file: /var/cvs/videolan/vlc/modules/demux/mpeg/audio.c,v
retrieving revision 1.18
diff -u -r1.18 audio.c
--- modules/demux/mpeg/audio.c	5 May 2003 22:23:36 -0000	1.18
+++ modules/demux/mpeg/audio.c	26 May 2003 22:28:45 -0000
@@ -37,6 +37,7 @@
    
************************************************************************ 
*****/
  static int  Activate ( vlc_object_t * );
  static int  Demux ( input_thread_t * );
+static int  SetDemuxOptions( input_thread_t *, int, int, int );

  /* TODO: support MPEG-2.5, not difficult, but I need somes samples...  
*/

@@ -105,6 +106,12 @@
      int i_samplerate;
      int i_samplelength;
      int i_framelength;
+
+    /* info for SetDemuxOptions i.e. ff / rew */
+    int i_packet_skip_rate;
+    int i_frame_skip_rate;
+    int i_drop_count;
+    int i_packet_counter;
  };


@@ -490,6 +497,7 @@
      int i_max_pos;

      /* Set the demux function */
+    p_input->pf_setdemuxoptions = SetDemuxOptions;
      p_input->pf_demux = Demux;

      /* Initialize access plug-in structures. */
@@ -650,6 +658,29 @@
  }

   
/ 
************************************************************************ 
*****
+ * SetDemuxOptions: sets options for the demuxer to work with i.e. ff  
/ rew
+ * parameters.  The idea is that only the demux plugin(s) know how to  
identify
+ * things like MP3 frames, MPEG sequence headers, GOPs, I-frames, etc.  
and if
+ * we want to be able to seek in a more specific manner i.e. "go back  
10 MP3
+ * frames" or "advance to the third GOP from now" the demux plugin(s)  
should
+ * be involved, so we won't need to duplicate code elsewhere.
+  
************************************************************************ 
*****/
+
+static int SetDemuxOptions( input_thread_t *p_input,
+                            int i_offsettime,
+                            int i_offsetframe,
+                            int i_drop )
+{
+    demux_sys_t  *p_demux = p_input->p_demux_data;
+
+    p_demux->i_packet_skip_rate = i_offsettime;
+    p_demux->i_frame_skip_rate = i_offsetframe;
+    p_demux->i_drop_count = i_drop;
+
+    return 0;
+}
+
+/ 
************************************************************************ 
*****
   * Demux: reads and demuxes data packets
    
************************************************************************ 
*****
   * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
@@ -660,6 +691,29 @@
      pes_packet_t *p_pes;
      int          i_skip;

+    /* First see if we're in ff / rewind mode and if we need to seek */
+
+    p_demux->i_packet_counter ++;
+
+    #define A p_input->stream
+
+    if ( p_demux->i_packet_counter % p_demux->i_drop_count == 0 )
+    {
+        if ( p_demux->i_packet_skip_rate != 1 )
+        {
+            vlc_mutex_lock( &p_input->stream.stream_lock );
+            int i_new_pos = A.p_selected_area->i_tell / ( 50 *  
A.i_mux_rate ) +
+                            p_demux->i_packet_skip_rate;
+            vlc_mutex_unlock( &p_input->stream.stream_lock );
+            input_Seek( p_input, i_new_pos, INPUT_SEEK_SECONDS |  
INPUT_SEEK_SET );
+        }
+        else if ( p_demux->i_frame_skip_rate != 0 )
+        {
+        }
+    }
+
+    #undef A
+
      if( !GetHeader( p_input,
                      &p_demux->mpeg,
                      8192,
@@ -714,7 +768,18 @@
      }
      else
      {
-        input_DecodePES( p_demux->p_es->p_decoder_fifo, p_pes );
+        if ( p_demux->i_frame_skip_rate == 0 )
+        {
+            input_DecodePES( p_demux->p_es->p_decoder_fifo, p_pes );
+        }
+        else if ( p_demux->i_packet_counter % p_demux->i_drop_count !=  
0 )
+        {
+            #define A p_input->stream
+            input_DecodePES( p_demux->p_es->p_decoder_fifo, p_pes );
+
+
+            #undef A
+        }
      }
      p_demux->i_pts += (mtime_t)90000 *
                        (mtime_t)p_demux->i_samplelength /
Index: src/input/input.c
===================================================================
RCS file: /var/cvs/videolan/vlc/src/input/input.c,v
retrieving revision 1.230
diff -u -r1.230 input.c
--- src/input/input.c	22 May 2003 16:01:02 -0000	1.230
+++ src/input/input.c	26 May 2003 22:28:53 -0000
@@ -84,6 +84,7 @@

      /* Demux */
      p_input->p_demux = NULL;
+    p_input->pf_setdemuxoptions = NULL;

      /* Access */
      p_input->p_access = NULL;
@@ -134,6 +135,8 @@
      p_input->stream.control.i_rate = DEFAULT_RATE;
      p_input->stream.control.b_mute = 0;
      p_input->stream.control.b_grayscale = config_GetInt( p_input,  
"grayscale" );
+    p_input->stream.control.i_packet_skip_rate = 1;
+    p_input->stream.control.i_frame_skip_rate = 0;

      /* Initialize input info */
      p_input->stream.p_info = malloc( sizeof( input_info_category_t ) );
@@ -335,6 +338,20 @@

              p_input->stream.b_new_mute = MUTE_NO_CHANGE;
          }
+
+        /* Set demux options (if we need to ff / rew or not, for  
instance */
+
+        #define A p_input->stream
+
+        if ( p_input->pf_setdemuxoptions )
+        {
+            p_input->pf_setdemuxoptions( p_input,
+                                         A.control.i_packet_skip_rate,
+                                         A.control.i_frame_skip_rate,
+                                         10 );
+        }
+
+        #undef A

          vlc_mutex_unlock( &p_input->stream.stream_lock );

Index: src/input/input_clock.c
===================================================================
RCS file: /var/cvs/videolan/vlc/src/input/input_clock.c,v
retrieving revision 1.37
diff -u -r1.37 input_clock.c
--- src/input/input_clock.c	22 May 2003 16:01:02 -0000	1.37
+++ src/input/input_clock.c	26 May 2003 22:28:56 -0000
@@ -188,7 +188,10 @@
          ClockNewRef( p_pgrm, i_clock,
                       ClockToSysdate( p_input, p_pgrm, i_clock ) );

-        if( p_input->stream.control.i_status == PLAYING_S )
+        if( p_input->stream.control.i_status == PLAYING_S ||
+            p_input->stream.control.i_status == REWIND_S ||
+            p_input->stream.control.i_status == FORWARD_S )
+
          {
              p_input->stream.control.i_rate = DEFAULT_RATE;
              p_input->stream.control.b_mute = 0;
Index: src/input/input_ext-intf.c
===================================================================
RCS file: /var/cvs/videolan/vlc/src/input/input_ext-intf.c,v
retrieving revision 1.49
diff -u -r1.49 input_ext-intf.c
--- src/input/input_ext-intf.c	4 May 2003 22:42:17 -0000	1.49
+++ src/input/input_ext-intf.c	26 May 2003 22:28:59 -0000
@@ -52,6 +52,84 @@

      switch( i_mode )
      {
+    case INPUT_STATUS_FASTFORWARD_TS:
+        if ( p_input->stream.control.i_packet_skip_rate ==  
MAX_FF_REW_SKIP )
+        {
+            msg_Dbg( p_input, "can't do packet-skipping fast-forward  
any faster" );
+        }
+        else
+        {
+            p_input->stream.control.i_packet_skip_rate ++;
+
+            if ( p_input->stream.control.i_packet_skip_rate == 0 )
+            {
+                p_input->stream.control.i_packet_skip_rate ++;
+            }
+
+            p_input->stream.i_new_status = FORWARD_S;
+        }
+        break;
+
+    case INPUT_STATUS_REWIND_TS:
+        if ( p_input->stream.control.i_packet_skip_rate == 0 -  
MAX_FF_REW_SKIP )
+        {
+            msg_Dbg( p_input, "can't do packet-skipping rewind any  
faster" );
+        }
+        else
+        {
+            p_input->stream.control.i_packet_skip_rate --;
+
+            if ( p_input->stream.control.i_packet_skip_rate == 0 )
+            {
+                p_input->stream.control.i_packet_skip_rate --;
+            }
+
+            p_input->stream.i_new_status = REWIND_S;
+        }
+        break;
+
+    case INPUT_STATUS_FASTFORWARD_FS:
+
+        if ( p_input->stream.control.i_frame_skip_rate ==  
MAX_FF_REW_SKIP )
+        {
+            msg_Dbg( p_input, "can't do frame-skipping fast-forward  
any faster" );
+        }
+        else
+        {
+            p_input->stream.control.i_frame_skip_rate ++;
+
+            if ( p_input->stream.control.i_frame_skip_rate == 0 )
+            {
+                p_input->stream.control.i_frame_skip_rate ++;
+            }
+
+            p_input->stream.p_selected_area->i_seek = 1;
+            p_input->stream.i_new_status = FORWARD_S;
+        }
+
+        break;
+
+    case INPUT_STATUS_REWIND_FS:
+
+        if ( p_input->stream.control.i_frame_skip_rate == 0 -  
MAX_FF_REW_SKIP )
+        {
+            msg_Dbg( p_input, "can't do frame-skipping rewind any  
faster" );
+        }
+        else
+        {
+            p_input->stream.control.i_frame_skip_rate --;
+
+            if ( p_input->stream.control.i_frame_skip_rate == 0 )
+            {
+                p_input->stream.control.i_frame_skip_rate --;
+            }
+
+            p_input->stream.p_selected_area->i_seek = 1;
+            p_input->stream.i_new_status = REWIND_S;
+        }
+
+        break;
+
      case INPUT_STATUS_END:
          p_input->stream.i_new_status = PLAYING_S;
          p_input->b_eof = 1;
@@ -60,6 +138,8 @@

      case INPUT_STATUS_PLAY:
          p_input->stream.i_new_status = PLAYING_S;
+        p_input->stream.control.i_packet_skip_rate = 1;
+        p_input->stream.control.i_frame_skip_rate = 0;
          msg_Dbg( p_input, "playing at normal rate" );
          break;




> Just send it to the list, or send a link to a download location (even  
> better).

Regards,

John

Falling You - exploring the beauty of voice and sound
New EP, "hope thrown down," available now at
http://www.mp3.com/fallingyou











-- 
This is the vlc-devel mailing-list, see http://www.videolan.org/vlc/
To unsubscribe, please read http://developers.videolan.org/lists.html
If you are in trouble, please contact <postmaster at videolan.org>



More information about the vlc-devel mailing list