Useful where ffmpeg is used by applications that transcode on the fly and want to provide some throttling (among other things)
From e2f3aa14979675a373a210bd9a028b01a5a0c7eb Mon Sep 17 00:00:00 2001 From: jluce50 <jeremyl...@gmail.com> Date: Fri, 6 Mar 2015 17:13:40 -0600 Subject: [PATCH 1/4] Add pause/resume via keyboard interaction
--- ffmpeg.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/ffmpeg.c b/ffmpeg.c index 6604ff0..edfd01d 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -120,6 +120,7 @@ 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 int run_as_daemon = 0; static int nb_frames_dup = 0; @@ -146,6 +147,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 */ @@ -3268,6 +3272,14 @@ static int check_keyboard_interaction(int64_t cur_time) last_time = cur_time; }else key = -1; + // if (key == 'u' && paused_start) { + if (key != -1 && paused_start) { // Any valid key unpauses (backward compatibility) + paused_time += (av_gettime_relative() - paused_start); + paused_start = 0; + } + if (key == 'p' && !paused_start) { + paused_start = av_gettime_relative(); + } if (key == 'q') return AVERROR_EXIT; if (key == '+') av_log_set_level(av_log_get_level()+10); @@ -3346,7 +3358,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" "s Show QP histogram\n" ); } @@ -3778,6 +3792,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,7 +3857,7 @@ static int transcode(void) #endif while (!received_sigterm) { - int64_t cur_time= av_gettime_relative(); + int64_t cur_time = av_gettime_relative(); /* if 'q' pressed, exits */ if (stdin_interaction) @@ -3861,7 +3880,7 @@ static int transcode(void) } /* dump report by using the output first video and audio streams */ - print_report(0, timer_start, cur_time); + print_report(0, timer_start, gettime_relative_minus_pause()); } #if HAVE_PTHREADS free_input_threads(); @@ -3885,7 +3904,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 +3953,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) { -- 1.9.1 From 0fb80c6d3df396119d06049f40d552d0f3a81d3b Mon Sep 17 00:00:00 2001 From: jluce50 <jeremyl...@gmail.com> Date: Sat, 7 Mar 2015 10:03:39 -0600 Subject: [PATCH 2/4] Cleanup for pause/unpause --- ffmpeg.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/ffmpeg.c b/ffmpeg.c index edfd01d..a505e46 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -1451,7 +1451,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); @@ -3360,7 +3359,7 @@ static int check_keyboard_interaction(int64_t cur_time) "h dump packets/hex press to cycle through the 3 states\n" "p pause transcoding\n" "q quit\n" - "u unpause transcoding" + "u unpause transcoding\n" "s Show QP histogram\n" ); } @@ -3857,11 +3856,9 @@ static int transcode(void) #endif while (!received_sigterm) { - int64_t cur_time = av_gettime_relative(); - /* 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 */ -- 1.9.1 From 5763c991ea889107ed6f88bdbd4304936d0b7fc8 Mon Sep 17 00:00:00 2001 From: jluce50 <jeremyl...@gmail.com> Date: Sat, 7 Mar 2015 15:29:40 -0600 Subject: [PATCH 3/4] Cleanup for pause/unpause --- ffmpeg.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ffmpeg.c b/ffmpeg.c index a505e46..7e24e6a 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -3271,8 +3271,9 @@ static int check_keyboard_interaction(int64_t cur_time) last_time = cur_time; }else key = -1; - // if (key == 'u' && paused_start) { - if (key != -1 && paused_start) { // Any valid key unpauses (backward compatibility) + // Reserve 'u' for unpausing a paused transcode, but allow any key to + // unpause for backward compatibility + if ((key == 'u' || key != -1) && paused_start) { paused_time += (av_gettime_relative() - paused_start); paused_start = 0; } @@ -3856,6 +3857,8 @@ static int transcode(void) #endif while (!received_sigterm) { + int64_t cur_time = gettime_relative_minus_pause(); + /* if 'q' pressed, exits */ if (stdin_interaction) if (check_keyboard_interaction(av_gettime_relative()) < 0) @@ -3877,7 +3880,7 @@ static int transcode(void) } /* dump report by using the output first video and audio streams */ - print_report(0, timer_start, gettime_relative_minus_pause()); + print_report(0, timer_start, cur_time); } #if HAVE_PTHREADS free_input_threads(); -- 1.9.1 From 036fededb42e66f1e45c34faa48519896fb56cc1 Mon Sep 17 00:00:00 2001 From: jluce50 <jeremyl...@gmail.com> Date: Mon, 9 Mar 2015 15:55:14 -0500 Subject: [PATCH 4/4] Add pausing for input threads and some cleanup --- ffmpeg.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/ffmpeg.c b/ffmpeg.c index 7e24e6a..3498dfe 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -121,6 +121,8 @@ 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 pauseTranscoding(void); +static void unpauseTranscoding(void); static int run_as_daemon = 0; static int nb_frames_dup = 0; @@ -3259,12 +3261,28 @@ static OutputStream *choose_output(void) return ost_min; } +static void pauseTranscoding(void) +{ + if (!paused_start) + paused_start = av_gettime_relative(); +} + +static void unpauseTranscoding(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) { + unpauseTranscoding(); return AVERROR_EXIT; + } /* read_key() returns 0 on EOF */ if(cur_time - last_time >= 100000 && !run_as_daemon){ key = read_key(); @@ -3273,13 +3291,8 @@ static int check_keyboard_interaction(int64_t cur_time) key = -1; // Reserve 'u' for unpausing a paused transcode, but allow any key to // unpause for backward compatibility - if ((key == 'u' || key != -1) && paused_start) { - paused_time += (av_gettime_relative() - paused_start); - paused_start = 0; - } - if (key == 'p' && !paused_start) { - paused_start = av_gettime_relative(); - } + if (key == 'u' || key != -1) unpauseTranscoding(); + if (key == 'p') pauseTranscoding(); if (key == 'q') return AVERROR_EXIT; if (key == '+') av_log_set_level(av_log_get_level()+10); @@ -3375,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); -- 1.9.1
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel