[FFmpeg-devel] [PATCH] Add ability to pause transcoding via keyboard interaction

Jeremy Luce jeremyluce at gmail.com
Wed Mar 11 14:34:39 CET 2015


Resubmitting with [PATCH] tag and unified diff.

Adds functionality to pause transcoding with 'p' key and upause with 'u'
key over stdin. Pauses in the main transcode loop as well as the
input_thread loop.

-----------------

diff --git a/ffmpeg.c b/ffmpeg.c
index 6604ff0..37b351a 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -120,6 +120,9 @@ const char *const forced_keyframes_const_names[] = {
 static void do_video_stats(OutputStream *ost, int frame_size);
 static int64_t getutime(void);
 static int64_t getmaxrss(void);
+static int64_t gettime_relative_minus_pause(void);
+static void pause_transcoding(void);
+static void unpause_transcoding(void);

 static int run_as_daemon  = 0;
 static int nb_frames_dup = 0;
@@ -146,6 +149,9 @@ int         nb_output_files   = 0;
 FilterGraph **filtergraphs;
 int        nb_filtergraphs;

+int64_t paused_start = 0;
+int64_t paused_time = 0;
+
 #if HAVE_TERMIOS_H

 /* init terminal so that we can grab keys */
@@ -1447,7 +1453,6 @@ static void print_report(int is_last_report,
int64_t timer_start, int64_t cur_ti
         last_time = cur_time;
     }

-
     oc = output_files[0]->ctx;

     total_size = avio_size(oc->pb);
@@ -3256,18 +3261,38 @@ static OutputStream *choose_output(void)
     return ost_min;
 }

+static void pause_transcoding(void)
+{
+    if (!paused_start)
+        paused_start = av_gettime_relative();
+}
+
+static void unpause_transcoding(void)
+{
+    if (paused_start) {
+        paused_time += av_gettime_relative() - paused_start;
+        paused_start = 0;
+    }
+}
+
 static int check_keyboard_interaction(int64_t cur_time)
 {
     int i, ret, key;
     static int64_t last_time;
-    if (received_nb_signals)
+    if (received_nb_signals) {
+        unpause_transcoding();
         return AVERROR_EXIT;
+    }
     /* read_key() returns 0 on EOF */
     if(cur_time - last_time >= 100000 && !run_as_daemon){
         key =  read_key();
         last_time = cur_time;
     }else
         key = -1;
+    // Reserve 'u' for unpausing a paused transcode, but allow any key to
+    // unpause for backward compatibility
+    if (key == 'u' || key != -1) unpause_transcoding();
+    if (key == 'p') pause_transcoding();
     if (key == 'q')
         return AVERROR_EXIT;
     if (key == '+') av_log_set_level(av_log_get_level()+10);
@@ -3346,7 +3371,9 @@ static int check_keyboard_interaction(int64_t cur_time)
                         "C      Send/Que command to all matching filters\n"
                         "D      cycle through available debug modes\n"
                         "h      dump packets/hex press to cycle
through the 3 states\n"
+                        "p      pause transcoding\n"
                         "q      quit\n"
+                        "u      unpause transcoding\n"
                         "s      Show QP histogram\n"
         );
     }
@@ -3361,6 +3388,10 @@ static void *input_thread(void *arg)
     int ret = 0;

     while (1) {
+        if (paused_start) {
+            av_usleep(1000); // Be more responsive to unpausing than
main thread
+            continue;
+        }
         AVPacket pkt;
         ret = av_read_frame(f->ctx, &pkt);

@@ -3778,6 +3809,11 @@ static int transcode_step(void)
     InputStream  *ist;
     int ret;

+    if (paused_start) {
+        av_usleep(10000);
+        return 0;
+    }
+
     ost = choose_output();
     if (!ost) {
         if (got_eagain()) {
@@ -3838,11 +3874,11 @@ static int transcode(void)
 #endif

     while (!received_sigterm) {
-        int64_t cur_time= av_gettime_relative();
+        int64_t cur_time = gettime_relative_minus_pause();

         /* if 'q' pressed, exits */
         if (stdin_interaction)
-            if (check_keyboard_interaction(cur_time) < 0)
+            if (check_keyboard_interaction(av_gettime_relative()) < 0)
                 break;

         /* check if there's any stream where output is still needed */
@@ -3885,7 +3921,7 @@ static int transcode(void)
     }

     /* dump report by using the first video and audio streams */
-    print_report(1, timer_start, av_gettime_relative());
+    print_report(1, timer_start, gettime_relative_minus_pause());

     /* close each encoder */
     for (i = 0; i < nb_output_streams; i++) {
@@ -3934,6 +3970,11 @@ static int transcode(void)
     return ret;
 }

+static int64_t gettime_relative_minus_pause(void)
+{
+    return av_gettime_relative() - paused_time -
+            (paused_start ? av_gettime_relative() - paused_start : 0);
+}

 static int64_t getutime(void)
 {


More information about the ffmpeg-devel mailing list