[FFmpeg-devel] [PATCH] ffplay: add support for interactive volume control

Ganesh Ajjanagadde gajjanagadde at gmail.com
Sat Sep 26 16:47:36 CEST 2015


This is a feature heavily inspired by the mpv player. At the moment, methods
for adjusting volume in ffplay are rather clumsy: either one needs to set it
system-wide, or one needs to set it via the volume filter.

This patch adds key bindings identical to the mpv defaults for muting/unmuting
and increasing/decreasing the volume interactively without any introduction of
external dependencies.

Key repeats have been introduced simply because they improve usability
in my experience for volume, brightness, and other such controls by speeding up
the time taken to go from 0 to max intensity. As a side benefit, this enables
rapid seeking through a file via left/right keys.

TODO: doc update, possible mouse button bindings (mpv has this).

Signed-off-by: Ganesh Ajjanagadde <gajjanagadde at gmail.com>
---
 ffplay.c | 44 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 43 insertions(+), 1 deletion(-)

diff --git a/ffplay.c b/ffplay.c
index d302793..4f3322b 100644
--- a/ffplay.c
+++ b/ffplay.c
@@ -73,6 +73,9 @@ const int program_birth_year = 2003;
 /* Calculate actual buffer size keeping in mind not cause too frequent audio callbacks */
 #define SDL_AUDIO_MAX_CALLBACKS_PER_SEC 30
 
+/* Step size for volume control */
+#define SDL_VOLUME_STEP 2
+
 /* no AV sync correction is done if below the minimum AV sync threshold */
 #define AV_SYNC_THRESHOLD_MIN 0.04
 /* AV sync correction is done if above the maximum AV sync threshold */
@@ -246,6 +249,8 @@ typedef struct VideoState {
     unsigned int audio_buf1_size;
     int audio_buf_index; /* in bytes */
     int audio_write_buf_size;
+    int audio_volume;
+    int muted;
     struct AudioParams audio_src;
 #if CONFIG_AVFILTER
     struct AudioParams audio_filter_src;
@@ -1348,6 +1353,25 @@ static void toggle_pause(VideoState *is)
     is->step = 0;
 }
 
+static void toggle_mute(VideoState *is)
+{
+    is->muted = !is->muted;
+}
+
+static void update_volume(VideoState *is, int sign, int step)
+{
+    if (sign > 0) {
+        is->audio_volume += step;
+        if (is->audio_volume > SDL_MIX_MAXVOLUME)
+            is->audio_volume = SDL_MIX_MAXVOLUME;
+    }
+    else {
+        is->audio_volume -= step;
+        if (is->audio_volume < 0)
+            is->audio_volume = 0;
+    }
+}
+
 static void step_to_next_frame(VideoState *is)
 {
     /* if the stream is paused unpause it, then step */
@@ -2447,7 +2471,10 @@ static void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
         len1 = is->audio_buf_size - is->audio_buf_index;
         if (len1 > len)
             len1 = len;
-        memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);
+        if (is->muted)
+            SDL_MixAudio(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1, 0);
+        else
+            SDL_MixAudio(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1, is->audio_volume);
         len -= len1;
         stream += len1;
         is->audio_buf_index += len1;
@@ -2634,6 +2661,8 @@ static int stream_component_open(VideoState *is, int stream_index)
         is->audio_src = is->audio_tgt;
         is->audio_buf_size  = 0;
         is->audio_buf_index = 0;
+        is->audio_volume = SDL_MIX_MAXVOLUME;
+        is->muted = 0;
 
         /* init averaging filter */
         is->audio_diff_avg_coef  = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
@@ -3311,6 +3340,17 @@ static void event_loop(VideoState *cur_stream)
             case SDLK_SPACE:
                 toggle_pause(cur_stream);
                 break;
+            case SDLK_m:
+                toggle_mute(cur_stream);
+                break;
+            case SDLK_ASTERISK:
+            case SDLK_0:
+                update_volume(cur_stream, 1, SDL_VOLUME_STEP);
+                break;
+            case SDLK_SLASH:
+            case SDLK_9:
+                update_volume(cur_stream, -1, SDL_VOLUME_STEP);
+                break;
             case SDLK_s: // S: Step to next frame
                 step_to_next_frame(cur_stream);
                 break;
@@ -3740,6 +3780,8 @@ int main(int argc, char **argv)
     SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
     SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
 
+    SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
+
     if (av_lockmgr_register(lockmgr)) {
         av_log(NULL, AV_LOG_FATAL, "Could not initialize lock manager!\n");
         do_exit(NULL);
-- 
2.5.3



More information about the ffmpeg-devel mailing list