FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/fftools/ffmpeg_filter.c
Date: 2026-09-28 04:46:15
Exec Total Coverage
Lines: 1449 1951 74.3%
Functions: 72 77 93.5%
Branches: 858 1333 64.4%

Line Branch Exec Source
1 /*
2 * ffmpeg filter configuration
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 #include <stdint.h>
22
23 #include "ffmpeg.h"
24 #include "graph/graphprint.h"
25
26 #include "libavfilter/avfilter.h"
27 #include "libavfilter/buffersink.h"
28 #include "libavfilter/buffersrc.h"
29
30 #include "libavutil/attributes.h"
31 #include "libavutil/avassert.h"
32 #include "libavutil/avstring.h"
33 #include "libavutil/bprint.h"
34 #include "libavutil/channel_layout.h"
35 #include "libavutil/downmix_info.h"
36 #include "libavutil/mem.h"
37 #include "libavutil/opt.h"
38 #include "libavutil/pixdesc.h"
39 #include "libavutil/pixfmt.h"
40 #include "libavutil/samplefmt.h"
41 #include "libavutil/time.h"
42 #include "libavutil/timestamp.h"
43
44 typedef struct FilterGraphPriv {
45 FilterGraph fg;
46
47 // name used for logging
48 char log_name[32];
49
50 int is_simple;
51 // true when the filtergraph contains only meta filters
52 // that do not modify the frame data
53 int is_meta;
54 int disable_conversions;
55
56 unsigned nb_outputs_done;
57
58 int nb_threads;
59
60 // frame for temporarily holding output from the filtergraph
61 AVFrame *frame;
62 // frame for sending output to the encoder
63 AVFrame *frame_enc;
64
65 Scheduler *sch;
66 unsigned sch_idx;
67 } FilterGraphPriv;
68
69 2310900 static FilterGraphPriv *fgp_from_fg(FilterGraph *fg)
70 {
71 2310900 return (FilterGraphPriv*)fg;
72 }
73
74 39254 static const FilterGraphPriv *cfgp_from_cfg(const FilterGraph *fg)
75 {
76 39254 return (const FilterGraphPriv*)fg;
77 }
78
79 // data that is local to the filter thread and not visible outside of it
80 typedef struct FilterGraphThread {
81 AVFilterGraph *graph;
82
83 AVFrame *frame;
84
85 // Temporary buffer for output frames, since on filtergraph reset
86 // we cannot send them to encoders immediately.
87 // The output index is stored in frame opaque.
88 AVFifo *frame_queue_out;
89
90 // index of the next input to request from the scheduler
91 unsigned next_in;
92 // set to 1 after at least one frame passed through this output
93 int got_frame;
94
95 // EOF status of each input/output, as received by the thread
96 uint8_t *eof_in;
97 uint8_t *eof_out;
98 } FilterGraphThread;
99
100 typedef struct InputFilterPriv {
101 InputFilter ifilter;
102
103 InputFilterOptions opts;
104
105 // used to hold submitted input
106 AVFrame *frame;
107
108 // For inputs bound to a filtergraph output
109 OutputFilter *ofilter_src;
110
111 // source data type: AVMEDIA_TYPE_SUBTITLE for sub2video,
112 // same as type otherwise
113 enum AVMediaType type_src;
114
115 int eof;
116 int bound;
117 int drop_warned;
118 uint64_t nb_dropped;
119
120 // parameters configured for this input
121 int format;
122
123 int width, height;
124 AVRational sample_aspect_ratio;
125 enum AVColorSpace color_space;
126 enum AVColorRange color_range;
127 enum AVAlphaMode alpha_mode;
128
129 int sample_rate;
130 AVChannelLayout ch_layout;
131
132 AVRational time_base;
133
134 AVFrameSideData **side_data;
135 int nb_side_data;
136
137 AVFifo *frame_queue;
138
139 AVBufferRef *hw_frames_ctx;
140
141 int displaymatrix_present;
142 int displaymatrix_applied;
143 int32_t displaymatrix[9];
144
145 int downmixinfo_present;
146 AVDownmixInfo downmixinfo;
147
148 AVBufferRef *downmixmatrix;
149 size_t downmixmatrix_size;
150 int downmixmatrix_present;
151
152 struct {
153 AVFrame *frame;
154
155 int64_t last_pts;
156 int64_t end_pts;
157
158 /// marks if sub2video_update should force an initialization
159 unsigned int initialize;
160 } sub2video;
161 } InputFilterPriv;
162
163 1350103 static InputFilterPriv *ifp_from_ifilter(InputFilter *ifilter)
164 {
165 1350103 return (InputFilterPriv*)ifilter;
166 }
167
168 typedef struct FPSConvContext {
169 AVFrame *last_frame;
170 /* number of frames emitted by the video-encoding sync code */
171 int64_t frame_number;
172 /* history of nb_frames_prev, i.e. the number of times the
173 * previous frame was duplicated by vsync code in recent
174 * do_video_out() calls */
175 int64_t frames_prev_hist[3];
176
177 uint64_t dup_warning;
178
179 int last_dropped;
180 int dropped_keyframe;
181
182 enum VideoSyncMethod vsync_method;
183
184 AVRational framerate;
185 AVRational framerate_max;
186 const AVRational *framerate_supported;
187 int framerate_clip;
188 } FPSConvContext;
189
190 typedef struct ReinitOpts {
191 int64_t pts;
192 AVDictionary *dict;
193 } ReinitOpts;
194
195 typedef struct OutputFilterPriv {
196 OutputFilter ofilter;
197
198 void *log_parent;
199 char log_name[32];
200
201 int needed;
202
203 /* desired output stream properties */
204 int format;
205 int width, height;
206 int sample_rate;
207 AVChannelLayout ch_layout;
208 enum AVColorSpace color_space;
209 enum AVColorRange color_range;
210 enum AVAlphaMode alpha_mode;
211
212 unsigned crop_top;
213 unsigned crop_bottom;
214 unsigned crop_left;
215 unsigned crop_right;
216
217 AVFrameSideData **side_data;
218 int nb_side_data;
219
220 // time base in which the output is sent to our downstream
221 // does not need to match the filtersink's timebase
222 AVRational tb_out;
223 // at least one frame with the above timebase was sent
224 // to our downstream, so it cannot change anymore
225 int tb_out_locked;
226
227 AVRational sample_aspect_ratio;
228
229 AVDictionary *sws_opts;
230 AVDictionary *swr_opts;
231
232 // those are only set if no format is specified and the encoder gives us multiple options
233 // They point directly to the relevant lists of the encoder.
234 union {
235 const enum AVPixelFormat *pix_fmts;
236 const enum AVSampleFormat *sample_fmts;
237 };
238 const AVChannelLayout *ch_layouts;
239 const int *sample_rates;
240 const enum AVColorSpace *color_spaces;
241 const enum AVColorRange *color_ranges;
242 const enum AVAlphaMode *alpha_modes;
243
244 int32_t displaymatrix[9];
245
246 AVRational enc_timebase;
247 int64_t trim_start_us;
248 int64_t trim_duration_us;
249 // offset for output timestamps, in AV_TIME_BASE_Q
250 int64_t ts_offset;
251 int64_t next_pts;
252 FPSConvContext fps;
253
254 AVFifo *reinit_opts_fifo;
255 ReinitOpts reinit_opts;
256
257 unsigned flags;
258 } OutputFilterPriv;
259
260 971095 static OutputFilterPriv *ofp_from_ofilter(OutputFilter *ofilter)
261 {
262 971095 return (OutputFilterPriv*)ofilter;
263 }
264
265 typedef struct FilterCommand {
266 char *target;
267 char *command;
268 char *arg;
269
270 double time;
271 int all_filters;
272 } FilterCommand;
273
274 ✗ static void filter_command_free(void *opaque, uint8_t *data)
275 {
276 ✗ FilterCommand *fc = (FilterCommand*)data;
277
278 ✗ av_freep(&fc->target);
279 ✗ av_freep(&fc->command);
280 ✗ av_freep(&fc->arg);
281
282 ✗ av_free(data);
283 ✗ }
284
285 180 static int sub2video_get_blank_frame(InputFilterPriv *ifp)
286 {
287 180 AVFrame *frame = ifp->sub2video.frame;
288 int ret;
289
290 180 av_frame_unref(frame);
291
292 180 frame->width = ifp->width;
293 180 frame->height = ifp->height;
294 180 frame->format = ifp->format;
295 180 frame->colorspace = ifp->color_space;
296 180 frame->color_range = ifp->color_range;
297 180 frame->alpha_mode = ifp->alpha_mode;
298
299 180 ret = av_frame_get_buffer(frame, 0);
300
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 180 times.
180 if (ret < 0)
301 ✗ return ret;
302
303 180 memset(frame->data[0], 0, frame->height * frame->linesize[0]);
304
305 180 return 0;
306 }
307
308 89 static void sub2video_copy_rect(uint8_t *dst, int dst_linesize, int w, int h,
309 AVSubtitleRect *r)
310 {
311 uint32_t *pal, *dst2;
312 uint8_t *src, *src2;
313 int x, y;
314
315
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 89 times.
89 if (r->type != SUBTITLE_BITMAP) {
316 ✗ av_log(NULL, AV_LOG_WARNING, "sub2video: non-bitmap subtitle\n");
317 ✗ return;
318 }
319
4/8
✓ Branch 0 taken 89 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 89 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 89 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 89 times.
89 if (r->x < 0 || r->x + r->w > w || r->y < 0 || r->y + r->h > h) {
320 ✗ av_log(NULL, AV_LOG_WARNING, "sub2video: rectangle (%d %d %d %d) overflowing %d %d\n",
321 r->x, r->y, r->w, r->h, w, h
322 );
323 ✗ return;
324 }
325
326 89 dst += r->y * dst_linesize + r->x * 4;
327 89 src = r->data[0];
328 89 pal = (uint32_t *)r->data[1];
329
2/2
✓ Branch 0 taken 3291 times.
✓ Branch 1 taken 89 times.
3380 for (y = 0; y < r->h; y++) {
330 3291 dst2 = (uint32_t *)dst;
331 3291 src2 = src;
332
2/2
✓ Branch 0 taken 1036075 times.
✓ Branch 1 taken 3291 times.
1039366 for (x = 0; x < r->w; x++)
333 1036075 *(dst2++) = pal[*(src2++)];
334 3291 dst += dst_linesize;
335 3291 src += r->linesize[0];
336 }
337 }
338
339 271 static void sub2video_push_ref(InputFilterPriv *ifp, int64_t pts)
340 {
341 271 AVFrame *frame = ifp->sub2video.frame;
342 int ret;
343
344 av_assert1(frame->data[0]);
345 271 ifp->sub2video.last_pts = frame->pts = pts;
346 271 ret = av_buffersrc_add_frame_flags(ifp->ifilter.filter, frame,
347 AV_BUFFERSRC_FLAG_KEEP_REF |
348 AV_BUFFERSRC_FLAG_PUSH);
349
2/4
✓ Branch 0 taken 271 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 271 times.
271 if (ret != AVERROR_EOF && ret < 0)
350 ✗ av_log(ifp->ifilter.graph, AV_LOG_WARNING,
351 "Error while add the frame to buffer source(%s).\n",
352 ✗ av_err2str(ret));
353 271 }
354
355 180 static void sub2video_update(InputFilterPriv *ifp, int64_t heartbeat_pts,
356 const AVSubtitle *sub)
357 {
358 180 AVFrame *frame = ifp->sub2video.frame;
359 uint8_t *dst;
360 int dst_linesize;
361 int num_rects;
362 int64_t pts, end_pts;
363
364
2/2
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 92 times.
180 if (sub) {
365 88 pts = av_rescale_q(sub->pts + sub->start_display_time * 1000LL,
366 88 AV_TIME_BASE_Q, ifp->time_base);
367 88 end_pts = av_rescale_q(sub->pts + sub->end_display_time * 1000LL,
368 88 AV_TIME_BASE_Q, ifp->time_base);
369 88 num_rects = sub->num_rects;
370 } else {
371 /* If we are initializing the system, utilize current heartbeat
372 PTS as the start time, and show until the following subpicture
373 is received. Otherwise, utilize the previous subpicture's end time
374 as the fall-back value. */
375 184 pts = ifp->sub2video.initialize ?
376
2/2
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 4 times.
92 heartbeat_pts : ifp->sub2video.end_pts;
377 92 end_pts = INT64_MAX;
378 92 num_rects = 0;
379 }
380
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 180 times.
180 if (sub2video_get_blank_frame(ifp) < 0) {
381 ✗ av_log(ifp->ifilter.graph, AV_LOG_ERROR,
382 "Impossible to get a blank canvas.\n");
383 ✗ return;
384 }
385 180 dst = frame->data [0];
386 180 dst_linesize = frame->linesize[0];
387
2/2
✓ Branch 0 taken 89 times.
✓ Branch 1 taken 180 times.
269 for (int i = 0; i < num_rects; i++)
388 89 sub2video_copy_rect(dst, dst_linesize, frame->width, frame->height, sub->rects[i]);
389 180 sub2video_push_ref(ifp, pts);
390 180 ifp->sub2video.end_pts = end_pts;
391 180 ifp->sub2video.initialize = 0;
392 }
393
394 /* Define a function for appending a list of allowed formats
395 * to an AVBPrint. If nonempty, the list will have a header. */
396 #define DEF_CHOOSE_FORMAT(name, type, var, supported_list, none, printf_format, get_name) \
397 static void choose_ ## name (OutputFilterPriv *ofp, AVBPrint *bprint) \
398 { \
399 if (ofp->var == none && !ofp->supported_list) \
400 return; \
401 av_bprintf(bprint, #name "="); \
402 if (ofp->var != none) { \
403 av_bprintf(bprint, printf_format, get_name(ofp->var)); \
404 } else { \
405 const type *p; \
406 \
407 for (p = ofp->supported_list; *p != none; p++) { \
408 av_bprintf(bprint, printf_format "|", get_name(*p)); \
409 } \
410 if (bprint->len > 0) \
411 bprint->str[--bprint->len] = '\0'; \
412 } \
413 av_bprint_chars(bprint, ':', 1); \
414 }
415
416
9/10
✓ Branch 0 taken 1567 times.
✓ Branch 1 taken 5415 times.
✓ Branch 2 taken 1190 times.
✓ Branch 3 taken 377 times.
✓ Branch 5 taken 5415 times.
✓ Branch 6 taken 377 times.
✓ Branch 11 taken 2406 times.
✓ Branch 12 taken 377 times.
✓ Branch 13 taken 377 times.
✗ Branch 14 not taken.
9388 DEF_CHOOSE_FORMAT(pix_fmts, enum AVPixelFormat, format, pix_fmts,
417 AV_PIX_FMT_NONE, "%s", av_get_pix_fmt_name)
418
419
8/10
✓ Branch 0 taken 1452 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1452 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 1452 times.
✓ Branch 11 taken 1566 times.
✓ Branch 12 taken 1452 times.
✓ Branch 13 taken 1452 times.
✗ Branch 14 not taken.
3020 DEF_CHOOSE_FORMAT(sample_fmts, enum AVSampleFormat, format, sample_fmts,
420 AV_SAMPLE_FMT_NONE, "%s", av_get_sample_fmt_name)
421
422
9/10
✓ Branch 0 taken 1436 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 1346 times.
✓ Branch 3 taken 90 times.
✓ Branch 5 taken 18 times.
✓ Branch 6 taken 90 times.
✓ Branch 9 taken 563 times.
✓ Branch 10 taken 90 times.
✓ Branch 11 taken 90 times.
✗ Branch 12 not taken.
2017 DEF_CHOOSE_FORMAT(sample_rates, int, sample_rate, sample_rates, 0,
423 "%d", )
424
425
4/10
✓ Branch 0 taken 6962 times.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 6962 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
6982 DEF_CHOOSE_FORMAT(color_spaces, enum AVColorSpace, color_space, color_spaces,
426 AVCOL_SPC_UNSPECIFIED, "%s", av_color_space_name)
427
428
9/10
✓ Branch 0 taken 5299 times.
✓ Branch 1 taken 1683 times.
✓ Branch 2 taken 4768 times.
✓ Branch 3 taken 531 times.
✓ Branch 5 taken 1683 times.
✓ Branch 6 taken 531 times.
✓ Branch 11 taken 568 times.
✓ Branch 12 taken 531 times.
✓ Branch 13 taken 531 times.
✗ Branch 14 not taken.
7550 DEF_CHOOSE_FORMAT(color_ranges, enum AVColorRange, color_range, color_ranges,
429 AVCOL_RANGE_UNSPECIFIED, "%s", av_color_range_name)
430
431
9/10
✓ Branch 0 taken 6974 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 6944 times.
✓ Branch 3 taken 30 times.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 30 times.
✓ Branch 11 taken 30 times.
✓ Branch 12 taken 30 times.
✓ Branch 13 taken 30 times.
✗ Branch 14 not taken.
7012 DEF_CHOOSE_FORMAT(alpha_modes, enum AVAlphaMode, alpha_mode, alpha_modes,
432 AVALPHA_MODE_UNSPECIFIED, "%s", av_alpha_mode_name)
433
434 1454 static void choose_channel_layouts(OutputFilterPriv *ofp, AVBPrint *bprint)
435 {
436
2/2
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 1442 times.
1454 if (av_channel_layout_check(&ofp->ch_layout)) {
437 12 av_bprintf(bprint, "channel_layouts=");
438 12 av_channel_layout_describe_bprint(&ofp->ch_layout, bprint);
439
2/2
✓ Branch 0 taken 105 times.
✓ Branch 1 taken 1337 times.
1442 } else if (ofp->ch_layouts) {
440 const AVChannelLayout *p;
441
442 105 av_bprintf(bprint, "channel_layouts=");
443
2/2
✓ Branch 0 taken 554 times.
✓ Branch 1 taken 105 times.
659 for (p = ofp->ch_layouts; p->nb_channels; p++) {
444 554 av_channel_layout_describe_bprint(p, bprint);
445 554 av_bprintf(bprint, "|");
446 }
447
1/2
✓ Branch 0 taken 105 times.
✗ Branch 1 not taken.
105 if (bprint->len > 0)
448 105 bprint->str[--bprint->len] = '\0';
449 } else
450 1337 return;
451 117 av_bprint_chars(bprint, ':', 1);
452 }
453
454 ✗ static int read_binary(void *logctx, const char *path,
455 uint8_t **data, int *len)
456 {
457 ✗ AVIOContext *io = NULL;
458 int64_t fsize;
459 int ret;
460
461 ✗ *data = NULL;
462 ✗ *len = 0;
463
464 ✗ ret = avio_open2(&io, path, AVIO_FLAG_READ, &int_cb, NULL);
465 ✗ if (ret < 0) {
466 ✗ av_log(logctx, AV_LOG_ERROR, "Cannot open file '%s': %s\n",
467 ✗ path, av_err2str(ret));
468 ✗ return ret;
469 }
470
471 ✗ fsize = avio_size(io);
472 ✗ if (fsize < 0 || fsize > INT_MAX) {
473 ✗ av_log(logctx, AV_LOG_ERROR, "Cannot obtain size of file %s\n", path);
474 ✗ ret = AVERROR(EIO);
475 ✗ goto fail;
476 }
477
478 ✗ *data = av_malloc(fsize);
479 ✗ if (!*data) {
480 ✗ ret = AVERROR(ENOMEM);
481 ✗ goto fail;
482 }
483
484 ✗ ret = avio_read(io, *data, fsize);
485 ✗ if (ret != fsize) {
486 ✗ av_log(logctx, AV_LOG_ERROR, "Error reading file %s\n", path);
487 ✗ ret = ret < 0 ? ret : AVERROR(EIO);
488 ✗ goto fail;
489 }
490
491 ✗ *len = fsize;
492
493 ✗ ret = 0;
494 ✗ fail:
495 ✗ avio_close(io);
496 ✗ if (ret < 0) {
497 ✗ av_freep(data);
498 ✗ *len = 0;
499 }
500 ✗ return ret;
501 }
502
503 33093 static int filter_opt_apply(void *logctx, AVFilterContext *f,
504 const char *key, const char *val)
505 {
506 33093 const AVOption *o = NULL;
507 int ret;
508
509 33093 ret = av_opt_set(f, key, val, AV_OPT_SEARCH_CHILDREN);
510
1/2
✓ Branch 0 taken 33093 times.
✗ Branch 1 not taken.
33093 if (ret >= 0)
511 33093 return 0;
512
513 ✗ if (ret == AVERROR_OPTION_NOT_FOUND && key[0] == '/')
514 ✗ o = av_opt_find(f, key + 1, NULL, 0, AV_OPT_SEARCH_CHILDREN);
515 ✗ if (!o)
516 ✗ goto err_apply;
517
518 // key is a valid option name prefixed with '/'
519 // interpret value as a path from which to load the actual option value
520 ✗ key++;
521
522 ✗ if (o->type == AV_OPT_TYPE_BINARY) {
523 uint8_t *data;
524 int len;
525
526 ✗ ret = read_binary(logctx, val, &data, &len);
527 ✗ if (ret < 0)
528 ✗ goto err_load;
529
530 ✗ ret = av_opt_set_bin(f, key, data, len, AV_OPT_SEARCH_CHILDREN);
531 ✗ av_freep(&data);
532 } else {
533 ✗ char *data = read_file_to_string(val);
534 ✗ if (!data) {
535 ✗ ret = AVERROR(EIO);
536 ✗ goto err_load;
537 }
538
539 ✗ ret = av_opt_set(f, key, data, AV_OPT_SEARCH_CHILDREN);
540 ✗ av_freep(&data);
541 }
542 ✗ if (ret < 0)
543 ✗ goto err_apply;
544
545 ✗ return 0;
546
547 ✗ err_apply:
548 ✗ av_log(logctx, AV_LOG_ERROR,
549 "Error applying option '%s' to filter '%s': %s\n",
550 ✗ key, f->filter->name, av_err2str(ret));
551 ✗ return ret;
552 ✗ err_load:
553 ✗ av_log(logctx, AV_LOG_ERROR,
554 "Error loading value for option '%s' from file '%s'\n",
555 key, val);
556 ✗ return ret;
557 }
558
559 16560 static int graph_opts_apply(void *logctx, AVFilterGraphSegment *seg)
560 {
561
2/2
✓ Branch 0 taken 16992 times.
✓ Branch 1 taken 16560 times.
33552 for (size_t i = 0; i < seg->nb_chains; i++) {
562 16992 AVFilterChain *ch = seg->chains[i];
563
564
2/2
✓ Branch 0 taken 37457 times.
✓ Branch 1 taken 16992 times.
54449 for (size_t j = 0; j < ch->nb_filters; j++) {
565 37457 AVFilterParams *p = ch->filters[j];
566 37457 const AVDictionaryEntry *e = NULL;
567
568
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37457 times.
37457 av_assert0(p->filter);
569
570
2/2
✓ Branch 1 taken 33093 times.
✓ Branch 2 taken 37457 times.
70550 while ((e = av_dict_iterate(p->opts, e))) {
571 33093 int ret = filter_opt_apply(logctx, p->filter, e->key, e->value);
572
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33093 times.
33093 if (ret < 0)
573 ✗ return ret;
574 }
575
576 37457 av_dict_free(&p->opts);
577 }
578 }
579
580 16560 return 0;
581 }
582
583 16560 static int graph_parse(void *logctx,
584 AVFilterGraph *graph, const char *desc,
585 AVFilterInOut **inputs, AVFilterInOut **outputs,
586 AVBufferRef *hw_device)
587 {
588 AVFilterGraphSegment *seg;
589 int ret;
590
591 16560 *inputs = NULL;
592 16560 *outputs = NULL;
593
594 16560 ret = avfilter_graph_segment_parse(graph, desc, 0, &seg);
595
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16560 times.
16560 if (ret < 0)
596 ✗ return ret;
597
598 16560 ret = avfilter_graph_segment_create_filters(seg, 0);
599
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16560 times.
16560 if (ret < 0)
600 ✗ goto fail;
601
602
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16560 times.
16560 if (hw_device) {
603 ✗ for (int i = 0; i < graph->nb_filters; i++) {
604 ✗ AVFilterContext *f = graph->filters[i];
605
606 ✗ if (!(f->filter->flags & AVFILTER_FLAG_HWDEVICE))
607 ✗ continue;
608 ✗ f->hw_device_ctx = av_buffer_ref(hw_device);
609 ✗ if (!f->hw_device_ctx) {
610 ✗ ret = AVERROR(ENOMEM);
611 ✗ goto fail;
612 }
613 }
614 }
615
616 16560 ret = graph_opts_apply(logctx, seg);
617
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16560 times.
16560 if (ret < 0)
618 ✗ goto fail;
619
620 16560 ret = avfilter_graph_segment_apply(seg, 0, inputs, outputs);
621
622 16560 fail:
623 16560 avfilter_graph_segment_free(&seg);
624 16560 return ret;
625 }
626
627 // Filters can be configured only if the formats of all inputs are known.
628 15495 static int ifilter_has_all_input_formats(FilterGraph *fg)
629 {
630
2/2
✓ Branch 0 taken 14703 times.
✓ Branch 1 taken 8302 times.
23005 for (int i = 0; i < fg->nb_inputs; i++) {
631 14703 InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]);
632
2/2
✓ Branch 0 taken 7193 times.
✓ Branch 1 taken 7510 times.
14703 if (ifp->format < 0)
633 7193 return 0;
634 }
635 8302 return 1;
636 }
637
638 static int filter_thread(void *arg);
639
640 15559 static char *describe_filter_link(FilterGraph *fg, AVFilterInOut *inout, int in)
641 {
642 15559 AVFilterContext *ctx = inout->filter_ctx;
643
2/2
✓ Branch 0 taken 7166 times.
✓ Branch 1 taken 8393 times.
15559 AVFilterPad *pads = in ? ctx->input_pads : ctx->output_pads;
644
2/2
✓ Branch 0 taken 7166 times.
✓ Branch 1 taken 8393 times.
15559 int nb_pads = in ? ctx->nb_inputs : ctx->nb_outputs;
645
646
2/2
✓ Branch 0 taken 169 times.
✓ Branch 1 taken 15390 times.
15559 if (nb_pads > 1)
647 169 return av_strdup(ctx->filter->name);
648 15390 return av_asprintf("%s:%s", ctx->filter->name,
649 avfilter_pad_get_name(pads, inout->pad_idx));
650 }
651
652 3 static const char *ofilter_item_name(void *obj)
653 {
654 3 OutputFilterPriv *ofp = obj;
655 3 return ofp->log_name;
656 }
657
658 static const AVOption ofilter_options[] = {
659 {"video_size", "set video size", offsetof(OutputFilterPriv, width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, INT_MAX },
660 {"pixel_format", "set pixel format", offsetof(OutputFilterPriv, format), AV_OPT_TYPE_PIXEL_FMT, {.i64 = AV_PIX_FMT_NONE}, -1, INT_MAX },
661 {"colorspace", "color space", offsetof(OutputFilterPriv, color_space), AV_OPT_TYPE_INT, {.i64 = AVCOL_SPC_UNSPECIFIED }, 0, INT_MAX },
662 {"color_range", "color range", offsetof(OutputFilterPriv, color_range), AV_OPT_TYPE_INT, {.i64 = AVCOL_RANGE_UNSPECIFIED }, 0, INT_MAX },
663 {"alpha_mode", "color range", offsetof(OutputFilterPriv, alpha_mode), AV_OPT_TYPE_INT, {.i64 = AVALPHA_MODE_UNSPECIFIED }, 0, INT_MAX },
664 {"ar", "set audio sampling rate (in Hz)", offsetof(OutputFilterPriv, sample_rate), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX },
665 {"ch_layout", NULL, offsetof(OutputFilterPriv, ch_layout), AV_OPT_TYPE_CHLAYOUT, {.str = NULL }, 0, 0 },
666 { NULL },
667 };
668
669 static const AVClass ofilter_class = {
670 .class_name = "OutputFilter",
671 .version = LIBAVUTIL_VERSION_INT,
672 .item_name = ofilter_item_name,
673 .option = ofilter_options,
674 .parent_log_context_offset = offsetof(OutputFilterPriv, log_parent),
675 .category = AV_CLASS_CATEGORY_FILTER,
676 };
677
678 8393 static OutputFilter *ofilter_alloc(FilterGraph *fg, enum AVMediaType type)
679 {
680 OutputFilterPriv *ofp;
681 OutputFilter *ofilter;
682
683 8393 ofp = allocate_array_elem(&fg->outputs, sizeof(*ofp), &fg->nb_outputs);
684
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8393 times.
8393 if (!ofp)
685 ✗ return NULL;
686
687 8393 ofilter = &ofp->ofilter;
688 8393 ofilter->class = &ofilter_class;
689 8393 ofp->log_parent = fg;
690 8393 ofilter->graph = fg;
691 8393 ofilter->type = type;
692 8393 av_opt_set_defaults(ofp);
693 8393 ofp->reinit_opts = (ReinitOpts){ .pts = AV_NOPTS_VALUE };
694 8393 ofilter->index = fg->nb_outputs - 1;
695
696 16786 snprintf(ofp->log_name, sizeof(ofp->log_name), "%co%d",
697 8393 av_get_media_type_string(type)[0], ofilter->index);
698
699 8393 return ofilter;
700 }
701
702 7156 static int ifilter_bind_ist(InputFilter *ifilter, InputStream *ist,
703 const ViewSpecifier *vs)
704 {
705 7156 InputFilterPriv *ifp = ifp_from_ifilter(ifilter);
706 7156 FilterGraphPriv *fgp = fgp_from_fg(ifilter->graph);
707 SchedulerNode src;
708 int ret;
709
710
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7156 times.
7156 av_assert0(!ifp->bound);
711 7156 ifp->bound = 1;
712
713
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 7152 times.
7156 if (ifilter->type != ist->par->codec_type &&
714
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 !(ifilter->type == AVMEDIA_TYPE_VIDEO && ist->par->codec_type == AVMEDIA_TYPE_SUBTITLE)) {
715 ✗ av_log(fgp, AV_LOG_ERROR, "Tried to connect %s stream to %s filtergraph input\n",
716 ✗ av_get_media_type_string(ist->par->codec_type), av_get_media_type_string(ifilter->type));
717 ✗ return AVERROR(EINVAL);
718 }
719
720 7156 ifp->type_src = ist->st->codecpar->codec_type;
721
722 7156 ifp->opts.fallback = av_frame_alloc();
723
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7156 times.
7156 if (!ifp->opts.fallback)
724 ✗ return AVERROR(ENOMEM);
725
726 7156 ret = ist_filter_add(ist, ifilter, filtergraph_is_simple(ifilter->graph),
727 vs, &ifp->opts, &src);
728
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7156 times.
7156 if (ret < 0)
729 ✗ return ret;
730
731 7156 ifilter->input_name = av_strdup(ifp->opts.name);
732
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7156 times.
7156 if (!ifilter->input_name)
733 ✗ return AVERROR(EINVAL);
734
735 7156 ret = sch_connect(fgp->sch,
736 7156 src, SCH_FILTER_IN(fgp->sch_idx, ifilter->index));
737
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7156 times.
7156 if (ret < 0)
738 ✗ return ret;
739
740
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 7152 times.
7156 if (ifp->type_src == AVMEDIA_TYPE_SUBTITLE) {
741 4 ifp->sub2video.frame = av_frame_alloc();
742
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!ifp->sub2video.frame)
743 ✗ return AVERROR(ENOMEM);
744
745 4 ifp->width = ifp->opts.sub2video_width;
746 4 ifp->height = ifp->opts.sub2video_height;
747
748 /* rectangles are AV_PIX_FMT_PAL8, but we have no guarantee that the
749 palettes for all rectangles are identical or compatible */
750 4 ifp->format = AV_PIX_FMT_RGB32;
751
752 4 ifp->time_base = AV_TIME_BASE_Q;
753
754 4 av_log(fgp, AV_LOG_VERBOSE, "sub2video: using %dx%d canvas\n",
755 ifp->width, ifp->height);
756 }
757
758 7156 return 0;
759 }
760
761 1 static int ifilter_bind_dec(InputFilterPriv *ifp, Decoder *dec,
762 const ViewSpecifier *vs)
763 {
764 1 FilterGraphPriv *fgp = fgp_from_fg(ifp->ifilter.graph);
765 SchedulerNode src;
766 int ret;
767
768
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 av_assert0(!ifp->bound);
769 1 ifp->bound = 1;
770
771
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ifp->ifilter.type != dec->type) {
772 ✗ av_log(fgp, AV_LOG_ERROR, "Tried to connect %s decoder to %s filtergraph input\n",
773 av_get_media_type_string(dec->type), av_get_media_type_string(ifp->ifilter.type));
774 ✗ return AVERROR(EINVAL);
775 }
776
777 1 ifp->type_src = ifp->ifilter.type;
778
779 1 ret = dec_filter_add(dec, &ifp->ifilter, &ifp->opts, vs, &src);
780
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
781 ✗ return ret;
782
783 1 ifp->ifilter.input_name = av_strdup(ifp->opts.name);
784
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!ifp->ifilter.input_name)
785 ✗ return AVERROR(EINVAL);
786
787 1 ret = sch_connect(fgp->sch, src, SCH_FILTER_IN(fgp->sch_idx, ifp->ifilter.index));
788
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
789 ✗ return ret;
790
791 1 return 0;
792 }
793
794 11 static int set_channel_layout(OutputFilterPriv *f, const AVChannelLayout *layouts_allowed,
795 const AVChannelLayout *layout_requested)
796 {
797 int i, err;
798
799
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10 times.
11 if (layout_requested->order != AV_CHANNEL_ORDER_UNSPEC) {
800 /* Pass the layout through for all orders but UNSPEC */
801 1 err = av_channel_layout_copy(&f->ch_layout, layout_requested);
802
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (err < 0)
803 ✗ return err;
804 1 return 0;
805 }
806
807 /* Requested layout is of order UNSPEC */
808
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if (!layouts_allowed) {
809 /* Use the default native layout for the requested amount of channels when the
810 encoder doesn't have a list of supported layouts */
811 10 av_channel_layout_default(&f->ch_layout, layout_requested->nb_channels);
812 10 return 0;
813 }
814 /* Encoder has a list of supported layouts. Pick the first layout in it with the
815 same amount of channels as the requested layout */
816 ✗ for (i = 0; layouts_allowed[i].nb_channels; i++) {
817 ✗ if (layouts_allowed[i].nb_channels == layout_requested->nb_channels)
818 ✗ break;
819 }
820 ✗ if (layouts_allowed[i].nb_channels) {
821 /* Use it if one is found */
822 ✗ err = av_channel_layout_copy(&f->ch_layout, &layouts_allowed[i]);
823 ✗ if (err < 0)
824 ✗ return err;
825 ✗ return 0;
826 }
827 /* If no layout for the amount of channels requested was found, use the default
828 native layout for it. */
829 ✗ av_channel_layout_default(&f->ch_layout, layout_requested->nb_channels);
830
831 ✗ return 0;
832 }
833
834 ✗ static int parse_reinit_opts(AVFifo **pout, const char *opts, void *logctx)
835 {
836 AVFifo *out;
837 ✗ int ret = AVERROR_BUG;
838 ✗ char *ptr, *str, *substr = NULL;
839 const char *token;
840
841 ✗ str = av_strdup(opts);
842 ✗ if (!str)
843 ✗ return AVERROR(ENOMEM);
844
845 ✗ out = av_fifo_alloc2(1, sizeof(ReinitOpts), AV_FIFO_FLAG_AUTO_GROW);
846 ✗ if (!out) {
847 ✗ ret = AVERROR(ENOMEM);
848 ✗ goto end;
849 }
850
851 ✗ token = av_strtok(str, ",", &ptr);
852 ✗ while (token) {
853 ✗ ReinitOpts o = { 0 };
854 const char *subtoken;
855 char *subptr, *endptr;
856
857 ✗ substr = av_strdup(token);
858 ✗ if (!substr) {
859 ✗ ret = AVERROR(ENOMEM);
860 ✗ goto end;
861 }
862 ✗ subtoken = av_strtok(substr, "|", &subptr);
863 ✗ if (subtoken && subptr) {
864 ✗ if (!av_strstart(subtoken, "pts=", &subtoken)) {
865 ✗ av_log(logctx, AV_LOG_ERROR, "Invalid reinit identifier\n");
866 ✗ ret = AVERROR(ENOMEM);
867 ✗ goto end;
868 }
869 ✗ o.pts = strtoll(subtoken, &endptr, 0);
870 ✗ if (*endptr || o.pts < 0) {
871 ✗ ret = AVERROR(EINVAL);
872 ✗ goto end;
873 }
874 ✗ ret = av_dict_parse_string(&o.dict, subptr, "=", ":", 0);
875 ✗ if (ret < 0) {
876 ✗ av_log(logctx, AV_LOG_ERROR, "Error parsing encoder options\n");
877 ✗ goto end;
878 }
879 ✗ ret = av_fifo_write(out, &o, 1);
880 ✗ if (ret < 0) {
881 ✗ av_dict_free(&o.dict);
882 ✗ goto end;
883 }
884 } else {
885 ✗ ret = AVERROR(EINVAL);
886 ✗ goto end;
887 }
888 ✗ av_freep(&substr);
889 ✗ if (ptr)
890 ✗ ptr += strspn(ptr, " \n\t\r");
891 ✗ token = av_strtok(NULL, ",", &ptr);
892 }
893
894 ✗ ret = 0;
895 ✗ end:
896 ✗ *pout = out;
897 ✗ av_free(substr);
898 ✗ av_free(str);
899
900 ✗ return ret;
901 }
902
903 8389 int ofilter_bind_enc(OutputFilter *ofilter, unsigned sched_idx_enc,
904 const OutputFilterOptions *opts)
905 {
906 8389 OutputFilterPriv *ofp = ofp_from_ofilter(ofilter);
907 8389 FilterGraph *fg = ofilter->graph;
908 8389 FilterGraphPriv *fgp = fgp_from_fg(fg);
909 int ret;
910
911
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8389 times.
8389 av_assert0(!ofilter->bound);
912
2/4
✓ Branch 0 taken 8389 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8389 times.
8389 av_assert0(!opts->enc ||
913 ofilter->type == opts->enc->type);
914
915 8389 ofp->needed = ofilter->bound = 1;
916 8389 av_freep(&ofilter->linklabel);
917
918 8389 ofp->flags |= opts->flags;
919 8389 ofp->ts_offset = opts->ts_offset;
920 8389 ofp->enc_timebase = opts->output_tb;
921
922 8389 ofp->trim_start_us = opts->trim_start_us;
923 8389 ofp->trim_duration_us = opts->trim_duration_us;
924
925 8389 ofilter->output_name = av_strdup(opts->name);
926
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8389 times.
8389 if (!ofilter->output_name)
927 ✗ return AVERROR(EINVAL);
928
929
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8389 times.
8389 if (opts->reinit_opts) {
930 ✗ ret = parse_reinit_opts(&ofp->reinit_opts_fifo, opts->reinit_opts, ofilter);
931 ✗ if (ret < 0)
932 ✗ return ret;
933 }
934
935 8389 ret = av_dict_copy(&ofp->sws_opts, opts->sws_opts, 0);
936
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8389 times.
8389 if (ret < 0)
937 ✗ return ret;
938
939 8389 ret = av_dict_copy(&ofp->swr_opts, opts->swr_opts, 0);
940
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8389 times.
8389 if (ret < 0)
941 ✗ return ret;
942
943
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 8324 times.
8389 if (opts->flags & OFILTER_FLAG_AUDIO_24BIT)
944 65 av_dict_set(&ofp->swr_opts, "output_sample_bits", "24", 0);
945
946
2/2
✓ Branch 0 taken 6980 times.
✓ Branch 1 taken 1409 times.
8389 if (fgp->is_simple) {
947 // for simple filtergraph there is just one output,
948 // so use only graph-level information for logging
949 6980 ofp->log_parent = NULL;
950 6980 av_strlcpy(ofp->log_name, fgp->log_name, sizeof(ofp->log_name));
951 } else
952 1409 av_strlcatf(ofp->log_name, sizeof(ofp->log_name), "->%s", ofilter->output_name);
953
954
2/3
✓ Branch 0 taken 6935 times.
✓ Branch 1 taken 1454 times.
✗ Branch 2 not taken.
8389 switch (ofilter->type) {
955 6935 case AVMEDIA_TYPE_VIDEO:
956 6935 ofp->width = opts->width;
957 6935 ofp->height = opts->height;
958
2/2
✓ Branch 0 taken 5369 times.
✓ Branch 1 taken 1566 times.
6935 if (opts->format != AV_PIX_FMT_NONE) {
959 5369 ofp->format = opts->format;
960 } else
961 1566 ofp->pix_fmts = opts->pix_fmts;
962
963
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6935 times.
6935 if (opts->color_space != AVCOL_SPC_UNSPECIFIED)
964 ✗ ofp->color_space = opts->color_space;
965 else
966 6935 ofp->color_spaces = opts->color_spaces;
967
968
2/2
✓ Branch 0 taken 1652 times.
✓ Branch 1 taken 5283 times.
6935 if (opts->color_range != AVCOL_RANGE_UNSPECIFIED)
969 1652 ofp->color_range = opts->color_range;
970 else
971 5283 ofp->color_ranges = opts->color_ranges;
972
973
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6935 times.
6935 if (opts->alpha_mode != AVALPHA_MODE_UNSPECIFIED)
974 ✗ ofp->alpha_mode = opts->alpha_mode;
975 else
976 6935 ofp->alpha_modes = opts->alpha_modes;
977
978 6935 fgp->disable_conversions |= !!(ofp->flags & OFILTER_FLAG_DISABLE_CONVERT);
979
980 6935 ofp->fps.last_frame = av_frame_alloc();
981
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6935 times.
6935 if (!ofp->fps.last_frame)
982 ✗ return AVERROR(ENOMEM);
983
984 6935 ofp->fps.vsync_method = opts->vsync_method;
985 6935 ofp->fps.framerate = opts->frame_rate;
986 6935 ofp->fps.framerate_max = opts->max_frame_rate;
987 6935 ofp->fps.framerate_supported = opts->frame_rates;
988
989 // reduce frame rate for mpeg4 to be within the spec limits
990
3/4
✓ Branch 0 taken 6935 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 72 times.
✓ Branch 3 taken 6863 times.
6935 if (opts->enc && opts->enc->id == AV_CODEC_ID_MPEG4)
991 72 ofp->fps.framerate_clip = 65535;
992
993 6935 ofp->fps.dup_warning = 1000;
994
995 6935 break;
996 1454 case AVMEDIA_TYPE_AUDIO:
997
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1453 times.
1454 if (opts->format != AV_SAMPLE_FMT_NONE) {
998 1 ofp->format = opts->format;
999 } else {
1000 1453 ofp->sample_fmts = opts->sample_fmts;
1001 }
1002
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 1437 times.
1454 if (opts->sample_rate) {
1003 17 ofp->sample_rate = opts->sample_rate;
1004 } else
1005 1437 ofp->sample_rates = opts->sample_rates;
1006
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1443 times.
1454 if (opts->ch_layout.nb_channels) {
1007 11 int ret = set_channel_layout(ofp, opts->ch_layouts, &opts->ch_layout);
1008
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if (ret < 0)
1009 ✗ return ret;
1010 } else {
1011 1443 ofp->ch_layouts = opts->ch_layouts;
1012 }
1013 1454 break;
1014 }
1015
1016 8389 ret = sch_connect(fgp->sch, SCH_FILTER_OUT(fgp->sch_idx, ofilter->index),
1017 8389 SCH_ENC(sched_idx_enc));
1018
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8389 times.
8389 if (ret < 0)
1019 ✗ return ret;
1020
1021 8389 return 0;
1022 }
1023
1024 1 static int ofilter_bind_ifilter(OutputFilter *ofilter, InputFilterPriv *ifp,
1025 const OutputFilterOptions *opts)
1026 {
1027 1 OutputFilterPriv *ofp = ofp_from_ofilter(ofilter);
1028
1029
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 av_assert0(!ofilter->bound);
1030
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 av_assert0(ofilter->type == ifp->ifilter.type);
1031
1032 1 ofp->needed = ofilter->bound = 1;
1033 1 av_freep(&ofilter->linklabel);
1034
1035 1 ofilter->output_name = av_strdup(opts->name);
1036
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!ofilter->output_name)
1037 ✗ return AVERROR(EINVAL);
1038
1039 1 ifp->ofilter_src = ofilter;
1040
1041 1 av_strlcatf(ofp->log_name, sizeof(ofp->log_name), "->%s", ofilter->output_name);
1042
1043 1 return 0;
1044 }
1045
1046 1 static int ifilter_bind_fg(InputFilterPriv *ifp, FilterGraph *fg_src, int out_idx)
1047 {
1048 1 FilterGraphPriv *fgp = fgp_from_fg(ifp->ifilter.graph);
1049 1 OutputFilter *ofilter_src = fg_src->outputs[out_idx];
1050 OutputFilterOptions opts;
1051 char name[32];
1052 int ret;
1053
1054
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 av_assert0(!ifp->bound);
1055 1 ifp->bound = 1;
1056
1057
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ifp->ifilter.type != ofilter_src->type) {
1058 ✗ av_log(fgp, AV_LOG_ERROR, "Tried to connect %s output to %s input\n",
1059 av_get_media_type_string(ofilter_src->type),
1060 av_get_media_type_string(ifp->ifilter.type));
1061 ✗ return AVERROR(EINVAL);
1062 }
1063
1064 1 ifp->type_src = ifp->ifilter.type;
1065
1066 1 memset(&opts, 0, sizeof(opts));
1067
1068 1 snprintf(name, sizeof(name), "fg:%d:%d", fgp->fg.index, ifp->ifilter.index);
1069 1 opts.name = name;
1070
1071 1 ret = ofilter_bind_ifilter(ofilter_src, ifp, &opts);
1072
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
1073 ✗ return ret;
1074
1075 1 ret = sch_connect(fgp->sch, SCH_FILTER_OUT(fg_src->index, out_idx),
1076 1 SCH_FILTER_IN(fgp->sch_idx, ifp->ifilter.index));
1077
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
1078 ✗ return ret;
1079
1080 1 return 0;
1081 }
1082
1083 7166 static InputFilter *ifilter_alloc(FilterGraph *fg)
1084 {
1085 InputFilterPriv *ifp;
1086 InputFilter *ifilter;
1087
1088 7166 ifp = allocate_array_elem(&fg->inputs, sizeof(*ifp), &fg->nb_inputs);
1089
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7166 times.
7166 if (!ifp)
1090 ✗ return NULL;
1091
1092 7166 ifilter = &ifp->ifilter;
1093 7166 ifilter->graph = fg;
1094
1095 7166 ifp->frame = av_frame_alloc();
1096
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7166 times.
7166 if (!ifp->frame)
1097 ✗ return NULL;
1098
1099 7166 ifilter->index = fg->nb_inputs - 1;
1100 7166 ifp->format = -1;
1101 7166 ifp->color_space = AVCOL_SPC_UNSPECIFIED;
1102 7166 ifp->color_range = AVCOL_RANGE_UNSPECIFIED;
1103 7166 ifp->alpha_mode = AVALPHA_MODE_UNSPECIFIED;
1104
1105 7166 ifp->frame_queue = av_fifo_alloc2(8, sizeof(AVFrame*), AV_FIFO_FLAG_AUTO_GROW);
1106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7166 times.
7166 if (!ifp->frame_queue)
1107 ✗ return NULL;
1108
1109 7166 return ifilter;
1110 }
1111
1112 10675 void fg_free(FilterGraph **pfg)
1113 {
1114 10675 FilterGraph *fg = *pfg;
1115 FilterGraphPriv *fgp;
1116
1117
2/2
✓ Branch 0 taken 2416 times.
✓ Branch 1 taken 8259 times.
10675 if (!fg)
1118 2416 return;
1119 8259 fgp = fgp_from_fg(fg);
1120
1121
2/2
✓ Branch 0 taken 7166 times.
✓ Branch 1 taken 8259 times.
15425 for (int j = 0; j < fg->nb_inputs; j++) {
1122 7166 InputFilter *ifilter = fg->inputs[j];
1123 7166 InputFilterPriv *ifp = ifp_from_ifilter(ifilter);
1124
1125
1/2
✓ Branch 0 taken 7166 times.
✗ Branch 1 not taken.
7166 if (ifp->frame_queue) {
1126 AVFrame *frame;
1127
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7166 times.
7166 while (av_fifo_read(ifp->frame_queue, &frame, 1) >= 0)
1128 ✗ av_frame_free(&frame);
1129 7166 av_fifo_freep2(&ifp->frame_queue);
1130 }
1131 7166 av_frame_free(&ifp->sub2video.frame);
1132
1133 7166 av_frame_free(&ifp->frame);
1134 7166 av_frame_free(&ifp->opts.fallback);
1135
1136 7166 av_buffer_unref(&ifp->hw_frames_ctx);
1137 7166 av_channel_layout_uninit(&ifp->ch_layout);
1138 7166 av_freep(&ifilter->linklabel);
1139 7166 av_freep(&ifp->opts.name);
1140 7166 av_buffer_unref(&ifp->downmixmatrix);
1141 7166 av_frame_side_data_free(&ifp->side_data, &ifp->nb_side_data);
1142 7166 av_freep(&ifilter->name);
1143 7166 av_freep(&ifilter->input_name);
1144 7166 av_freep(&fg->inputs[j]);
1145 }
1146 8259 av_freep(&fg->inputs);
1147
2/2
✓ Branch 0 taken 8393 times.
✓ Branch 1 taken 8259 times.
16652 for (int j = 0; j < fg->nb_outputs; j++) {
1148 8393 OutputFilter *ofilter = fg->outputs[j];
1149 8393 OutputFilterPriv *ofp = ofp_from_ofilter(ofilter);
1150
1151 8393 av_frame_free(&ofp->fps.last_frame);
1152 8393 av_dict_free(&ofp->sws_opts);
1153 8393 av_dict_free(&ofp->swr_opts);
1154
1155 8393 av_freep(&ofilter->linklabel);
1156 8393 av_freep(&ofilter->name);
1157 8393 av_freep(&ofilter->output_name);
1158 8393 av_freep(&ofilter->apad);
1159 8393 av_dict_free(&ofp->reinit_opts.dict);
1160
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8393 times.
8393 if (ofp->reinit_opts_fifo) {
1161 ✗ while (av_fifo_read(ofp->reinit_opts_fifo, &ofp->reinit_opts, 1) >= 0)
1162 ✗ av_dict_free(&ofp->reinit_opts.dict);
1163 ✗ av_fifo_freep2(&ofp->reinit_opts_fifo);
1164 }
1165 8393 av_channel_layout_uninit(&ofp->ch_layout);
1166 8393 av_frame_side_data_free(&ofp->side_data, &ofp->nb_side_data);
1167 8393 av_freep(&fg->outputs[j]);
1168 }
1169 8259 av_freep(&fg->outputs);
1170 8259 av_freep(&fg->graph_desc);
1171
1172 8259 av_frame_free(&fgp->frame);
1173 8259 av_frame_free(&fgp->frame_enc);
1174
1175 8259 av_freep(pfg);
1176 }
1177
1178 62 static const char *fg_item_name(void *obj)
1179 {
1180 62 const FilterGraphPriv *fgp = obj;
1181
1182 62 return fgp->log_name;
1183 }
1184
1185 static const AVClass fg_class = {
1186 .class_name = "FilterGraph",
1187 .version = LIBAVUTIL_VERSION_INT,
1188 .item_name = fg_item_name,
1189 .category = AV_CLASS_CATEGORY_FILTER,
1190 };
1191
1192 8259 int fg_create(FilterGraph **pfg, char **graph_desc, Scheduler *sch,
1193 const OutputFilterOptions *opts)
1194 {
1195 FilterGraphPriv *fgp;
1196 FilterGraph *fg;
1197
1198 AVFilterInOut *inputs, *outputs;
1199 AVFilterGraph *graph;
1200 8259 int ret = 0;
1201
1202 8259 fgp = av_mallocz(sizeof(*fgp));
1203
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8259 times.
8259 if (!fgp) {
1204 ✗ av_freep(graph_desc);
1205 ✗ return AVERROR(ENOMEM);
1206 }
1207 8259 fg = &fgp->fg;
1208
1209
2/2
✓ Branch 0 taken 6981 times.
✓ Branch 1 taken 1278 times.
8259 if (pfg) {
1210 6981 *pfg = fg;
1211 6981 fg->index = -1;
1212 } else {
1213 1278 ret = av_dynarray_add_nofree(&filtergraphs, &nb_filtergraphs, fgp);
1214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1278 times.
1278 if (ret < 0) {
1215 ✗ av_freep(graph_desc);
1216 ✗ av_freep(&fgp);
1217 ✗ return ret;
1218 }
1219
1220 1278 fg->index = nb_filtergraphs - 1;
1221 }
1222
1223 8259 fg->class = &fg_class;
1224 8259 fg->graph_desc = *graph_desc;
1225 8259 fgp->disable_conversions = !auto_conversion_filters;
1226 8259 fgp->nb_threads = -1;
1227 8259 fgp->sch = sch;
1228
1229 8259 *graph_desc = NULL;
1230
1231 8259 snprintf(fgp->log_name, sizeof(fgp->log_name), "fc#%d", fg->index);
1232
1233 8259 fgp->frame = av_frame_alloc();
1234 8259 fgp->frame_enc = av_frame_alloc();
1235
2/4
✓ Branch 0 taken 8259 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8259 times.
8259 if (!fgp->frame || !fgp->frame_enc)
1236 ✗ return AVERROR(ENOMEM);
1237
1238 /* this graph is only used for determining the kinds of inputs
1239 * and outputs we have, and is discarded on exit from this function */
1240 8259 graph = avfilter_graph_alloc();
1241
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8259 times.
8259 if (!graph)
1242 ✗ return AVERROR(ENOMEM);;
1243 8259 graph->nb_threads = 1;
1244
1245 8259 ret = graph_parse(fg, graph, fg->graph_desc, &inputs, &outputs,
1246 hw_device_for_filter());
1247
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8258 times.
8259 if (ret < 0)
1248 1 goto fail;
1249
1250
2/2
✓ Branch 0 taken 7166 times.
✓ Branch 1 taken 8258 times.
15424 for (AVFilterInOut *cur = inputs; cur; cur = cur->next) {
1251 7166 InputFilter *const ifilter = ifilter_alloc(fg);
1252
1253
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7166 times.
7166 if (!ifilter) {
1254 ✗ ret = AVERROR(ENOMEM);
1255 ✗ goto fail;
1256 }
1257
1258 7166 ifilter->linklabel = cur->name;
1259 7166 cur->name = NULL;
1260
1261 7166 ifilter->type = avfilter_pad_get_type(cur->filter_ctx->input_pads,
1262 cur->pad_idx);
1263
1264
3/4
✓ Branch 0 taken 1391 times.
✓ Branch 1 taken 5775 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1391 times.
7166 if (ifilter->type != AVMEDIA_TYPE_VIDEO && ifilter->type != AVMEDIA_TYPE_AUDIO) {
1265 ✗ av_log(fg, AV_LOG_FATAL, "Only video and audio filters supported "
1266 "currently.\n");
1267 ✗ ret = AVERROR(ENOSYS);
1268 ✗ goto fail;
1269 }
1270
1271 7166 ifilter->name = describe_filter_link(fg, cur, 1);
1272
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7166 times.
7166 if (!ifilter->name) {
1273 ✗ ret = AVERROR(ENOMEM);
1274 ✗ goto fail;
1275 }
1276 }
1277
1278
2/2
✓ Branch 0 taken 8393 times.
✓ Branch 1 taken 8258 times.
16651 for (AVFilterInOut *cur = outputs; cur; cur = cur->next) {
1279 8393 const enum AVMediaType type = avfilter_pad_get_type(cur->filter_ctx->output_pads,
1280 cur->pad_idx);
1281 8393 OutputFilter *const ofilter = ofilter_alloc(fg, type);
1282 OutputFilterPriv *ofp;
1283
1284
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8393 times.
8393 if (!ofilter) {
1285 ✗ ret = AVERROR(ENOMEM);
1286 ✗ goto fail;
1287 }
1288 8393 ofp = ofp_from_ofilter(ofilter);
1289
1290 8393 ofilter->linklabel = cur->name;
1291 8393 cur->name = NULL;
1292
1293 8393 ofilter->name = describe_filter_link(fg, cur, 0);
1294
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8393 times.
8393 if (!ofilter->name) {
1295 ✗ ret = AVERROR(ENOMEM);
1296 ✗ goto fail;
1297 }
1298
1299 // opts should only be needed in this function to fill fields from filtergraphs
1300 // whose output is meant to be treated as if it was stream, e.g. merged HEIF
1301 // tile groups.
1302
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 8387 times.
8393 if (opts) {
1303 6 ofp->flags = opts->flags;
1304 6 ofp->side_data = opts->side_data;
1305 6 ofp->nb_side_data = opts->nb_side_data;
1306
1307 6 ofp->crop_top = opts->crop_top;
1308 6 ofp->crop_bottom = opts->crop_bottom;
1309 6 ofp->crop_left = opts->crop_left;
1310 6 ofp->crop_right = opts->crop_right;
1311
1312 6 const AVFrameSideData *sd = av_frame_side_data_get(ofp->side_data, ofp->nb_side_data,
1313 AV_FRAME_DATA_DISPLAYMATRIX);
1314
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (sd)
1315 ✗ memcpy(ofp->displaymatrix, sd->data, sizeof(ofp->displaymatrix));
1316 }
1317 }
1318
1319
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8258 times.
8258 if (!fg->nb_outputs) {
1320 ✗ av_log(fg, AV_LOG_FATAL, "A filtergraph has zero outputs, this is not supported\n");
1321 ✗ ret = AVERROR(ENOSYS);
1322 ✗ goto fail;
1323 }
1324
1325 8258 ret = sch_add_filtergraph(sch, fg->nb_inputs, fg->nb_outputs,
1326 filter_thread, fgp);
1327
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8258 times.
8258 if (ret < 0)
1328 ✗ goto fail;
1329 8258 fgp->sch_idx = ret;
1330
1331 8259 fail:
1332 8259 avfilter_inout_free(&inputs);
1333 8259 avfilter_inout_free(&outputs);
1334 8259 avfilter_graph_free(&graph);
1335
1336
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8258 times.
8259 if (ret < 0)
1337 1 return ret;
1338
1339 8258 return 0;
1340 }
1341
1342 6981 int fg_create_simple(FilterGraph **pfg,
1343 InputStream *ist,
1344 char **graph_desc,
1345 Scheduler *sch, unsigned sched_idx_enc,
1346 const OutputFilterOptions *opts)
1347 {
1348 6981 const enum AVMediaType type = ist->par->codec_type;
1349 FilterGraph *fg;
1350 FilterGraphPriv *fgp;
1351 int ret;
1352
1353 6981 ret = fg_create(pfg, graph_desc, sch, NULL);
1354
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6980 times.
6981 if (ret < 0)
1355 1 return ret;
1356 6980 fg = *pfg;
1357 6980 fgp = fgp_from_fg(fg);
1358
1359 6980 fgp->is_simple = 1;
1360
1361 6980 snprintf(fgp->log_name, sizeof(fgp->log_name), "%cf%s",
1362 6980 av_get_media_type_string(type)[0], opts->name);
1363
1364
2/4
✓ Branch 0 taken 6980 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6980 times.
6980 if (fg->nb_inputs != 1 || fg->nb_outputs != 1) {
1365 ✗ av_log(fg, AV_LOG_ERROR, "Simple filtergraph '%s' was expected "
1366 "to have exactly 1 input and 1 output. "
1367 "However, it had %d input(s) and %d output(s). Please adjust, "
1368 "or use a complex filtergraph (-filter_complex) instead.\n",
1369 *graph_desc, fg->nb_inputs, fg->nb_outputs);
1370 ✗ return AVERROR(EINVAL);
1371 }
1372
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6980 times.
6980 if (fg->outputs[0]->type != type) {
1373 ✗ av_log(fg, AV_LOG_ERROR, "Filtergraph has a %s output, cannot connect "
1374 "it to %s output stream\n",
1375 ✗ av_get_media_type_string(fg->outputs[0]->type),
1376 av_get_media_type_string(type));
1377 ✗ return AVERROR(EINVAL);
1378 }
1379
1380 6980 ret = ifilter_bind_ist(fg->inputs[0], ist, opts->vs);
1381
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6980 times.
6980 if (ret < 0)
1382 ✗ return ret;
1383
1384 6980 ret = ofilter_bind_enc(fg->outputs[0], sched_idx_enc, opts);
1385
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6980 times.
6980 if (ret < 0)
1386 ✗ return ret;
1387
1388
2/2
✓ Branch 0 taken 4322 times.
✓ Branch 1 taken 2658 times.
6980 if (opts->nb_threads >= 0)
1389 4322 fgp->nb_threads = opts->nb_threads;
1390
1391 6980 return 0;
1392 }
1393
1394 363 static int fg_complex_bind_input(FilterGraph *fg, InputFilter *ifilter, int commit)
1395 {
1396 363 InputFilterPriv *ifp = ifp_from_ifilter(ifilter);
1397 363 InputStream *ist = NULL;
1398 363 enum AVMediaType type = ifilter->type;
1399 363 ViewSpecifier vs = { .type = VIEW_SPECIFIER_TYPE_NONE };
1400 const char *spec;
1401 char *p;
1402 int i, ret;
1403
1404
4/4
✓ Branch 0 taken 249 times.
✓ Branch 1 taken 114 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 248 times.
363 if (ifilter->linklabel && !strncmp(ifilter->linklabel, "dec:", 4)) {
1405 // bind to a standalone decoder
1406 int dec_idx;
1407
1408 1 dec_idx = strtol(ifilter->linklabel + 4, &p, 0);
1409
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (dec_idx < 0 || dec_idx >= nb_decoders) {
1410 ✗ av_log(fg, AV_LOG_ERROR, "Invalid decoder index %d in filtergraph description %s\n",
1411 dec_idx, fg->graph_desc);
1412 ✗ return AVERROR(EINVAL);
1413 }
1414
1415
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (type == AVMEDIA_TYPE_VIDEO) {
1416
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 spec = *p == ':' ? p + 1 : p;
1417 1 ret = view_specifier_parse(&spec, &vs);
1418
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
1419 ✗ return ret;
1420 }
1421
1422 1 ret = ifilter_bind_dec(ifp, decoders[dec_idx], &vs);
1423
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
1424 ✗ av_log(fg, AV_LOG_ERROR, "Error binding a decoder to filtergraph input %s\n",
1425 ifilter->name);
1426 1 return ret;
1427
2/2
✓ Branch 0 taken 248 times.
✓ Branch 1 taken 114 times.
362 } else if (ifilter->linklabel) {
1428 StreamSpecifier ss;
1429 AVFormatContext *s;
1430 248 AVStream *st = NULL;
1431 int file_idx;
1432
1433 // try finding an unbound filtergraph output with this label
1434
2/2
✓ Branch 0 taken 258 times.
✓ Branch 1 taken 246 times.
504 for (int i = 0; i < nb_filtergraphs; i++) {
1435 258 FilterGraph *fg_src = filtergraphs[i];
1436
1437
2/2
✓ Branch 0 taken 248 times.
✓ Branch 1 taken 10 times.
258 if (fg == fg_src)
1438 248 continue;
1439
1440
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 8 times.
18 for (int j = 0; j < fg_src->nb_outputs; j++) {
1441 10 OutputFilter *ofilter = fg_src->outputs[j];
1442
1443
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
10 if (!ofilter->bound && ofilter->linklabel &&
1444
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 !strcmp(ofilter->linklabel, ifilter->linklabel)) {
1445
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (commit) {
1446 1 av_log(fg, AV_LOG_VERBOSE,
1447 "Binding input with label '%s' to filtergraph output %d:%d\n",
1448 ifilter->linklabel, i, j);
1449
1450 1 ret = ifilter_bind_fg(ifp, fg_src, j);
1451
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0) {
1452 ✗ av_log(fg, AV_LOG_ERROR, "Error binding filtergraph input %s\n",
1453 ifilter->linklabel);
1454 2 return ret;
1455 }
1456 } else
1457 1 ofp_from_ofilter(ofilter)->needed = 1;
1458 2 return 0;
1459 }
1460 }
1461 }
1462
1463 // bind to an explicitly specified demuxer stream
1464 246 file_idx = strtol(ifilter->linklabel, &p, 0);
1465
2/4
✓ Branch 0 taken 246 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 246 times.
246 if (file_idx < 0 || file_idx >= nb_input_files) {
1466 ✗ av_log(fg, AV_LOG_FATAL, "Invalid file index %d in filtergraph description %s.\n",
1467 file_idx, fg->graph_desc);
1468 ✗ return AVERROR(EINVAL);
1469 }
1470 246 s = input_files[file_idx]->ctx;
1471
1472
2/2
✓ Branch 0 taken 238 times.
✓ Branch 1 taken 8 times.
246 ret = stream_specifier_parse(&ss, *p == ':' ? p + 1 : p, 1, fg);
1473
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 246 times.
246 if (ret < 0) {
1474 ✗ av_log(fg, AV_LOG_ERROR, "Invalid stream specifier: %s\n", p);
1475 ✗ return ret;
1476 }
1477
1478
2/2
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 170 times.
246 if (type == AVMEDIA_TYPE_VIDEO) {
1479
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 76 times.
76 spec = ss.remainder ? ss.remainder : "";
1480 76 ret = view_specifier_parse(&spec, &vs);
1481
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 76 times.
76 if (ret < 0) {
1482 ✗ stream_specifier_uninit(&ss);
1483 ✗ return ret;
1484 }
1485 }
1486
1487
1/2
✓ Branch 0 taken 299 times.
✗ Branch 1 not taken.
299 for (i = 0; i < s->nb_streams; i++) {
1488 299 enum AVMediaType stream_type = s->streams[i]->codecpar->codec_type;
1489
4/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 283 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 6 times.
299 if (stream_type != type &&
1490
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 !(stream_type == AVMEDIA_TYPE_SUBTITLE &&
1491 type == AVMEDIA_TYPE_VIDEO /* sub2video hack */))
1492 6 continue;
1493
2/2
✓ Branch 1 taken 246 times.
✓ Branch 2 taken 47 times.
293 if (stream_specifier_match(&ss, s, s->streams[i], fg)) {
1494 246 st = s->streams[i];
1495 246 break;
1496 }
1497 }
1498 246 stream_specifier_uninit(&ss);
1499
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 246 times.
246 if (!st) {
1500 ✗ av_log(fg, AV_LOG_FATAL, "Stream specifier '%s' in filtergraph description %s "
1501 "matches no streams.\n", p, fg->graph_desc);
1502 ✗ return AVERROR(EINVAL);
1503 }
1504 246 ist = input_files[file_idx]->streams[st->index];
1505
1506
2/2
✓ Branch 0 taken 119 times.
✓ Branch 1 taken 127 times.
246 if (commit)
1507 119 av_log(fg, AV_LOG_VERBOSE,
1508 "Binding input with label '%s' to input stream %d:%d\n",
1509 119 ifilter->linklabel, ist->file->index, ist->index);
1510 } else {
1511 // try finding an unbound filtergraph output
1512
2/2
✓ Branch 0 taken 114 times.
✓ Branch 1 taken 114 times.
228 for (int i = 0; i < nb_filtergraphs; i++) {
1513 114 FilterGraph *fg_src = filtergraphs[i];
1514
1515
1/2
✓ Branch 0 taken 114 times.
✗ Branch 1 not taken.
114 if (fg == fg_src)
1516 114 continue;
1517
1518 ✗ for (int j = 0; j < fg_src->nb_outputs; j++) {
1519 ✗ OutputFilter *ofilter = fg_src->outputs[j];
1520
1521 ✗ if (!ofilter->bound) {
1522 ✗ if (commit) {
1523 ✗ av_log(fg, AV_LOG_VERBOSE,
1524 "Binding unlabeled filtergraph input to filtergraph output %d:%d\n", i, j);
1525
1526 ✗ ret = ifilter_bind_fg(ifp, fg_src, j);
1527 ✗ if (ret < 0) {
1528 ✗ av_log(fg, AV_LOG_ERROR, "Error binding filtergraph input %d:%d\n", i, j);
1529 ✗ return ret;
1530 }
1531 } else
1532 ✗ ofp_from_ofilter(ofilter)->needed = 1;
1533 ✗ return 0;
1534 }
1535 }
1536 }
1537
1538 114 ist = ist_find_unused(type);
1539
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 114 times.
114 if (!ist) {
1540 ✗ av_log(fg, AV_LOG_FATAL,
1541 "Cannot find an unused %s input stream to feed the "
1542 "unlabeled input pad %s.\n",
1543 av_get_media_type_string(type), ifilter->name);
1544 ✗ return AVERROR(EINVAL);
1545 }
1546
1547
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 57 times.
114 if (commit)
1548 57 av_log(fg, AV_LOG_VERBOSE,
1549 "Binding unlabeled input %d to input stream %d:%d\n",
1550 57 ifilter->index, ist->file->index, ist->index);
1551 }
1552
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 360 times.
360 av_assert0(ist);
1553
1554
2/2
✓ Branch 0 taken 176 times.
✓ Branch 1 taken 184 times.
360 if (commit) {
1555 176 ret = ifilter_bind_ist(ifilter, ist, &vs);
1556
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 176 times.
176 if (ret < 0) {
1557 ✗ av_log(fg, AV_LOG_ERROR,
1558 "Error binding an input stream to complex filtergraph input %s.\n",
1559 ifilter->name);
1560 ✗ return ret;
1561 }
1562 }
1563
1564 360 return 0;
1565 }
1566
1567 2553 static int bind_inputs(FilterGraph *fg, int commit)
1568 {
1569 // bind filtergraph inputs to input streams or other filtergraphs
1570
2/2
✓ Branch 0 taken 364 times.
✓ Branch 1 taken 2553 times.
2917 for (int i = 0; i < fg->nb_inputs; i++) {
1571 364 InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]);
1572 int ret;
1573
1574
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 363 times.
364 if (ifp->bound)
1575 1 continue;
1576
1577 363 ret = fg_complex_bind_input(fg, &ifp->ifilter, commit);
1578
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 363 times.
363 if (ret < 0)
1579 ✗ return ret;
1580 }
1581
1582 2553 return 0;
1583 }
1584
1585 8835 int fg_finalise_bindings(void)
1586 {
1587 int ret;
1588
1589
2/2
✓ Branch 0 taken 1278 times.
✓ Branch 1 taken 8835 times.
10113 for (int i = 0; i < nb_filtergraphs; i++) {
1590 1278 ret = bind_inputs(filtergraphs[i], 0);
1591
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1278 times.
1278 if (ret < 0)
1592 ✗ return ret;
1593 }
1594
1595 // check that all outputs were bound
1596
2/2
✓ Branch 0 taken 1278 times.
✓ Branch 1 taken 8835 times.
10113 for (int i = nb_filtergraphs - 1; i >= 0; i--) {
1597 1278 FilterGraph *fg = filtergraphs[i];
1598 1278 FilterGraphPriv *fgp = fgp_from_fg(filtergraphs[i]);
1599
1600
2/2
✓ Branch 0 taken 1413 times.
✓ Branch 1 taken 1275 times.
2688 for (int j = 0; j < fg->nb_outputs; j++) {
1601 1413 OutputFilter *output = fg->outputs[j];
1602
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1410 times.
1413 if (!ofp_from_ofilter(output)->needed) {
1603
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!fg->is_internal) {
1604 ✗ av_log(fg, AV_LOG_FATAL,
1605 "Filter '%s' has output %d (%s) unconnected\n",
1606 output->name, j,
1607 ✗ output->linklabel ? (const char *)output->linklabel : "unlabeled");
1608 ✗ return AVERROR(EINVAL);
1609 }
1610
1611 3 av_log(fg, AV_LOG_DEBUG,
1612 "Internal filter '%s' has output %d (%s) unconnected. Removing graph\n",
1613 output->name, j,
1614
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 output->linklabel ? (const char *)output->linklabel : "unlabeled");
1615 3 sch_remove_filtergraph(fgp->sch, fgp->sch_idx);
1616 3 fg_free(&filtergraphs[i]);
1617 3 nb_filtergraphs--;
1618
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (nb_filtergraphs > 0)
1619 ✗ memmove(&filtergraphs[i],
1620 ✗ &filtergraphs[i + 1],
1621 ✗ (nb_filtergraphs - i) * sizeof(*filtergraphs));
1622 3 break;
1623 }
1624 }
1625 }
1626
1627
2/2
✓ Branch 0 taken 1275 times.
✓ Branch 1 taken 8835 times.
10110 for (int i = 0; i < nb_filtergraphs; i++) {
1628 1275 ret = bind_inputs(filtergraphs[i], 1);
1629
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1275 times.
1275 if (ret < 0)
1630 ✗ return ret;
1631 }
1632
1633 8835 return 0;
1634 }
1635
1636 15640 static int insert_trim(void *logctx, int64_t start_time, int64_t duration,
1637 AVFilterContext **last_filter, int *pad_idx,
1638 const char *filter_name)
1639 {
1640 15640 AVFilterGraph *graph = (*last_filter)->graph;
1641 AVFilterContext *ctx;
1642 const AVFilter *trim;
1643 15640 enum AVMediaType type = avfilter_pad_get_type((*last_filter)->output_pads, *pad_idx);
1644
2/2
✓ Branch 0 taken 12795 times.
✓ Branch 1 taken 2845 times.
15640 const char *name = (type == AVMEDIA_TYPE_VIDEO) ? "trim" : "atrim";
1645 15640 int ret = 0;
1646
1647
4/4
✓ Branch 0 taken 14262 times.
✓ Branch 1 taken 1378 times.
✓ Branch 2 taken 14238 times.
✓ Branch 3 taken 24 times.
15640 if (duration == INT64_MAX && start_time == AV_NOPTS_VALUE)
1648 14238 return 0;
1649
1650 1402 trim = avfilter_get_by_name(name);
1651
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1402 times.
1402 if (!trim) {
1652 ✗ av_log(logctx, AV_LOG_ERROR, "%s filter not present, cannot limit "
1653 "recording time.\n", name);
1654 ✗ return AVERROR_FILTER_NOT_FOUND;
1655 }
1656
1657 1402 ctx = avfilter_graph_alloc_filter(graph, trim, filter_name);
1658
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1402 times.
1402 if (!ctx)
1659 ✗ return AVERROR(ENOMEM);
1660
1661
2/2
✓ Branch 0 taken 1378 times.
✓ Branch 1 taken 24 times.
1402 if (duration != INT64_MAX) {
1662 1378 ret = av_opt_set_int(ctx, "durationi", duration,
1663 AV_OPT_SEARCH_CHILDREN);
1664 }
1665
3/4
✓ Branch 0 taken 1402 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
✓ Branch 3 taken 1375 times.
1402 if (ret >= 0 && start_time != AV_NOPTS_VALUE) {
1666 27 ret = av_opt_set_int(ctx, "starti", start_time,
1667 AV_OPT_SEARCH_CHILDREN);
1668 }
1669
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1402 times.
1402 if (ret < 0) {
1670 ✗ av_log(ctx, AV_LOG_ERROR, "Error configuring the %s filter", name);
1671 ✗ return ret;
1672 }
1673
1674 1402 ret = avfilter_init_str(ctx, NULL);
1675
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1402 times.
1402 if (ret < 0)
1676 ✗ return ret;
1677
1678 1402 ret = avfilter_link(*last_filter, *pad_idx, ctx, 0);
1679
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1402 times.
1402 if (ret < 0)
1680 ✗ return ret;
1681
1682 1402 *last_filter = ctx;
1683 1402 *pad_idx = 0;
1684 1402 return 0;
1685 }
1686
1687 24 static int insert_filter(AVFilterContext **last_filter, int *pad_idx,
1688 const char *filter_name, const char *args)
1689 {
1690 24 AVFilterGraph *graph = (*last_filter)->graph;
1691 24 const AVFilter *filter = avfilter_get_by_name(filter_name);
1692 AVFilterContext *ctx;
1693 int ret;
1694
1695
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (!filter)
1696 ✗ return AVERROR_BUG;
1697
1698 24 ret = avfilter_graph_create_filter(&ctx,
1699 filter,
1700 filter_name, args, NULL, graph);
1701
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (ret < 0)
1702 ✗ return ret;
1703
1704 24 ret = avfilter_link(*last_filter, *pad_idx, ctx, 0);
1705
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (ret < 0)
1706 ✗ return ret;
1707
1708 24 *last_filter = ctx;
1709 24 *pad_idx = 0;
1710 24 return 0;
1711 }
1712
1713 6982 static int configure_output_video_filter(FilterGraphPriv *fgp, AVFilterGraph *graph,
1714 OutputFilter *ofilter, AVFilterInOut *out)
1715 {
1716 6982 OutputFilterPriv *ofp = ofp_from_ofilter(ofilter);
1717 6982 AVFilterContext *last_filter = out->filter_ctx;
1718 AVBPrint bprint;
1719 6982 int pad_idx = out->pad_idx;
1720 int ret;
1721 char name[255];
1722
1723 6982 snprintf(name, sizeof(name), "out_%s", ofilter->output_name);
1724 6982 ret = avfilter_graph_create_filter(&ofilter->filter,
1725 avfilter_get_by_name("buffersink"),
1726 name, NULL, NULL, graph);
1727
1728
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6982 times.
6982 if (ret < 0)
1729 ✗ return ret;
1730
1731
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 6979 times.
6982 if (ofp->flags & OFILTER_FLAG_CROP) {
1732 char crop_buf[64];
1733 3 snprintf(crop_buf, sizeof(crop_buf), "w=iw-%u-%u:h=ih-%u-%u:x=%u:y=%u",
1734 ofp->crop_left, ofp->crop_right,
1735 ofp->crop_top, ofp->crop_bottom,
1736 ofp->crop_left, ofp->crop_top);
1737 3 ret = insert_filter(&last_filter, &pad_idx, "crop", crop_buf);
1738
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
1739 ✗ return ret;
1740 }
1741
1742
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 6979 times.
6982 if (ofp->flags & OFILTER_FLAG_AUTOROTATE) {
1743 3 int32_t *displaymatrix = ofp->displaymatrix;
1744 double theta;
1745
1746 3 theta = get_rotation(displaymatrix);
1747
1748
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (fabs(theta - 90) < 1.0) {
1749 ✗ ret = insert_filter(&last_filter, &pad_idx, "transpose",
1750 ✗ displaymatrix[3] > 0 ? "cclock_flip" : "clock");
1751
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 } else if (fabs(theta - 180) < 1.0) {
1752 ✗ if (displaymatrix[0] < 0) {
1753 ✗ ret = insert_filter(&last_filter, &pad_idx, "hflip", NULL);
1754 ✗ if (ret < 0)
1755 ✗ return ret;
1756 }
1757 ✗ if (displaymatrix[4] < 0) {
1758 ✗ ret = insert_filter(&last_filter, &pad_idx, "vflip", NULL);
1759 }
1760
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 } else if (fabs(theta - 270) < 1.0) {
1761 ✗ ret = insert_filter(&last_filter, &pad_idx, "transpose",
1762 ✗ displaymatrix[3] < 0 ? "clock_flip" : "cclock");
1763
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 } else if (fabs(theta) > 1.0) {
1764 char rotate_buf[64];
1765 ✗ snprintf(rotate_buf, sizeof(rotate_buf), "%f*PI/180", theta);
1766 ✗ ret = insert_filter(&last_filter, &pad_idx, "rotate", rotate_buf);
1767
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 } else if (fabs(theta) < 1.0) {
1768 ✗ if (displaymatrix && displaymatrix[4] < 0) {
1769 ✗ ret = insert_filter(&last_filter, &pad_idx, "vflip", NULL);
1770 }
1771 }
1772
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
1773 ✗ return ret;
1774
1775 3 av_frame_side_data_remove(&ofp->side_data, &ofp->nb_side_data, AV_FRAME_DATA_DISPLAYMATRIX);
1776 }
1777
1778
4/6
✓ Branch 0 taken 5586 times.
✓ Branch 1 taken 1396 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5586 times.
✓ Branch 4 taken 1396 times.
✗ Branch 5 not taken.
6982 if ((ofp->width || ofp->height) && (ofp->flags & OFILTER_FLAG_AUTOSCALE) &&
1779 // skip add scale for hardware format
1780
2/2
✓ Branch 0 taken 1371 times.
✓ Branch 1 taken 25 times.
1396 !(ofp->format != AV_PIX_FMT_NONE &&
1781
1/2
✓ Branch 1 taken 1371 times.
✗ Branch 2 not taken.
1371 av_pix_fmt_desc_get(ofp->format)->flags & AV_PIX_FMT_FLAG_HWACCEL)) {
1782 char args[255];
1783 AVFilterContext *filter;
1784 1396 const AVDictionaryEntry *e = NULL;
1785
1786 1396 snprintf(args, sizeof(args), "%d:%d",
1787 ofp->width, ofp->height);
1788
1789
2/2
✓ Branch 1 taken 1382 times.
✓ Branch 2 taken 1396 times.
2778 while ((e = av_dict_iterate(ofp->sws_opts, e))) {
1790 1382 av_strlcatf(args, sizeof(args), ":%s=%s", e->key, e->value);
1791 }
1792
1793 1396 snprintf(name, sizeof(name), "scaler_out_%s", ofilter->output_name);
1794
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1396 times.
1396 if ((ret = avfilter_graph_create_filter(&filter, avfilter_get_by_name("scale"),
1795 name, args, NULL, graph)) < 0)
1796 ✗ return ret;
1797
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1396 times.
1396 if ((ret = avfilter_link(last_filter, pad_idx, filter, 0)) < 0)
1798 ✗ return ret;
1799
1800 1396 last_filter = filter;
1801 1396 pad_idx = 0;
1802 }
1803
1804
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 6982 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
6982 av_assert0(!(ofp->flags & OFILTER_FLAG_DISABLE_CONVERT) ||
1805 ofp->format != AV_PIX_FMT_NONE || !ofp->pix_fmts);
1806 6982 av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED);
1807 6982 choose_pix_fmts(ofp, &bprint);
1808 6982 choose_color_spaces(ofp, &bprint);
1809 6982 choose_color_ranges(ofp, &bprint);
1810 6982 choose_alpha_modes(ofp, &bprint);
1811
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6982 times.
6982 if (!av_bprint_is_complete(&bprint))
1812 ✗ return AVERROR(ENOMEM);
1813
1814
2/2
✓ Branch 0 taken 5792 times.
✓ Branch 1 taken 1190 times.
6982 if (bprint.len) {
1815 AVFilterContext *filter;
1816
1817 5792 ret = avfilter_graph_create_filter(&filter,
1818 avfilter_get_by_name("format"),
1819 5792 "format", bprint.str, NULL, graph);
1820 5792 av_bprint_finalize(&bprint, NULL);
1821
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5792 times.
5792 if (ret < 0)
1822 ✗ return ret;
1823
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5792 times.
5792 if ((ret = avfilter_link(last_filter, pad_idx, filter, 0)) < 0)
1824 ✗ return ret;
1825
1826 5792 last_filter = filter;
1827 5792 pad_idx = 0;
1828 }
1829
1830 6982 snprintf(name, sizeof(name), "trim_out_%s", ofilter->output_name);
1831 6982 ret = insert_trim(fgp, ofp->trim_start_us, ofp->trim_duration_us,
1832 &last_filter, &pad_idx, name);
1833
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6982 times.
6982 if (ret < 0)
1834 ✗ return ret;
1835
1836
1837
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6982 times.
6982 if ((ret = avfilter_link(last_filter, pad_idx, ofilter->filter, 0)) < 0)
1838 ✗ return ret;
1839
1840 6982 return 0;
1841 }
1842
1843 1454 static int configure_output_audio_filter(FilterGraphPriv *fgp, AVFilterGraph *graph,
1844 OutputFilter *ofilter, AVFilterInOut *out)
1845 {
1846 1454 OutputFilterPriv *ofp = ofp_from_ofilter(ofilter);
1847 1454 AVFilterContext *last_filter = out->filter_ctx;
1848 1454 int pad_idx = out->pad_idx;
1849 AVBPrint args;
1850 char name[255];
1851 int ret;
1852
1853 1454 snprintf(name, sizeof(name), "out_%s", ofilter->output_name);
1854 1454 ret = avfilter_graph_create_filter(&ofilter->filter,
1855 avfilter_get_by_name("abuffersink"),
1856 name, NULL, NULL, graph);
1857
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1454 times.
1454 if (ret < 0)
1858 ✗ return ret;
1859
1860 #define AUTO_INSERT_FILTER(opt_name, filter_name, arg) do { \
1861 AVFilterContext *filt_ctx; \
1862 \
1863 av_log(ofilter, AV_LOG_INFO, opt_name " is forwarded to lavfi " \
1864 "similarly to -af " filter_name "=%s.\n", arg); \
1865 \
1866 ret = avfilter_graph_create_filter(&filt_ctx, \
1867 avfilter_get_by_name(filter_name), \
1868 filter_name, arg, NULL, graph); \
1869 if (ret < 0) \
1870 goto fail; \
1871 \
1872 ret = avfilter_link(last_filter, pad_idx, filt_ctx, 0); \
1873 if (ret < 0) \
1874 goto fail; \
1875 \
1876 last_filter = filt_ctx; \
1877 pad_idx = 0; \
1878 } while (0)
1879 1454 av_bprint_init(&args, 0, AV_BPRINT_SIZE_UNLIMITED);
1880
1881 1454 choose_sample_fmts(ofp, &args);
1882 1454 choose_sample_rates(ofp, &args);
1883 1454 choose_channel_layouts(ofp, &args);
1884
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1454 times.
1454 if (!av_bprint_is_complete(&args)) {
1885 ✗ ret = AVERROR(ENOMEM);
1886 ✗ goto fail;
1887 }
1888
1/2
✓ Branch 0 taken 1454 times.
✗ Branch 1 not taken.
1454 if (args.len) {
1889 AVFilterContext *format;
1890
1891 1454 snprintf(name, sizeof(name), "format_out_%s", ofilter->output_name);
1892 1454 ret = avfilter_graph_create_filter(&format,
1893 avfilter_get_by_name("aformat"),
1894 1454 name, args.str, NULL, graph);
1895
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1454 times.
1454 if (ret < 0)
1896 ✗ goto fail;
1897
1898 1454 ret = avfilter_link(last_filter, pad_idx, format, 0);
1899
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1454 times.
1454 if (ret < 0)
1900 ✗ goto fail;
1901
1902 1454 last_filter = format;
1903 1454 pad_idx = 0;
1904 }
1905
1906
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1454 times.
1454 if (ofilter->apad)
1907 ✗ AUTO_INSERT_FILTER("-apad", "apad", ofilter->apad);
1908
1909 1454 snprintf(name, sizeof(name), "trim for output %s", ofilter->output_name);
1910 1454 ret = insert_trim(fgp, ofp->trim_start_us, ofp->trim_duration_us,
1911 &last_filter, &pad_idx, name);
1912
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1454 times.
1454 if (ret < 0)
1913 ✗ goto fail;
1914
1915
1/2
✓ Branch 1 taken 1454 times.
✗ Branch 2 not taken.
1454 if ((ret = avfilter_link(last_filter, pad_idx, ofilter->filter, 0)) < 0)
1916 ✗ goto fail;
1917 1454 fail:
1918 1454 av_bprint_finalize(&args, NULL);
1919
1920 1454 return ret;
1921 }
1922
1923 8436 static int configure_output_filter(FilterGraphPriv *fgp, AVFilterGraph *graph,
1924 OutputFilter *ofilter, AVFilterInOut *out)
1925 {
1926
2/3
✓ Branch 0 taken 6982 times.
✓ Branch 1 taken 1454 times.
✗ Branch 2 not taken.
8436 switch (ofilter->type) {
1927 6982 case AVMEDIA_TYPE_VIDEO: return configure_output_video_filter(fgp, graph, ofilter, out);
1928 1454 case AVMEDIA_TYPE_AUDIO: return configure_output_audio_filter(fgp, graph, ofilter, out);
1929 ✗ default: av_assert0(0); return 0;
1930 }
1931 }
1932
1933 4 static void sub2video_prepare(InputFilterPriv *ifp)
1934 {
1935 4 ifp->sub2video.last_pts = INT64_MIN;
1936 4 ifp->sub2video.end_pts = INT64_MIN;
1937
1938 /* sub2video structure has been (re-)initialized.
1939 Mark it as such so that the system will be
1940 initialized with the first received heartbeat. */
1941 4 ifp->sub2video.initialize = 1;
1942 4 }
1943
1944 5813 static int configure_input_video_filter(FilterGraph *fg, AVFilterGraph *graph,
1945 InputFilter *ifilter, AVFilterInOut *in)
1946 {
1947 5813 InputFilterPriv *ifp = ifp_from_ifilter(ifilter);
1948
1949 AVFilterContext *last_filter;
1950 5813 const AVFilter *buffer_filt = avfilter_get_by_name("buffer");
1951 const AVPixFmtDescriptor *desc;
1952 char name[255];
1953 5813 int ret, pad_idx = 0;
1954 5813 AVBufferSrcParameters *par = av_buffersrc_parameters_alloc();
1955
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5813 times.
5813 if (!par)
1956 ✗ return AVERROR(ENOMEM);
1957
1958
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 5809 times.
5813 if (ifp->type_src == AVMEDIA_TYPE_SUBTITLE)
1959 4 sub2video_prepare(ifp);
1960
1961 5813 snprintf(name, sizeof(name), "graph %d input from stream %s", fg->index,
1962 ifp->opts.name);
1963
1964 5813 ifilter->filter = avfilter_graph_alloc_filter(graph, buffer_filt, name);
1965
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5813 times.
5813 if (!ifilter->filter) {
1966 ✗ ret = AVERROR(ENOMEM);
1967 ✗ goto fail;
1968 }
1969
1970 5813 par->format = ifp->format;
1971 5813 par->time_base = ifp->time_base;
1972 5813 par->frame_rate = ifp->opts.framerate;
1973 5813 par->width = ifp->width;
1974 5813 par->height = ifp->height;
1975 5813 par->sample_aspect_ratio = ifp->sample_aspect_ratio.den > 0 ?
1976
2/2
✓ Branch 0 taken 5809 times.
✓ Branch 1 taken 4 times.
5813 ifp->sample_aspect_ratio : (AVRational){ 0, 1 };
1977 5813 par->color_space = ifp->color_space;
1978 5813 par->color_range = ifp->color_range;
1979 5813 par->alpha_mode = ifp->alpha_mode;
1980 5813 par->hw_frames_ctx = ifp->hw_frames_ctx;
1981 5813 par->side_data = ifp->side_data;
1982 5813 par->nb_side_data = ifp->nb_side_data;
1983
1984 5813 ret = av_buffersrc_parameters_set(ifilter->filter, par);
1985
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5813 times.
5813 if (ret < 0)
1986 ✗ goto fail;
1987 5813 av_freep(&par);
1988
1989 5813 ret = avfilter_init_dict(ifilter->filter, NULL);
1990
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5813 times.
5813 if (ret < 0)
1991 ✗ goto fail;
1992
1993 5813 last_filter = ifilter->filter;
1994
1995 5813 desc = av_pix_fmt_desc_get(ifp->format);
1996
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5813 times.
5813 av_assert0(desc);
1997
1998
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5807 times.
5813 if ((ifp->opts.flags & IFILTER_FLAG_CROP)) {
1999 char crop_buf[64];
2000 6 snprintf(crop_buf, sizeof(crop_buf), "w=iw-%u-%u:h=ih-%u-%u:x=%u:y=%u",
2001 ifp->opts.crop_left, ifp->opts.crop_right,
2002 ifp->opts.crop_top, ifp->opts.crop_bottom,
2003 ifp->opts.crop_left, ifp->opts.crop_top);
2004 6 ret = insert_filter(&last_filter, &pad_idx, "crop", crop_buf);
2005
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (ret < 0)
2006 ✗ return ret;
2007 }
2008
2009 // TODO: insert hwaccel enabled filters like transpose_vaapi into the graph
2010 5813 ifp->displaymatrix_applied = 0;
2011
2/2
✓ Branch 0 taken 5808 times.
✓ Branch 1 taken 5 times.
5813 if ((ifp->opts.flags & IFILTER_FLAG_AUTOROTATE) &&
2012
1/2
✓ Branch 0 taken 5808 times.
✗ Branch 1 not taken.
5808 !(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) {
2013 5808 int32_t *displaymatrix = ifp->displaymatrix;
2014 double theta;
2015
2016 5808 theta = get_rotation(displaymatrix);
2017
2018
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 5793 times.
5808 if (fabs(theta - 90) < 1.0) {
2019 15 ret = insert_filter(&last_filter, &pad_idx, "transpose",
2020
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 1 times.
15 displaymatrix[3] > 0 ? "cclock_flip" : "clock");
2021
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5793 times.
5793 } else if (fabs(theta - 180) < 1.0) {
2022 ✗ if (displaymatrix[0] < 0) {
2023 ✗ ret = insert_filter(&last_filter, &pad_idx, "hflip", NULL);
2024 ✗ if (ret < 0)
2025 ✗ return ret;
2026 }
2027 ✗ if (displaymatrix[4] < 0) {
2028 ✗ ret = insert_filter(&last_filter, &pad_idx, "vflip", NULL);
2029 }
2030
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5793 times.
5793 } else if (fabs(theta - 270) < 1.0) {
2031 ✗ ret = insert_filter(&last_filter, &pad_idx, "transpose",
2032 ✗ displaymatrix[3] < 0 ? "clock_flip" : "cclock");
2033
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5793 times.
5793 } else if (fabs(theta) > 1.0) {
2034 char rotate_buf[64];
2035 ✗ snprintf(rotate_buf, sizeof(rotate_buf), "%f*PI/180", theta);
2036 ✗ ret = insert_filter(&last_filter, &pad_idx, "rotate", rotate_buf);
2037
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 5784 times.
5793 } else if (fabs(theta) < 1.0) {
2038
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
9 if (displaymatrix && displaymatrix[4] < 0) {
2039 ✗ ret = insert_filter(&last_filter, &pad_idx, "vflip", NULL);
2040 }
2041 }
2042
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5808 times.
5808 if (ret < 0)
2043 ✗ return ret;
2044
2045 5808 ifp->displaymatrix_applied = 1;
2046 }
2047
2048 5813 snprintf(name, sizeof(name), "trim_in_%s", ifp->opts.name);
2049 5813 ret = insert_trim(fg, ifp->opts.trim_start_us, ifp->opts.trim_end_us,
2050 &last_filter, &pad_idx, name);
2051
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5813 times.
5813 if (ret < 0)
2052 ✗ return ret;
2053
2054
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5813 times.
5813 if ((ret = avfilter_link(last_filter, 0, in->filter_ctx, in->pad_idx)) < 0)
2055 ✗ return ret;
2056 5813 return 0;
2057 ✗ fail:
2058 ✗ av_freep(&par);
2059
2060 ✗ return ret;
2061 }
2062
2063 1391 static int configure_input_audio_filter(FilterGraph *fg, AVFilterGraph *graph,
2064 InputFilter *ifilter, AVFilterInOut *in)
2065 {
2066 1391 InputFilterPriv *ifp = ifp_from_ifilter(ifilter);
2067 AVFilterContext *last_filter;
2068 AVBufferSrcParameters *par;
2069 1391 const AVFilter *abuffer_filt = avfilter_get_by_name("abuffer");
2070 AVBPrint args;
2071 char name[255];
2072 1391 int ret, pad_idx = 0;
2073
2074 1391 av_bprint_init(&args, 0, AV_BPRINT_SIZE_AUTOMATIC);
2075 1391 av_bprintf(&args, "time_base=%d/%d:sample_rate=%d:sample_fmt=%s",
2076 ifp->time_base.num, ifp->time_base.den,
2077 ifp->sample_rate,
2078 1391 av_get_sample_fmt_name(ifp->format));
2079
1/2
✓ Branch 1 taken 1391 times.
✗ Branch 2 not taken.
1391 if (av_channel_layout_check(&ifp->ch_layout) &&
2080
2/2
✓ Branch 0 taken 1371 times.
✓ Branch 1 taken 20 times.
1391 ifp->ch_layout.order != AV_CHANNEL_ORDER_UNSPEC) {
2081 1371 av_bprintf(&args, ":channel_layout=");
2082 1371 av_channel_layout_describe_bprint(&ifp->ch_layout, &args);
2083 } else
2084 20 av_bprintf(&args, ":channels=%d", ifp->ch_layout.nb_channels);
2085 1391 snprintf(name, sizeof(name), "graph_%d_in_%s", fg->index, ifp->opts.name);
2086
2087
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1391 times.
1391 if ((ret = avfilter_graph_create_filter(&ifilter->filter, abuffer_filt,
2088 1391 name, args.str, NULL,
2089 graph)) < 0)
2090 ✗ return ret;
2091 1391 par = av_buffersrc_parameters_alloc();
2092
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1391 times.
1391 if (!par)
2093 ✗ return AVERROR(ENOMEM);
2094 1391 par->side_data = ifp->side_data;
2095 1391 par->nb_side_data = ifp->nb_side_data;
2096 1391 ret = av_buffersrc_parameters_set(ifilter->filter, par);
2097 1391 av_free(par);
2098
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1391 times.
1391 if (ret < 0)
2099 ✗ return ret;
2100 1391 last_filter = ifilter->filter;
2101
2102 1391 snprintf(name, sizeof(name), "trim for input stream %s", ifp->opts.name);
2103 1391 ret = insert_trim(fg, ifp->opts.trim_start_us, ifp->opts.trim_end_us,
2104 &last_filter, &pad_idx, name);
2105
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1391 times.
1391 if (ret < 0)
2106 ✗ return ret;
2107
2108
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1391 times.
1391 if ((ret = avfilter_link(last_filter, 0, in->filter_ctx, in->pad_idx)) < 0)
2109 ✗ return ret;
2110
2111 1391 return 0;
2112 }
2113
2114 7204 static int configure_input_filter(FilterGraph *fg, AVFilterGraph *graph,
2115 InputFilter *ifilter, AVFilterInOut *in)
2116 {
2117
2/3
✓ Branch 0 taken 5813 times.
✓ Branch 1 taken 1391 times.
✗ Branch 2 not taken.
7204 switch (ifilter->type) {
2118 5813 case AVMEDIA_TYPE_VIDEO: return configure_input_video_filter(fg, graph, ifilter, in);
2119 1391 case AVMEDIA_TYPE_AUDIO: return configure_input_audio_filter(fg, graph, ifilter, in);
2120 ✗ default: av_assert0(0); return 0;
2121 }
2122 }
2123
2124 8302 static void cleanup_filtergraph(FilterGraph *fg, FilterGraphThread *fgt)
2125 {
2126
2/2
✓ Branch 0 taken 8437 times.
✓ Branch 1 taken 8302 times.
16739 for (int i = 0; i < fg->nb_outputs; i++)
2127 8437 fg->outputs[i]->filter = NULL;
2128
2/2
✓ Branch 0 taken 7205 times.
✓ Branch 1 taken 8302 times.
15507 for (int i = 0; i < fg->nb_inputs; i++)
2129 7205 fg->inputs[i]->filter = NULL;
2130 8302 avfilter_graph_free(&fgt->graph);
2131 8302 }
2132
2133 9564 static int filter_is_buffersrc(const AVFilterContext *f)
2134 {
2135
2/2
✓ Branch 0 taken 4316 times.
✓ Branch 1 taken 5248 times.
13880 return f->nb_inputs == 0 &&
2136
2/2
✓ Branch 0 taken 1910 times.
✓ Branch 1 taken 2406 times.
4316 (!strcmp(f->filter->name, "buffer") ||
2137
2/2
✓ Branch 0 taken 707 times.
✓ Branch 1 taken 1203 times.
1910 !strcmp(f->filter->name, "abuffer"));
2138 }
2139
2140 8300 static int graph_is_meta(AVFilterGraph *graph)
2141 {
2142
2/2
✓ Branch 0 taken 18327 times.
✓ Branch 1 taken 1849 times.
20176 for (unsigned i = 0; i < graph->nb_filters; i++) {
2143 18327 const AVFilterContext *f = graph->filters[i];
2144
2145 /* in addition to filters flagged as meta, also
2146 * disregard sinks and buffersources (but not other sources,
2147 * since they introduce data we are not aware of)
2148 */
2149
4/4
✓ Branch 0 taken 12677 times.
✓ Branch 1 taken 5650 times.
✓ Branch 2 taken 6451 times.
✓ Branch 3 taken 3113 times.
27891 if (!((f->filter->flags & AVFILTER_FLAG_METADATA_ONLY) ||
2150
2/2
✓ Branch 0 taken 9564 times.
✓ Branch 1 taken 3113 times.
12677 f->nb_outputs == 0 ||
2151 9564 filter_is_buffersrc(f)))
2152 6451 return 0;
2153 }
2154 1849 return 1;
2155 }
2156
2157 static int sub2video_frame(InputFilter *ifilter, AVFrame *frame, int buffer);
2158
2159 8301 static int configure_filtergraph(FilterGraph *fg, FilterGraphThread *fgt)
2160 {
2161 8301 FilterGraphPriv *fgp = fgp_from_fg(fg);
2162 AVBufferRef *hw_device;
2163 AVFilterInOut *inputs, *outputs, *cur;
2164 8301 int ret = AVERROR_BUG, i, simple = filtergraph_is_simple(fg);
2165 8301 int have_input_eof = 0;
2166 8301 const char *graph_desc = fg->graph_desc;
2167
2168 8301 cleanup_filtergraph(fg, fgt);
2169 8301 fgt->graph = avfilter_graph_alloc();
2170
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8301 times.
8301 if (!fgt->graph)
2171 ✗ return AVERROR(ENOMEM);
2172
2173
2/2
✓ Branch 0 taken 7026 times.
✓ Branch 1 taken 1275 times.
8301 if (simple) {
2174 7026 OutputFilterPriv *ofp = ofp_from_ofilter(fg->outputs[0]);
2175
2176
2/2
✓ Branch 0 taken 391 times.
✓ Branch 1 taken 6635 times.
7026 if (filter_nbthreads) {
2177 391 ret = av_opt_set(fgt->graph, "threads", filter_nbthreads, 0);
2178
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 391 times.
391 if (ret < 0)
2179 ✗ goto fail;
2180
2/2
✓ Branch 0 taken 4105 times.
✓ Branch 1 taken 2530 times.
6635 } else if (fgp->nb_threads >= 0) {
2181 4105 ret = av_opt_set_int(fgt->graph, "threads", fgp->nb_threads, 0);
2182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4105 times.
4105 if (ret < 0)
2183 ✗ return ret;
2184 }
2185
2186
2/2
✓ Branch 1 taken 4471 times.
✓ Branch 2 taken 2555 times.
7026 if (av_dict_count(ofp->sws_opts)) {
2187 4471 ret = av_dict_get_string(ofp->sws_opts,
2188 4471 &fgt->graph->scale_sws_opts,
2189 '=', ':');
2190
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4471 times.
4471 if (ret < 0)
2191 ✗ goto fail;
2192 }
2193
2194
2/2
✓ Branch 1 taken 65 times.
✓ Branch 2 taken 6961 times.
7026 if (av_dict_count(ofp->swr_opts)) {
2195 char *args;
2196 65 ret = av_dict_get_string(ofp->swr_opts, &args, '=', ':');
2197
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 if (ret < 0)
2198 ✗ goto fail;
2199 65 av_opt_set(fgt->graph, "aresample_swr_opts", args, 0);
2200 65 av_free(args);
2201 }
2202 } else {
2203 1275 fgt->graph->nb_threads = filter_complex_nbthreads;
2204 }
2205
2206
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8300 times.
8301 if (filter_buffered_frames) {
2207 1 ret = av_opt_set_int(fgt->graph, "max_buffered_frames", filter_buffered_frames, 0);
2208
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
2209 ✗ return ret;
2210 }
2211
2212 8301 hw_device = hw_device_for_filter();
2213
2214 8301 ret = graph_parse(fg, fgt->graph, graph_desc, &inputs, &outputs, hw_device);
2215
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8301 times.
8301 if (ret < 0)
2216 ✗ goto fail;
2217
2218
2/2
✓ Branch 0 taken 7204 times.
✓ Branch 1 taken 8301 times.
15505 for (cur = inputs, i = 0; cur; cur = cur->next, i++)
2219
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7204 times.
7204 if ((ret = configure_input_filter(fg, fgt->graph, fg->inputs[i], cur)) < 0) {
2220 ✗ avfilter_inout_free(&inputs);
2221 ✗ avfilter_inout_free(&outputs);
2222 ✗ goto fail;
2223 }
2224 8301 avfilter_inout_free(&inputs);
2225
2226
2/2
✓ Branch 0 taken 8436 times.
✓ Branch 1 taken 8301 times.
16737 for (cur = outputs, i = 0; cur; cur = cur->next, i++) {
2227 8436 ret = configure_output_filter(fgp, fgt->graph, fg->outputs[i], cur);
2228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8436 times.
8436 if (ret < 0) {
2229 ✗ avfilter_inout_free(&outputs);
2230 ✗ goto fail;
2231 }
2232 }
2233 8301 avfilter_inout_free(&outputs);
2234
2235
2/2
✓ Branch 0 taken 6366 times.
✓ Branch 1 taken 1935 times.
8301 if (fgp->disable_conversions)
2236 6366 avfilter_graph_set_auto_convert(fgt->graph, AVFILTER_AUTO_CONVERT_NONE);
2237
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 8300 times.
8301 if ((ret = avfilter_graph_config(fgt->graph, NULL)) < 0)
2238 1 goto fail;
2239
2240 8300 fgp->is_meta = graph_is_meta(fgt->graph);
2241
2242 /* limit the lists of allowed formats to the ones selected, to
2243 * make sure they stay the same if the filtergraph is reconfigured later */
2244
2/2
✓ Branch 0 taken 8435 times.
✓ Branch 1 taken 8300 times.
16735 for (int i = 0; i < fg->nb_outputs; i++) {
2245 const AVFrameSideData *const *sd;
2246 int nb_sd;
2247 8435 OutputFilter *ofilter = fg->outputs[i];
2248 8435 OutputFilterPriv *ofp = ofp_from_ofilter(ofilter);
2249 8435 AVFilterContext *sink = ofilter->filter;
2250
2251 8435 ofp->format = av_buffersink_get_format(sink);
2252
2253 8435 ofp->width = av_buffersink_get_w(sink);
2254 8435 ofp->height = av_buffersink_get_h(sink);
2255 8435 ofp->color_space = av_buffersink_get_colorspace(sink);
2256 8435 ofp->color_range = av_buffersink_get_color_range(sink);
2257 8435 ofp->alpha_mode = av_buffersink_get_alpha_mode(sink);
2258
2259 // If the timing parameters are not locked yet, get the tentative values
2260 // here but don't lock them. They will only be used if no output frames
2261 // are ever produced.
2262
2/2
✓ Branch 0 taken 8388 times.
✓ Branch 1 taken 47 times.
8435 if (!ofp->tb_out_locked) {
2263 8388 AVRational fr = av_buffersink_get_frame_rate(sink);
2264
3/4
✓ Branch 0 taken 8367 times.
✓ Branch 1 taken 21 times.
✓ Branch 2 taken 8367 times.
✗ Branch 3 not taken.
8388 if (ofp->fps.framerate.num <= 0 && ofp->fps.framerate.den <= 0 &&
2265
4/4
✓ Branch 0 taken 6912 times.
✓ Branch 1 taken 1455 times.
✓ Branch 2 taken 6898 times.
✓ Branch 3 taken 14 times.
8367 fr.num > 0 && fr.den > 0)
2266 6898 ofp->fps.framerate = fr;
2267 8388 ofp->tb_out = av_buffersink_get_time_base(sink);
2268 }
2269 8435 ofp->sample_aspect_ratio = av_buffersink_get_sample_aspect_ratio(sink);
2270
2271 8435 ofp->sample_rate = av_buffersink_get_sample_rate(sink);
2272 8435 av_channel_layout_uninit(&ofp->ch_layout);
2273 8435 ret = av_buffersink_get_ch_layout(sink, &ofp->ch_layout);
2274
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8435 times.
8435 if (ret < 0)
2275 ✗ goto fail;
2276 8435 sd = av_buffersink_get_side_data(sink, &nb_sd);
2277
2/2
✓ Branch 0 taken 268 times.
✓ Branch 1 taken 8167 times.
8435 if (nb_sd)
2278
2/2
✓ Branch 0 taken 289 times.
✓ Branch 1 taken 268 times.
557 for (int j = 0; j < nb_sd; j++) {
2279 289 ret = av_frame_side_data_clone(&ofp->side_data, &ofp->nb_side_data,
2280 289 sd[j], AV_FRAME_SIDE_DATA_FLAG_REPLACE);
2281
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 289 times.
289 if (ret < 0) {
2282 ✗ av_frame_side_data_free(&ofp->side_data, &ofp->nb_side_data);
2283 ✗ goto fail;
2284 }
2285 }
2286 }
2287
2288
2/2
✓ Branch 0 taken 7203 times.
✓ Branch 1 taken 8300 times.
15503 for (int i = 0; i < fg->nb_inputs; i++) {
2289 7203 InputFilter *ifilter = fg->inputs[i];
2290 7203 InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]);
2291 AVFrame *tmp;
2292
2/2
✓ Branch 1 taken 157 times.
✓ Branch 2 taken 7203 times.
7360 while (av_fifo_read(ifp->frame_queue, &tmp, 1) >= 0) {
2293
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 142 times.
157 if (ifp->type_src == AVMEDIA_TYPE_SUBTITLE) {
2294 15 sub2video_frame(&ifp->ifilter, tmp, !fgt->graph);
2295 } else {
2296
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 94 times.
142 if (ifp->type_src == AVMEDIA_TYPE_VIDEO) {
2297
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 if (ifp->displaymatrix_applied)
2298 48 av_frame_remove_side_data(tmp, AV_FRAME_DATA_DISPLAYMATRIX);
2299 }
2300 142 ret = av_buffersrc_add_frame(ifilter->filter, tmp);
2301 }
2302 157 av_frame_free(&tmp);
2303
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 157 times.
157 if (ret < 0)
2304 ✗ goto fail;
2305 }
2306 }
2307
2308 /* send the EOFs for the finished inputs */
2309
2/2
✓ Branch 0 taken 7203 times.
✓ Branch 1 taken 8300 times.
15503 for (int i = 0; i < fg->nb_inputs; i++) {
2310 7203 InputFilter *ifilter = fg->inputs[i];
2311
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 7186 times.
7203 if (fgt->eof_in[i]) {
2312 17 ret = av_buffersrc_add_frame(ifilter->filter, NULL);
2313
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (ret < 0)
2314 ✗ goto fail;
2315 17 have_input_eof = 1;
2316 }
2317 }
2318
2319
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 8289 times.
8300 if (have_input_eof) {
2320 // make sure the EOF propagates to the end of the graph
2321 11 ret = avfilter_graph_request_oldest(fgt->graph);
2322
4/6
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 8 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
11 if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)
2323 ✗ goto fail;
2324 }
2325
2326 8300 return 0;
2327 1 fail:
2328 1 cleanup_filtergraph(fg, fgt);
2329 1 return ret;
2330 }
2331
2332 7198 static int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame)
2333 {
2334 7198 InputFilterPriv *ifp = ifp_from_ifilter(ifilter);
2335 AVFrameSideData *sd;
2336 int ret;
2337
2338 7198 ret = av_buffer_replace(&ifp->hw_frames_ctx, frame->hw_frames_ctx);
2339
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7198 times.
7198 if (ret < 0)
2340 ✗ return ret;
2341
2342
2/2
✓ Branch 0 taken 1388 times.
✓ Branch 1 taken 5810 times.
12976 ifp->time_base = (ifilter->type == AVMEDIA_TYPE_AUDIO) ? (AVRational){ 1, frame->sample_rate } :
2343
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 5778 times.
5810 (ifp->opts.flags & IFILTER_FLAG_CFR) ? av_inv_q(ifp->opts.framerate) :
2344 frame->time_base;
2345
2346 7198 ifp->format = frame->format;
2347
2348 7198 ifp->width = frame->width;
2349 7198 ifp->height = frame->height;
2350 7198 ifp->sample_aspect_ratio = frame->sample_aspect_ratio;
2351 7198 ifp->color_space = frame->colorspace;
2352 7198 ifp->color_range = frame->color_range;
2353 7198 ifp->alpha_mode = frame->alpha_mode;
2354
2355 7198 ifp->sample_rate = frame->sample_rate;
2356 7198 ret = av_channel_layout_copy(&ifp->ch_layout, &frame->ch_layout);
2357
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7198 times.
7198 if (ret < 0)
2358 ✗ return ret;
2359
2360 7198 av_frame_side_data_free(&ifp->side_data, &ifp->nb_side_data);
2361
2/2
✓ Branch 0 taken 637 times.
✓ Branch 1 taken 7198 times.
7835 for (int i = 0; i < frame->nb_side_data; i++) {
2362 637 const AVSideDataDescriptor *desc = av_frame_side_data_desc(frame->side_data[i]->type);
2363
2364
2/2
✓ Branch 0 taken 334 times.
✓ Branch 1 taken 303 times.
637 if (!(desc->props & AV_SIDE_DATA_PROP_GLOBAL))
2365 334 continue;
2366
2367 303 ret = av_frame_side_data_clone(&ifp->side_data,
2368 &ifp->nb_side_data,
2369 303 frame->side_data[i], 0);
2370
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 303 times.
303 if (ret < 0)
2371 ✗ return ret;
2372 }
2373
2374 7198 sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX);
2375
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 7171 times.
7198 if (sd) {
2376 27 memcpy(ifp->displaymatrix, sd->data, sizeof(ifp->displaymatrix));
2377
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 3 times.
27 if (ifp->opts.flags & IFILTER_FLAG_AUTOROTATE)
2378 24 av_frame_side_data_remove(&ifp->side_data, &ifp->nb_side_data, AV_FRAME_DATA_DISPLAYMATRIX);
2379 }
2380 7198 ifp->displaymatrix_present = !!sd;
2381
2382 /* Copy downmix related side data to InputFilterPriv so it may be propagated
2383 * to the filter chain even though it's not "global", as filters like aresample
2384 * require this information during init and not when remixing a frame */
2385 7198 sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DOWNMIX_INFO);
2386
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 7190 times.
7198 if (sd) {
2387 8 ret = av_frame_side_data_clone(&ifp->side_data,
2388 &ifp->nb_side_data, sd, 0);
2389
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ret < 0)
2390 ✗ return ret;
2391 8 memcpy(&ifp->downmixinfo, sd->data, sizeof(ifp->downmixinfo));
2392 }
2393 7198 ifp->downmixinfo_present = !!sd;
2394 7198 sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DOWNMIX_MATRIX);
2395
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 7194 times.
7198 if (sd) {
2396 4 ret = av_frame_side_data_clone(&ifp->side_data,
2397 &ifp->nb_side_data, sd, 0);
2398
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0)
2399 ✗ return ret;
2400 4 ret = av_buffer_replace(&ifp->downmixmatrix, sd->buf);
2401
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ret < 0)
2402 ✗ return ret;
2403 4 ifp->downmixmatrix_size = sd->size;
2404 }
2405 7198 ifp->downmixmatrix_present = !!sd;
2406
2407 7198 return 0;
2408 }
2409
2410 1 static int ifilter_parameters_from_ofilter(InputFilter *ifilter, OutputFilter *ofilter)
2411 {
2412 1 const OutputFilterPriv *ofp = ofp_from_ofilter(ofilter);
2413 1 InputFilterPriv *ifp = ifp_from_ifilter(ifilter);
2414
2415
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!ifp->opts.framerate.num) {
2416 1 ifp->opts.framerate = ofp->fps.framerate;
2417
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if (ifp->opts.framerate.num > 0 && ifp->opts.framerate.den > 0)
2418 1 ifp->opts.flags |= IFILTER_FLAG_CFR;
2419 }
2420
2421
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 for (int i = 0; i < ofp->nb_side_data; i++) {
2422 ✗ int ret = av_frame_side_data_clone(&ifp->side_data, &ifp->nb_side_data,
2423 ✗ ofp->side_data[i], AV_FRAME_SIDE_DATA_FLAG_REPLACE);
2424 ✗ if (ret < 0)
2425 ✗ return ret;
2426 }
2427
2428 1 return 0;
2429 }
2430
2431 39254 int filtergraph_is_simple(const FilterGraph *fg)
2432 {
2433 39254 const FilterGraphPriv *fgp = cfgp_from_cfg(fg);
2434 39254 return fgp->is_simple;
2435 }
2436
2437 ✗ static void send_command(FilterGraph *fg, AVFilterGraph *graph,
2438 double time, const char *target,
2439 const char *command, const char *arg, int all_filters)
2440 {
2441 int ret;
2442
2443 ✗ if (!graph)
2444 ✗ return;
2445
2446 ✗ if (time < 0) {
2447 char response[4096];
2448 ✗ ret = avfilter_graph_send_command(graph, target, command, arg,
2449 response, sizeof(response),
2450 all_filters ? 0 : AVFILTER_CMD_FLAG_ONE);
2451 ✗ fprintf(stderr, "Command reply for stream %d: ret:%d res:\n%s",
2452 fg->index, ret, response);
2453 ✗ } else if (!all_filters) {
2454 ✗ fprintf(stderr, "Queuing commands only on filters supporting the specific command is unsupported\n");
2455 } else {
2456 ✗ ret = avfilter_graph_queue_command(graph, target, command, arg, 0, time);
2457 ✗ if (ret < 0)
2458 ✗ fprintf(stderr, "Queuing command failed with error %s\n", av_err2str(ret));
2459 }
2460 }
2461
2462 421877 static int choose_input(const FilterGraph *fg, const FilterGraphThread *fgt)
2463 {
2464 421877 int nb_requests, nb_requests_max = -1;
2465 421877 int best_input = -1;
2466
2467
2/2
✓ Branch 0 taken 436825 times.
✓ Branch 1 taken 421877 times.
858702 for (int i = 0; i < fg->nb_inputs; i++) {
2468 436825 InputFilter *ifilter = fg->inputs[i];
2469
2470
2/2
✓ Branch 0 taken 1224 times.
✓ Branch 1 taken 435601 times.
436825 if (fgt->eof_in[i])
2471 1224 continue;
2472
2473 435601 nb_requests = av_buffersrc_get_nb_failed_requests(ifilter->filter);
2474
2/2
✓ Branch 0 taken 424416 times.
✓ Branch 1 taken 11185 times.
435601 if (nb_requests > nb_requests_max) {
2475 424416 nb_requests_max = nb_requests;
2476 424416 best_input = i;
2477 }
2478 }
2479
2480
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 421877 times.
421877 av_assert0(best_input >= 0);
2481
2482 421877 return best_input;
2483 }
2484
2485 8385 static int choose_out_timebase(OutputFilterPriv *ofp, AVFrame *frame)
2486 {
2487 8385 OutputFilter *ofilter = &ofp->ofilter;
2488 8385 FPSConvContext *fps = &ofp->fps;
2489 8385 AVRational tb = (AVRational){ 0, 0 };
2490 AVRational fr;
2491 const FrameData *fd;
2492
2493 8385 fd = frame_data_c(frame);
2494
2495 // apply -enc_time_base
2496
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8384 times.
8385 if (ofp->enc_timebase.num == ENC_TIME_BASE_DEMUX &&
2497
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 (fd->dec.tb.num <= 0 || fd->dec.tb.den <= 0)) {
2498 ✗ av_log(ofp, AV_LOG_ERROR,
2499 "Demuxing timebase not available - cannot use it for encoding\n");
2500 ✗ return AVERROR(EINVAL);
2501 }
2502
2503
2/4
✓ Branch 0 taken 8384 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8385 switch (ofp->enc_timebase.num) {
2504 8384 case 0: break;
2505 1 case ENC_TIME_BASE_DEMUX: tb = fd->dec.tb; break;
2506 ✗ case ENC_TIME_BASE_FILTER: tb = frame->time_base; break;
2507 ✗ default: tb = ofp->enc_timebase; break;
2508 }
2509
2510
2/2
✓ Branch 0 taken 1450 times.
✓ Branch 1 taken 6935 times.
8385 if (ofilter->type == AVMEDIA_TYPE_AUDIO) {
2511
1/2
✓ Branch 0 taken 1450 times.
✗ Branch 1 not taken.
1450 tb = tb.num ? tb : (AVRational){ 1, frame->sample_rate };
2512 1450 goto finish;
2513 }
2514
2515 6935 fr = fps->framerate;
2516
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 6919 times.
6935 if (!fr.num) {
2517 16 AVRational fr_sink = av_buffersink_get_frame_rate(ofilter->filter);
2518
3/4
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
16 if (fr_sink.num > 0 && fr_sink.den > 0)
2519 ✗ fr = fr_sink;
2520 }
2521
2522
4/4
✓ Branch 0 taken 5778 times.
✓ Branch 1 taken 1157 times.
✓ Branch 2 taken 366 times.
✓ Branch 3 taken 5412 times.
6935 if (fps->vsync_method == VSYNC_CFR || fps->vsync_method == VSYNC_VSCFR) {
2523
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1523 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1523 if (!fr.num && !fps->framerate_max.num) {
2524 ✗ fr = (AVRational){25, 1};
2525 ✗ av_log(ofp, AV_LOG_WARNING,
2526 "No information "
2527 "about the input framerate is available. Falling "
2528 "back to a default value of 25fps. Use the -r option "
2529 "if you want a different framerate.\n");
2530 }
2531
2532
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1523 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1523 if (fps->framerate_max.num &&
2533 ✗ (av_q2d(fr) > av_q2d(fps->framerate_max) ||
2534 ✗ !fr.den))
2535 ✗ fr = fps->framerate_max;
2536 }
2537
2538
2/2
✓ Branch 0 taken 6919 times.
✓ Branch 1 taken 16 times.
6935 if (fr.num > 0) {
2539
2/2
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 6843 times.
6919 if (fps->framerate_supported) {
2540 76 int idx = av_find_nearest_q_idx(fr, fps->framerate_supported);
2541 76 fr = fps->framerate_supported[idx];
2542 }
2543
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 6847 times.
6919 if (fps->framerate_clip) {
2544 72 av_reduce(&fr.num, &fr.den,
2545 72 fr.num, fr.den, fps->framerate_clip);
2546 }
2547 }
2548
2549
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6934 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
6935 if (!(tb.num > 0 && tb.den > 0))
2550 6934 tb = av_inv_q(fr);
2551
3/4
✓ Branch 0 taken 6919 times.
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6919 times.
6935 if (!(tb.num > 0 && tb.den > 0))
2552 16 tb = frame->time_base;
2553
2554 6935 fps->framerate = fr;
2555 8385 finish:
2556 8385 ofp->tb_out = tb;
2557 8385 ofp->tb_out_locked = 1;
2558
2559 8385 return 0;
2560 }
2561
2562 144068 static double adjust_frame_pts_to_encoder_tb(void *logctx, AVFrame *frame,
2563 AVRational tb_dst, int64_t start_time)
2564 {
2565 144068 double float_pts = AV_NOPTS_VALUE; // this is identical to frame.pts but with higher precision
2566
2567 144068 AVRational tb = tb_dst;
2568 144068 AVRational filter_tb = frame->time_base;
2569 144068 const int extra_bits = av_clip(29 - av_log2(tb.den), 0, 16);
2570
2571
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144068 times.
144068 if (frame->pts == AV_NOPTS_VALUE)
2572 ✗ goto early_exit;
2573
2574 144068 tb.den <<= extra_bits;
2575 144068 float_pts = av_rescale_q(frame->pts, filter_tb, tb) -
2576 144068 av_rescale_q(start_time, AV_TIME_BASE_Q, tb);
2577 144068 float_pts /= 1 << extra_bits;
2578 // when float_pts is not exactly an integer,
2579 // avoid exact midpoints to reduce the chance of rounding differences, this
2580 // can be removed in case the fps code is changed to work with integers
2581
2/2
✓ Branch 0 taken 6024 times.
✓ Branch 1 taken 138044 times.
144068 if (float_pts != llrint(float_pts))
2582
1/2
✓ Branch 0 taken 6024 times.
✗ Branch 1 not taken.
6024 float_pts += FFSIGN(float_pts) * 1.0 / (1<<17);
2583
2584 144068 frame->pts = av_rescale_q(frame->pts, filter_tb, tb_dst) -
2585 144068 av_rescale_q(start_time, AV_TIME_BASE_Q, tb_dst);
2586 144068 frame->time_base = tb_dst;
2587
2588 144068 early_exit:
2589
2590
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144068 times.
144068 if (debug_ts) {
2591 ✗ av_log(logctx, AV_LOG_INFO,
2592 "filter -> pts:%s pts_time:%s exact:%f time_base:%d/%d\n",
2593 ✗ frame ? av_ts2str(frame->pts) : "NULL",
2594 ✗ av_ts2timestr(frame->pts, &tb_dst),
2595 float_pts, tb_dst.num, tb_dst.den);
2596 }
2597
2598 144068 return float_pts;
2599 }
2600
2601 3880 static int64_t median3(int64_t a, int64_t b, int64_t c)
2602 {
2603 int64_t max2, min2, m;
2604
2605
1/2
✓ Branch 0 taken 3880 times.
✗ Branch 1 not taken.
3880 if (a >= b) {
2606 3880 max2 = a;
2607 3880 min2 = b;
2608 } else {
2609 ✗ max2 = b;
2610 ✗ min2 = a;
2611 }
2612 3880 m = (c >= max2) ? max2 : c;
2613
2614 3880 return (m >= min2) ? m : min2;
2615 }
2616
2617
2618 /* Convert frame timestamps to the encoder timebase and decide how many times
2619 * should this (and possibly previous) frame be repeated in order to conform to
2620 * desired target framerate (if any).
2621 */
2622 147948 static void video_sync_process(OutputFilterPriv *ofp, AVFrame *frame,
2623 int64_t *nb_frames, int64_t *nb_frames_prev)
2624 {
2625 147948 OutputFilter *ofilter = &ofp->ofilter;
2626 147948 FPSConvContext *fps = &ofp->fps;
2627 double delta0, delta, sync_ipts, duration;
2628
2629
2/2
✓ Branch 0 taken 3880 times.
✓ Branch 1 taken 144068 times.
147948 if (!frame) {
2630 3880 *nb_frames_prev = *nb_frames = median3(fps->frames_prev_hist[0],
2631 fps->frames_prev_hist[1],
2632 fps->frames_prev_hist[2]);
2633
2634
4/4
✓ Branch 0 taken 3879 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 3877 times.
3880 if (!*nb_frames && fps->last_dropped) {
2635 2 atomic_fetch_add(&ofilter->nb_frames_drop, 1);
2636 2 fps->last_dropped++;
2637 }
2638
2639 3880 goto finish;
2640 }
2641
2642 144068 duration = frame->duration * av_q2d(frame->time_base) / av_q2d(ofp->tb_out);
2643
2644 144068 sync_ipts = adjust_frame_pts_to_encoder_tb(ofilter->graph, frame,
2645 ofp->tb_out, ofp->ts_offset);
2646 /* delta0 is the "drift" between the input frame and
2647 * where it would fall in the output. */
2648 144068 delta0 = sync_ipts - ofp->next_pts;
2649 144068 delta = delta0 + duration;
2650
2651 // tracks the number of times the PREVIOUS frame should be duplicated,
2652 // mostly for variable framerate (VFR)
2653 144068 *nb_frames_prev = 0;
2654 /* by default, we output a single frame */
2655 144068 *nb_frames = 1;
2656
2657
4/4
✓ Branch 0 taken 5035 times.
✓ Branch 1 taken 139033 times.
✓ Branch 2 taken 3848 times.
✓ Branch 3 taken 1187 times.
144068 if (delta0 < 0 &&
2658 3848 delta > 0 &&
2659
1/2
✓ Branch 0 taken 3848 times.
✗ Branch 1 not taken.
3848 fps->vsync_method != VSYNC_PASSTHROUGH) {
2660
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 3803 times.
3848 if (delta0 < -0.6) {
2661 45 av_log(ofp, AV_LOG_VERBOSE, "Past duration %f too large\n", -delta0);
2662 } else
2663 3803 av_log(ofp, AV_LOG_DEBUG, "Clipping frame in rate conversion by %f\n", -delta0);
2664 3848 sync_ipts = ofp->next_pts;
2665 3848 duration += delta0;
2666 3848 delta0 = 0;
2667 }
2668
2669
4/5
✓ Branch 0 taken 7838 times.
✓ Branch 1 taken 29015 times.
✓ Branch 2 taken 84264 times.
✓ Branch 3 taken 22951 times.
✗ Branch 4 not taken.
144068 switch (fps->vsync_method) {
2670 7838 case VSYNC_VSCFR:
2671
3/4
✓ Branch 0 taken 366 times.
✓ Branch 1 taken 7472 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 366 times.
7838 if (fps->frame_number == 0 && delta0 >= 0.5) {
2672 ✗ av_log(ofp, AV_LOG_DEBUG, "Not duplicating %d initial frames\n", (int)lrintf(delta0));
2673 ✗ delta = duration;
2674 ✗ delta0 = 0;
2675 ✗ ofp->next_pts = llrint(sync_ipts);
2676 }
2677 av_fallthrough;
2678 case VSYNC_CFR:
2679 // FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c
2680
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 36853 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
36853 if (frame_drop_threshold && delta < frame_drop_threshold && fps->frame_number) {
2681 ✗ *nb_frames = 0;
2682
2/2
✓ Branch 0 taken 375 times.
✓ Branch 1 taken 36478 times.
36853 } else if (delta < -1.1)
2683 375 *nb_frames = 0;
2684
2/2
✓ Branch 0 taken 677 times.
✓ Branch 1 taken 35801 times.
36478 else if (delta > 1.1) {
2685 677 *nb_frames = llrintf(delta);
2686
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 675 times.
677 if (delta0 > 1.1)
2687 2 *nb_frames_prev = llrintf(delta0 - 0.6);
2688 }
2689 36853 frame->duration = 1;
2690 36853 break;
2691 84264 case VSYNC_VFR:
2692
2/2
✓ Branch 0 taken 99 times.
✓ Branch 1 taken 84165 times.
84264 if (delta <= -0.6)
2693 99 *nb_frames = 0;
2694
2/2
✓ Branch 0 taken 66812 times.
✓ Branch 1 taken 17353 times.
84165 else if (delta > 0.6)
2695 66812 ofp->next_pts = llrint(sync_ipts);
2696 84264 frame->duration = llrint(duration);
2697 84264 break;
2698 22951 case VSYNC_PASSTHROUGH:
2699 22951 ofp->next_pts = llrint(sync_ipts);
2700 22951 frame->duration = llrint(duration);
2701 22951 break;
2702 ✗ default:
2703 ✗ av_assert0(0);
2704 }
2705
2706 147948 finish:
2707 147948 memmove(fps->frames_prev_hist + 1,
2708 147948 fps->frames_prev_hist,
2709 sizeof(fps->frames_prev_hist[0]) * (FF_ARRAY_ELEMS(fps->frames_prev_hist) - 1));
2710 147948 fps->frames_prev_hist[0] = *nb_frames_prev;
2711
2712
4/4
✓ Branch 0 taken 147945 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 474 times.
✓ Branch 3 taken 147471 times.
147948 if (*nb_frames_prev == 0 && fps->last_dropped) {
2713 474 atomic_fetch_add(&ofilter->nb_frames_drop, 1);
2714 474 av_log(ofp, AV_LOG_VERBOSE,
2715 "*** dropping frame %"PRId64" at ts %"PRId64"\n",
2716 474 fps->frame_number, fps->last_frame->pts);
2717 }
2718
5/6
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 147945 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 269 times.
✓ Branch 5 taken 147679 times.
147948 if (*nb_frames > (*nb_frames_prev && fps->last_dropped) + (*nb_frames > *nb_frames_prev)) {
2719 uint64_t nb_frames_dup;
2720
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 269 times.
269 if (*nb_frames > dts_error_threshold * 30) {
2721 ✗ av_log(ofp, AV_LOG_ERROR, "%"PRId64" frame duplication too large, skipping\n", *nb_frames - 1);
2722 ✗ atomic_fetch_add(&ofilter->nb_frames_drop, 1);
2723 ✗ *nb_frames = 0;
2724 ✗ return;
2725 }
2726
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 266 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
269 nb_frames_dup = atomic_fetch_add(&ofilter->nb_frames_dup,
2727 *nb_frames - (*nb_frames_prev && fps->last_dropped) - (*nb_frames > *nb_frames_prev));
2728 269 av_log(ofp, AV_LOG_VERBOSE, "*** %"PRId64" dup!\n", *nb_frames - 1);
2729
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 269 times.
269 if (nb_frames_dup > fps->dup_warning) {
2730 ✗ av_log(ofp, AV_LOG_WARNING, "More than %"PRIu64" frames duplicated\n", fps->dup_warning);
2731 ✗ fps->dup_warning *= 10;
2732 }
2733 }
2734
2735
4/4
✓ Branch 0 taken 4354 times.
✓ Branch 1 taken 143594 times.
✓ Branch 2 taken 474 times.
✓ Branch 3 taken 3880 times.
147948 fps->last_dropped = *nb_frames == *nb_frames_prev && frame;
2736
4/4
✓ Branch 0 taken 474 times.
✓ Branch 1 taken 147474 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 467 times.
147948 fps->dropped_keyframe |= fps->last_dropped && (frame->flags & AV_FRAME_FLAG_KEY);
2737 }
2738
2739 1760 static void close_input(InputFilterPriv *ifp)
2740 {
2741 1760 FilterGraphPriv *fgp = fgp_from_fg(ifp->ifilter.graph);
2742
2743
2/2
✓ Branch 0 taken 409 times.
✓ Branch 1 taken 1351 times.
1760 if (!ifp->eof) {
2744 409 sch_filter_receive_finish(fgp->sch, fgp->sch_idx, ifp->ifilter.index);
2745 409 ifp->eof = 1;
2746 }
2747 1760 }
2748
2749 5291 static int close_output(OutputFilterPriv *ofp, FilterGraphThread *fgt)
2750 {
2751 5291 FilterGraphPriv *fgp = fgp_from_fg(ofp->ofilter.graph);
2752 int ret;
2753
2754 // we are finished and no frames were ever seen at this output,
2755 // at least initialize the encoder with a dummy frame
2756
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5288 times.
5291 if (!fgt->got_frame) {
2757 3 AVFrame *frame = fgt->frame;
2758 FrameData *fd;
2759
2760 3 frame->time_base = ofp->tb_out;
2761 3 frame->format = ofp->format;
2762
2763 3 frame->width = ofp->width;
2764 3 frame->height = ofp->height;
2765 3 frame->sample_aspect_ratio = ofp->sample_aspect_ratio;
2766
2767 3 frame->sample_rate = ofp->sample_rate;
2768
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (ofp->ch_layout.nb_channels) {
2769 3 ret = av_channel_layout_copy(&frame->ch_layout, &ofp->ch_layout);
2770
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
2771 ✗ return ret;
2772 }
2773
2774 3 fd = frame_data(frame);
2775
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!fd)
2776 ✗ return AVERROR(ENOMEM);
2777
2778 3 av_frame_side_data_free(&fd->side_data, &fd->nb_side_data);
2779 3 ret = clone_side_data(&fd->side_data, &fd->nb_side_data,
2780 3 ofp->side_data, ofp->nb_side_data, 0);
2781
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
2782 ✗ return ret;
2783
2784 3 fd->frame_rate_filter = ofp->fps.framerate;
2785
2786
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 av_assert0(!frame->buf[0]);
2787
2788 3 av_log(ofp, AV_LOG_WARNING,
2789 "No filtered frames for output stream, trying to "
2790 "initialize anyway.\n");
2791
2792 3 ret = sch_filter_send(fgp->sch, fgp->sch_idx, ofp->ofilter.index, frame);
2793
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0) {
2794 ✗ av_frame_unref(frame);
2795 ✗ return ret;
2796 }
2797 }
2798
2799 5291 fgt->eof_out[ofp->ofilter.index] = 1;
2800
2801 5291 ret = sch_filter_send(fgp->sch, fgp->sch_idx, ofp->ofilter.index, NULL);
2802
2/2
✓ Branch 0 taken 5126 times.
✓ Branch 1 taken 165 times.
5291 return (ret == AVERROR_EOF) ? 0 : ret;
2803 }
2804
2805 456063 static int fg_output_frame(OutputFilterPriv *ofp, FilterGraphThread *fgt,
2806 AVFrame *frame)
2807 {
2808 456063 FilterGraphPriv *fgp = fgp_from_fg(ofp->ofilter.graph);
2809 456063 AVFrame *frame_prev = ofp->fps.last_frame;
2810 456063 enum AVMediaType type = ofp->ofilter.type;
2811
2812 456063 int64_t nb_frames = !!frame, nb_frames_prev = 0;
2813
2814
5/6
✓ Branch 0 taken 147948 times.
✓ Branch 1 taken 308115 times.
✓ Branch 2 taken 3880 times.
✓ Branch 3 taken 144068 times.
✓ Branch 4 taken 3880 times.
✗ Branch 5 not taken.
456063 if (type == AVMEDIA_TYPE_VIDEO && (frame || fgt->got_frame))
2815 147948 video_sync_process(ofp, frame, &nb_frames, &nb_frames_prev);
2816
2817
2/2
✓ Branch 0 taken 450730 times.
✓ Branch 1 taken 452966 times.
903696 for (int64_t i = 0; i < nb_frames; i++) {
2818 AVFrame *frame_out;
2819 int ret;
2820
2821
2/2
✓ Branch 0 taken 144026 times.
✓ Branch 1 taken 306704 times.
450730 if (type == AVMEDIA_TYPE_VIDEO) {
2822
1/2
✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
69 AVFrame *frame_in = (i < nb_frames_prev && frame_prev->buf[0]) ?
2823
2/2
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 143957 times.
144095 frame_prev : frame;
2824
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144026 times.
144026 if (!frame_in)
2825 ✗ break;
2826
2827 144026 frame_out = fgp->frame_enc;
2828 144026 ret = av_frame_ref(frame_out, frame_in);
2829
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144026 times.
144026 if (ret < 0)
2830 ✗ return ret;
2831
2832 144026 frame_out->pts = ofp->next_pts;
2833
2834
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 144019 times.
144026 if (ofp->fps.dropped_keyframe) {
2835 7 frame_out->flags |= AV_FRAME_FLAG_KEY;
2836 7 ofp->fps.dropped_keyframe = 0;
2837 }
2838 } else {
2839
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 306704 times.
306704 frame->pts = (frame->pts == AV_NOPTS_VALUE) ? ofp->next_pts :
2840 306704 av_rescale_q(frame->pts, frame->time_base, ofp->tb_out) -
2841 306704 av_rescale_q(ofp->ts_offset, AV_TIME_BASE_Q, ofp->tb_out);
2842
2843 306704 frame->time_base = ofp->tb_out;
2844 306704 frame->duration = av_rescale_q(frame->nb_samples,
2845 306704 (AVRational){ 1, frame->sample_rate },
2846 ofp->tb_out);
2847
2848 306704 ofp->next_pts = frame->pts + frame->duration;
2849
2850 306704 frame_out = frame;
2851 }
2852
2853 // send the frame to consumers
2854 450730 ret = sch_filter_send(fgp->sch, fgp->sch_idx, ofp->ofilter.index, frame_out);
2855
2/2
✓ Branch 0 taken 3097 times.
✓ Branch 1 taken 447633 times.
450730 if (ret < 0) {
2856 3097 av_frame_unref(frame_out);
2857
2858
1/2
✓ Branch 0 taken 3097 times.
✗ Branch 1 not taken.
3097 if (!fgt->eof_out[ofp->ofilter.index]) {
2859 3097 fgt->eof_out[ofp->ofilter.index] = 1;
2860 3097 fgp->nb_outputs_done++;
2861 }
2862
2863
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3097 times.
3097 return ret == AVERROR_EOF ? 0 : ret;
2864 }
2865
2866
2/2
✓ Branch 0 taken 140971 times.
✓ Branch 1 taken 306662 times.
447633 if (type == AVMEDIA_TYPE_VIDEO) {
2867 140971 ofp->fps.frame_number++;
2868 140971 ofp->next_pts++;
2869
2870
3/4
✓ Branch 0 taken 140539 times.
✓ Branch 1 taken 432 times.
✓ Branch 2 taken 140539 times.
✗ Branch 3 not taken.
140971 if (i == nb_frames_prev && frame)
2871 140539 frame->flags &= ~AV_FRAME_FLAG_KEY;
2872 }
2873
2874 447633 fgt->got_frame = 1;
2875 }
2876
2877
4/4
✓ Branch 0 taken 447675 times.
✓ Branch 1 taken 5291 times.
✓ Branch 2 taken 141012 times.
✓ Branch 3 taken 306663 times.
452966 if (frame && frame_prev) {
2878 141012 av_frame_unref(frame_prev);
2879 141012 av_frame_move_ref(frame_prev, frame);
2880 }
2881
2882
2/2
✓ Branch 0 taken 5291 times.
✓ Branch 1 taken 447675 times.
452966 if (!frame)
2883 5291 return close_output(ofp, fgt);
2884
2885 447675 return 0;
2886 }
2887
2888 920790 static int fg_output_step(OutputFilterPriv *ofp, FilterGraphThread *fgt,
2889 AVFrame *frame)
2890 {
2891 920790 FilterGraphPriv *fgp = fgp_from_fg(ofp->ofilter.graph);
2892 920790 AVFilterContext *filter = ofp->ofilter.filter;
2893 FrameData *fd;
2894 int ret;
2895
2896 920790 ret = av_buffersink_get_frame_flags(filter, frame,
2897 AV_BUFFERSINK_FLAG_NO_REQUEST);
2898
4/4
✓ Branch 0 taken 4311 times.
✓ Branch 1 taken 916479 times.
✓ Branch 2 taken 3682 times.
✓ Branch 3 taken 629 times.
920790 if (ret == AVERROR_EOF && !fgt->eof_out[ofp->ofilter.index]) {
2899 3682 ret = fg_output_frame(ofp, fgt, NULL);
2900
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3682 times.
3682 return (ret < 0) ? ret : 1;
2901
4/4
✓ Branch 0 taken 451403 times.
✓ Branch 1 taken 465705 times.
✓ Branch 2 taken 629 times.
✓ Branch 3 taken 450774 times.
917108 } else if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
2902 466334 return 1;
2903
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 450774 times.
450774 } else if (ret < 0) {
2904 ✗ av_log(ofp, AV_LOG_WARNING,
2905 "Error in retrieving a frame from the filtergraph: %s\n",
2906 ✗ av_err2str(ret));
2907 ✗ return ret;
2908 }
2909
2910
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 450772 times.
450774 if (fgt->eof_out[ofp->ofilter.index]) {
2911 2 av_frame_unref(frame);
2912 2 return 0;
2913 }
2914
2915 450772 frame->time_base = av_buffersink_get_time_base(filter);
2916
2917
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 450772 times.
450772 if (debug_ts)
2918 ✗ av_log(ofp, AV_LOG_INFO, "filter_raw -> pts:%s pts_time:%s time_base:%d/%d\n",
2919 ✗ av_ts2str(frame->pts), av_ts2timestr(frame->pts, &frame->time_base),
2920 frame->time_base.num, frame->time_base.den);
2921
2922 // Choose the output timebase the first time we get a frame.
2923
2/2
✓ Branch 0 taken 8385 times.
✓ Branch 1 taken 442387 times.
450772 if (!ofp->tb_out_locked) {
2924 8385 ret = choose_out_timebase(ofp, frame);
2925
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8385 times.
8385 if (ret < 0) {
2926 ✗ av_log(ofp, AV_LOG_ERROR, "Could not choose an output time base\n");
2927 ✗ av_frame_unref(frame);
2928 ✗ return ret;
2929 }
2930 }
2931
2932 450772 fd = frame_data(frame);
2933
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 450772 times.
450772 if (!fd) {
2934 ✗ av_frame_unref(frame);
2935 ✗ return AVERROR(ENOMEM);
2936 }
2937
2938 450772 av_frame_side_data_free(&fd->side_data, &fd->nb_side_data);
2939
2/2
✓ Branch 0 taken 8251 times.
✓ Branch 1 taken 442521 times.
450772 if (!fgt->got_frame) {
2940 8251 ret = clone_side_data(&fd->side_data, &fd->nb_side_data,
2941 8251 ofp->side_data, ofp->nb_side_data, 0);
2942
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8251 times.
8251 if (ret < 0) {
2943 ✗ av_frame_unref(frame);
2944 ✗ return ret;
2945 }
2946 }
2947
2948 450772 fd->wallclock[LATENCY_PROBE_FILTER_POST] = av_gettime_relative();
2949
2950 // only use bits_per_raw_sample passed through from the decoder
2951 // if the filtergraph did not touch the frame data
2952
2/2
✓ Branch 0 taken 335769 times.
✓ Branch 1 taken 115003 times.
450772 if (!fgp->is_meta)
2953 335769 fd->bits_per_raw_sample = 0;
2954
2955
2/2
✓ Branch 0 taken 144068 times.
✓ Branch 1 taken 306704 times.
450772 if (ofp->ofilter.type == AVMEDIA_TYPE_VIDEO) {
2956
2/2
✓ Branch 0 taken 2421 times.
✓ Branch 1 taken 141647 times.
144068 if (!frame->duration) {
2957 2421 AVRational fr = av_buffersink_get_frame_rate(filter);
2958
4/4
✓ Branch 0 taken 2328 times.
✓ Branch 1 taken 93 times.
✓ Branch 2 taken 1787 times.
✓ Branch 3 taken 541 times.
2421 if (fr.num > 0 && fr.den > 0)
2959 1787 frame->duration = av_rescale_q(1, av_inv_q(fr), frame->time_base);
2960 }
2961
2962 144068 fd->frame_rate_filter = ofp->fps.framerate;
2963 }
2964
2965 450772 ret = fg_output_frame(ofp, fgt, frame);
2966 450772 av_frame_unref(frame);
2967
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 450772 times.
450772 if (ret < 0)
2968 ✗ return ret;
2969
2970 450772 return 0;
2971 }
2972
2973 /* retrieve all frames available at filtergraph outputs
2974 * and send them to consumers */
2975 461846 static int read_frames(FilterGraph *fg, FilterGraphThread *fgt,
2976 AVFrame *frame)
2977 {
2978 461846 FilterGraphPriv *fgp = fgp_from_fg(fg);
2979
2980 // graph not configured, just select the input to request
2981
2/2
✓ Branch 0 taken 171 times.
✓ Branch 1 taken 461675 times.
461846 if (!fgt->graph) {
2982
1/2
✓ Branch 0 taken 487 times.
✗ Branch 1 not taken.
487 for (int i = 0; i < fg->nb_inputs; i++) {
2983 487 InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]);
2984
3/4
✓ Branch 0 taken 171 times.
✓ Branch 1 taken 316 times.
✓ Branch 2 taken 171 times.
✗ Branch 3 not taken.
487 if (ifp->format < 0 && !fgt->eof_in[i]) {
2985 171 fgt->next_in = i;
2986 171 return 0;
2987 }
2988 }
2989
2990 // This state - graph is not configured, but all inputs are either
2991 // initialized or EOF - should be unreachable because sending EOF to a
2992 // filter without even a fallback format should fail
2993 ✗ av_assert0(0);
2994 return AVERROR_BUG;
2995 }
2996
2997
2/2
✓ Branch 0 taken 458583 times.
✓ Branch 1 taken 3092 times.
461675 if (fgp->nb_outputs_done < fg->nb_outputs) {
2998 int ret;
2999
3000 /* Reap all buffers present in the buffer sinks */
3001
2/2
✓ Branch 0 taken 470016 times.
✓ Branch 1 taken 458583 times.
928599 for (int i = 0; i < fg->nb_outputs; i++) {
3002 470016 OutputFilterPriv *ofp = ofp_from_ofilter(fg->outputs[i]);
3003
3004 470016 ret = 0;
3005
2/2
✓ Branch 0 taken 920790 times.
✓ Branch 1 taken 470016 times.
1390806 while (!ret) {
3006 920790 ret = fg_output_step(ofp, fgt, frame);
3007
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 920790 times.
920790 if (ret < 0)
3008 ✗ return ret;
3009 }
3010 }
3011
3012
3013 458583 ret = avfilter_graph_request_oldest(fgt->graph);
3014
2/2
✓ Branch 0 taken 421877 times.
✓ Branch 1 taken 36706 times.
458583 if (ret == AVERROR(EAGAIN)) {
3015 421877 fgt->next_in = choose_input(fg, fgt);
3016 421877 return 0;
3017
2/2
✓ Branch 0 taken 5150 times.
✓ Branch 1 taken 31556 times.
36706 } else if (ret < 0) {
3018
1/2
✓ Branch 0 taken 5150 times.
✗ Branch 1 not taken.
5150 if (ret == AVERROR_EOF)
3019 5150 av_log(fg, AV_LOG_VERBOSE, "Filtergraph returned EOF, finishing\n");
3020 else
3021 ✗ av_log(fg, AV_LOG_ERROR,
3022 "Error requesting a frame from the filtergraph: %s\n",
3023 ✗ av_err2str(ret));
3024 5150 return ret;
3025 }
3026 31556 fgt->next_in = fg->nb_inputs;
3027
3028 // return so that scheduler can rate-control us
3029 31556 return 0;
3030 }
3031
3032 3092 return AVERROR_EOF;
3033 }
3034
3035 948 static void sub2video_heartbeat(InputFilter *ifilter, int64_t pts, AVRational tb)
3036 {
3037 948 InputFilterPriv *ifp = ifp_from_ifilter(ifilter);
3038 int64_t pts2;
3039
3040 /* subtitles seem to be usually muxed ahead of other streams;
3041 if not, subtracting a larger time here is necessary */
3042 948 pts2 = av_rescale_q(pts, tb, ifp->time_base) - 1;
3043
3044 /* do not send the heartbeat frame if the subtitle is already ahead */
3045
2/2
✓ Branch 0 taken 769 times.
✓ Branch 1 taken 179 times.
948 if (pts2 <= ifp->sub2video.last_pts)
3046 769 return;
3047
3048
3/4
✓ Branch 0 taken 91 times.
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 91 times.
179 if (pts2 >= ifp->sub2video.end_pts || ifp->sub2video.initialize)
3049 /* if we have hit the end of the current displayed subpicture,
3050 or if we need to initialize the system, update the
3051 overlaid subpicture and its start/end times */
3052 88 sub2video_update(ifp, pts2 + 1, NULL);
3053 else
3054 91 sub2video_push_ref(ifp, pts2);
3055 }
3056
3057 1055 static int sub2video_frame(InputFilter *ifilter, AVFrame *frame, int buffer)
3058 {
3059 1055 InputFilterPriv *ifp = ifp_from_ifilter(ifilter);
3060 int ret;
3061
3062
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 1040 times.
1055 if (buffer) {
3063 AVFrame *tmp;
3064
3065
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (!frame)
3066 ✗ return 0;
3067
3068 15 tmp = av_frame_alloc();
3069
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (!tmp)
3070 ✗ return AVERROR(ENOMEM);
3071
3072 15 av_frame_move_ref(tmp, frame);
3073
3074 15 ret = av_fifo_write(ifp->frame_queue, &tmp, 1);
3075
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (ret < 0) {
3076 ✗ av_frame_free(&tmp);
3077 ✗ return ret;
3078 }
3079
3080 15 return 0;
3081 }
3082
3083 // heartbeat frame
3084
4/4
✓ Branch 0 taken 1036 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 948 times.
✓ Branch 3 taken 88 times.
1040 if (frame && !frame->buf[0]) {
3085 948 sub2video_heartbeat(ifilter, frame->pts, frame->time_base);
3086 948 return 0;
3087 }
3088
3089
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 88 times.
92 if (!frame) {
3090
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (ifp->sub2video.end_pts < INT64_MAX)
3091 4 sub2video_update(ifp, INT64_MAX, NULL);
3092
3093 4 return av_buffersrc_add_frame(ifilter->filter, NULL);
3094 }
3095
3096
1/2
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
88 ifp->width = frame->width ? frame->width : ifp->width;
3097
1/2
✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
88 ifp->height = frame->height ? frame->height : ifp->height;
3098
3099 88 sub2video_update(ifp, INT64_MIN, (const AVSubtitle*)frame->buf[0]->data);
3100
3101 88 return 0;
3102 }
3103
3104 3475 static int send_eof(FilterGraphThread *fgt, InputFilter *ifilter,
3105 int64_t pts, AVRational tb)
3106 {
3107 3475 InputFilterPriv *ifp = ifp_from_ifilter(ifilter);
3108 int ret;
3109
3110
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3475 times.
3475 if (fgt->eof_in[ifilter->index])
3111 ✗ return 0;
3112
3113 3475 fgt->eof_in[ifilter->index] = 1;
3114
3115
2/2
✓ Branch 0 taken 3458 times.
✓ Branch 1 taken 17 times.
3475 if (ifilter->filter) {
3116 3458 pts = av_rescale_q_rnd(pts, tb, ifp->time_base,
3117 AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);
3118
3119 3458 ret = av_buffersrc_close(ifilter->filter, pts, AV_BUFFERSRC_FLAG_PUSH);
3120
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3458 times.
3458 if (ret < 0)
3121 ✗ return ret;
3122 } else {
3123
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 14 times.
17 if (ifp->format < 0) {
3124 // the filtergraph was never configured, use the fallback parameters
3125 3 ifp->format = ifp->opts.fallback->format;
3126 3 ifp->sample_rate = ifp->opts.fallback->sample_rate;
3127 3 ifp->width = ifp->opts.fallback->width;
3128 3 ifp->height = ifp->opts.fallback->height;
3129 3 ifp->sample_aspect_ratio = ifp->opts.fallback->sample_aspect_ratio;
3130 3 ifp->color_space = ifp->opts.fallback->colorspace;
3131 3 ifp->color_range = ifp->opts.fallback->color_range;
3132 3 ifp->alpha_mode = ifp->opts.fallback->alpha_mode;
3133 3 ifp->time_base = ifp->opts.fallback->time_base;
3134
3135 3 ret = av_channel_layout_copy(&ifp->ch_layout,
3136 3 &ifp->opts.fallback->ch_layout);
3137
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
3138 ✗ return ret;
3139
3140 3 av_frame_side_data_free(&ifp->side_data, &ifp->nb_side_data);
3141 3 ret = clone_side_data(&ifp->side_data, &ifp->nb_side_data,
3142 3 ifp->opts.fallback->side_data,
3143 3 ifp->opts.fallback->nb_side_data, 0);
3144
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
3145 ✗ return ret;
3146
3147
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 if (ifilter_has_all_input_formats(ifilter->graph)) {
3148 3 ret = configure_filtergraph(ifilter->graph, fgt);
3149
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0) {
3150 ✗ av_log(ifilter->graph, AV_LOG_ERROR, "Error initializing filters!\n");
3151 ✗ return ret;
3152 }
3153 }
3154 }
3155
3156
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (ifp->format < 0) {
3157 ✗ av_log(ifilter->graph, AV_LOG_ERROR,
3158 "Cannot determine format of input %s after EOF\n",
3159 ifp->opts.name);
3160 ✗ return AVERROR_INVALIDDATA;
3161 }
3162 }
3163
3164 3475 return 0;
3165 }
3166
3167 enum ReinitReason {
3168 VIDEO_CHANGED = (1 << 0),
3169 AUDIO_CHANGED = (1 << 1),
3170 MATRIX_CHANGED = (1 << 2),
3171 DOWNMIX_CHANGED = (1 << 3),
3172 HWACCEL_CHANGED = (1 << 4)
3173 };
3174
3175 185 static const char *unknown_if_null(const char *str)
3176 {
3177
1/2
✓ Branch 0 taken 185 times.
✗ Branch 1 not taken.
185 return str ? str : "unknown";
3178 }
3179
3180 424785 static int send_frame(FilterGraph *fg, FilterGraphThread *fgt,
3181 InputFilter *ifilter, AVFrame *frame, int force_reinit)
3182 {
3183 424785 FilterGraphPriv *fgp = fgp_from_fg(fg);
3184 424785 InputFilterPriv *ifp = ifp_from_ifilter(ifilter);
3185 FrameData *fd;
3186 AVFrameSideData *sd;
3187 424785 int need_reinit = 0, ret;
3188
3189 /* determine if the parameters for this input changed */
3190
2/3
✓ Branch 0 taken 306533 times.
✓ Branch 1 taken 118252 times.
✗ Branch 2 not taken.
424785 switch (ifilter->type) {
3191 306533 case AVMEDIA_TYPE_AUDIO:
3192
2/2
✓ Branch 0 taken 305146 times.
✓ Branch 1 taken 1387 times.
306533 if (ifp->format != frame->format ||
3193
3/4
✓ Branch 0 taken 305146 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 305145 times.
610292 ifp->sample_rate != frame->sample_rate ||
3194 305146 av_channel_layout_compare(&ifp->ch_layout, &frame->ch_layout))
3195 1388 need_reinit |= AUDIO_CHANGED;
3196 306533 break;
3197 118252 case AVMEDIA_TYPE_VIDEO:
3198
2/2
✓ Branch 0 taken 112398 times.
✓ Branch 1 taken 5854 times.
118252 if (ifp->format != frame->format ||
3199
2/2
✓ Branch 0 taken 112370 times.
✓ Branch 1 taken 28 times.
112398 ifp->width != frame->width ||
3200
2/2
✓ Branch 0 taken 112363 times.
✓ Branch 1 taken 7 times.
112370 ifp->height != frame->height ||
3201
2/2
✓ Branch 0 taken 112346 times.
✓ Branch 1 taken 17 times.
112363 ifp->color_space != frame->colorspace ||
3202
1/2
✓ Branch 0 taken 112346 times.
✗ Branch 1 not taken.
112346 ifp->color_range != frame->color_range ||
3203
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112346 times.
112346 ifp->alpha_mode != frame->alpha_mode)
3204 5906 need_reinit |= VIDEO_CHANGED;
3205 118252 break;
3206 }
3207
3208
2/2
✓ Branch 1 taken 221 times.
✓ Branch 2 taken 424564 times.
424785 if (sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX)) {
3209
2/2
✓ Branch 0 taken 194 times.
✓ Branch 1 taken 27 times.
221 if (!ifp->displaymatrix_present ||
3210
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 194 times.
194 memcmp(sd->data, ifp->displaymatrix, sizeof(ifp->displaymatrix)))
3211 27 need_reinit |= MATRIX_CHANGED;
3212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 424564 times.
424564 } else if (ifp->displaymatrix_present)
3213 ✗ need_reinit |= MATRIX_CHANGED;
3214
3215
2/2
✓ Branch 1 taken 720 times.
✓ Branch 2 taken 424065 times.
424785 if (sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DOWNMIX_INFO)) {
3216
2/2
✓ Branch 0 taken 712 times.
✓ Branch 1 taken 8 times.
720 if (!ifp->downmixinfo_present ||
3217
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 712 times.
712 memcmp(sd->data, &ifp->downmixinfo, sizeof(ifp->downmixinfo)))
3218 8 need_reinit |= DOWNMIX_CHANGED;
3219
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 424065 times.
424065 } else if (ifp->downmixinfo_present)
3220 ✗ need_reinit |= DOWNMIX_CHANGED;
3221
3222
2/2
✓ Branch 1 taken 22 times.
✓ Branch 2 taken 424763 times.
424785 if (sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DOWNMIX_MATRIX)) {
3223
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 4 times.
22 if (!ifp->downmixmatrix_present ||
3224
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 sd->size != ifp->downmixmatrix_size || memcmp(sd->data, ifp->downmixmatrix->data, sd->size))
3225 4 need_reinit |= DOWNMIX_CHANGED;
3226
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 424763 times.
424763 } else if (ifp->downmixmatrix_present)
3227 ✗ need_reinit |= DOWNMIX_CHANGED;
3228
3229
5/6
✓ Branch 0 taken 7294 times.
✓ Branch 1 taken 417491 times.
✓ Branch 2 taken 144 times.
✓ Branch 3 taken 7150 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 144 times.
424785 if (need_reinit && fgt->graph && (ifp->opts.flags & IFILTER_FLAG_DROPCHANGED)) {
3230 ✗ ifp->nb_dropped++;
3231 ✗ av_log_once(fg, AV_LOG_WARNING, AV_LOG_DEBUG, &ifp->drop_warned, "Avoiding reinit; dropping frame pts: %s bound for %s\n", av_ts2str(frame->pts), ifilter->name);
3232 ✗ av_frame_unref(frame);
3233 ✗ return 0;
3234 }
3235
3236
4/4
✓ Branch 0 taken 187 times.
✓ Branch 1 taken 424598 times.
✓ Branch 2 taken 182 times.
✓ Branch 3 taken 5 times.
424785 if (!(ifp->opts.flags & IFILTER_FLAG_REINIT) && fgt->graph)
3237 182 need_reinit = 0;
3238
3239
1/2
✓ Branch 0 taken 424785 times.
✗ Branch 1 not taken.
424785 if (!!ifp->hw_frames_ctx != !!frame->hw_frames_ctx ||
3240
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 424785 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
424785 (ifp->hw_frames_ctx && ifp->hw_frames_ctx->data != frame->hw_frames_ctx->data))
3241 ✗ need_reinit |= HWACCEL_CHANGED;
3242
3243
2/2
✓ Branch 0 taken 7198 times.
✓ Branch 1 taken 417587 times.
424785 if (need_reinit) {
3244 7198 ret = ifilter_parameters_from_frame(ifilter, frame);
3245
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7198 times.
7198 if (ret < 0)
3246 ✗ return ret;
3247
3248 /* Inputs bound to a filtergraph output will have some fields unset.
3249 * Handle them here */
3250
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7197 times.
7198 if (ifp->ofilter_src) {
3251 1 ret = ifilter_parameters_from_ofilter(ifilter, ifp->ofilter_src);
3252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
3253 ✗ return ret;
3254 }
3255 }
3256
3257 /* (re)init the graph if possible, otherwise buffer the frame and return */
3258
5/6
✓ Branch 0 taken 417587 times.
✓ Branch 1 taken 7198 times.
✓ Branch 2 taken 417587 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 40 times.
✓ Branch 5 taken 417547 times.
424785 if (need_reinit || force_reinit || !fgt->graph) {
3259 7238 AVFrame *tmp = av_frame_alloc();
3260
3261
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7238 times.
7238 if (!tmp)
3262 144 return AVERROR(ENOMEM);
3263
3264
2/2
✓ Branch 1 taken 142 times.
✓ Branch 2 taken 7096 times.
7238 if (!ifilter_has_all_input_formats(fg)) {
3265 142 av_frame_move_ref(tmp, frame);
3266
3267 142 ret = av_fifo_write(ifp->frame_queue, &tmp, 1);
3268
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 142 times.
142 if (ret < 0)
3269 ✗ av_frame_free(&tmp);
3270
3271 142 return ret;
3272 }
3273
3274
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 7048 times.
7096 ret = fgt->graph ? read_frames(fg, fgt, tmp) : 0;
3275 7096 av_frame_free(&tmp);
3276
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7095 times.
7096 if (ret < 0)
3277 1 return ret;
3278
3279
2/2
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 7048 times.
7095 if (fgt->graph) {
3280 AVBPrint reason;
3281 47 av_bprint_init(&reason, 0, AV_BPRINT_SIZE_AUTOMATIC);
3282
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 46 times.
47 if (need_reinit & AUDIO_CHANGED) {
3283 1 const char *sample_format_name = av_get_sample_fmt_name(frame->format);
3284 1 av_bprintf(&reason, "audio parameters changed to %d Hz, ", frame->sample_rate);
3285 1 av_channel_layout_describe_bprint(&frame->ch_layout, &reason);
3286 1 av_bprintf(&reason, ", %s, ", unknown_if_null(sample_format_name));
3287 }
3288
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 1 times.
47 if (need_reinit & VIDEO_CHANGED) {
3289 46 const char *pixel_format_name = av_get_pix_fmt_name(frame->format);
3290 46 const char *color_space_name = av_color_space_name(frame->colorspace);
3291 46 const char *color_range_name = av_color_range_name(frame->color_range);
3292 46 const char *alpha_mode = av_alpha_mode_name(frame->alpha_mode);
3293 46 av_bprintf(&reason, "video parameters changed to %s(%s, %s), %dx%d, %s alpha, ",
3294 unknown_if_null(pixel_format_name), unknown_if_null(color_range_name),
3295 unknown_if_null(color_space_name), frame->width, frame->height,
3296 unknown_if_null(alpha_mode));
3297 }
3298
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 47 times.
47 if (need_reinit & MATRIX_CHANGED)
3299 ✗ av_bprintf(&reason, "display matrix changed, ");
3300
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 47 times.
47 if (need_reinit & DOWNMIX_CHANGED)
3301 ✗ av_bprintf(&reason, "downmix medatata changed, ");
3302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 47 times.
47 if (need_reinit & HWACCEL_CHANGED)
3303 ✗ av_bprintf(&reason, "hwaccel changed, ");
3304
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 47 times.
47 if (force_reinit)
3305 ✗ av_bprintf(&reason, "reinitialization arguments were provided, ");
3306
1/2
✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
47 if (reason.len > 1)
3307 47 reason.str[reason.len - 2] = '\0'; // remove last comma
3308
1/2
✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
47 av_log(fg, AV_LOG_INFO, "Reconfiguring filter graph%s%s\n", reason.len ? " because " : "", reason.str);
3309 } else {
3310 /* Choke all input to avoid buffering excessive frames while the
3311 * initial filter graph is being configured, and before we have a
3312 * preferred input */
3313 7048 sch_filter_choke_inputs(fgp->sch, fgp->sch_idx);
3314 }
3315
3316 7095 ret = configure_filtergraph(fg, fgt);
3317
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7094 times.
7095 if (ret < 0) {
3318 1 av_log(fg, AV_LOG_ERROR, "Error reinitializing filters!\n");
3319 1 return ret;
3320 }
3321 }
3322
3323 424641 frame->pts = av_rescale_q(frame->pts, frame->time_base, ifp->time_base);
3324 424641 frame->duration = av_rescale_q(frame->duration, frame->time_base, ifp->time_base);
3325 424641 frame->time_base = ifp->time_base;
3326
3327
2/2
✓ Branch 0 taken 118148 times.
✓ Branch 1 taken 306493 times.
424641 if (ifp->displaymatrix_applied)
3328 118148 av_frame_remove_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX);
3329
3330 424641 fd = frame_data(frame);
3331
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 424641 times.
424641 if (!fd)
3332 ✗ return AVERROR(ENOMEM);
3333 424641 fd->wallclock[LATENCY_PROBE_FILTER_PRE] = av_gettime_relative();
3334
3335 424641 ret = av_buffersrc_add_frame_flags(ifilter->filter, frame,
3336 AV_BUFFERSRC_FLAG_PUSH);
3337
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 424641 times.
424641 if (ret < 0) {
3338 ✗ av_frame_unref(frame);
3339 ✗ if (ret != AVERROR_EOF)
3340 ✗ av_log(fg, AV_LOG_ERROR, "Error while filtering: %s\n", av_err2str(ret));
3341 ✗ return ret;
3342 }
3343
3344 424641 return 0;
3345 }
3346
3347 8254 static void fg_thread_set_name(const FilterGraph *fg)
3348 {
3349 char name[16];
3350
2/2
✓ Branch 1 taken 6979 times.
✓ Branch 2 taken 1275 times.
8254 if (filtergraph_is_simple(fg)) {
3351 6979 OutputFilterPriv *ofp = ofp_from_ofilter(fg->outputs[0]);
3352 13958 snprintf(name, sizeof(name), "%cf%s",
3353 6979 av_get_media_type_string(ofp->ofilter.type)[0],
3354 ofp->ofilter.output_name);
3355 } else {
3356 1275 snprintf(name, sizeof(name), "fc%d", fg->index);
3357 }
3358
3359 8254 ff_thread_setname(name);
3360 8254 }
3361
3362 8254 static void fg_thread_uninit(FilterGraphThread *fgt)
3363 {
3364
1/2
✓ Branch 0 taken 8254 times.
✗ Branch 1 not taken.
8254 if (fgt->frame_queue_out) {
3365 AVFrame *frame;
3366
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8254 times.
8254 while (av_fifo_read(fgt->frame_queue_out, &frame, 1) >= 0)
3367 ✗ av_frame_free(&frame);
3368 8254 av_fifo_freep2(&fgt->frame_queue_out);
3369 }
3370
3371 8254 av_frame_free(&fgt->frame);
3372 8254 av_freep(&fgt->eof_in);
3373 8254 av_freep(&fgt->eof_out);
3374
3375 8254 avfilter_graph_free(&fgt->graph);
3376
3377 8254 memset(fgt, 0, sizeof(*fgt));
3378 8254 }
3379
3380 8254 static int fg_thread_init(FilterGraphThread *fgt, const FilterGraph *fg)
3381 {
3382 8254 memset(fgt, 0, sizeof(*fgt));
3383
3384 8254 fgt->frame = av_frame_alloc();
3385
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8254 times.
8254 if (!fgt->frame)
3386 ✗ goto fail;
3387
3388 8254 fgt->eof_in = av_calloc(fg->nb_inputs, sizeof(*fgt->eof_in));
3389
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8254 times.
8254 if (!fgt->eof_in)
3390 ✗ goto fail;
3391
3392 8254 fgt->eof_out = av_calloc(fg->nb_outputs, sizeof(*fgt->eof_out));
3393
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8254 times.
8254 if (!fgt->eof_out)
3394 ✗ goto fail;
3395
3396 8254 fgt->frame_queue_out = av_fifo_alloc2(1, sizeof(AVFrame*), AV_FIFO_FLAG_AUTO_GROW);
3397
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8254 times.
8254 if (!fgt->frame_queue_out)
3398 ✗ goto fail;
3399
3400 8254 return 0;
3401
3402 ✗ fail:
3403 ✗ fg_thread_uninit(fgt);
3404 ✗ return AVERROR(ENOMEM);
3405 }
3406
3407 424785 static int check_reinit(FilterGraph *fg, FilterGraphThread *fgt)
3408 {
3409 424785 int ret, reinit = 0;
3410
3411
2/2
✓ Branch 0 taken 435224 times.
✓ Branch 1 taken 424785 times.
860009 for (unsigned i = 0; i < fg->nb_outputs; i++) {
3412 435224 OutputFilterPriv *ofp = ofp_from_ofilter(fg->outputs[i]);
3413
3414
2/6
✓ Branch 0 taken 435224 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 435224 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
435224 if (ofp->reinit_opts.pts == AV_NOPTS_VALUE && ofp->reinit_opts_fifo &&
3415 ✗ av_fifo_can_read(ofp->reinit_opts_fifo)) {
3416 ✗ av_fifo_read(ofp->reinit_opts_fifo, &ofp->reinit_opts, 1);
3417 }
3418
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 435224 times.
435224 if (ofp->reinit_opts.pts != AV_NOPTS_VALUE &&
3419 ✗ ofp->reinit_opts.pts <= av_rescale_q(fgt->frame->pts, fgt->frame->time_base, AV_TIME_BASE_Q)) {
3420 ✗ FrameData *fd = frame_data(fgt->frame);
3421 ✗ if (!fd)
3422 ✗ return AVERROR(ENOMEM);
3423
3424 ✗ av_dict_free(&fd->reinit_opts);
3425 ✗ ret = av_dict_copy(&fd->reinit_opts, ofp->reinit_opts.dict, 0);
3426 ✗ if (ret < 0)
3427 ✗ return ret;
3428
3429 ✗ av_opt_set_dict(ofp, &ofp->reinit_opts.dict);
3430 ✗ av_dict_free(&ofp->reinit_opts.dict);
3431
3432 ✗ if (av_fifo_can_read(ofp->reinit_opts_fifo))
3433 ✗ av_fifo_read(ofp->reinit_opts_fifo, &ofp->reinit_opts, 1);
3434 else
3435 ✗ ofp->reinit_opts = (ReinitOpts){ .pts = AV_NOPTS_VALUE };
3436 ✗ reinit = 1;
3437 }
3438 }
3439
3440 424785 return reinit;
3441 }
3442
3443 8254 static int filter_thread(void *arg)
3444 {
3445 8254 FilterGraphPriv *fgp = arg;
3446 8254 FilterGraph *fg = &fgp->fg;
3447
3448 FilterGraphThread fgt;
3449 8254 int ret = 0, input_status = 0;
3450
3451 8254 ret = fg_thread_init(&fgt, fg);
3452
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8254 times.
8254 if (ret < 0)
3453 ✗ goto finish;
3454
3455 8254 fg_thread_set_name(fg);
3456
3457 // if we have all input parameters the graph can now be configured
3458
2/2
✓ Branch 1 taken 7051 times.
✓ Branch 2 taken 1203 times.
8254 if (ifilter_has_all_input_formats(fg)) {
3459 1203 ret = configure_filtergraph(fg, &fgt);
3460
1/2
✓ Branch 0 taken 1203 times.
✗ Branch 1 not taken.
1203 if (ret < 0) {
3461 ✗ av_log(fg, AV_LOG_ERROR, "Error configuring filter graph: %s\n",
3462 ✗ av_err2str(ret));
3463 ✗ goto finish;
3464 }
3465 }
3466
3467 453558 while (1) {
3468 InputFilter *ifilter;
3469 461812 InputFilterPriv *ifp = NULL;
3470 enum FrameOpaque o;
3471 461812 unsigned input_idx = fgt.next_in;
3472
3473 461812 input_status = sch_filter_receive(fgp->sch, fgp->sch_idx,
3474 461812 &input_idx, fgt.frame);
3475
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 461800 times.
461812 if (input_status == AVERROR_EOF) {
3476 12 av_log(fg, AV_LOG_VERBOSE, "Filtering thread received EOF\n");
3477 12 break;
3478
2/2
✓ Branch 0 taken 32500 times.
✓ Branch 1 taken 429300 times.
461800 } else if (input_status == AVERROR(EAGAIN)) {
3479 // should only happen when we didn't request any input
3480
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32500 times.
32500 av_assert0(input_idx == fg->nb_inputs);
3481 32500 goto read_frames;
3482 }
3483
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 429300 times.
429300 av_assert0(input_status >= 0);
3484
3485 429300 o = (intptr_t)fgt.frame->opaque;
3486
3487 // message on the control stream
3488
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 429300 times.
429300 if (input_idx == fg->nb_inputs) {
3489 FilterCommand *fc;
3490
3491 ✗ av_assert0(o == FRAME_OPAQUE_SEND_COMMAND && fgt.frame->buf[0]);
3492
3493 ✗ fc = (FilterCommand*)fgt.frame->buf[0]->data;
3494 ✗ send_command(fg, fgt.graph, fc->time, fc->target, fc->command, fc->arg,
3495 fc->all_filters);
3496 ✗ av_frame_unref(fgt.frame);
3497 1 continue;
3498 }
3499
3500 // we received an input frame or EOF
3501 429300 ifilter = fg->inputs[input_idx];
3502 429300 ifp = ifp_from_ifilter(ifilter);
3503
3504
2/2
✓ Branch 0 taken 1040 times.
✓ Branch 1 taken 428260 times.
429300 if (ifp->type_src == AVMEDIA_TYPE_SUBTITLE) {
3505
3/4
✓ Branch 0 taken 1040 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 948 times.
✓ Branch 3 taken 92 times.
1040 int hb_frame = input_status >= 0 && o == FRAME_OPAQUE_SUB_HEARTBEAT;
3506
2/2
✓ Branch 0 taken 948 times.
✓ Branch 1 taken 4 times.
1040 ret = sub2video_frame(ifilter, (fgt.frame->buf[0] || hb_frame) ? fgt.frame : NULL,
3507
2/2
✓ Branch 0 taken 952 times.
✓ Branch 1 taken 88 times.
1040 !fgt.graph);
3508
2/2
✓ Branch 0 taken 424785 times.
✓ Branch 1 taken 3475 times.
428260 } else if (fgt.frame->buf[0]) {
3509 424785 ret = check_reinit(fg, &fgt);
3510
1/2
✓ Branch 0 taken 424785 times.
✗ Branch 1 not taken.
424785 if (ret >= 0)
3511 424785 ret = send_frame(fg, &fgt, ifilter, fgt.frame, ret);
3512 } else {
3513 av_assert1(o == FRAME_OPAQUE_EOF);
3514 3475 ret = send_eof(&fgt, ifilter, fgt.frame->pts, fgt.frame->time_base);
3515 }
3516 429300 av_frame_unref(fgt.frame);
3517
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 429299 times.
429300 if (ret == AVERROR_EOF) {
3518 1 av_log(fg, AV_LOG_VERBOSE, "Input %u no longer accepts new data\n",
3519 input_idx);
3520 1 close_input(ifp);
3521 1 continue;
3522 }
3523
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 429298 times.
429299 if (ret < 0)
3524 1 goto finish;
3525
3526 429298 read_frames:
3527 // retrieve all newly available frames
3528 461798 ret = read_frames(fg, &fgt, fgt.frame);
3529
2/2
✓ Branch 0 taken 8241 times.
✓ Branch 1 taken 453557 times.
461798 if (ret == AVERROR_EOF) {
3530 8241 av_log(fg, AV_LOG_VERBOSE, "All consumers returned EOF\n");
3531
3/4
✓ Branch 0 taken 6731 times.
✓ Branch 1 taken 1510 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6731 times.
8241 if (ifp && ifp->opts.flags & IFILTER_FLAG_DROPCHANGED)
3532 ✗ av_log(fg, AV_LOG_INFO, "Total changed input frames dropped : %"PRId64"\n", ifp->nb_dropped);
3533 8241 break;
3534
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 453557 times.
453557 } else if (ret < 0) {
3535 ✗ av_log(fg, AV_LOG_ERROR, "Error sending frames to consumers: %s\n",
3536 ✗ av_err2str(ret));
3537 ✗ goto finish;
3538 }
3539
3540 // ensure all inputs no longer accepting data are closed
3541
4/4
✓ Branch 0 taken 892081 times.
✓ Branch 1 taken 171 times.
✓ Branch 2 taken 438695 times.
✓ Branch 3 taken 453386 times.
892252 for (int i = 0; fgt.graph && i < fg->nb_inputs; i++) {
3542 438695 InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]);
3543
2/2
✓ Branch 1 taken 1759 times.
✓ Branch 2 taken 436936 times.
438695 if (av_buffersrc_get_status(ifp->ifilter.filter))
3544 1759 close_input(ifp);
3545 }
3546 }
3547
3548
2/2
✓ Branch 0 taken 8388 times.
✓ Branch 1 taken 8253 times.
16641 for (unsigned i = 0; i < fg->nb_outputs; i++) {
3549 8388 OutputFilterPriv *ofp = ofp_from_ofilter(fg->outputs[i]);
3550
3551
3/4
✓ Branch 0 taken 1609 times.
✓ Branch 1 taken 6779 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1609 times.
8388 if (fgt.eof_out[i] || !fgt.graph)
3552 6779 continue;
3553
3554 1609 ret = fg_output_frame(ofp, &fgt, NULL);
3555
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1609 times.
1609 if (ret < 0)
3556 ✗ goto finish;
3557 }
3558
3559 8253 finish:
3560
3561
2/4
✓ Branch 0 taken 8254 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8254 times.
8254 if (print_graphs || print_graphs_file)
3562 ✗ print_filtergraph(fg, fgt.graph);
3563
3564 // EOF is normal termination
3565
2/2
✓ Branch 0 taken 6706 times.
✓ Branch 1 taken 1548 times.
8254 if (ret == AVERROR_EOF)
3566 6706 ret = 0;
3567
3568 8254 fg_thread_uninit(&fgt);
3569
3570 8254 return ret;
3571 }
3572
3573 ✗ void fg_send_command(FilterGraph *fg, double time, const char *target,
3574 const char *command, const char *arg, int all_filters)
3575 {
3576 ✗ FilterGraphPriv *fgp = fgp_from_fg(fg);
3577 AVBufferRef *buf;
3578 FilterCommand *fc;
3579
3580 ✗ fc = av_mallocz(sizeof(*fc));
3581 ✗ if (!fc)
3582 ✗ return;
3583
3584 ✗ buf = av_buffer_create((uint8_t*)fc, sizeof(*fc), filter_command_free, NULL, 0);
3585 ✗ if (!buf) {
3586 ✗ av_freep(&fc);
3587 ✗ return;
3588 }
3589
3590 ✗ fc->target = av_strdup(target);
3591 ✗ fc->command = av_strdup(command);
3592 ✗ fc->arg = av_strdup(arg);
3593 ✗ if (!fc->target || !fc->command || !fc->arg) {
3594 ✗ av_buffer_unref(&buf);
3595 ✗ return;
3596 }
3597
3598 ✗ fc->time = time;
3599 ✗ fc->all_filters = all_filters;
3600
3601 ✗ fgp->frame->buf[0] = buf;
3602 ✗ fgp->frame->opaque = (void*)(intptr_t)FRAME_OPAQUE_SEND_COMMAND;
3603
3604 ✗ sch_filter_command(fgp->sch, fgp->sch_idx, fgp->frame);
3605 }
3606