FFmpeg coverage


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