Add estimated completion time to vpxenc
Make the progress line more useful by providing per-frame updates of processing frame rate and estimated time remaining. Fixes issue #534. Change-Id: Ic91551878ff4b2f5db1cedaafb588add220cfa52
This commit is contained in:
Родитель
a5762191d7
Коммит
60d8c50514
89
vpxenc.c
89
vpxenc.c
|
@ -301,6 +301,7 @@ struct detect_buffer {
|
|||
struct input_state {
|
||||
char *fn;
|
||||
FILE *file;
|
||||
off_t length;
|
||||
y4m_input y4m;
|
||||
struct detect_buffer detect;
|
||||
enum video_file_type file_type;
|
||||
|
@ -1730,6 +1731,14 @@ void open_input_file(struct input_state *input) {
|
|||
if (!input->file)
|
||||
fatal("Failed to open input file");
|
||||
|
||||
if (!fseeko(input->file, 0, SEEK_END)) {
|
||||
/* Input file is seekable. Figure out how long it is, so we can get
|
||||
* progress info.
|
||||
*/
|
||||
input->length = ftello(input->file);
|
||||
rewind(input->file);
|
||||
}
|
||||
|
||||
/* For RAW input sources, these bytes will applied on the first frame
|
||||
* in read_frame().
|
||||
*/
|
||||
|
@ -2246,9 +2255,6 @@ static void get_cx_data(struct stream_state *stream,
|
|||
if (!(pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT)) {
|
||||
stream->frames_out++;
|
||||
}
|
||||
if (!global->quiet)
|
||||
fprintf(stderr, " %6luF",
|
||||
(unsigned long)pkt->data.frame.sz);
|
||||
|
||||
update_rate_histogram(&stream->rate_hist, cfg, pkt);
|
||||
if (stream->config.write_webm) {
|
||||
|
@ -2292,9 +2298,6 @@ static void get_cx_data(struct stream_state *stream,
|
|||
break;
|
||||
case VPX_CODEC_STATS_PKT:
|
||||
stream->frames_out++;
|
||||
if (!global->quiet)
|
||||
fprintf(stderr, " %6luS",
|
||||
(unsigned long)pkt->data.twopass_stats.sz);
|
||||
stats_write(&stream->stats,
|
||||
pkt->data.twopass_stats.buf,
|
||||
pkt->data.twopass_stats.sz);
|
||||
|
@ -2308,8 +2311,6 @@ static void get_cx_data(struct stream_state *stream,
|
|||
stream->psnr_sse_total += pkt->data.psnr.sse[0];
|
||||
stream->psnr_samples_total += pkt->data.psnr.samples[0];
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (!global->quiet)
|
||||
fprintf(stderr, "%.3f ", pkt->data.psnr.psnr[i]);
|
||||
stream->psnr_totals[i] += pkt->data.psnr.psnr[i];
|
||||
}
|
||||
stream->psnr_count++;
|
||||
|
@ -2342,7 +2343,7 @@ static void show_psnr(struct stream_state *stream) {
|
|||
}
|
||||
|
||||
|
||||
float usec_to_fps(uint64_t usec, unsigned int frames) {
|
||||
static float usec_to_fps(uint64_t usec, unsigned int frames) {
|
||||
return (float)(usec > 0 ? frames * 1000000.0 / (float)usec : 0);
|
||||
}
|
||||
|
||||
|
@ -2367,6 +2368,24 @@ static void test_decode(struct stream_state *stream) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static void print_time(const char *label, int64_t etl) {
|
||||
int hours, mins, secs;
|
||||
|
||||
if (etl >= 0) {
|
||||
hours = etl / 3600;
|
||||
etl -= hours * 3600;
|
||||
mins = etl / 60;
|
||||
etl -= mins * 60;
|
||||
secs = etl;
|
||||
|
||||
fprintf(stderr, "[%3s %2d:%02d:%02d] ",
|
||||
label, hours, mins, secs);
|
||||
} else {
|
||||
fprintf(stderr, "[%3s unknown] ", label);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv_) {
|
||||
int pass;
|
||||
vpx_image_t raw;
|
||||
|
@ -2424,6 +2443,9 @@ int main(int argc, const char **argv_) {
|
|||
|
||||
for (pass = global.pass ? global.pass - 1 : 0; pass < global.passes; pass++) {
|
||||
int frames_in = 0;
|
||||
int64_t estimated_time_left = -1;
|
||||
int64_t average_rate = -1;
|
||||
off_t lagged_count = 0;
|
||||
|
||||
open_input_file(&input);
|
||||
|
||||
|
@ -2500,18 +2522,23 @@ int main(int argc, const char **argv_) {
|
|||
frames_in++;
|
||||
|
||||
if (!global.quiet) {
|
||||
float fps = usec_to_fps(cx_time, frames_in);
|
||||
fprintf(stderr, "\rPass %d/%d ", pass + 1, global.passes);
|
||||
|
||||
if (stream_cnt == 1)
|
||||
fprintf(stderr,
|
||||
"\rPass %d/%d frame %4d/%-4d %7"PRId64"B \033[K",
|
||||
pass + 1, global.passes, frames_in,
|
||||
streams->frames_out, (int64_t)streams->nbytes);
|
||||
"frame %4d/%-4d %7"PRId64"B ",
|
||||
frames_in, streams->frames_out, (int64_t)streams->nbytes);
|
||||
else
|
||||
fprintf(stderr,
|
||||
"\rPass %d/%d frame %4d %7lu %s (%.2f fps)\033[K",
|
||||
pass + 1, global.passes, frames_in,
|
||||
cx_time > 9999999 ? cx_time / 1000 : cx_time,
|
||||
cx_time > 9999999 ? "ms" : "us",
|
||||
usec_to_fps(cx_time, frames_in));
|
||||
fprintf(stderr, "frame %4d ", frames_in);
|
||||
|
||||
fprintf(stderr, "%7lu %s %.2f %s ",
|
||||
cx_time > 9999999 ? cx_time / 1000 : cx_time,
|
||||
cx_time > 9999999 ? "ms" : "us",
|
||||
fps >= 1.0 ? fps : 1000.0 / fps,
|
||||
fps >= 1.0 ? "fps" : "ms/f");
|
||||
print_time("ETA", estimated_time_left);
|
||||
fprintf(stderr, "\033[K");
|
||||
}
|
||||
|
||||
} else
|
||||
|
@ -2530,6 +2557,32 @@ int main(int argc, const char **argv_) {
|
|||
got_data = 0;
|
||||
FOREACH_STREAM(get_cx_data(stream, &global, &got_data));
|
||||
|
||||
if (!got_data && input.length && !streams->frames_out) {
|
||||
lagged_count = global.limit ? frames_in : ftello(input.file);
|
||||
} else if (got_data && input.length) {
|
||||
int64_t remaining;
|
||||
int64_t rate;
|
||||
|
||||
if (global.limit) {
|
||||
int frame_in_lagged = (frames_in - lagged_count) * 1000;
|
||||
|
||||
rate = cx_time ? frame_in_lagged * (int64_t)1000000 / cx_time : 0;
|
||||
remaining = 1000 * (global.limit - frames_in + lagged_count);
|
||||
} else {
|
||||
off_t input_pos = ftello(input.file);
|
||||
off_t input_pos_lagged = input_pos - lagged_count;
|
||||
int64_t limit = input.length;
|
||||
|
||||
rate = cx_time ? input_pos_lagged * (int64_t)1000000 / cx_time : 0;
|
||||
remaining = limit - input_pos + lagged_count;
|
||||
}
|
||||
|
||||
average_rate = (average_rate <= 0)
|
||||
? rate
|
||||
: (average_rate * 7 + rate) / 8;
|
||||
estimated_time_left = average_rate ? remaining / average_rate : -1;
|
||||
}
|
||||
|
||||
if (got_data && global.test_decode)
|
||||
FOREACH_STREAM(test_decode(stream));
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче