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