changeset 13710:d7af73cc38da

allow changing playback speed during playback. Based on patch by Steve Mueller (diffusor <at> ugcs (dot) caltech [dot] edu), OSD support by Frank Schertan (scherthan (at) uni-landau <dot> de), several modifications by me.
author reimar
date Wed, 20 Oct 2004 20:07:50 +0000
parents 3bf608c6e34c
children eb70cfbc7aa2
files AUTHORS DOCS/man/de/mplayer.1 DOCS/man/en/mplayer.1 DOCS/tech/slave.txt DOCS/xml/en/usage.xml etc/input.conf input/input.c input/input.h mplayer.c
diffstat 9 files changed, 108 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/AUTHORS	Wed Oct 20 18:32:07 2004 +0000
+++ b/AUTHORS	Wed Oct 20 20:07:50 2004 +0000
@@ -194,6 +194,8 @@
 
 Döffinger, Reimar (reimar) <reimar.doeffinger@stud.uni-karlsruhe.de>
     * GL code fixes
+    * various fixes all over the place
+    * reworked live changing playback speed
 
 Dolbeau, Romain <romain@dolbeau.org>
     * random AltiVec (PowerPC multimedia extensions) stuff
@@ -523,6 +525,9 @@
     * various docs updates and fixes
     * 1st half of the documentation HTML --> XML conversion
 
+Mueller, Steven <diffusor@ugcs.caltech.edu>
+    * first implementation of live changing playback speed
+
 MPlayerPL - Polish MPlayer Translation Team (http://mplayerpl.emdej.com)
     * Waclaw Schiller (Torinthiel) <torinthiel@wp.pl>
     * Kuba Misiorny (Qba) <jim85@wp.pl>
@@ -620,6 +625,9 @@
 Sauerbeck, Tilman <tsauerbeck@users.sourceforge.net>
     * TGA decoder (RLE/uncomp), -mf tga support
 
+Scherthan, Frank <scherthan@uni-landau.de>
+    * added OSD handling for live changing playback speed
+
 Schneider, Florian <flo-mplayer-dev@gmx.net>
     * RealVideo codec libraries interface, .rm demuxer fixes
 
--- a/DOCS/man/de/mplayer.1	Wed Oct 20 18:32:07 2004 +0000
+++ b/DOCS/man/de/mplayer.1	Wed Oct 20 20:07:50 2004 +0000
@@ -227,6 +227,12 @@
 Springe 1 Minute zurück/\:vor.
 .IPs "BildHoch und BildRunter (bzw.\& PGUP/\:PGDOWN)"
 Springe 10 Minuten zurück/\:vor.
+.IPs "[ und ]"
+Verringert/erhöht die Abspielgeschwindigkeit um 10%.
+.IPs "{ und }"
+Halbiert/verdoppelt die Abspielgeschwindigkeit.
+.IPs "Löschen (Backspace)"
+Setzt die Abspielgeschwindigkeit zurück.
 .IPs "< und >"
 zurück\:vor in der Playlist
 .IPs "Pos1 und Ende"
--- a/DOCS/man/en/mplayer.1	Wed Oct 20 18:32:07 2004 +0000
+++ b/DOCS/man/en/mplayer.1	Wed Oct 20 20:07:50 2004 +0000
@@ -219,6 +219,12 @@
 Seek backward/\:forward 1 minute.
 .IPs "pgup and pgdown"
 Seek backward/\:forward 10 minutes.
+.IPs "[ and ]"
+Decreases/increases current playback speed by 10%.
+.IPs "{ and }"
+Halves/doubles current playback speed.
+.IPs "Backspace"
+Reset playback speed to normal.
 .IPs "< and >"
 backward/\:forward in playlist
 .IPs "HOME and END"
--- a/DOCS/tech/slave.txt	Wed Oct 20 18:32:07 2004 +0000
+++ b/DOCS/tech/slave.txt	Wed Oct 20 20:07:50 2004 +0000
@@ -15,6 +15,15 @@
         1 is a seek to <value> % in the movie.
         2 is a seek to an absolute position of <value> seconds.
 
+speed_set <value>
+    Set the speed to <value>.
+
+speed_incr <value>
+    Add <value> to the current playback speed.
+
+speed_mult <value>
+    Multiply the current speed with <value>.
+
 edl_mark
     ???
 
--- a/DOCS/xml/en/usage.xml	Wed Oct 20 18:32:07 2004 +0000
+++ b/DOCS/xml/en/usage.xml	Wed Oct 20 20:07:50 2004 +0000
@@ -221,6 +221,18 @@
   Type <literal>0</literal> is a relative seek of +/- val seconds.
   Type <literal>1</literal> seek to val % in the movie.
   </para></listitem>
+<listitem><para><literal>speed_mult</literal> (float) val</para>
+  <para>
+  Multiply the current speed with val.
+  </para></listitem>
+<listitem><para><literal>speed_incr</literal> (float) val</para>
+  <para>
+  Add val to the current playback speed.
+  </para></listitem>
+<listitem><para><literal>speed_set</literal> (float) val</para>
+  <para>
+  Set the speed to val.
+  </para></listitem>
 <listitem><para><literal>audio_delay</literal> (float) val</para>
   <para>
   Adjust the audio delay of val seconds
--- a/etc/input.conf	Wed Oct 20 18:32:07 2004 +0000
+++ b/etc/input.conf	Wed Oct 20 20:07:50 2004 +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
--- a/input/input.c	Wed Oct 20 18:32:07 2004 +0000
+++ b/input/input.c	Wed Oct 20 20:07:50 2004 +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, { {MP_CMD_ARG_INT,{0}}, {-1,{0}} } },
   { MP_CMD_PAUSE, "pause", 0, { {-1,{0}} } },
   { MP_CMD_FRAME_STEP, "frame_step", 0, { {-1,{0}} } },
