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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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
[email protected]
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel