[MPlayer-dev-eng] [PATCH] ffw-av - interactive fastforward/slow with audio speed adjust (1st draft)

Steven Mueller diffusor at ugcs.caltech.edu
Wed Sep 10 11:07:16 CEST 2003


Hello,

Here is a first attempt at a live interactive fast/slow-forward patch
that also modifies the speed of sound playback to (approximately)
match the video playback rate.   It applies cleanly against current
cvs as of the time of writing.  It's still rather quirky, owing to my
not quite understanding the A-V sync structure and the various audio
output layers, and possibly due to limitations in the demuxers as
postulated below.  I've implemented sound output reinitialization
to scale the sample rate, but I'm not sure if what I did was kosher,
so I'd appreciate a few eyes on it.

The patch adds three new mappable commands for input.conf:

speed_set  float     set the playback rate.  1.0 is normal speed
speed_mult float     multiply the current speed (positive only)
speed_incr float     increment the current speed (can be negative)

Default keyboard mappings:
[, ]    Decrease/increase the speed by a small factor (= 1.1)
{, }    Decrease/increase the speed by a large factor (= 2)
Backspace	Reset the speed to normal

The playback_speed is implemented using the infrastructure for the
-speed commandline argument, so the allowable range is .01 to 100.

Caveats:

1.
Not all sound drivers can accelerate the sound speed past a certain
sample rate.  Some also hold back the video speed.  (For example,
alsa9 on my system on certain divx files limits the playback rate to
1.0.  However, the OSS emulation of my alsa driver does not suffer the
same problem...  The divx5.0 files from www.redvsblue.com
exhibit this behavior, for example.)

One can sort of work around this by specifying "-aop list=resample" on
the commandline.  This causes the speed modifications to apply to the
resample audio plugin, and therefore uses more cpu but can have a
wider range of possibilities.  It also will not limit the video
playback rate as far as I've seen.  However (this is a big however!)
increasing or decreasing the speed too much can cause the A-V sync to
go very out of control.  Using "-mc 10" can slightly alleviate this
problem, but only to a certain extent (about 5x on my 1.3 ghz tbird).

Every time I change the speed, alsa9 reports the same samplerate
(48000) until I increase the speed too high (~10x), at which point the
debug message suddenly shows the resampling being applied to the alsa
chain directly and the sound reverts to 1x speed.

Of course, this problem also happens with the -speed commandline
option.

2.
Changing the speed rate can cause minor jumps in the video file.  On
some files (notably quicktime and wmv), the movie is sped up for a
short moment so that you miss a half second or so, regardless of
whether you're slowing way down or speeding way up.

Note that this phenomenon occurs when pausing and resuming in normal
speed playback as well, so I'm thinking this could be limitations with
the individual codecs' demuxers rather than with the way I
reinitialize the sound.

3.
Using a very low speed can make mplayer very unresponsive, since
mplayer can only accept one command per rendered frame...

4.
The speed display at the end of the status display line only appears
when both audio and video are being played, but I'm not sure this
field is good anyway since it easily puts the line length at more than
80 characters.  Regardless, I can easily add it to the
audio/video-only lines if anyone is interested.  Another option would
be to make it display the speed only when it is not 1x (which I kinda
like best, actually...)

TODO:
* Add an OSD to display the new speed for a short while whenever it's
  changed (and the osd level is high enough)
* Display speed on status line iff playback_speed != 1.0 +/- delta
* Add an option to partially mute the sound volume a given amount
  whenever the speed is not exactly 1.0x (or maybe there should be
  some (configurable?) tolerance?)
* Write proper documentation (changes to manpage and DOC files)
* Examine the play loop more closely to determine whether the skips of
  accelerated playback in certain videos (as described above) can be
  avoided, and perhaps get the audio to more instantaneously sync, too...

Anyway, I hope people find it useful, and I hope to get it to a point
where it can be included in mplayer.  After writing the bulk of the
patch, I discovered the following thread in the archives, so I'm
hoping there's still a bit of interest:

http://mplayerhq.hu/pipermail/mplayer-dev-eng/2003-February/015835.html

Thanks,
Steve

PS - Sorry for the excessively long description.  :)

-- 
Steven Mueller
diffusor at ugcs.caltech.edu
-------------- next part --------------
mplayer_ffw-av.patch - interactive fastforward and slowforward

patch author: Steven Mueller <diffusor at ugcs.caltech.edu>
Last Modified: September 09, 2003 13:22 Tuesday -0700

Licencse:
This modification to mplayer is released under the same terms as
mplayer's license, of course.  See main/LICENSE in the mplayer cvs
tree.


