FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/fftools/ffmpeg_filter.c
Date: 2025-08-19 23:55:23
Exec Total Coverage
Lines: 1293 1725 75.0%
Functions: 65 71 91.5%
Branches: 758 1161 65.3%

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