avfilter/avfiltergraph: fix constant string comparision
[ffmpeg.git] / fftools / ffmpeg.c
1 /*
2 * Copyright (c) 2000-2003 Fabrice Bellard
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 /**
22 * @file
23 * multimedia converter based on the FFmpeg libraries
24 */
25
26 #include "config.h"
27
28 #include <errno.h>
29 #include <limits.h>
30 #include <stdatomic.h>
31 #include <stdint.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <time.h>
35
36 #if HAVE_IO_H
37 #include <io.h>
38 #endif
39 #if HAVE_UNISTD_H
40 #include <unistd.h>
41 #endif
42
43 #if HAVE_SYS_RESOURCE_H
44 #include <sys/time.h>
45 #include <sys/types.h>
46 #include <sys/resource.h>
47 #elif HAVE_GETPROCESSTIMES
48 #include <windows.h>
49 #endif
50 #if HAVE_GETPROCESSMEMORYINFO
51 #include <windows.h>
52 #include <psapi.h>
53 #endif
54 #if HAVE_SETCONSOLECTRLHANDLER
55 #include <windows.h>
56 #endif
57
58 #if HAVE_SYS_SELECT_H
59 #include <sys/select.h>
60 #endif
61
62 #if HAVE_TERMIOS_H
63 #include <fcntl.h>
64 #include <sys/ioctl.h>
65 #include <sys/time.h>
66 #include <termios.h>
67 #elif HAVE_KBHIT
68 #include <conio.h>
69 #endif
70
71 #include "libavutil/bprint.h"
72 #include "libavutil/dict.h"
73 #include "libavutil/mem.h"
74 #include "libavutil/time.h"
75
76 #include "libavformat/avformat.h"
77
78 #include "libavdevice/avdevice.h"
79
80 #include "cmdutils.h"
81 #if CONFIG_MEDIACODEC
82 #include "compat/android/binder.h"
83 #endif
84 #include "ffmpeg.h"
85 #include "ffmpeg_sched.h"
86 #include "ffmpeg_utils.h"
87 #include "graph/graphprint.h"
88
89 const char program_name[] = "ffmpeg";
90 const int program_birth_year = 2000;
91
92 FILE *vstats_file;
93
94 typedef struct BenchmarkTimeStamps {
95 int64_t real_usec;
96 int64_t user_usec;
97 int64_t sys_usec;
98 } BenchmarkTimeStamps;
99
100 static BenchmarkTimeStamps get_benchmark_time_stamps(void);
101 static int64_t getmaxrss(void);
102
103 atomic_uint nb_output_dumped = 0;
104
105 static BenchmarkTimeStamps current_time;
106 AVIOContext *progress_avio = NULL;
107
108 InputFile **input_files = NULL;
109 int nb_input_files = 0;
110
111 OutputFile **output_files = NULL;
112 int nb_output_files = 0;
113
114 FilterGraph **filtergraphs;
115 int nb_filtergraphs;
116
117 Decoder **decoders;
118 int nb_decoders;
119
120 #if HAVE_TERMIOS_H
121
122 /* init terminal so that we can grab keys */
123 static struct termios oldtty;
124 static int restore_tty;
125 #endif
126
127 static void term_exit_sigsafe(void)
128 {
129 #if HAVE_TERMIOS_H
130 if(restore_tty)
131 tcsetattr (0, TCSANOW, &oldtty);
132 #endif
133 }
134
135 void term_exit(void)
136 {
137 av_log(NULL, AV_LOG_QUIET, "%s", "");
138 term_exit_sigsafe();
139 }
140
141 static volatile int received_sigterm = 0;
142 static volatile int received_nb_signals = 0;
143 static atomic_int transcode_init_done = 0;
144 static volatile int ffmpeg_exited = 0;
145 static int64_t copy_ts_first_pts = AV_NOPTS_VALUE;
146
147 static void
148 sigterm_handler(int sig)
149 {
150 int ret;
151 received_sigterm = sig;
152 received_nb_signals++;
153 term_exit_sigsafe();
154 if(received_nb_signals > 3) {
155 ret = write(2/*STDERR_FILENO*/, "Received > 3 system signals, hard exiting\n",
156 strlen("Received > 3 system signals, hard exiting\n"));
157 if (ret < 0) { /* Do nothing */ };
158 exit(123);
159 }
160 }
161
162 #if HAVE_SETCONSOLECTRLHANDLER
163 static BOOL WINAPI CtrlHandler(DWORD fdwCtrlType)
164 {
165 av_log(NULL, AV_LOG_DEBUG, "\nReceived windows signal %ld\n", fdwCtrlType);
166
167 switch (fdwCtrlType)
168 {
169 case CTRL_C_EVENT:
170 case CTRL_BREAK_EVENT:
171 sigterm_handler(SIGINT);
172 return TRUE;
173
174 case CTRL_CLOSE_EVENT:
175 case CTRL_LOGOFF_EVENT:
176 case CTRL_SHUTDOWN_EVENT:
177 sigterm_handler(SIGTERM);
178 /* Basically, with these 3 events, when we return from this method the
179 process is hard terminated, so stall as long as we need to
180 to try and let the main thread(s) clean up and gracefully terminate
181 (we have at most 5 seconds, but should be done far before that). */
182 while (!ffmpeg_exited) {
183 Sleep(0);
184 }
185 return TRUE;
186
187 default:
188 av_log(NULL, AV_LOG_ERROR, "Received unknown windows signal %ld\n", fdwCtrlType);
189 return FALSE;
190 }
191 }
192 #endif
193
194 #ifdef __linux__
195 #define SIGNAL(sig, func) \
196 do { \
197 action.sa_handler = func; \
198 sigaction(sig, &action, NULL); \
199 } while (0)
200 #else
201 #define SIGNAL(sig, func) \
202 signal(sig, func)
203 #endif
204
205 void term_init(void)
206 {
207 #if defined __linux__
208 struct sigaction action = {0};
209 action.sa_handler = sigterm_handler;
210
211 /* block other interrupts while processing this one */
212 sigfillset(&action.sa_mask);
213
214 /* restart interruptible functions (i.e. don't fail with EINTR) */
215 action.sa_flags = SA_RESTART;
216 #endif
217
218 #if HAVE_TERMIOS_H
219 if (stdin_interaction) {
220 struct termios tty;
221 if (tcgetattr (0, &tty) == 0) {
222 oldtty = tty;
223 restore_tty = 1;
224
225 tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
226 |INLCR|IGNCR|ICRNL|IXON);
227 tty.c_oflag |= OPOST;
228 tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
229 tty.c_cflag &= ~(CSIZE|PARENB);
230 tty.c_cflag |= CS8;
231 tty.c_cc[VMIN] = 1;
232 tty.c_cc[VTIME] = 0;
233
234 tcsetattr (0, TCSANOW, &tty);
235 }
236 SIGNAL(SIGQUIT, sigterm_handler); /* Quit (POSIX). */
237 }
238 #endif
239
240 SIGNAL(SIGINT , sigterm_handler); /* Interrupt (ANSI). */
241 SIGNAL(SIGTERM, sigterm_handler); /* Termination (ANSI). */
242 #ifdef SIGXCPU
243 SIGNAL(SIGXCPU, sigterm_handler);
244 #endif
245 #ifdef SIGPIPE
246 signal(SIGPIPE, SIG_IGN); /* Broken pipe (POSIX). */
247 #endif
248 #if HAVE_SETCONSOLECTRLHANDLER
249 SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE);
250 #endif
251 }
252
253 /* read a key without blocking */
254 static int read_key(void)
255 {
256 unsigned char ch = -1;
257 #if HAVE_TERMIOS_H
258 int n = 1;
259 struct timeval tv;
260 fd_set rfds;
261
262 FD_ZERO(&rfds);
263 FD_SET(0, &rfds);
264 tv.tv_sec = 0;
265 tv.tv_usec = 0;
266 n = select(1, &rfds, NULL, NULL, &tv);
267 if (n > 0) {
268 n = read(0, &ch, 1);
269 if (n == 1)
270 return ch;
271
272 return n;
273 }
274 #elif HAVE_KBHIT
275 # if HAVE_PEEKNAMEDPIPE && HAVE_GETSTDHANDLE
276 static int is_pipe;
277 static HANDLE input_handle;
278 DWORD dw, nchars;
279 if(!input_handle){
280 input_handle = GetStdHandle(STD_INPUT_HANDLE);
281 is_pipe = !GetConsoleMode(input_handle, &dw);
282 }
283
284 if (is_pipe) {
285 /* When running under a GUI, you will end here. */
286 if (!PeekNamedPipe(input_handle, NULL, 0, NULL, &nchars, NULL)) {
287 // input pipe may have been closed by the program that ran ffmpeg
288 return -1;
289 }
290 //Read it
291 if(nchars != 0) {
292 if (read(0, &ch, 1) == 1)
293 return ch;
294 return 0;
295 }else{
296 return -1;
297 }
298 }
299 # endif
300 if(kbhit())
301 return(getch());
302 #endif
303 return ch;
304 }
305
306 static int decode_interrupt_cb(void *ctx)
307 {
308 return received_nb_signals > atomic_load(&transcode_init_done);
309 }
310
311 const AVIOInterruptCB int_cb = { decode_interrupt_cb, NULL };
312
313 static void ffmpeg_cleanup(int ret)
314 {
315 if ((print_graphs || print_graphs_file) && nb_output_files > 0)
316 print_filtergraphs(filtergraphs, nb_filtergraphs, input_files, nb_input_files, output_files, nb_output_files);
317
318 if (do_benchmark) {
319 int64_t maxrss = getmaxrss() / 1024;
320 av_log(NULL, AV_LOG_INFO, "bench: maxrss=%"PRId64"KiB\n", maxrss);
321 }
322
323 for (int i = 0; i < nb_filtergraphs; i++)
324 fg_free(&filtergraphs[i]);
325 av_freep(&filtergraphs);
326
327 for (int i = 0; i < nb_output_files; i++)
328 of_free(&output_files[i]);
329
330 for (int i = 0; i < nb_input_files; i++)
331 ifile_close(&input_files[i]);
332
333 for (int i = 0; i < nb_decoders; i++)
334 dec_free(&decoders[i]);
335 av_freep(&decoders);
336
337 if (vstats_file) {
338 if (fclose(vstats_file))
339 av_log(NULL, AV_LOG_ERROR,
340 "Error closing vstats file, loss of information possible: %s\n",
341 av_err2str(AVERROR(errno)));
342 }
343 av_freep(&vstats_filename);
344 of_enc_stats_close();
345
346 hw_device_free_all();
347
348 av_freep(&filter_nbthreads);
349
350 av_freep(&print_graphs_file);
351 av_freep(&print_graphs_format);
352
353 av_freep(&input_files);
354 av_freep(&output_files);
355
356 uninit_opts();
357
358 avformat_network_deinit();
359
360 if (received_sigterm) {
361 av_log(NULL, AV_LOG_INFO, "Exiting normally, received signal %d.\n",
362 (int) received_sigterm);
363 } else if (ret && atomic_load(&transcode_init_done)) {
364 av_log(NULL, AV_LOG_INFO, "Conversion failed!\n");
365 }
366 term_exit();
367 ffmpeg_exited = 1;
368 }
369
370 OutputStream *ost_iter(OutputStream *prev)
371 {
372 int of_idx = prev ? prev->file->index : 0;
373 int ost_idx = prev ? prev->index + 1 : 0;
374
375 for (; of_idx < nb_output_files; of_idx++) {
376 OutputFile *of = output_files[of_idx];
377 if (ost_idx < of->nb_streams)
378 return of->streams[ost_idx];
379
380 ost_idx = 0;
381 }
382
383 return NULL;
384 }
385
386 InputStream *ist_iter(InputStream *prev)
387 {
388 int if_idx = prev ? prev->file->index : 0;
389 int ist_idx = prev ? prev->index + 1 : 0;
390
391 for (; if_idx < nb_input_files; if_idx++) {
392 InputFile *f = input_files[if_idx];
393 if (ist_idx < f->nb_streams)
394 return f->streams[ist_idx];
395
396 ist_idx = 0;
397 }
398
399 return NULL;
400 }
401
402 static void frame_data_free(void *opaque, uint8_t *data)
403 {
404 FrameData *fd = (FrameData *)data;
405
406 av_frame_side_data_free(&fd->side_data, &fd->nb_side_data);
407 avcodec_parameters_free(&fd->par_enc);
408
409 av_free(data);
410 }
411
412 static int frame_data_ensure(AVBufferRef **dst, int writable)
413 {
414 AVBufferRef *src = *dst;
415
416 if (!src || (writable && !av_buffer_is_writable(src))) {
417 FrameData *fd;
418
419 fd = av_mallocz(sizeof(*fd));
420 if (!fd)
421 return AVERROR(ENOMEM);
422
423 *dst = av_buffer_create((uint8_t *)fd, sizeof(*fd),
424 frame_data_free, NULL, 0);
425 if (!*dst) {
426 av_buffer_unref(&src);
427 av_freep(&fd);
428 return AVERROR(ENOMEM);
429 }
430
431 if (src) {
432 const FrameData *fd_src = (const FrameData *)src->data;
433
434 memcpy(fd, fd_src, sizeof(*fd));
435 fd->par_enc = NULL;
436 fd->side_data = NULL;
437 fd->nb_side_data = 0;
438
439 if (fd_src->par_enc) {
440 int ret = 0;
441
442 fd->par_enc = avcodec_parameters_alloc();
443 ret = fd->par_enc ?
444 avcodec_parameters_copy(fd->par_enc, fd_src->par_enc) :
445 AVERROR(ENOMEM);
446 if (ret < 0) {
447 av_buffer_unref(dst);
448 av_buffer_unref(&src);
449 return ret;
450 }
451 }
452
453 if (fd_src->nb_side_data) {
454 int ret = clone_side_data(&fd->side_data, &fd->nb_side_data,
455 fd_src->side_data, fd_src->nb_side_data, 0);
456 if (ret < 0) {
457 av_buffer_unref(dst);
458 av_buffer_unref(&src);
459 return ret;
460 }
461 }
462
463 av_buffer_unref(&src);
464 } else {
465 fd->dec.frame_num = UINT64_MAX;
466 fd->dec.pts = AV_NOPTS_VALUE;
467
468 for (unsigned i = 0; i < FF_ARRAY_ELEMS(fd->wallclock); i++)
469 fd->wallclock[i] = INT64_MIN;
470 }
471 }
472
473 return 0;
474 }
475
476 FrameData *frame_data(AVFrame *frame)
477 {
478 int ret = frame_data_ensure(&frame->opaque_ref, 1);
479 return ret < 0 ? NULL : (FrameData*)frame->opaque_ref->data;
480 }
481
482 const FrameData *frame_data_c(AVFrame *frame)
483 {
484 int ret = frame_data_ensure(&frame->opaque_ref, 0);
485 return ret < 0 ? NULL : (const FrameData*)frame->opaque_ref->data;
486 }
487
488 FrameData *packet_data(AVPacket *pkt)
489 {
490 int ret = frame_data_ensure(&pkt->opaque_ref, 1);
491 return ret < 0 ? NULL : (FrameData*)pkt->opaque_ref->data;
492 }
493
494 const FrameData *packet_data_c(AVPacket *pkt)
495 {
496 int ret = frame_data_ensure(&pkt->opaque_ref, 0);
497 return ret < 0 ? NULL : (const FrameData*)pkt->opaque_ref->data;
498 }
499
500 int check_avoptions_used(const AVDictionary *opts, const AVDictionary *opts_used,
501 void *logctx, int decode)
502 {
503 const AVClass *class = avcodec_get_class();
504 const AVClass *fclass = avformat_get_class();
505
506 const int flag = decode ? AV_OPT_FLAG_DECODING_PARAM :
507 AV_OPT_FLAG_ENCODING_PARAM;
508 const AVDictionaryEntry *e = NULL;
509
510 while ((e = av_dict_iterate(opts, e))) {
511 const AVOption *option, *foption;
512 char *optname, *p;
513
514 if (av_dict_get(opts_used, e->key, NULL, 0))
515 continue;
516
517 optname = av_strdup(e->key);
518 if (!optname)
519 return AVERROR(ENOMEM);
520
521 p = strchr(optname, ':');
522 if (p)
523 *p = 0;
524
525 option = av_opt_find(&class, optname, NULL, 0,
526 AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ);
527 foption = av_opt_find(&fclass, optname, NULL, 0,
528 AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ);
529 av_freep(&optname);
530 if (!option || foption)
531 continue;
532
533 if (!(option->flags & flag)) {
534 av_log(logctx, AV_LOG_ERROR, "Codec AVOption %s (%s) is not a %s "
535 "option.\n", e->key, option->help ? option->help : "",
536 decode ? "decoding" : "encoding");
537 return AVERROR(EINVAL);
538 }
539
540 av_log(logctx, AV_LOG_WARNING, "Codec AVOption %s (%s) has not been used "
541 "for any stream. The most likely reason is either wrong type "
542 "(e.g. a video option with no video streams) or that it is a "
543 "private option of some decoder which was not actually used "
544 "for any stream.\n", e->key, option->help ? option->help : "");
545 }
546
547 return 0;
548 }
549
550 void update_benchmark(const char *fmt, ...)
551 {
552 if (do_benchmark_all) {
553 BenchmarkTimeStamps t = get_benchmark_time_stamps();
554 va_list va;
555 char buf[1024];
556
557 if (fmt) {
558 va_start(va, fmt);
559 vsnprintf(buf, sizeof(buf), fmt, va);
560 va_end(va);
561 av_log(NULL, AV_LOG_INFO,
562 "bench: %8" PRIu64 " user %8" PRIu64 " sys %8" PRIu64 " real %s \n",
563 t.user_usec - current_time.user_usec,
564 t.sys_usec - current_time.sys_usec,
565 t.real_usec - current_time.real_usec, buf);
566 }
567 current_time = t;
568 }
569 }
570
571 static void print_report(int is_last_report, int64_t timer_start, int64_t cur_time, int64_t pts)
572 {
573 AVBPrint buf, buf_script;
574 int64_t total_size = of_filesize(output_files[0]);
575 int vid;
576 double bitrate;
577 double speed;
578 static int64_t last_time = -1;
579 static int first_report = 1;
580 uint64_t nb_frames_dup = 0, nb_frames_drop = 0;
581 int mins, secs, ms, us;
582 int64_t hours;
583 const char *hours_sign;
584 int ret;
585 float t;
586
587 if (!print_stats && !is_last_report && !progress_avio)
588 return;
589
590 if (!is_last_report) {
591 if (last_time == -1) {
592 last_time = cur_time;
593 }
594 if (((cur_time - last_time) < stats_period && !first_report) ||
595 (first_report && atomic_load(&nb_output_dumped) < nb_output_files))
596 return;
597 last_time = cur_time;
598 }
599
600 t = (cur_time-timer_start) / 1000000.0;
601
602 vid = 0;
603 av_bprint_init(&buf, 0, AV_BPRINT_SIZE_AUTOMATIC);
604 av_bprint_init(&buf_script, 0, AV_BPRINT_SIZE_AUTOMATIC);
605
606 for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) {
607 const float q = ost->enc ? atomic_load(&ost->quality) / (float) FF_QP2LAMBDA : -1;
608
609 if (vid && ost->type == AVMEDIA_TYPE_VIDEO) {
610 av_bprintf(&buf, "q=%2.1f ", q);
611 av_bprintf(&buf_script, "stream_%d_%d_q=%.1f\n",
612 ost->file->index, ost->index, q);
613 }
614 if (!vid && ost->type == AVMEDIA_TYPE_VIDEO) {
615 float fps;
616 uint64_t frame_number = atomic_load(&ost->packets_written);
617
618 fps = t > 1 ? frame_number / t : 0;
619 av_bprintf(&buf, "frame=%5"PRId64" fps=%3.*f q=%3.1f ",
620 frame_number, fps < 9.95, fps, q);
621 av_bprintf(&buf_script, "frame=%"PRId64"\n", frame_number);
622 av_bprintf(&buf_script, "fps=%.2f\n", fps);
623 av_bprintf(&buf_script, "stream_%d_%d_q=%.1f\n",
624 ost->file->index, ost->index, q);
625 if (is_last_report)
626 av_bprintf(&buf, "L");
627
628 if (ost->filter) {
629 nb_frames_dup = atomic_load(&ost->filter->nb_frames_dup);
630 nb_frames_drop = atomic_load(&ost->filter->nb_frames_drop);
631 }
632
633 vid = 1;
634 }
635 }
636
637 if (copy_ts) {
638 if (copy_ts_first_pts == AV_NOPTS_VALUE && pts > 1)
639 copy_ts_first_pts = pts;
640 if (copy_ts_first_pts != AV_NOPTS_VALUE)
641 pts -= copy_ts_first_pts;
642 }
643
644 us = FFABS64U(pts) % AV_TIME_BASE;
645 secs = FFABS64U(pts) / AV_TIME_BASE % 60;
646 mins = FFABS64U(pts) / AV_TIME_BASE / 60 % 60;
647 hours = FFABS64U(pts) / AV_TIME_BASE / 3600;
648 hours_sign = (pts < 0) ? "-" : "";
649
650 bitrate = pts != AV_NOPTS_VALUE && pts && total_size >= 0 ? total_size * 8 / (pts / 1000.0) : -1;
651 speed = pts != AV_NOPTS_VALUE && t != 0.0 ? (double)pts / AV_TIME_BASE / t : -1;
652
653 if (total_size < 0) av_bprintf(&buf, "size=N/A time=");
654 else av_bprintf(&buf, "size=%8.0fKiB time=", total_size / 1024.0);
655 if (pts == AV_NOPTS_VALUE) {
656 av_bprintf(&buf, "N/A ");
657 } else {
658 av_bprintf(&buf, "%s%02"PRId64":%02d:%02d.%02d ",
659 hours_sign, hours, mins, secs, (100 * us) / AV_TIME_BASE);
660 }
661
662 if (bitrate < 0) {
663 av_bprintf(&buf, "bitrate=N/A");
664 av_bprintf(&buf_script, "bitrate=N/A\n");
665 }else{
666 av_bprintf(&buf, "bitrate=%6.1fkbits/s", bitrate);
667 av_bprintf(&buf_script, "bitrate=%6.1fkbits/s\n", bitrate);
668 }
669
670 if (total_size < 0) av_bprintf(&buf_script, "total_size=N/A\n");
671 else av_bprintf(&buf_script, "total_size=%"PRId64"\n", total_size);
672 if (pts == AV_NOPTS_VALUE) {
673 av_bprintf(&buf_script, "out_time_us=N/A\n");
674 av_bprintf(&buf_script, "out_time_ms=N/A\n");
675 av_bprintf(&buf_script, "out_time=N/A\n");
676 } else {
677 av_bprintf(&buf_script, "out_time_us=%"PRId64"\n", pts);
678 av_bprintf(&buf_script, "out_time_ms=%"PRId64"\n", pts);
679 av_bprintf(&buf_script, "out_time=%s%02"PRId64":%02d:%02d.%06d\n",
680 hours_sign, hours, mins, secs, us);
681 }
682
683 if (nb_frames_dup || nb_frames_drop)
684 av_bprintf(&buf, " dup=%"PRId64" drop=%"PRId64, nb_frames_dup, nb_frames_drop);
685 av_bprintf(&buf_script, "dup_frames=%"PRId64"\n", nb_frames_dup);
686 av_bprintf(&buf_script, "drop_frames=%"PRId64"\n", nb_frames_drop);
687
688 if (speed < 0) {
689 av_bprintf(&buf, " speed=N/A");
690 av_bprintf(&buf_script, "speed=N/A\n");
691 } else {
692 av_bprintf(&buf, " speed=%4.3gx", speed);
693 av_bprintf(&buf_script, "speed=%4.3gx\n", speed);
694 }
695
696 secs = (int)t;
697 ms = (int)((t - secs) * 1000);
698 mins = secs / 60;
699 secs %= 60;
700 hours = mins / 60;
701 mins %= 60;
702
703 av_bprintf(&buf, " elapsed=%"PRId64":%02d:%02d.%02d", hours, mins, secs, ms / 10);
704
705 if (print_stats || is_last_report) {
706 const char end = is_last_report ? '\n' : '\r';
707 if (print_stats==1 && AV_LOG_INFO > av_log_get_level()) {
708 fprintf(stderr, "%s %c", buf.str, end);
709 } else
710 av_log(NULL, AV_LOG_INFO, "%s %c", buf.str, end);
711
712 fflush(stderr);
713 }
714 av_bprint_finalize(&buf, NULL);
715
716 if (progress_avio) {
717 av_bprintf(&buf_script, "progress=%s\n",
718 is_last_report ? "end" : "continue");
719 avio_write(progress_avio, buf_script.str,
720 FFMIN(buf_script.len, buf_script.size - 1));
721 avio_flush(progress_avio);
722 av_bprint_finalize(&buf_script, NULL);
723 if (is_last_report) {
724 if ((ret = avio_closep(&progress_avio)) < 0)
725 av_log(NULL, AV_LOG_ERROR,
726 "Error closing progress log, loss of information possible: %s\n", av_err2str(ret));
727 }
728 }
729
730 first_report = 0;
731 }
732
733 static void print_stream_maps(void)
734 {
735 av_log(NULL, AV_LOG_INFO, "Stream mapping:\n");
736 for (InputStream *ist = ist_iter(NULL); ist; ist = ist_iter(ist)) {
737 for (int j = 0; j < ist->nb_filters; j++) {
738 if (!filtergraph_is_simple(ist->filters[j]->graph)) {
739 av_log(NULL, AV_LOG_INFO, " Stream #%d:%d (%s) -> %s",
740 ist->file->index, ist->index, ist->dec ? ist->dec->name : "?",
741 ist->filters[j]->name);
742 if (nb_filtergraphs > 1)
743 av_log(NULL, AV_LOG_INFO, " (graph %d)", ist->filters[j]->graph->index);
744 av_log(NULL, AV_LOG_INFO, "\n");
745 }
746 }
747 }
748
749 for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) {
750 if (ost->attachment_filename) {
751 /* an attached file */
752 av_log(NULL, AV_LOG_INFO, " File %s -> Stream #%d:%d\n",
753 ost->attachment_filename, ost->file->index, ost->index);
754 continue;
755 }
756
757 if (ost->filter && !filtergraph_is_simple(ost->filter->graph)) {
758 /* output from a complex graph */
759 av_log(NULL, AV_LOG_INFO, " %s", ost->filter->name);
760 if (nb_filtergraphs > 1)
761 av_log(NULL, AV_LOG_INFO, " (graph %d)", ost->filter->graph->index);
762
763 av_log(NULL, AV_LOG_INFO, " -> Stream #%d:%d (%s)\n", ost->file->index,
764 ost->index, ost->enc->enc_ctx->codec->name);
765 continue;
766 }
767
768 av_log(NULL, AV_LOG_INFO, " Stream #%d:%d -> #%d:%d",
769 ost->ist->file->index,
770 ost->ist->index,
771 ost->file->index,
772 ost->index);
773 if (ost->enc) {
774 const AVCodec *in_codec = ost->ist->dec;
775 const AVCodec *out_codec = ost->enc->enc_ctx->codec;
776 const char *decoder_name = "?";
777 const char *in_codec_name = "?";
778 const char *encoder_name = "?";
779 const char *out_codec_name = "?";
780 const AVCodecDescriptor *desc;
781
782 if (in_codec) {
783 decoder_name = in_codec->name;
784 desc = avcodec_descriptor_get(in_codec->id);
785 if (desc)
786 in_codec_name = desc->name;
787 if (!strcmp(decoder_name, in_codec_name))
788 decoder_name = "native";
789 }
790
791 if (out_codec) {
792 encoder_name = out_codec->name;
793 desc = avcodec_descriptor_get(out_codec->id);
794 if (desc)
795 out_codec_name = desc->name;
796 if (!strcmp(encoder_name, out_codec_name))
797 encoder_name = "native";
798 }
799
800 av_log(NULL, AV_LOG_INFO, " (%s (%s) -> %s (%s))",
801 in_codec_name, decoder_name,
802 out_codec_name, encoder_name);
803 } else
804 av_log(NULL, AV_LOG_INFO, " (copy)");
805 av_log(NULL, AV_LOG_INFO, "\n");
806 }
807 }
808
809 static void set_tty_echo(int on)
810 {
811 #if HAVE_TERMIOS_H
812 struct termios tty;
813 if (tcgetattr(0, &tty) == 0) {
814 if (on) tty.c_lflag |= ECHO;
815 else tty.c_lflag &= ~ECHO;
816 tcsetattr(0, TCSANOW, &tty);
817 }
818 #endif
819 }
820
821 static int check_keyboard_interaction(int64_t cur_time)
822 {
823 int i, key;
824 static int64_t last_time;
825 /* read_key() returns 0 on EOF */
826 if (cur_time - last_time >= 100000) {
827 key = read_key();
828 last_time = cur_time;
829 }else
830 key = -1;
831 if (key == 'q') {
832 av_log(NULL, AV_LOG_INFO, "\n\n[q] command received. Exiting.\n\n");
833 return AVERROR_EXIT;
834 }
835 if (key == '+') av_log_set_level(av_log_get_level()+10);
836 if (key == '-') av_log_set_level(av_log_get_level()-10);
837 if (key == 'c' || key == 'C'){
838 char buf[4096], target[64], command[256], arg[256] = {0};
839 double time;
840 int k, n = 0;
841 fprintf(stderr, "\nEnter command: <target>|all <time>|-1 <command>[ <argument>]\n");
842 i = 0;
843 set_tty_echo(1);
844 while ((k = read_key()) != '\n' && k != '\r' && i < sizeof(buf)-1)
845 if (k > 0)
846 buf[i++] = k;
847 buf[i] = 0;
848 set_tty_echo(0);
849 fprintf(stderr, "\n");
850 if (k > 0 &&
851 (n = sscanf(buf, "%63[^ ] %lf %255[^ ] %255[^\n]", target, &time, command, arg)) >= 3) {
852 av_log(NULL, AV_LOG_DEBUG, "Processing command target:%s time:%f command:%s arg:%s",
853 target, time, command, arg);
854 for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) {
855 if (ost->fg_simple)
856 fg_send_command(ost->fg_simple, time, target, command, arg,
857 key == 'C');
858 }
859 for (i = 0; i < nb_filtergraphs; i++)
860 fg_send_command(filtergraphs[i], time, target, command, arg,
861 key == 'C');
862 } else {
863 av_log(NULL, AV_LOG_ERROR,
864 "Parse error, at least 3 arguments were expected, "
865 "only %d given in string '%s'\n", n, buf);
866 }
867 }
868 if (key == '?'){
869 fprintf(stderr, "key function\n"
870 "? show this help\n"
871 "+ increase verbosity\n"
872 "- decrease verbosity\n"
873 "c Send command to first matching filter supporting it\n"
874 "C Send/Queue command to all matching filters\n"
875 "h dump packets/hex press to cycle through the 3 states\n"
876 "q quit\n"
877 "s Show QP histogram\n"
878 );
879 }
880 return 0;
881 }
882
883 /*
884 * The following code is the main loop of the file converter
885 */
886 static int transcode(Scheduler *sch)
887 {
888 int ret = 0;
889 int64_t timer_start, transcode_ts = 0;
890
891 print_stream_maps();
892
893 atomic_store(&transcode_init_done, 1);
894
895 ret = sch_start(sch);
896 if (ret < 0)
897 return ret;
898
899 if (stdin_interaction) {
900 av_log(NULL, AV_LOG_INFO, "Press [q] to stop, [?] for help\n");
901 }
902
903 timer_start = av_gettime_relative();
904
905 while (!sch_wait(sch, stats_period, &transcode_ts)) {
906 int64_t cur_time= av_gettime_relative();
907
908 if (received_nb_signals)
909 break;
910
911 /* if 'q' pressed, exits */
912 if (stdin_interaction)
913 if (check_keyboard_interaction(cur_time) < 0)
914 break;
915
916 /* dump report by using the output first video and audio streams */
917 print_report(0, timer_start, cur_time, transcode_ts);
918 }
919
920 ret = sch_stop(sch, &transcode_ts);
921
922 /* write the trailer if needed */
923 for (int i = 0; i < nb_output_files; i++) {
924 int err = of_write_trailer(output_files[i]);
925 ret = err_merge(ret, err);
926 }
927
928 term_exit();
929
930 /* dump report by using the first video and audio streams */
931 print_report(1, timer_start, av_gettime_relative(), transcode_ts);
932
933 return ret;
934 }
935
936 static BenchmarkTimeStamps get_benchmark_time_stamps(void)
937 {
938 BenchmarkTimeStamps time_stamps = { av_gettime_relative() };
939 #if HAVE_GETRUSAGE
940 struct rusage rusage;
941
942 getrusage(RUSAGE_SELF, &rusage);
943 time_stamps.user_usec =
944 (rusage.ru_utime.tv_sec * 1000000LL) + rusage.ru_utime.tv_usec;
945 time_stamps.sys_usec =
946 (rusage.ru_stime.tv_sec * 1000000LL) + rusage.ru_stime.tv_usec;
947 #elif HAVE_GETPROCESSTIMES
948 HANDLE proc;
949 FILETIME c, e, k, u;
950 proc = GetCurrentProcess();
951 GetProcessTimes(proc, &c, &e, &k, &u);
952 time_stamps.user_usec =
953 ((int64_t)u.dwHighDateTime << 32 | u.dwLowDateTime) / 10;
954 time_stamps.sys_usec =
955 ((int64_t)k.dwHighDateTime << 32 | k.dwLowDateTime) / 10;
956 #else
957 time_stamps.user_usec = time_stamps.sys_usec = 0;
958 #endif
959 return time_stamps;
960 }
961
962 static int64_t getmaxrss(void)
963 {
964 #if HAVE_GETRUSAGE && HAVE_STRUCT_RUSAGE_RU_MAXRSS
965 struct rusage rusage;
966 getrusage(RUSAGE_SELF, &rusage);
967 return (int64_t)rusage.ru_maxrss * 1024;
968 #elif HAVE_GETPROCESSMEMORYINFO
969 HANDLE proc;
970 PROCESS_MEMORY_COUNTERS memcounters;
971 proc = GetCurrentProcess();
972 memcounters.cb = sizeof(memcounters);
973 GetProcessMemoryInfo(proc, &memcounters, sizeof(memcounters));
974 return memcounters.PeakPagefileUsage;
975 #else
976 return 0;
977 #endif
978 }
979
980 int main(int argc, char **argv)
981 {
982 Scheduler *sch = NULL;
983
984 int ret;
985 BenchmarkTimeStamps ti;
986
987 init_dynload();
988
989 setvbuf(stderr,NULL,_IONBF,0); /* win32 runtime needs this */
990
991 av_log_set_flags(AV_LOG_SKIP_REPEATED);
992 parse_loglevel(argc, argv, options);
993
994 #if CONFIG_AVDEVICE
995 avdevice_register_all();
996 #endif
997 avformat_network_init();
998
999 show_banner(argc, argv, options);
1000
1001 sch = sch_alloc();
1002 if (!sch) {
1003 ret = AVERROR(ENOMEM);
1004 goto finish;
1005 }
1006
1007 /* parse options and open all input/output files */
1008 ret = ffmpeg_parse_options(argc, argv, sch);
1009 if (ret < 0)
1010 goto finish;
1011
1012 if (nb_output_files <= 0 && nb_input_files == 0) {
1013 show_usage();
1014 av_log(NULL, AV_LOG_WARNING, "Use -h to get full help or, even better, run 'man %s'\n", program_name);
1015 ret = 1;
1016 goto finish;
1017 }
1018
1019 if (nb_output_files <= 0) {
1020 av_log(NULL, AV_LOG_FATAL, "At least one output file must be specified\n");
1021 ret = 1;
1022 goto finish;
1023 }
1024
1025 #if CONFIG_MEDIACODEC
1026 android_binder_threadpool_init_if_required();
1027 #endif
1028
1029 current_time = ti = get_benchmark_time_stamps();
1030 ret = transcode(sch);
1031 if (ret >= 0 && do_benchmark) {
1032 int64_t utime, stime, rtime;
1033 current_time = get_benchmark_time_stamps();
1034 utime = current_time.user_usec - ti.user_usec;
1035 stime = current_time.sys_usec - ti.sys_usec;
1036 rtime = current_time.real_usec - ti.real_usec;
1037 av_log(NULL, AV_LOG_INFO,
1038 "bench: utime=%0.3fs stime=%0.3fs rtime=%0.3fs\n",
1039 utime / 1000000.0, stime / 1000000.0, rtime / 1000000.0);
1040 }
1041
1042 ret = received_nb_signals ? 255 :
1043 (ret == FFMPEG_ERROR_RATE_EXCEEDED) ? 69 : ret;
1044
1045 finish:
1046 if (ret == AVERROR_EXIT)
1047 ret = 0;
1048
1049 ffmpeg_cleanup(ret);
1050
1051 sch_free(&sch);
1052
1053 av_log(NULL, AV_LOG_VERBOSE, "\n");
1054 av_log(NULL, AV_LOG_VERBOSE, "Exiting with exit code %d\n", ret);
1055
1056 return ret;
1057 }