Index: mplayer.c
===================================================================
RCS file: /cvsroot/mplayer/main/mplayer.c,v
retrieving revision 1.725
diff -u -r1.725 mplayer.c
--- mplayer.c	29 Aug 2003 21:41:03 -0000	1.725
+++ mplayer.c	9 Sep 2003 20:01:14 -0000
@@ -703,6 +703,29 @@
 #include <SDL.h>
 #endif
 
+// reinit to get the audio scaled to a new playback_speed
+void reinit_audio_speed(sh_audio_t *sh_audio, ao_functions_t *audio_out, ao_data_t *ao_data)
+{
+    if(sh_audio) {
+	audio_out->reset(); // stop audio, throwing away buffered data
+	audio_out->uninit();
+	ao_data->samplerate=force_srate?force_srate:sh_audio->samplerate*playback_speed;
+	audio_out->init(ao_data->samplerate,
+		audio_output_channels?audio_output_channels:ao_data->channels,
+		audio_output_format?audio_output_format:ao_data->format,0);
+	//	  rel_seek_secs-= 0.01;  // causes bad behavior on media with keyframes
+	resync_audio_stream(sh_audio);
+    }
+}
+
+// return the closest acceptable speed to that requested
+float bound_play_speed(float requested_speed)
+{
+    if( requested_speed < 0.01 ) return 0.01;
+    else if( requested_speed > 100.0 ) return 100.0;
+    else return requested_speed;
+}
+
 
 int main(int argc,char* argv[]){
 
@@ -2312,7 +2335,7 @@
         else
           max_pts_correction=sh_video->frametime*0.10; // +-10% of time
 	if(!frame_time_remaining){ sh_audio->delay+=x; c_total+=x;} // correction
-        if(!quiet) mp_msg(MSGT_AVSYNC,MSGL_STATUS,"A:%6.1f V:%6.1f A-V:%7.3f ct:%7.3f  %3d/%3d  %2d%% %2d%% %4.1f%% %d %d %d%%\r",
+        if(!quiet) mp_msg(MSGT_AVSYNC,MSGL_STATUS,"A:%6.1f V:%6.1f A-V:%7.3f ct:%7.3f  %3d/%3d  %2d%% %2d%% %4.1f%% %d %d %d%% %6.2fx    \r",
 	  a_pts-audio_delay-delay,v_pts,AV_delay,c_total,
           (int)sh_video->num_frames,(int)sh_video->num_frames_decoded,
           (sh_video->timer>0.5)?(int)(100.0*video_time_usage*playback_speed/(double)sh_video->timer):0,
@@ -2321,6 +2344,7 @@
           ,drop_frame_cnt
 	  ,output_quality
 	  ,cache_fill_status
+	  ,playback_speed
         );
         fflush(stdout);
       }
@@ -2509,6 +2533,21 @@
       audio_delay += v;
       osd_show_av_delay = 9;
       if(sh_audio) sh_audio->delay+= v;
+    } break;
+    case MP_CMD_SPEED_INCR : {
+      float v = cmd->args[0].v.f;
+      playback_speed = bound_play_speed(playback_speed + v);
+      reinit_audio_speed(sh_audio, audio_out, &ao_data);
+    } break;
+    case MP_CMD_SPEED_MULT : {
+      float v = cmd->args[0].v.f;
+      playback_speed = bound_play_speed(playback_speed * v);
+      reinit_audio_speed(sh_audio, audio_out, &ao_data);
+    } break;
+    case MP_CMD_SPEED_SET : {
+      float v = cmd->args[0].v.f;
+      playback_speed = bound_play_speed(v);
+      reinit_audio_speed(sh_audio, audio_out, &ao_data);
     } break;
     case MP_CMD_PAUSE : {
       osd_function=OSD_PAUSE;
Index: etc/input.conf
===================================================================
RCS file: /cvsroot/mplayer/main/etc/input.conf,v
retrieving revision 1.10
diff -u -r1.10 input.conf
--- etc/input.conf	5 May 2003 03:13:43 -0000	1.10
+++ etc/input.conf	9 Sep 2003 20:01:17 -0000
@@ -15,6 +15,11 @@
 PGDWN seek -600
 - audio_delay 0.100
 + audio_delay -0.100
+[ speed_mult 0.9091	# scale playback speed
+] speed_mult 1.1
+{ speed_mult 0.5
+} speed_mult 2.0
+BS speed_set 1.0	# reset speed to normal
 q quit
 ESC quit
 ENTER pt_step 1 1
Index: input/input.c
===================================================================
RCS file: /cvsroot/mplayer/main/input/input.c,v
retrieving revision 1.84
diff -u -r1.84 input.c
--- input/input.c	2 Sep 2003 17:44:38 -0000	1.84
+++ input/input.c	9 Sep 2003 20:01:21 -0000
@@ -55,6 +55,9 @@
   { MP_CMD_EDL_MARK, "edl_mark", 0, { {-1,{0}} } },
 #endif
   { MP_CMD_AUDIO_DELAY, "audio_delay", 1, { {MP_CMD_ARG_FLOAT,{0}}, {-1,{0}} } },
+  { MP_CMD_SPEED_INCR, "speed_incr", 1, { {MP_CMD_ARG_FLOAT,{0}}, {-1,{0}} } },
+  { MP_CMD_SPEED_MULT, "speed_mult", 1, { {MP_CMD_ARG_FLOAT,{0}}, {-1,{0}} } },
+  { MP_CMD_SPEED_SET, "speed_set", 1, { {MP_CMD_ARG_FLOAT,{0}}, {-1,{0}} } },
   { MP_CMD_QUIT, "quit", 0, { {-1,{0}} } },
   { MP_CMD_PAUSE, "pause", 0, { {-1,{0}} } },
   { MP_CMD_GRAB_FRAMES, "grab_frames",0, { {-1,{0}} }  },
@@ -258,6 +261,11 @@
   { { KEY_PAGE_DOWN, 0 }, "seek -600" },
   { { '-', 0 }, "audio_delay 0.100" },
   { { '+', 0 }, "audio_delay -0.100" },
+  { { '[', 0 }, "speed_mult 0.9091" },
+  { { ']', 0 }, "speed_mult 1.1" },
+  { { '{', 0 }, "speed_mult 0.5" },
+  { { '}', 0 }, "speed_mult 2.0" },
+  { { KEY_BACKSPACE, 0 }, "speed_set 1.0" },
   { { 'q', 0 }, "quit" },
   { { KEY_ESC, 0 }, "quit" },
 #ifndef HAVE_NEW_GUI
Index: input/input.h
===================================================================
RCS file: /cvsroot/mplayer/main/input/input.h,v
retrieving revision 1.36
diff -u -r1.36 input.h
--- input/input.h	12 Aug 2003 13:22:35 -0000	1.36
+++ input/input.h	9 Sep 2003 20:01:21 -0000
@@ -50,6 +50,11 @@
 #define MP_CMD_TV_SET_HUE 46
 #define MP_CMD_TV_SET_SATURATION 47
 
+/* Speed mod commands */
+#define MP_CMD_SPEED_INCR 48
+#define MP_CMD_SPEED_MULT 49
+#define MP_CMD_SPEED_SET 50
+
 #define MP_CMD_GUI_EVENTS       5000
 #define MP_CMD_GUI_LOADFILE     5001
 #define MP_CMD_GUI_LOADSUBTITLE 5002
Index: libvo/wskeys.h
===================================================================
RCS file: /cvsroot/mplayer/main/libvo/wskeys.h,v
retrieving revision 1.6
diff -u -r1.6 wskeys.h
--- libvo/wskeys.h	9 Apr 2003 17:05:35 -0000	1.6
+++ libvo/wskeys.h	9 Sep 2003 20:01:27 -0000
@@ -4,6 +4,8 @@
 
 #define wsosbrackets '['
 #define wscsbrackets ']'
+#define wsocbraces   '{'
+#define wsccbraces   '}'
 
 #define wsq 'q'
 #define wsa 'a'
Index: libvo/x11_common.c
===================================================================
RCS file: /cvsroot/mplayer/main/libvo/x11_common.c,v
retrieving revision 1.155
diff -u -r1.155 x11_common.c
--- libvo/x11_common.c	2 Sep 2003 14:39:02 -0000	1.155
+++ libvo/x11_common.c	9 Sep 2003 20:01:32 -0000
@@ -492,6 +492,10 @@
    case wsDiv:       mplayer_put_key('/'); break;
    case wsLess:      mplayer_put_key('<'); break;
    case wsMore:      mplayer_put_key('>'); break;
+   case wsosbrackets: mplayer_put_key('['); break;
+   case wscsbrackets: mplayer_put_key(']'); break;
+   case wsocbraces:  mplayer_put_key('{'); break;
+   case wsccbraces:  mplayer_put_key('}'); break;
    case wsGray0:     mplayer_put_key(KEY_KP0); break;
    case wsGrayEnd:
    case wsGray1:     mplayer_put_key(KEY_KP1); break;


More information about the MPlayer-dev-eng mailing list