@@ -270,6 +273,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
--- a/input/input.h	Wed Oct 20 18:32:07 2004 +0000
+++ b/input/input.h	Wed Oct 20 20:07:50 2004 +0000
@@ -58,6 +58,9 @@
 #define MP_CMD_SWITCH_VSYNC 54
 #define MP_CMD_SWITCH_RATIO 55
 #define MP_CMD_FRAME_STEP 56
+#define MP_CMD_SPEED_INCR 57
+#define MP_CMD_SPEED_MULT 58
+#define MP_CMD_SPEED_SET 59
 
 #define MP_CMD_GUI_EVENTS       5000
 #define MP_CMD_GUI_LOADFILE     5001
--- a/mplayer.c	Wed Oct 20 18:32:07 2004 +0000
+++ b/mplayer.c	Wed Oct 20 20:07:50 2004 +0000
@@ -756,6 +756,31 @@
 #include <SDL.h>
 #endif
 
+/**
+ * \brief build a chain of audio filters that converts the input format
+ * to the ao's format, taking into account the current playback_speed.
+ * \param sh_audio describes the requested input format of the chain.
+ * \param ao_data describes the requested output format of the chain.
+ */
+static int build_afilter_chain(sh_audio_t *sh_audio, ao_data_t *ao_data)
+{
+  int new_srate = sh_audio->samplerate * playback_speed;
+  if (!sh_audio)
+    return 0;
+  if (new_srate != ao_data->samplerate) {
+    // limits are taken from libaf/af_resample.c
+    if (new_srate < 8000)
+      new_srate = 8000;
+    if (new_srate > 192000)
+      new_srate = 192000;
+    playback_speed = (float)new_srate / (float)sh_audio->samplerate;
+  }
+  return init_audio_filters(sh_audio, new_srate,
+           sh_audio->channels, sh_audio->sample_format, sh_audio->samplesize,
+           ao_data->samplerate, ao_data->channels, ao_data->format,
+           audio_out_format_bits(ao_data->format) / 8, /* ao_data.bps, */
+           ao_data->outburst * 4, ao_data->buffersize);
+}
 
 int main(int argc,char* argv[]){
 
@@ -776,6 +801,7 @@
 int osd_last_pts=-303;
 int osd_show_av_delay = 0;
 int osd_show_text = 0;
+int osd_show_speed = 0;
 int osd_show_sub_delay = 0;
 int osd_show_sub_pos = 0;
 int osd_show_sub_visibility = 0;
@@ -1927,12 +1953,7 @@
     // init audio filters:
 #if 1
     current_module="af_init";
-    if(!init_audio_filters(sh_audio, 
-        (int)(sh_audio->samplerate*playback_speed),
-	sh_audio->channels, sh_audio->sample_format, sh_audio->samplesize,
-	ao_data.samplerate, ao_data.channels, ao_data.format,
-	audio_out_format_bits(ao_data.format)/8, /* ao_data.bps, */
-	ao_data.outburst*4, ao_data.buffersize)){
+    if(!build_afilter_chain(sh_audio, &ao_data)) {
       mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_NoMatchingFilter);
 //      mp_msg(MSGT_CPLAYER,MSGL_ERR,"Couldn't find matching filter / ao format! -> NOSOUND\n");
 //      uninit_player(INITED_ACODEC|INITED_AO); // close codec & ao
@@ -2085,7 +2106,7 @@
       if ((' ' == hhmmssf[6]) && (' ' != hhmmssf[5])) {
         hhmmssf[6] = '0';
       }
-             mp_msg(MSGT_AVSYNC,MSGL_STATUS,"A:  %s %4.1f%% %d%%   \r"
+             mp_msg(MSGT_AVSYNC,MSGL_STATUS,"A:  %s %4.1f%% %d%% %4.2fx  \r"
 		    ,hhmmssf
 		    ,(sh_audio->delay>0.5)?100.0*audio_time_usage/(double)sh_audio->delay:0
 		    ,cache_fill_status
@@ -2385,7 +2406,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%% %4.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,
@@ -2394,6 +2415,7 @@
           ,drop_frame_cnt
 	  ,output_quality
 	  ,cache_fill_status
+	  ,playback_speed
         );
         fflush(stdout);
       }
@@ -2597,6 +2619,24 @@
       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 += v;
+      osd_show_speed = sh_video->fps;
+      build_afilter_chain(sh_audio, &ao_data);
+    } break;
+    case MP_CMD_SPEED_MULT : {
+      float v = cmd->args[0].v.f;
+      playback_speed *= v;
+      osd_show_speed = sh_video->fps;
+      build_afilter_chain(sh_audio, &ao_data);
+    } break;
+    case MP_CMD_SPEED_SET : {
+      float v = cmd->args[0].v.f;
+      playback_speed = v;
+      osd_show_speed = sh_video->fps;
+      build_afilter_chain(sh_audio, &ao_data);
+    } break;
     case MP_CMD_FRAME_STEP :
     case MP_CMD_PAUSE : {
       osd_function=OSD_PAUSE;
@@ -3791,6 +3831,9 @@
       if (osd_show_av_delay) {
 	  snprintf(osd_text_tmp, 63, "A-V delay: %d ms", ROUND(audio_delay*1000));
 	  osd_show_av_delay--;
+      } else if (osd_show_speed) {
+	  snprintf(osd_text_tmp, 63, "Speed: x %6.2f", playback_speed);
+	  osd_show_speed--;
       } else if (osd_show_ontop) {
 	  snprintf(osd_text_tmp, 63, "Stay on top: %sabled", vo_ontop?"en":"dis");
 	  osd_show_ontop--;