FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/fftools/ffmpeg.c
Date: 2024-04-23 06:12:56
Exec Total Coverage
Lines: 299 438 68.3%
Functions: 20 26 76.9%
Branches: 182 288 63.2%

Line Branch Exec Source
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 13513 static void term_exit_sigsafe(void)
124 {
125 #if HAVE_TERMIOS_H
126
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13513 times.
13513 if(restore_tty)
127 tcsetattr (0, TCSANOW, &oldtty);
128 #endif
129 13513 }
130
131 13513 void term_exit(void)
132 {
133 13513 av_log(NULL, AV_LOG_QUIET, "%s", "");
134 13513 term_exit_sigsafe();
135 13513 }
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 6756 void term_init(void)
202 {
203 #if defined __linux__
204 6756 struct sigaction action = {0};
205 6756 action.sa_handler = sigterm_handler;
206
207 /* block other interrupts while processing this one */
208 6756 sigfillset(&action.sa_mask);
209
210 /* restart interruptible functions (i.e. don't fail with EINTR) */
211 6756 action.sa_flags = SA_RESTART;
212 #endif
213
214 #if HAVE_TERMIOS_H
215
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6756 times.
6756 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 6756 SIGNAL(SIGINT , sigterm_handler); /* Interrupt (ANSI). */
237 6756 SIGNAL(SIGTERM, sigterm_handler); /* Termination (ANSI). */
238 #ifdef SIGXCPU
239 6756 SIGNAL(SIGXCPU, sigterm_handler);
240 #endif
241 #ifdef SIGPIPE
242 6756 signal(SIGPIPE, SIG_IGN); /* Broken pipe (POSIX). */
243 #endif
244 #if HAVE_SETCONSOLECTRLHANDLER
245 SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE);
246 #endif
247 6756 }
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 read(0, &ch, 1);
289 return ch;
290 }else{
291 return -1;
292 }
293 }
294 # endif
295 if(kbhit())
296 return(getch());
297 #endif
298 return -1;
299 }
300
301 684487 static int decode_interrupt_cb(void *ctx)
302 {
303 684487 return received_nb_signals > atomic_load(&transcode_init_done);
304 }
305
306 const AVIOInterruptCB int_cb = { decode_interrupt_cb, NULL };
307
308 6757 static void ffmpeg_cleanup(int ret)
309 {
310
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6757 times.
6757 if (do_benchmark) {
311 int maxrss = getmaxrss() / 1024;
312 av_log(NULL, AV_LOG_INFO, "bench: maxrss=%iKiB\n", maxrss);
313 }
314
315
2/2
✓ Branch 0 taken 117 times.
✓ Branch 1 taken 6757 times.
6874 for (int i = 0; i < nb_filtergraphs; i++)
316 117 fg_free(&filtergraphs[i]);
317 6757 av_freep(&filtergraphs);
318
319
2/2
✓ Branch 0 taken 6758 times.
✓ Branch 1 taken 6757 times.
13515 for (int i = 0; i < nb_output_files; i++)
320 6758 of_free(&output_files[i]);
321
322
2/2
✓ Branch 0 taken 6787 times.
✓ Branch 1 taken 6757 times.
13544 for (int i = 0; i < nb_input_files; i++)
323 6787 ifile_close(&input_files[i]);
324
325
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6757 times.
6758 for (int i = 0; i < nb_decoders; i++)
326 1 dec_free(&decoders[i]);
327 6757 av_freep(&decoders);
328
329
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6757 times.
6757 if (vstats_file) {
330 if (fclose(vstats_file))
331 av_log(NULL, AV_LOG_ERROR,
332 "Error closing vstats file, loss of information possible: %s\n",
333 av_err2str(AVERROR(errno)));
334 }
335 6757 av_freep(&vstats_filename);
336 6757 of_enc_stats_close();
337
338 6757 hw_device_free_all();
339
340 6757 av_freep(&filter_nbthreads);
341
342 6757 av_freep(&input_files);
343 6757 av_freep(&output_files);
344
345 6757 uninit_opts();
346
347 6757 avformat_network_deinit();
348
349
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6757 times.
6757 if (received_sigterm) {
350 av_log(NULL, AV_LOG_INFO, "Exiting normally, received signal %d.\n",
351 (int) received_sigterm);
352
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6756 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
6757 } else if (ret && atomic_load(&transcode_init_done)) {
353 1 av_log(NULL, AV_LOG_INFO, "Conversion failed!\n");
354 }
355 6757 term_exit();
356 6757 ffmpeg_exited = 1;
357 6757 }
358
359 27763 OutputStream *ost_iter(OutputStream *prev)
360 {
361
2/2
✓ Branch 0 taken 14226 times.
✓ Branch 1 taken 13537 times.
27763 int of_idx = prev ? prev->file->index : 0;
362
2/2
✓ Branch 0 taken 14226 times.
✓ Branch 1 taken 13537 times.
27763 int ost_idx = prev ? prev->index + 1 : 0;
363
364
2/2
✓ Branch 0 taken 27767 times.
✓ Branch 1 taken 13537 times.
41304 for (; of_idx < nb_output_files; of_idx++) {
365 27767 OutputFile *of = output_files[of_idx];
366
2/2
✓ Branch 0 taken 14226 times.
✓ Branch 1 taken 13541 times.
27767 if (ost_idx < of->nb_streams)
367 14226 return of->streams[ost_idx];
368
369 13541 ost_idx = 0;
370 }
371
372 13537 return NULL;
373 }
374
375 14219 InputStream *ist_iter(InputStream *prev)
376 {
377
2/2
✓ Branch 0 taken 7341 times.
✓ Branch 1 taken 6878 times.
14219 int if_idx = prev ? prev->file->index : 0;
378
2/2
✓ Branch 0 taken 7341 times.
✓ Branch 1 taken 6878 times.
14219 int ist_idx = prev ? prev->index + 1 : 0;
379
380
2/2
✓ Branch 0 taken 14270 times.
✓ Branch 1 taken 6775 times.
21045 for (; if_idx < nb_input_files; if_idx++) {
381 14270 InputFile *f = input_files[if_idx];
382
2/2
✓ Branch 0 taken 7444 times.
✓ Branch 1 taken 6826 times.
14270 if (ist_idx < f->nb_streams)
383 7444 return f->streams[ist_idx];
384
385 6826 ist_idx = 0;
386 }
387
388 6775 return NULL;
389 }
390
391 1320094 static void frame_data_free(void *opaque, uint8_t *data)
392 {
393 1320094 FrameData *fd = (FrameData *)data;
394
395 1320094 avcodec_parameters_free(&fd->par_enc);
396
397 1320094 av_free(data);
398 1320094 }
399
400 2720013 static int frame_data_ensure(AVBufferRef **dst, int writable)
401 {
402 2720013 AVBufferRef *src = *dst;
403
404
6/6
✓ Branch 0 taken 2256805 times.
✓ Branch 1 taken 463208 times.
✓ Branch 2 taken 2250457 times.
✓ Branch 3 taken 6348 times.
✓ Branch 5 taken 856886 times.
✓ Branch 6 taken 1393571 times.
2720013 if (!src || (writable && !av_buffer_is_writable(src))) {
405 FrameData *fd;
406
407 1320094 fd = av_mallocz(sizeof(*fd));
408
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1320094 times.
1320094 if (!fd)
409 return AVERROR(ENOMEM);
410
411 1320094 *dst = av_buffer_create((uint8_t *)fd, sizeof(*fd),
412 frame_data_free, NULL, 0);
413
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1320094 times.
1320094 if (!*dst) {
414 av_buffer_unref(&src);
415 av_freep(&fd);
416 return AVERROR(ENOMEM);
417 }
418
419
2/2
✓ Branch 0 taken 856886 times.
✓ Branch 1 taken 463208 times.
1320094 if (src) {
420 856886 const FrameData *fd_src = (const FrameData *)src->data;
421
422 856886 memcpy(fd, fd_src, sizeof(*fd));
423 856886 fd->par_enc = NULL;
424
425
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 856885 times.
856886 if (fd_src->par_enc) {
426 1 int ret = 0;
427
428 1 fd->par_enc = avcodec_parameters_alloc();
429 2 ret = fd->par_enc ?
430
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 avcodec_parameters_copy(fd->par_enc, fd_src->par_enc) :
431 AVERROR(ENOMEM);
432
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0) {
433 av_buffer_unref(dst);
434 av_buffer_unref(&src);
435 return ret;
436 }
437 }
438
439 856886 av_buffer_unref(&src);
440 } else {
441 463208 fd->dec.frame_num = UINT64_MAX;
442 463208 fd->dec.pts = AV_NOPTS_VALUE;
443
444
2/2
✓ Branch 0 taken 3242456 times.
✓ Branch 1 taken 463208 times.
3705664 for (unsigned i = 0; i < FF_ARRAY_ELEMS(fd->wallclock); i++)
445 3242456 fd->wallclock[i] = INT64_MIN;
446 }
447 }
448
449 2720013 return 0;
450 }
451
452 1500853 FrameData *frame_data(AVFrame *frame)
453 {
454 1500853 int ret = frame_data_ensure(&frame->opaque_ref, 1);
455
1/2
✓ Branch 0 taken 1500853 times.
✗ Branch 1 not taken.
1500853 return ret < 0 ? NULL : (FrameData*)frame->opaque_ref->data;
456 }
457
458 6431 const FrameData *frame_data_c(AVFrame *frame)
459 {
460 6431 int ret = frame_data_ensure(&frame->opaque_ref, 0);
461
1/2
✓ Branch 0 taken 6431 times.
✗ Branch 1 not taken.
6431 return ret < 0 ? NULL : (const FrameData*)frame->opaque_ref->data;
462 }
463
464 1212729 FrameData *packet_data(AVPacket *pkt)
465 {
466 1212729 int ret = frame_data_ensure(&pkt->opaque_ref, 1);
467
1/2
✓ Branch 0 taken 1212729 times.
✗ Branch 1 not taken.
1212729 return ret < 0 ? NULL : (FrameData*)pkt->opaque_ref->data;
468 }
469
470 const FrameData *packet_data_c(AVPacket *pkt)
471 {
472 int ret = frame_data_ensure(&pkt->opaque_ref, 0);
473 return ret < 0 ? NULL : (const FrameData*)pkt->opaque_ref->data;
474 }
475
476 6787 void remove_avoptions(AVDictionary **a, AVDictionary *b)
477 {
478 6787 const AVDictionaryEntry *t = NULL;
479
480
2/2
✓ Branch 1 taken 21630 times.
✓ Branch 2 taken 6787 times.
28417 while ((t = av_dict_iterate(b, t))) {
481 21630 av_dict_set(a, t->key, NULL, AV_DICT_MATCH_CASE);
482 }
483 6787 }
484
485 19650 int check_avoptions(AVDictionary *m)
486 {
487 const AVDictionaryEntry *t;
488
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 19650 times.
19650 if ((t = av_dict_get(m, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
489 av_log(NULL, AV_LOG_FATAL, "Option %s not found.\n", t->key);
490 return AVERROR_OPTION_NOT_FOUND;
491 }
492
493 19650 return 0;
494 }
495
496 2704938 void update_benchmark(const char *fmt, ...)
497 {
498
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2704938 times.
2704938 if (do_benchmark_all) {
499 BenchmarkTimeStamps t = get_benchmark_time_stamps();
500 va_list va;
501 char buf[1024];
502
503 if (fmt) {
504 va_start(va, fmt);
505 vsnprintf(buf, sizeof(buf), fmt, va);
506 va_end(va);
507 av_log(NULL, AV_LOG_INFO,
508 "bench: %8" PRIu64 " user %8" PRIu64 " sys %8" PRIu64 " real %s \n",
509 t.user_usec - current_time.user_usec,
510 t.sys_usec - current_time.sys_usec,
511 t.real_usec - current_time.real_usec, buf);
512 }
513 current_time = t;
514 }
515 2704938 }
516
517 21172 static void print_report(int is_last_report, int64_t timer_start, int64_t cur_time, int64_t pts)
518 {
519 AVBPrint buf, buf_script;
520 21172 int64_t total_size = of_filesize(output_files[0]);
521 int vid;
522 double bitrate;
523 double speed;
524 static int64_t last_time = -1;
525 static int first_report = 1;
526 21172 uint64_t nb_frames_dup = 0, nb_frames_drop = 0;
527 int mins, secs, us;
528 int64_t hours;
529 const char *hours_sign;
530 int ret;
531 float t;
532
533
5/6
✓ Branch 0 taken 21120 times.
✓ Branch 1 taken 52 times.
✓ Branch 2 taken 14391 times.
✓ Branch 3 taken 6729 times.
✓ Branch 4 taken 14391 times.
✗ Branch 5 not taken.
21172 if (!print_stats && !is_last_report && !progress_avio)
534 14391 return;
535
536
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 6756 times.
6781 if (!is_last_report) {
537
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 13 times.
25 if (last_time == -1) {
538 12 last_time = cur_time;
539 }
540
3/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
25 if (((cur_time - last_time) < stats_period && !first_report) ||
541
3/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
25 (first_report && atomic_load(&nb_output_dumped) < nb_output_files))
542 return;
543 25 last_time = cur_time;
544 }
545
546 6781 t = (cur_time-timer_start) / 1000000.0;
547
548 6781 vid = 0;
549 6781 av_bprint_init(&buf, 0, AV_BPRINT_SIZE_AUTOMATIC);
550 6781 av_bprint_init(&buf_script, 0, AV_BPRINT_SIZE_AUTOMATIC);
551
2/2
✓ Branch 2 taken 7126 times.
✓ Branch 3 taken 6781 times.
13907 for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) {
552
2/2
✓ Branch 0 taken 6498 times.
✓ Branch 1 taken 628 times.
7126 const float q = ost->enc ? atomic_load(&ost->quality) / (float) FF_QP2LAMBDA : -1;
553
554
4/4
✓ Branch 0 taken 112 times.
✓ Branch 1 taken 7014 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 100 times.
7126 if (vid && ost->type == AVMEDIA_TYPE_VIDEO) {
555 12 av_bprintf(&buf, "q=%2.1f ", q);
556 12 av_bprintf(&buf_script, "stream_%d_%d_q=%.1f\n",
557 12 ost->file->index, ost->index, q);
558 }
559
6/6
✓ Branch 0 taken 7014 times.
✓ Branch 1 taken 112 times.
✓ Branch 2 taken 5512 times.
✓ Branch 3 taken 1502 times.
✓ Branch 4 taken 5187 times.
✓ Branch 5 taken 325 times.
7126 if (!vid && ost->type == AVMEDIA_TYPE_VIDEO && ost->filter) {
560 float fps;
561 5187 uint64_t frame_number = atomic_load(&ost->packets_written);
562
563
2/2
✓ Branch 0 taken 977 times.
✓ Branch 1 taken 4210 times.
5187 fps = t > 1 ? frame_number / t : 0;
564 5187 av_bprintf(&buf, "frame=%5"PRId64" fps=%3.*f q=%3.1f ",
565 frame_number, fps < 9.95, fps, q);
566 5187 av_bprintf(&buf_script, "frame=%"PRId64"\n", frame_number);
567 5187 av_bprintf(&buf_script, "fps=%.2f\n", fps);
568 5187 av_bprintf(&buf_script, "stream_%d_%d_q=%.1f\n",
569 5187 ost->file->index, ost->index, q);
570
2/2
✓ Branch 0 taken 5186 times.
✓ Branch 1 taken 1 times.
5187 if (is_last_report)
571 5186 av_bprintf(&buf, "L");
572
573 5187 nb_frames_dup = atomic_load(&ost->filter->nb_frames_dup);
574 5187 nb_frames_drop = atomic_load(&ost->filter->nb_frames_drop);
575
576 5187 vid = 1;
577 }
578 }
579
580
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 6768 times.
6781 if (copy_ts) {
581
2/4
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
13 if (copy_ts_first_pts == AV_NOPTS_VALUE && pts > 1)
582 13 copy_ts_first_pts = pts;
583
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 if (copy_ts_first_pts != AV_NOPTS_VALUE)
584 13 pts -= copy_ts_first_pts;
585 }
586
587
2/2
✓ Branch 0 taken 122 times.
✓ Branch 1 taken 6659 times.
6781 us = FFABS64U(pts) % AV_TIME_BASE;
588
2/2
✓ Branch 0 taken 122 times.
✓ Branch 1 taken 6659 times.
6781 secs = FFABS64U(pts) / AV_TIME_BASE % 60;
589
2/2
✓ Branch 0 taken 122 times.
✓ Branch 1 taken 6659 times.
6781 mins = FFABS64U(pts) / AV_TIME_BASE / 60 % 60;
590
2/2
✓ Branch 0 taken 122 times.
✓ Branch 1 taken 6659 times.
6781 hours = FFABS64U(pts) / AV_TIME_BASE / 3600;
591
2/2
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 6675 times.
6781 hours_sign = (pts < 0) ? "-" : "";
592
593
6/6
✓ Branch 0 taken 6675 times.
✓ Branch 1 taken 106 times.
✓ Branch 2 taken 6659 times.
✓ Branch 3 taken 16 times.
✓ Branch 4 taken 6546 times.
✓ Branch 5 taken 113 times.
6781 bitrate = pts != AV_NOPTS_VALUE && pts && total_size >= 0 ? total_size * 8 / (pts / 1000.0) : -1;
594
3/4
✓ Branch 0 taken 6675 times.
✓ Branch 1 taken 106 times.
✓ Branch 2 taken 6675 times.
✗ Branch 3 not taken.
6781 speed = pts != AV_NOPTS_VALUE && t != 0.0 ? (double)pts / AV_TIME_BASE / t : -1;
595
596
2/2
✓ Branch 0 taken 115 times.
✓ Branch 1 taken 6666 times.
6781 if (total_size < 0) av_bprintf(&buf, "size=N/A time=");
597 6666 else av_bprintf(&buf, "size=%8.0fKiB time=", total_size / 1024.0);
598
2/2
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 6675 times.
6781 if (pts == AV_NOPTS_VALUE) {
599 106 av_bprintf(&buf, "N/A ");
600 } else {
601 6675 av_bprintf(&buf, "%s%02"PRId64":%02d:%02d.%02d ",
602 hours_sign, hours, mins, secs, (100 * us) / AV_TIME_BASE);
603 }
604
605
2/2
✓ Branch 0 taken 235 times.
✓ Branch 1 taken 6546 times.
6781 if (bitrate < 0) {
606 235 av_bprintf(&buf, "bitrate=N/A");
607 235 av_bprintf(&buf_script, "bitrate=N/A\n");
608 }else{
609 6546 av_bprintf(&buf, "bitrate=%6.1fkbits/s", bitrate);
610 6546 av_bprintf(&buf_script, "bitrate=%6.1fkbits/s\n", bitrate);
611 }
612
613
2/2
✓ Branch 0 taken 115 times.
✓ Branch 1 taken 6666 times.
6781 if (total_size < 0) av_bprintf(&buf_script, "total_size=N/A\n");
614 6666 else av_bprintf(&buf_script, "total_size=%"PRId64"\n", total_size);
615
2/2
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 6675 times.
6781 if (pts == AV_NOPTS_VALUE) {
616 106 av_bprintf(&buf_script, "out_time_us=N/A\n");
617 106 av_bprintf(&buf_script, "out_time_ms=N/A\n");
618 106 av_bprintf(&buf_script, "out_time=N/A\n");
619 } else {
620 6675 av_bprintf(&buf_script, "out_time_us=%"PRId64"\n", pts);
621 6675 av_bprintf(&buf_script, "out_time_ms=%"PRId64"\n", pts);
622 6675 av_bprintf(&buf_script, "out_time=%s%02"PRId64":%02d:%02d.%06d\n",
623 hours_sign, hours, mins, secs, us);
624 }
625
626
4/4
✓ Branch 0 taken 6765 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 6758 times.
6781 if (nb_frames_dup || nb_frames_drop)
627 23 av_bprintf(&buf, " dup=%"PRId64" drop=%"PRId64, nb_frames_dup, nb_frames_drop);
628 6781 av_bprintf(&buf_script, "dup_frames=%"PRId64"\n", nb_frames_dup);
629 6781 av_bprintf(&buf_script, "drop_frames=%"PRId64"\n", nb_frames_drop);
630
631
2/2
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 6675 times.
6781 if (speed < 0) {
632 106 av_bprintf(&buf, " speed=N/A");
633 106 av_bprintf(&buf_script, "speed=N/A\n");
634 } else {
635 6675 av_bprintf(&buf, " speed=%4.3gx", speed);
636 6675 av_bprintf(&buf_script, "speed=%4.3gx\n", speed);
637 }
638
639
3/4
✓ Branch 0 taken 6729 times.
✓ Branch 1 taken 52 times.
✓ Branch 2 taken 6729 times.
✗ Branch 3 not taken.
6781 if (print_stats || is_last_report) {
640
2/2
✓ Branch 0 taken 6756 times.
✓ Branch 1 taken 25 times.
6781 const char end = is_last_report ? '\n' : '\r';
641
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6781 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6781 if (print_stats==1 && AV_LOG_INFO > av_log_get_level()) {
642 fprintf(stderr, "%s %c", buf.str, end);
643 } else
644 6781 av_log(NULL, AV_LOG_INFO, "%s %c", buf.str, end);
645
646 6781 fflush(stderr);
647 }
648 6781 av_bprint_finalize(&buf, NULL);
649
650
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6781 times.
6781 if (progress_avio) {
651 av_bprintf(&buf_script, "progress=%s\n",
652 is_last_report ? "end" : "continue");
653 avio_write(progress_avio, buf_script.str,
654 FFMIN(buf_script.len, buf_script.size - 1));
655 avio_flush(progress_avio);
656 av_bprint_finalize(&buf_script, NULL);
657 if (is_last_report) {
658 if ((ret = avio_closep(&progress_avio)) < 0)
659 av_log(NULL, AV_LOG_ERROR,
660 "Error closing progress log, loss of information possible: %s\n", av_err2str(ret));
661 }
662 }
663
664 6781 first_report = 0;
665 }
666
667 6756 static void print_stream_maps(void)
668 {
669 6756 av_log(NULL, AV_LOG_INFO, "Stream mapping:\n");
670
2/2
✓ Branch 2 taken 7289 times.
✓ Branch 3 taken 6756 times.
14045 for (InputStream *ist = ist_iter(NULL); ist; ist = ist_iter(ist)) {
671
2/2
✓ Branch 0 taken 6398 times.
✓ Branch 1 taken 7289 times.
13687 for (int j = 0; j < ist->nb_filters; j++) {
672
2/2
✓ Branch 1 taken 131 times.
✓ Branch 2 taken 6267 times.
6398 if (!filtergraph_is_simple(ist->filters[j]->graph)) {
673 av_log(NULL, AV_LOG_INFO, " Stream #%d:%d (%s) -> %s",
674 131 ist->file->index, ist->index, ist->dec ? ist->dec->name : "?",
675
1/2
✓ Branch 0 taken 131 times.
✗ Branch 1 not taken.
131 ist->filters[j]->name);
676
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 131 times.
131 if (nb_filtergraphs > 1)
677 av_log(NULL, AV_LOG_INFO, " (graph %d)", ist->filters[j]->graph->index);
678 131 av_log(NULL, AV_LOG_INFO, "\n");
679 }
680 }
681 }
682
683
2/2
✓ Branch 2 taken 7100 times.
✓ Branch 3 taken 6756 times.
13856 for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) {
684
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7099 times.
7100 if (ost->attachment_filename) {
685 /* an attached file */
686 1 av_log(NULL, AV_LOG_INFO, " File %s -> Stream #%d:%d\n",
687 1 ost->attachment_filename, ost->file->index, ost->index);
688 1 continue;
689 }
690
691
4/4
✓ Branch 0 taken 6434 times.
✓ Branch 1 taken 665 times.
✓ Branch 3 taken 167 times.
✓ Branch 4 taken 6267 times.
7099 if (ost->filter && !filtergraph_is_simple(ost->filter->graph)) {
692 /* output from a complex graph */
693 167 av_log(NULL, AV_LOG_INFO, " %s", ost->filter->name);
694
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 167 times.
167 if (nb_filtergraphs > 1)
695 av_log(NULL, AV_LOG_INFO, " (graph %d)", ost->filter->graph->index);
696
697 167 av_log(NULL, AV_LOG_INFO, " -> Stream #%d:%d (%s)\n", ost->file->index,
698 167 ost->index, ost->enc_ctx->codec->name);
699 167 continue;
700 }
701
702 6932 av_log(NULL, AV_LOG_INFO, " Stream #%d:%d -> #%d:%d",
703 6932 ost->ist->file->index,
704 6932 ost->ist->index,
705 6932 ost->file->index,
706 ost->index);
707
2/2
✓ Branch 0 taken 6305 times.
✓ Branch 1 taken 627 times.
6932 if (ost->enc_ctx) {
708 6305 const AVCodec *in_codec = ost->ist->dec;
709 6305 const AVCodec *out_codec = ost->enc_ctx->codec;
710 6305 const char *decoder_name = "?";
711 6305 const char *in_codec_name = "?";
712 6305 const char *encoder_name = "?";
713 6305 const char *out_codec_name = "?";
714 const AVCodecDescriptor *desc;
715
716
1/2
✓ Branch 0 taken 6305 times.
✗ Branch 1 not taken.
6305 if (in_codec) {
717 6305 decoder_name = in_codec->name;
718 6305 desc = avcodec_descriptor_get(in_codec->id);
719
1/2
✓ Branch 0 taken 6305 times.
✗ Branch 1 not taken.
6305 if (desc)
720 6305 in_codec_name = desc->name;
721
2/2
✓ Branch 0 taken 6139 times.
✓ Branch 1 taken 166 times.
6305 if (!strcmp(decoder_name, in_codec_name))
722 6139 decoder_name = "native";
723 }
724
725
1/2
✓ Branch 0 taken 6305 times.
✗ Branch 1 not taken.
6305 if (out_codec) {
726 6305 encoder_name = out_codec->name;
727 6305 desc = avcodec_descriptor_get(out_codec->id);
728
1/2
✓ Branch 0 taken 6305 times.
✗ Branch 1 not taken.
6305 if (desc)
729 6305 out_codec_name = desc->name;
730
2/2
✓ Branch 0 taken 6196 times.
✓ Branch 1 taken 109 times.
6305 if (!strcmp(encoder_name, out_codec_name))
731 6196 encoder_name = "native";
732 }
733
734 6305 av_log(NULL, AV_LOG_INFO, " (%s (%s) -> %s (%s))",
735 in_codec_name, decoder_name,
736 out_codec_name, encoder_name);
737 } else
738 627 av_log(NULL, AV_LOG_INFO, " (copy)");
739 6932 av_log(NULL, AV_LOG_INFO, "\n");
740 }
741 6756 }
742
743 static void set_tty_echo(int on)
744 {
745 #if HAVE_TERMIOS_H
746 struct termios tty;
747 if (tcgetattr(0, &tty) == 0) {
748 if (on) tty.c_lflag |= ECHO;
749 else tty.c_lflag &= ~ECHO;
750 tcsetattr(0, TCSANOW, &tty);
751 }
752 #endif
753 }
754
755 static int check_keyboard_interaction(int64_t cur_time)
756 {
757 int i, key;
758 static int64_t last_time;
759 if (received_nb_signals)
760 return AVERROR_EXIT;
761 /* read_key() returns 0 on EOF */
762 if (cur_time - last_time >= 100000) {
763 key = read_key();
764 last_time = cur_time;
765 }else
766 key = -1;
767 if (key == 'q') {
768 av_log(NULL, AV_LOG_INFO, "\n\n[q] command received. Exiting.\n\n");
769 return AVERROR_EXIT;
770 }
771 if (key == '+') av_log_set_level(av_log_get_level()+10);
772 if (key == '-') av_log_set_level(av_log_get_level()-10);
773 if (key == 'c' || key == 'C'){
774 char buf[4096], target[64], command[256], arg[256] = {0};
775 double time;
776 int k, n = 0;
777 fprintf(stderr, "\nEnter command: <target>|all <time>|-1 <command>[ <argument>]\n");
778 i = 0;
779 set_tty_echo(1);
780 while ((k = read_key()) != '\n' && k != '\r' && i < sizeof(buf)-1)
781 if (k > 0)
782 buf[i++] = k;
783 buf[i] = 0;
784 set_tty_echo(0);
785 fprintf(stderr, "\n");
786 if (k > 0 &&
787 (n = sscanf(buf, "%63[^ ] %lf %255[^ ] %255[^\n]", target, &time, command, arg)) >= 3) {
788 av_log(NULL, AV_LOG_DEBUG, "Processing command target:%s time:%f command:%s arg:%s",
789 target, time, command, arg);
790 for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) {
791 if (ost->fg_simple)
792 fg_send_command(ost->fg_simple, time, target, command, arg,
793 key == 'C');
794 }
795 for (i = 0; i < nb_filtergraphs; i++)
796 fg_send_command(filtergraphs[i], time, target, command, arg,
797 key == 'C');
798 } else {
799 av_log(NULL, AV_LOG_ERROR,
800 "Parse error, at least 3 arguments were expected, "
801 "only %d given in string '%s'\n", n, buf);
802 }
803 }
804 if (key == '?'){
805 fprintf(stderr, "key function\n"
806 "? show this help\n"
807 "+ increase verbosity\n"
808 "- decrease verbosity\n"
809 "c Send command to first matching filter supporting it\n"
810 "C Send/Queue command to all matching filters\n"
811 "h dump packets/hex press to cycle through the 3 states\n"
812 "q quit\n"
813 "s Show QP histogram\n"
814 );
815 }
816 return 0;
817 }
818
819 /*
820 * The following code is the main loop of the file converter
821 */
822 6756 static int transcode(Scheduler *sch)
823 {
824 6756 int ret = 0;
825 6756 int64_t timer_start, transcode_ts = 0;
826
827 6756 print_stream_maps();
828
829 6756 atomic_store(&transcode_init_done, 1);
830
831 6756 ret = sch_start(sch);
832
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6756 times.
6756 if (ret < 0)
833 return ret;
834
835
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6756 times.
6756 if (stdin_interaction) {
836 av_log(NULL, AV_LOG_INFO, "Press [q] to stop, [?] for help\n");
837 }
838
839 6756 timer_start = av_gettime_relative();
840
841
2/2
✓ Branch 1 taken 14416 times.
✓ Branch 2 taken 6756 times.
21172 while (!sch_wait(sch, stats_period, &transcode_ts)) {
842 14416 int64_t cur_time= av_gettime_relative();
843
844 /* if 'q' pressed, exits */
845
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14416 times.
14416 if (stdin_interaction)
846 if (check_keyboard_interaction(cur_time) < 0)
847 break;
848
849 /* dump report by using the output first video and audio streams */
850 14416 print_report(0, timer_start, cur_time, transcode_ts);
851 }
852
853 6756 ret = sch_stop(sch, &transcode_ts);
854
855 /* write the trailer if needed */
856
2/2
✓ Branch 0 taken 6758 times.
✓ Branch 1 taken 6756 times.
13514 for (int i = 0; i < nb_output_files; i++) {
857 6758 int err = of_write_trailer(output_files[i]);
858 6758 ret = err_merge(ret, err);
859 }
860
861 6756 term_exit();
862
863 /* dump report by using the first video and audio streams */
864 6756 print_report(1, timer_start, av_gettime_relative(), transcode_ts);
865
866 6756 return ret;
867 }
868
869 6756 static BenchmarkTimeStamps get_benchmark_time_stamps(void)
870 {
871 6756 BenchmarkTimeStamps time_stamps = { av_gettime_relative() };
872 #if HAVE_GETRUSAGE
873 struct rusage rusage;
874
875 6756 getrusage(RUSAGE_SELF, &rusage);
876 6756 time_stamps.user_usec =
877 6756 (rusage.ru_utime.tv_sec * 1000000LL) + rusage.ru_utime.tv_usec;
878 6756 time_stamps.sys_usec =
879 6756 (rusage.ru_stime.tv_sec * 1000000LL) + rusage.ru_stime.tv_usec;
880 #elif HAVE_GETPROCESSTIMES
881 HANDLE proc;
882 FILETIME c, e, k, u;
883 proc = GetCurrentProcess();
884 GetProcessTimes(proc, &c, &e, &k, &u);
885 time_stamps.user_usec =
886 ((int64_t)u.dwHighDateTime << 32 | u.dwLowDateTime) / 10;
887 time_stamps.sys_usec =
888 ((int64_t)k.dwHighDateTime << 32 | k.dwLowDateTime) / 10;
889 #else
890 time_stamps.user_usec = time_stamps.sys_usec = 0;
891 #endif
892 6756 return time_stamps;
893 }
894
895 static int64_t getmaxrss(void)
896 {
897 #if HAVE_GETRUSAGE && HAVE_STRUCT_RUSAGE_RU_MAXRSS
898 struct rusage rusage;
899 getrusage(RUSAGE_SELF, &rusage);
900 return (int64_t)rusage.ru_maxrss * 1024;
901 #elif HAVE_GETPROCESSMEMORYINFO
902 HANDLE proc;
903 PROCESS_MEMORY_COUNTERS memcounters;
904 proc = GetCurrentProcess();
905 memcounters.cb = sizeof(memcounters);
906 GetProcessMemoryInfo(proc, &memcounters, sizeof(memcounters));
907 return memcounters.PeakPagefileUsage;
908 #else
909 return 0;
910 #endif
911 }
912
913 6757 int main(int argc, char **argv)
914 {
915 6757 Scheduler *sch = NULL;
916
917 int ret;
918 BenchmarkTimeStamps ti;
919
920 6757 init_dynload();
921
922 6757 setvbuf(stderr,NULL,_IONBF,0); /* win32 runtime needs this */
923
924 6757 av_log_set_flags(AV_LOG_SKIP_REPEATED);
925 6757 parse_loglevel(argc, argv, options);
926
927 #if CONFIG_AVDEVICE
928 6757 avdevice_register_all();
929 #endif
930 6757 avformat_network_init();
931
932 6757 show_banner(argc, argv, options);
933
934 6757 sch = sch_alloc();
935
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6757 times.
6757 if (!sch) {
936 ret = AVERROR(ENOMEM);
937 goto finish;
938 }
939
940 /* parse options and open all input/output files */
941 6757 ret = ffmpeg_parse_options(argc, argv, sch);
942
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6756 times.
6757 if (ret < 0)
943 1 goto finish;
944
945
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6756 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
6756 if (nb_output_files <= 0 && nb_input_files == 0) {
946 show_usage();
947 av_log(NULL, AV_LOG_WARNING, "Use -h to get full help or, even better, run 'man %s'\n", program_name);
948 ret = 1;
949 goto finish;
950 }
951
952
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6756 times.
6756 if (nb_output_files <= 0) {
953 av_log(NULL, AV_LOG_FATAL, "At least one output file must be specified\n");
954 ret = 1;
955 goto finish;
956 }
957
958 6756 current_time = ti = get_benchmark_time_stamps();
959 6756 ret = transcode(sch);
960
3/4
✓ Branch 0 taken 6755 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6755 times.
6756 if (ret >= 0 && do_benchmark) {
961 int64_t utime, stime, rtime;
962 current_time = get_benchmark_time_stamps();
963 utime = current_time.user_usec - ti.user_usec;
964 stime = current_time.sys_usec - ti.sys_usec;
965 rtime = current_time.real_usec - ti.real_usec;
966 av_log(NULL, AV_LOG_INFO,
967 "bench: utime=%0.3fs stime=%0.3fs rtime=%0.3fs\n",
968 utime / 1000000.0, stime / 1000000.0, rtime / 1000000.0);
969 }
970
971
1/2
✓ Branch 0 taken 6756 times.
✗ Branch 1 not taken.
13512 ret = received_nb_signals ? 255 :
972
2/2
✓ Branch 0 taken 6755 times.
✓ Branch 1 taken 1 times.
6756 (ret == FFMPEG_ERROR_RATE_EXCEEDED) ? 69 : ret;
973
974 6757 finish:
975
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6756 times.
6757 if (ret == AVERROR_EXIT)
976 1 ret = 0;
977
978 6757 ffmpeg_cleanup(ret);
979
980 6757 sch_free(&sch);
981
982 6757 return ret;
983 }
984