| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * filter layer | ||
| 3 | * Copyright (c) 2007 Bobby Bingham | ||
| 4 | * | ||
| 5 | * This file is part of FFmpeg. | ||
| 6 | * | ||
| 7 | * FFmpeg is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU Lesser General Public | ||
| 9 | * License as published by the Free Software Foundation; either | ||
| 10 | * version 2.1 of the License, or (at your option) any later version. | ||
| 11 | * | ||
| 12 | * FFmpeg is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 15 | * Lesser General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU Lesser General Public | ||
| 18 | * License along with FFmpeg; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include "libavutil/avassert.h" | ||
| 23 | #include "libavutil/avstring.h" | ||
| 24 | #include "libavutil/bprint.h" | ||
| 25 | #include "libavutil/buffer.h" | ||
| 26 | #include "libavutil/channel_layout.h" | ||
| 27 | #include "libavutil/common.h" | ||
| 28 | #include "libavutil/eval.h" | ||
| 29 | #include "libavutil/frame.h" | ||
| 30 | #include "libavutil/hwcontext.h" | ||
| 31 | #include "libavutil/internal.h" | ||
| 32 | #include "libavutil/mem.h" | ||
| 33 | #include "libavutil/opt.h" | ||
| 34 | #include "libavutil/pixdesc.h" | ||
| 35 | #include "libavutil/rational.h" | ||
| 36 | #include "libavutil/samplefmt.h" | ||
| 37 | |||
| 38 | #include "audio.h" | ||
| 39 | #include "avfilter.h" | ||
| 40 | #include "avfilter_internal.h" | ||
| 41 | #include "filters.h" | ||
| 42 | #include "formats.h" | ||
| 43 | #include "framequeue.h" | ||
| 44 | #include "framepool.h" | ||
| 45 | #include "video.h" | ||
| 46 | |||
| 47 | 1690787 | static void tlog_ref(void *ctx, AVFrame *ref, int end) | |
| 48 | { | ||
| 49 | #ifdef TRACE | ||
| 50 | ff_tlog(ctx, | ||
| 51 | "ref[%p buf:%p data:%p linesize[%d, %d, %d, %d] pts:%"PRId64, | ||
| 52 | ref, ref->buf, ref->data[0], | ||
| 53 | ref->linesize[0], ref->linesize[1], ref->linesize[2], ref->linesize[3], | ||
| 54 | ref->pts); | ||
| 55 | |||
| 56 | if (ref->width) { | ||
| 57 | ff_tlog(ctx, " a:%d/%d s:%dx%d i:%c iskey:%d type:%c", | ||
| 58 | ref->sample_aspect_ratio.num, ref->sample_aspect_ratio.den, | ||
| 59 | ref->width, ref->height, | ||
| 60 | !(ref->flags & AV_FRAME_FLAG_INTERLACED) ? 'P' : /* Progressive */ | ||
| 61 | (ref->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? 'T' : 'B', /* Top / Bottom */ | ||
| 62 | !!(ref->flags & AV_FRAME_FLAG_KEY), | ||
| 63 | av_get_picture_type_char(ref->pict_type)); | ||
| 64 | } | ||
| 65 | if (ref->nb_samples) { | ||
| 66 | AVBPrint bprint; | ||
| 67 | |||
| 68 | av_bprint_init(&bprint, 1, AV_BPRINT_SIZE_UNLIMITED); | ||
| 69 | av_channel_layout_describe_bprint(&ref->ch_layout, &bprint); | ||
| 70 | ff_tlog(ctx, " cl:%s n:%d r:%d", | ||
| 71 | bprint.str, | ||
| 72 | ref->nb_samples, | ||
| 73 | ref->sample_rate); | ||
| 74 | av_bprint_finalize(&bprint, NULL); | ||
| 75 | } | ||
| 76 | |||
| 77 | ff_tlog(ctx, "]%s", end ? "\n" : ""); | ||
| 78 | #endif | ||
| 79 | 1690787 | } | |
| 80 | |||
| 81 | ✗ | static void command_queue_pop(AVFilterContext *filter) | |
| 82 | { | ||
| 83 | ✗ | FFFilterContext *ctxi = fffilterctx(filter); | |
| 84 | ✗ | AVFilterCommand *c = ctxi->command_queue; | |
| 85 | ✗ | av_freep(&c->arg); | |
| 86 | ✗ | av_freep(&c->command); | |
| 87 | ✗ | ctxi->command_queue = c->next; | |
| 88 | ✗ | av_free(c); | |
| 89 | ✗ | } | |
| 90 | |||
| 91 | /** | ||
| 92 | * Append a new pad. | ||
| 93 | * | ||
| 94 | * @param count Pointer to the number of pads in the list | ||
| 95 | * @param pads Pointer to the pointer to the beginning of the list of pads | ||
| 96 | * @param links Pointer to the pointer to the beginning of the list of links | ||
| 97 | * @param newpad The new pad to add. A copy is made when adding. | ||
| 98 | * @return >= 0 in case of success, a negative AVERROR code on error | ||
| 99 | */ | ||
| 100 | 570 | static int append_pad(unsigned *count, AVFilterPad **pads, | |
| 101 | AVFilterLink ***links, AVFilterPad *newpad) | ||
| 102 | { | ||
| 103 | AVFilterLink **newlinks; | ||
| 104 | AVFilterPad *newpads; | ||
| 105 | 570 | unsigned idx = *count; | |
| 106 | |||
| 107 | 570 | newpads = av_realloc_array(*pads, idx + 1, sizeof(*newpads)); | |
| 108 | 570 | newlinks = av_realloc_array(*links, idx + 1, sizeof(*newlinks)); | |
| 109 |
1/2✓ Branch 0 taken 570 times.
✗ Branch 1 not taken.
|
570 | if (newpads) |
| 110 | 570 | *pads = newpads; | |
| 111 |
1/2✓ Branch 0 taken 570 times.
✗ Branch 1 not taken.
|
570 | if (newlinks) |
| 112 | 570 | *links = newlinks; | |
| 113 |
2/4✓ Branch 0 taken 570 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 570 times.
|
570 | if (!newpads || !newlinks) { |
| 114 | ✗ | if (newpad->flags & AVFILTERPAD_FLAG_FREE_NAME) | |
| 115 | ✗ | av_freep(&newpad->name); | |
| 116 | ✗ | return AVERROR(ENOMEM); | |
| 117 | } | ||
| 118 | |||
| 119 | 570 | memcpy(*pads + idx, newpad, sizeof(AVFilterPad)); | |
| 120 | 570 | (*links)[idx] = NULL; | |
| 121 | |||
| 122 | 570 | (*count)++; | |
| 123 | |||
| 124 | 570 | return 0; | |
| 125 | } | ||
| 126 | |||
| 127 | 283 | int ff_append_inpad(AVFilterContext *f, AVFilterPad *p) | |
| 128 | { | ||
| 129 | 283 | return append_pad(&f->nb_inputs, &f->input_pads, &f->inputs, p); | |
| 130 | } | ||
| 131 | |||
| 132 | 264 | int ff_append_inpad_free_name(AVFilterContext *f, AVFilterPad *p) | |
| 133 | { | ||
| 134 | 264 | p->flags |= AVFILTERPAD_FLAG_FREE_NAME; | |
| 135 | 264 | return ff_append_inpad(f, p); | |
| 136 | } | ||
| 137 | |||
| 138 | 287 | int ff_append_outpad(AVFilterContext *f, AVFilterPad *p) | |
| 139 | { | ||
| 140 | 287 | return append_pad(&f->nb_outputs, &f->output_pads, &f->outputs, p); | |
| 141 | } | ||
| 142 | |||
| 143 | 146 | int ff_append_outpad_free_name(AVFilterContext *f, AVFilterPad *p) | |
| 144 | { | ||
| 145 | 146 | p->flags |= AVFILTERPAD_FLAG_FREE_NAME; | |
| 146 | 146 | return ff_append_outpad(f, p); | |
| 147 | } | ||
| 148 | |||
| 149 | 47442 | int avfilter_link(AVFilterContext *src, unsigned srcpad, | |
| 150 | AVFilterContext *dst, unsigned dstpad) | ||
| 151 | { | ||
| 152 | FilterLinkInternal *li; | ||
| 153 | AVFilterLink *link; | ||
| 154 | |||
| 155 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 47442 times.
|
47442 | av_assert0(src->graph); |
| 156 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 47442 times.
|
47442 | av_assert0(dst->graph); |
| 157 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 47442 times.
|
47442 | av_assert0(src->graph == dst->graph); |
| 158 | |||
| 159 |
2/4✓ Branch 0 taken 47442 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 47442 times.
✗ Branch 3 not taken.
|
47442 | if (src->nb_outputs <= srcpad || dst->nb_inputs <= dstpad || |
| 160 |
2/4✓ Branch 0 taken 47442 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 47442 times.
|
47442 | src->outputs[srcpad] || dst->inputs[dstpad]) |
| 161 | ✗ | return AVERROR(EINVAL); | |
| 162 | |||
| 163 |
1/2✓ Branch 1 taken 47442 times.
✗ Branch 2 not taken.
|
47442 | if (!(fffilterctx(src)->state_flags & AV_CLASS_STATE_INITIALIZED) || |
| 164 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 47442 times.
|
47442 | !(fffilterctx(dst)->state_flags & AV_CLASS_STATE_INITIALIZED)) { |
| 165 | ✗ | av_log(src, AV_LOG_ERROR, "Filters must be initialized before linking.\n"); | |
| 166 | ✗ | return AVERROR(EINVAL); | |
| 167 | } | ||
| 168 | |||
| 169 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 47442 times.
|
47442 | if (src->output_pads[srcpad].type != dst->input_pads[dstpad].type) { |
| 170 | ✗ | av_log(src, AV_LOG_ERROR, | |
| 171 | "Media type mismatch between the '%s' filter output pad %d (%s) and the '%s' filter input pad %d (%s)\n", | ||
| 172 | ✗ | src->name, srcpad, (char *)av_x_if_null(av_get_media_type_string(src->output_pads[srcpad].type), "?"), | |
| 173 | ✗ | dst->name, dstpad, (char *)av_x_if_null(av_get_media_type_string(dst-> input_pads[dstpad].type), "?")); | |
| 174 | ✗ | return AVERROR(EINVAL); | |
| 175 | } | ||
| 176 | |||
| 177 | 47442 | li = av_mallocz(sizeof(*li)); | |
| 178 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 47442 times.
|
47442 | if (!li) |
| 179 | ✗ | return AVERROR(ENOMEM); | |
| 180 | 47442 | link = &li->l.pub; | |
| 181 | |||
| 182 | 47442 | src->outputs[srcpad] = dst->inputs[dstpad] = link; | |
| 183 | |||
| 184 | 47442 | link->src = src; | |
| 185 | 47442 | link->dst = dst; | |
| 186 | 47442 | link->srcpad = &src->output_pads[srcpad]; | |
| 187 | 47442 | link->dstpad = &dst->input_pads[dstpad]; | |
| 188 | 47442 | link->type = src->output_pads[srcpad].type; | |
| 189 | 47442 | li->l.graph = src->graph; | |
| 190 | av_assert0(AV_PIX_FMT_NONE == -1 && AV_SAMPLE_FMT_NONE == -1); | ||
| 191 | 47442 | link->format = -1; | |
| 192 | 47442 | link->colorspace = AVCOL_SPC_UNSPECIFIED; | |
| 193 | 47442 | ff_framequeue_init(&li->fifo, &fffiltergraph(src->graph)->frame_queues); | |
| 194 | |||
| 195 | 47442 | return 0; | |
| 196 | } | ||
| 197 | |||
| 198 | 47574 | static void link_free(AVFilterLink **link) | |
| 199 | { | ||
| 200 | FilterLinkInternal *li; | ||
| 201 | |||
| 202 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 47574 times.
|
47574 | if (!*link) |
| 203 | ✗ | return; | |
| 204 | 47574 | li = ff_link_internal(*link); | |
| 205 | |||
| 206 | 47574 | ff_framequeue_free(&li->fifo); | |
| 207 | 47574 | ff_frame_pool_uninit(&li->frame_pool); | |
| 208 | 47574 | av_channel_layout_uninit(&(*link)->ch_layout); | |
| 209 | 47574 | av_frame_side_data_free(&(*link)->side_data, &(*link)->nb_side_data); | |
| 210 | |||
| 211 | 47574 | av_buffer_unref(&li->l.hw_frames_ctx); | |
| 212 | |||
| 213 | 47574 | av_freep(link); | |
| 214 | } | ||
| 215 | |||
| 216 | 1702344 | static void update_link_current_pts(FilterLinkInternal *li, int64_t pts) | |
| 217 | { | ||
| 218 | 1702344 | AVFilterLink *const link = &li->l.pub; | |
| 219 | |||
| 220 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1702339 times.
|
1702344 | if (pts == AV_NOPTS_VALUE) |
| 221 | 5 | return; | |
| 222 | 1702339 | li->l.current_pts = pts; | |
| 223 | 1702339 | li->l.current_pts_us = av_rescale_q(pts, link->time_base, AV_TIME_BASE_Q); | |
| 224 | /* TODO use duration */ | ||
| 225 |
3/4✓ Branch 0 taken 1702339 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 459172 times.
✓ Branch 3 taken 1243167 times.
|
1702339 | if (li->l.graph && li->age_index >= 0) |
| 226 | 459172 | ff_avfilter_graph_update_heap(li->l.graph, li); | |
| 227 | } | ||
| 228 | |||
| 229 | 4220166 | void ff_filter_set_ready(AVFilterContext *filter, unsigned priority) | |
| 230 | { | ||
| 231 | 4220166 | FFFilterContext *ctxi = fffilterctx(filter); | |
| 232 | 4220166 | ctxi->ready = FFMAX(ctxi->ready, priority); | |
| 233 | 4220166 | } | |
| 234 | |||
| 235 | /** | ||
| 236 | * Clear frame_blocked_in on all outputs. | ||
| 237 | * This is necessary whenever something changes on input. | ||
| 238 | */ | ||
| 239 | 2519003 | static void filter_unblock(AVFilterContext *filter) | |
| 240 | { | ||
| 241 | unsigned i; | ||
| 242 | |||
| 243 |
2/2✓ Branch 0 taken 2059934 times.
✓ Branch 1 taken 2519003 times.
|
4578937 | for (i = 0; i < filter->nb_outputs; i++) { |
| 244 | 2059934 | FilterLinkInternal * const li = ff_link_internal(filter->outputs[i]); | |
| 245 | 2059934 | li->frame_blocked_in = 0; | |
| 246 | } | ||
| 247 | 2519003 | } | |
| 248 | |||
| 249 | |||
| 250 | 19736 | void ff_avfilter_link_set_in_status(AVFilterLink *link, int status, int64_t pts) | |
| 251 | { | ||
| 252 | 19736 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 253 | |||
| 254 |
2/2✓ Branch 0 taken 5633 times.
✓ Branch 1 taken 14103 times.
|
19736 | if (li->status_in == status) |
| 255 | 5633 | return; | |
| 256 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14103 times.
|
14103 | av_assert0(!li->status_in); |
| 257 | 14103 | li->status_in = status; | |
| 258 | 14103 | li->status_in_pts = pts; | |
| 259 | 14103 | li->frame_wanted_out = 0; | |
| 260 | 14103 | li->frame_blocked_in = 0; | |
| 261 | 14103 | filter_unblock(link->dst); | |
| 262 | 14103 | ff_filter_set_ready(link->dst, 200); | |
| 263 | } | ||
| 264 | |||
| 265 | /** | ||
| 266 | * Set the status field of a link from the destination filter. | ||
| 267 | * The pts should probably be left unset (AV_NOPTS_VALUE). | ||
| 268 | */ | ||
| 269 | 8602 | static void link_set_out_status(AVFilterLink *link, int status, int64_t pts) | |
| 270 | { | ||
| 271 | 8602 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 272 | |||
| 273 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8602 times.
|
8602 | av_assert0(!li->frame_wanted_out); |
| 274 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8602 times.
|
8602 | av_assert0(!li->status_out); |
| 275 | 8602 | li->status_out = status; | |
| 276 |
2/2✓ Branch 0 taken 6087 times.
✓ Branch 1 taken 2515 times.
|
8602 | if (pts != AV_NOPTS_VALUE) |
| 277 | 6087 | update_link_current_pts(li, pts); | |
| 278 | 8602 | filter_unblock(link->dst); | |
| 279 | 8602 | ff_filter_set_ready(link->src, 200); | |
| 280 | 8602 | } | |
| 281 | |||
| 282 | 1280 | int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt, | |
| 283 | unsigned filt_srcpad_idx, unsigned filt_dstpad_idx) | ||
| 284 | { | ||
| 285 | int ret; | ||
| 286 | 1280 | unsigned dstpad_idx = link->dstpad - link->dst->input_pads; | |
| 287 | |||
| 288 | 1280 | av_log(link->dst, AV_LOG_VERBOSE, "auto-inserting filter '%s' " | |
| 289 | "between the filter '%s' and the filter '%s'\n", | ||
| 290 | 1280 | filt->name, link->src->name, link->dst->name); | |
| 291 | |||
| 292 | 1280 | link->dst->inputs[dstpad_idx] = NULL; | |
| 293 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1280 times.
|
1280 | if ((ret = avfilter_link(filt, filt_dstpad_idx, link->dst, dstpad_idx)) < 0) { |
| 294 | /* failed to link output filter to new filter */ | ||
| 295 | ✗ | link->dst->inputs[dstpad_idx] = link; | |
| 296 | ✗ | return ret; | |
| 297 | } | ||
| 298 | |||
| 299 | /* re-hookup the link to the new destination filter we inserted */ | ||
| 300 | 1280 | link->dst = filt; | |
| 301 | 1280 | link->dstpad = &filt->input_pads[filt_srcpad_idx]; | |
| 302 | 1280 | filt->inputs[filt_srcpad_idx] = link; | |
| 303 | |||
| 304 | /* if any information on supported media formats already exists on the | ||
| 305 | * link, we need to preserve that */ | ||
| 306 |
1/2✓ Branch 0 taken 1280 times.
✗ Branch 1 not taken.
|
1280 | if (link->outcfg.formats) |
| 307 | 1280 | ff_formats_changeref(&link->outcfg.formats, | |
| 308 | 1280 | &filt->outputs[filt_dstpad_idx]->outcfg.formats); | |
| 309 |
2/2✓ Branch 0 taken 632 times.
✓ Branch 1 taken 648 times.
|
1280 | if (link->outcfg.color_spaces) |
| 310 | 632 | ff_formats_changeref(&link->outcfg.color_spaces, | |
| 311 | 632 | &filt->outputs[filt_dstpad_idx]->outcfg.color_spaces); | |
| 312 |
2/2✓ Branch 0 taken 632 times.
✓ Branch 1 taken 648 times.
|
1280 | if (link->outcfg.color_ranges) |
| 313 | 632 | ff_formats_changeref(&link->outcfg.color_ranges, | |
| 314 | 632 | &filt->outputs[filt_dstpad_idx]->outcfg.color_ranges); | |
| 315 |
2/2✓ Branch 0 taken 632 times.
✓ Branch 1 taken 648 times.
|
1280 | if (link->outcfg.alpha_modes) |
| 316 | 632 | ff_formats_changeref(&link->outcfg.alpha_modes, | |
| 317 | 632 | &filt->outputs[filt_dstpad_idx]->outcfg.alpha_modes); | |
| 318 |
2/2✓ Branch 0 taken 648 times.
✓ Branch 1 taken 632 times.
|
1280 | if (link->outcfg.samplerates) |
| 319 | 648 | ff_formats_changeref(&link->outcfg.samplerates, | |
| 320 | 648 | &filt->outputs[filt_dstpad_idx]->outcfg.samplerates); | |
| 321 |
2/2✓ Branch 0 taken 648 times.
✓ Branch 1 taken 632 times.
|
1280 | if (link->outcfg.channel_layouts) |
| 322 | 648 | ff_channel_layouts_changeref(&link->outcfg.channel_layouts, | |
| 323 | 648 | &filt->outputs[filt_dstpad_idx]->outcfg.channel_layouts); | |
| 324 | |||
| 325 | 1280 | return 0; | |
| 326 | } | ||
| 327 | |||
| 328 | 45462 | int ff_filter_config_links(AVFilterContext *filter) | |
| 329 | { | ||
| 330 | int (*config_link)(AVFilterLink *); | ||
| 331 | unsigned i; | ||
| 332 | int ret; | ||
| 333 | |||
| 334 |
2/2✓ Branch 0 taken 37205 times.
✓ Branch 1 taken 45458 times.
|
82663 | for (i = 0; i < filter->nb_inputs; i ++) { |
| 335 | 37205 | AVFilterLink *link = filter->inputs[i]; | |
| 336 | AVFilterLink *inlink; | ||
| 337 | 37205 | FilterLinkInternal *li = ff_link_internal(link); | |
| 338 | FilterLinkInternal *li_in; | ||
| 339 | |||
| 340 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 37205 times.
|
37205 | if (!link) continue; |
| 341 |
2/4✓ Branch 0 taken 37205 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 37205 times.
|
37205 | if (!link->src || !link->dst) { |
| 342 | ✗ | av_log(filter, AV_LOG_ERROR, | |
| 343 | "Not all input and output are properly linked (%d).\n", i); | ||
| 344 | ✗ | return AVERROR(EINVAL); | |
| 345 | } | ||
| 346 | |||
| 347 |
2/2✓ Branch 0 taken 28748 times.
✓ Branch 1 taken 8457 times.
|
37205 | inlink = link->src->nb_inputs ? link->src->inputs[0] : NULL; |
| 348 |
2/2✓ Branch 0 taken 28748 times.
✓ Branch 1 taken 8457 times.
|
37205 | li_in = inlink ? ff_link_internal(inlink) : NULL; |
| 349 | 37205 | li->l.current_pts = | |
| 350 | 37205 | li->l.current_pts_us = AV_NOPTS_VALUE; | |
| 351 | |||
| 352 |
3/4✓ Branch 0 taken 111 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 37092 times.
✗ Branch 3 not taken.
|
37205 | switch (li->init_state) { |
| 353 | 111 | case AVLINK_INIT: | |
| 354 | 111 | continue; | |
| 355 | 2 | case AVLINK_STARTINIT: | |
| 356 | 2 | av_log(filter, AV_LOG_INFO, "circular filter chain detected\n"); | |
| 357 | 2 | return 0; | |
| 358 | 37092 | case AVLINK_UNINIT: | |
| 359 | 37092 | li->init_state = AVLINK_STARTINIT; | |
| 360 | |||
| 361 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 37091 times.
|
37092 | if ((ret = ff_filter_config_links(link->src)) < 0) |
| 362 | 1 | return ret; | |
| 363 | |||
| 364 |
2/2✓ Branch 0 taken 19438 times.
✓ Branch 1 taken 17653 times.
|
37091 | if (!(config_link = link->srcpad->config_props)) { |
| 365 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19438 times.
|
19438 | if (link->src->nb_inputs != 1) { |
| 366 | ✗ | av_log(link->src, AV_LOG_ERROR, "Source filters and filters " | |
| 367 | "with more than one input " | ||
| 368 | "must set config_props() " | ||
| 369 | "callbacks on all outputs\n"); | ||
| 370 | ✗ | return AVERROR(EINVAL); | |
| 371 | } | ||
| 372 | } | ||
| 373 | |||
| 374 | /* Copy side data before link->srcpad->config_props() is called, so the filter | ||
| 375 | * may remove it for the next filter in the chain */ | ||
| 376 |
5/6✓ Branch 0 taken 28668 times.
✓ Branch 1 taken 8423 times.
✓ Branch 2 taken 261 times.
✓ Branch 3 taken 28407 times.
✓ Branch 4 taken 261 times.
✗ Branch 5 not taken.
|
37091 | if (inlink && inlink->nb_side_data && !link->nb_side_data) { |
| 377 |
2/2✓ Branch 0 taken 270 times.
✓ Branch 1 taken 261 times.
|
531 | for (int j = 0; j < inlink->nb_side_data; j++) { |
| 378 | 270 | ret = av_frame_side_data_clone(&link->side_data, &link->nb_side_data, | |
| 379 | 270 | inlink->side_data[j], 0); | |
| 380 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 270 times.
|
270 | if (ret < 0) { |
| 381 | ✗ | av_frame_side_data_free(&link->side_data, &link->nb_side_data); | |
| 382 | ✗ | return ret; | |
| 383 | } | ||
| 384 | } | ||
| 385 | } | ||
| 386 | |||
| 387 |
4/4✓ Branch 0 taken 17653 times.
✓ Branch 1 taken 19438 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 17652 times.
|
37091 | if (config_link && (ret = config_link(link)) < 0) { |
| 388 | 1 | av_log(link->src, AV_LOG_ERROR, | |
| 389 | "Failed to configure output pad on %s\n", | ||
| 390 | 1 | link->src->name); | |
| 391 | 1 | return ret; | |
| 392 | } | ||
| 393 | |||
| 394 |
2/3✓ Branch 0 taken 30999 times.
✓ Branch 1 taken 6091 times.
✗ Branch 2 not taken.
|
37090 | switch (link->type) { |
| 395 | 30999 | case AVMEDIA_TYPE_VIDEO: | |
| 396 |
3/4✓ Branch 0 taken 23731 times.
✓ Branch 1 taken 7268 times.
✓ Branch 2 taken 23731 times.
✗ Branch 3 not taken.
|
30999 | if (!link->time_base.num && !link->time_base.den) |
| 397 |
1/2✓ Branch 0 taken 23731 times.
✗ Branch 1 not taken.
|
23731 | link->time_base = inlink ? inlink->time_base : AV_TIME_BASE_Q; |
| 398 | |||
| 399 |
4/4✓ Branch 0 taken 26533 times.
✓ Branch 1 taken 4466 times.
✓ Branch 2 taken 16881 times.
✓ Branch 3 taken 9652 times.
|
30999 | if (!link->sample_aspect_ratio.num && !link->sample_aspect_ratio.den) |
| 400 | 16881 | link->sample_aspect_ratio = inlink ? | |
| 401 |
2/2✓ Branch 0 taken 16866 times.
✓ Branch 1 taken 15 times.
|
16881 | inlink->sample_aspect_ratio : (AVRational){1,1}; |
| 402 | |||
| 403 |
2/2✓ Branch 0 taken 23993 times.
✓ Branch 1 taken 7006 times.
|
30999 | if (inlink) { |
| 404 |
3/4✓ Branch 0 taken 23774 times.
✓ Branch 1 taken 219 times.
✓ Branch 2 taken 23774 times.
✗ Branch 3 not taken.
|
23993 | if (!li->l.frame_rate.num && !li->l.frame_rate.den) |
| 405 | 23774 | li->l.frame_rate = li_in->l.frame_rate; | |
| 406 |
2/2✓ Branch 0 taken 16378 times.
✓ Branch 1 taken 7615 times.
|
23993 | if (!link->w) |
| 407 | 16378 | link->w = inlink->w; | |
| 408 |
2/2✓ Branch 0 taken 16378 times.
✓ Branch 1 taken 7615 times.
|
23993 | if (!link->h) |
| 409 | 16378 | link->h = inlink->h; | |
| 410 |
2/4✓ Branch 0 taken 7006 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7006 times.
|
7006 | } else if (!link->w || !link->h) { |
| 411 | ✗ | av_log(link->src, AV_LOG_ERROR, | |
| 412 | "Video source filters must set their output link's " | ||
| 413 | "width and height\n"); | ||
| 414 | ✗ | return AVERROR(EINVAL); | |
| 415 | } | ||
| 416 | 30999 | break; | |
| 417 | |||
| 418 | 6091 | case AVMEDIA_TYPE_AUDIO: | |
| 419 |
2/2✓ Branch 0 taken 4674 times.
✓ Branch 1 taken 1417 times.
|
6091 | if (inlink) { |
| 420 |
3/4✓ Branch 0 taken 3151 times.
✓ Branch 1 taken 1523 times.
✓ Branch 2 taken 3151 times.
✗ Branch 3 not taken.
|
4674 | if (!link->time_base.num && !link->time_base.den) |
| 421 | 3151 | link->time_base = inlink->time_base; | |
| 422 | } | ||
| 423 | |||
| 424 |
3/4✓ Branch 0 taken 84 times.
✓ Branch 1 taken 6007 times.
✓ Branch 2 taken 84 times.
✗ Branch 3 not taken.
|
6091 | if (!link->time_base.num && !link->time_base.den) |
| 425 | 84 | link->time_base = (AVRational) {1, link->sample_rate}; | |
| 426 | } | ||
| 427 | |||
| 428 |
2/2✓ Branch 0 taken 28667 times.
✓ Branch 1 taken 8423 times.
|
37090 | if (link->src->nb_inputs && |
| 429 |
1/2✓ Branch 1 taken 28667 times.
✗ Branch 2 not taken.
|
28667 | !(fffilter(link->src->filter)->flags_internal & FF_FILTER_FLAG_HWFRAME_AWARE)) { |
| 430 | 28667 | FilterLink *l0 = ff_filter_link(link->src->inputs[0]); | |
| 431 | |||
| 432 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 28667 times.
|
28667 | av_assert0(!li->l.hw_frames_ctx && |
| 433 | "should not be set by non-hwframe-aware filter"); | ||
| 434 | |||
| 435 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 28667 times.
|
28667 | if (l0->hw_frames_ctx) { |
| 436 | ✗ | li->l.hw_frames_ctx = av_buffer_ref(l0->hw_frames_ctx); | |
| 437 | ✗ | if (!li->l.hw_frames_ctx) | |
| 438 | ✗ | return AVERROR(ENOMEM); | |
| 439 | } | ||
| 440 | } | ||
| 441 | |||
| 442 |
2/2✓ Branch 0 taken 4962 times.
✓ Branch 1 taken 32128 times.
|
37090 | if ((config_link = link->dstpad->config_props)) |
| 443 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4962 times.
|
4962 | if ((ret = config_link(link)) < 0) { |
| 444 | ✗ | av_log(link->dst, AV_LOG_ERROR, | |
| 445 | "Failed to configure input pad on %s\n", | ||
| 446 | ✗ | link->dst->name); | |
| 447 | ✗ | return ret; | |
| 448 | } | ||
| 449 | |||
| 450 | 37090 | li->init_state = AVLINK_INIT; | |
| 451 | } | ||
| 452 | } | ||
| 453 | |||
| 454 | 45458 | return 0; | |
| 455 | } | ||
| 456 | |||
| 457 | #ifdef TRACE | ||
| 458 | void ff_tlog_link(void *ctx, AVFilterLink *link, int end) | ||
| 459 | { | ||
| 460 | if (link->type == AVMEDIA_TYPE_VIDEO) { | ||
| 461 | ff_tlog(ctx, | ||
| 462 | "link[%p s:%dx%d fmt:%s %s->%s]%s", | ||
| 463 | link, link->w, link->h, | ||
| 464 | av_get_pix_fmt_name(link->format), | ||
| 465 | link->src ? link->src->filter->name : "", | ||
| 466 | link->dst ? link->dst->filter->name : "", | ||
| 467 | end ? "\n" : ""); | ||
| 468 | } else { | ||
| 469 | char buf[128]; | ||
| 470 | av_channel_layout_describe(&link->ch_layout, buf, sizeof(buf)); | ||
| 471 | |||
| 472 | ff_tlog(ctx, | ||
| 473 | "link[%p r:%d cl:%s fmt:%s %s->%s]%s", | ||
| 474 | link, (int)link->sample_rate, buf, | ||
| 475 | av_get_sample_fmt_name(link->format), | ||
| 476 | link->src ? link->src->filter->name : "", | ||
| 477 | link->dst ? link->dst->filter->name : "", | ||
| 478 | end ? "\n" : ""); | ||
| 479 | } | ||
| 480 | } | ||
| 481 | #endif | ||
| 482 | |||
| 483 | 805682 | int ff_request_frame(AVFilterLink *link) | |
| 484 | { | ||
| 485 | 805682 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 486 | |||
| 487 | FF_TPRINTF_START(NULL, request_frame); ff_tlog_link(NULL, link, 1); | ||
| 488 | |||
| 489 | av_assert1(!fffilter(link->dst->filter)->activate); | ||
| 490 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 805673 times.
|
805682 | if (li->status_out) |
| 491 | 9 | return li->status_out; | |
| 492 |
2/2✓ Branch 0 taken 6088 times.
✓ Branch 1 taken 799585 times.
|
805673 | if (li->status_in) { |
| 493 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6088 times.
|
6088 | if (ff_framequeue_queued_frames(&li->fifo)) { |
| 494 | av_assert1(!li->frame_wanted_out); | ||
| 495 | av_assert1(fffilterctx(link->dst)->ready >= 300); | ||
| 496 | ✗ | return 0; | |
| 497 | } else { | ||
| 498 | /* Acknowledge status change. Filters using ff_request_frame() will | ||
| 499 | handle the change automatically. Filters can also check the | ||
| 500 | status directly but none do yet. */ | ||
| 501 | 6088 | link_set_out_status(link, li->status_in, li->status_in_pts); | |
| 502 | 6088 | return li->status_out; | |
| 503 | } | ||
| 504 | } | ||
| 505 | 799585 | li->frame_wanted_out = 1; | |
| 506 | 799585 | ff_filter_set_ready(link->src, 100); | |
| 507 | 799585 | return 0; | |
| 508 | } | ||
| 509 | |||
| 510 | 6081 | static int64_t guess_status_pts(AVFilterContext *ctx, int status, AVRational link_time_base) | |
| 511 | { | ||
| 512 | unsigned i; | ||
| 513 | 6081 | int64_t r = INT64_MAX; | |
| 514 | |||
| 515 |
2/2✓ Branch 0 taken 6080 times.
✓ Branch 1 taken 6081 times.
|
12161 | for (i = 0; i < ctx->nb_inputs; i++) { |
| 516 | 6080 | FilterLinkInternal * const li = ff_link_internal(ctx->inputs[i]); | |
| 517 |
1/2✓ Branch 0 taken 6080 times.
✗ Branch 1 not taken.
|
6080 | if (li->status_out == status) |
| 518 | 6080 | r = FFMIN(r, av_rescale_q(li->l.current_pts, ctx->inputs[i]->time_base, link_time_base)); | |
| 519 | } | ||
| 520 |
2/2✓ Branch 0 taken 6080 times.
✓ Branch 1 taken 1 times.
|
6081 | if (r < INT64_MAX) |
| 521 | 6080 | return r; | |
| 522 | 1 | av_log(ctx, AV_LOG_WARNING, "EOF timestamp not reliable\n"); | |
| 523 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | for (i = 0; i < ctx->nb_inputs; i++) { |
| 524 | ✗ | FilterLinkInternal * const li = ff_link_internal(ctx->inputs[i]); | |
| 525 | ✗ | r = FFMIN(r, av_rescale_q(li->status_in_pts, ctx->inputs[i]->time_base, link_time_base)); | |
| 526 | } | ||
| 527 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (r < INT64_MAX) |
| 528 | ✗ | return r; | |
| 529 | 1 | return AV_NOPTS_VALUE; | |
| 530 | } | ||
| 531 | |||
| 532 | 805991 | static int request_frame_to_filter(AVFilterLink *link) | |
| 533 | { | ||
| 534 | 805991 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 535 | 805991 | int ret = -1; | |
| 536 | |||
| 537 | FF_TPRINTF_START(NULL, request_frame_to_filter); ff_tlog_link(NULL, link, 1); | ||
| 538 | /* Assume the filter is blocked, let the method clear it if not */ | ||
| 539 | 805991 | li->frame_blocked_in = 1; | |
| 540 |
2/2✓ Branch 0 taken 2014 times.
✓ Branch 1 taken 803977 times.
|
805991 | if (link->srcpad->request_frame) |
| 541 | 2014 | ret = link->srcpad->request_frame(link); | |
| 542 |
1/2✓ Branch 0 taken 803977 times.
✗ Branch 1 not taken.
|
803977 | else if (link->src->inputs[0]) |
| 543 | 803977 | ret = ff_request_frame(link->src->inputs[0]); | |
| 544 |
2/2✓ Branch 0 taken 6081 times.
✓ Branch 1 taken 799910 times.
|
805991 | if (ret < 0) { |
| 545 |
2/4✓ Branch 0 taken 6081 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6081 times.
✗ Branch 3 not taken.
|
6081 | if (ret != AVERROR(EAGAIN) && ret != li->status_in) |
| 546 | 6081 | ff_avfilter_link_set_in_status(link, ret, guess_status_pts(link->src, ret, link->time_base)); | |
| 547 |
1/2✓ Branch 0 taken 6081 times.
✗ Branch 1 not taken.
|
6081 | if (ret == AVERROR_EOF) |
| 548 | 6081 | ret = 0; | |
| 549 | } | ||
| 550 | 805991 | return ret; | |
| 551 | } | ||
| 552 | |||
| 553 | static const char *const var_names[] = { | ||
| 554 | "t", | ||
| 555 | "n", | ||
| 556 | "w", | ||
| 557 | "h", | ||
| 558 | NULL | ||
| 559 | }; | ||
| 560 | |||
| 561 | enum { | ||
| 562 | VAR_T, | ||
| 563 | VAR_N, | ||
| 564 | VAR_W, | ||
| 565 | VAR_H, | ||
| 566 | VAR_VARS_NB | ||
| 567 | }; | ||
| 568 | |||
| 569 | 6 | static int set_enable_expr(FFFilterContext *ctxi, const char *expr) | |
| 570 | { | ||
| 571 | 6 | AVFilterContext *ctx = &ctxi->p; | |
| 572 | int ret; | ||
| 573 | char *expr_dup; | ||
| 574 | 6 | AVExpr *old = ctxi->enable; | |
| 575 | |||
| 576 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (!(ctx->filter->flags & AVFILTER_FLAG_SUPPORT_TIMELINE)) { |
| 577 | ✗ | av_log(ctx, AV_LOG_ERROR, "Timeline ('enable' option) not supported " | |
| 578 | ✗ | "with filter '%s'\n", ctx->filter->name); | |
| 579 | ✗ | return AVERROR_PATCHWELCOME; | |
| 580 | } | ||
| 581 | |||
| 582 | 6 | expr_dup = av_strdup(expr); | |
| 583 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (!expr_dup) |
| 584 | ✗ | return AVERROR(ENOMEM); | |
| 585 | |||
| 586 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | if (!ctxi->var_values) { |
| 587 | 6 | ctxi->var_values = av_calloc(VAR_VARS_NB, sizeof(*ctxi->var_values)); | |
| 588 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (!ctxi->var_values) { |
| 589 | ✗ | av_free(expr_dup); | |
| 590 | ✗ | return AVERROR(ENOMEM); | |
| 591 | } | ||
| 592 | } | ||
| 593 | |||
| 594 | 6 | ret = av_expr_parse(&ctxi->enable, expr_dup, var_names, | |
| 595 | NULL, NULL, NULL, NULL, 0, ctx->priv); | ||
| 596 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (ret < 0) { |
| 597 | ✗ | av_log(ctx->priv, AV_LOG_ERROR, | |
| 598 | "Error when evaluating the expression '%s' for enable\n", | ||
| 599 | expr_dup); | ||
| 600 | ✗ | av_free(expr_dup); | |
| 601 | ✗ | return ret; | |
| 602 | } | ||
| 603 | |||
| 604 | 6 | av_expr_free(old); | |
| 605 | 6 | av_free(ctx->enable_str); | |
| 606 | 6 | ctx->enable_str = expr_dup; | |
| 607 | 6 | return 0; | |
| 608 | } | ||
| 609 | |||
| 610 | ✗ | int avfilter_process_command(AVFilterContext *filter, const char *cmd, const char *arg, char *res, int res_len, int flags) | |
| 611 | { | ||
| 612 | ✗ | if(!strcmp(cmd, "ping")){ | |
| 613 | ✗ | char local_res[256] = {0}; | |
| 614 | |||
| 615 | ✗ | if (!res) { | |
| 616 | ✗ | res = local_res; | |
| 617 | ✗ | res_len = sizeof(local_res); | |
| 618 | } | ||
| 619 | ✗ | av_strlcatf(res, res_len, "pong from:%s %s\n", filter->filter->name, filter->name); | |
| 620 | ✗ | if (res == local_res) | |
| 621 | ✗ | av_log(filter, AV_LOG_INFO, "%s", res); | |
| 622 | ✗ | return 0; | |
| 623 | ✗ | }else if(!strcmp(cmd, "enable")) { | |
| 624 | ✗ | return set_enable_expr(fffilterctx(filter), arg); | |
| 625 | ✗ | }else if (fffilter(filter->filter)->process_command) { | |
| 626 | ✗ | return fffilter(filter->filter)->process_command(filter, cmd, arg, res, res_len, flags); | |
| 627 | } | ||
| 628 | ✗ | return AVERROR(ENOSYS); | |
| 629 | } | ||
| 630 | |||
| 631 | ✗ | unsigned avfilter_filter_pad_count(const AVFilter *filter, int is_output) | |
| 632 | { | ||
| 633 | ✗ | return is_output ? fffilter(filter)->nb_outputs : fffilter(filter)->nb_inputs; | |
| 634 | } | ||
| 635 | |||
| 636 | 594 | static const char *default_filter_name(void *filter_ctx) | |
| 637 | { | ||
| 638 | 594 | AVFilterContext *ctx = filter_ctx; | |
| 639 |
1/2✓ Branch 0 taken 594 times.
✗ Branch 1 not taken.
|
594 | return ctx->name ? ctx->name : ctx->filter->name; |
| 640 | } | ||
| 641 | |||
| 642 | 57144 | static void *filter_child_next(void *obj, void *prev) | |
| 643 | { | ||
| 644 | 57144 | AVFilterContext *ctx = obj; | |
| 645 |
5/8✓ Branch 0 taken 57138 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 57138 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 57138 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 57138 times.
✗ Branch 7 not taken.
|
57144 | if (!prev && ctx->filter && ctx->filter->priv_class && ctx->priv) |
| 646 | 57138 | return ctx->priv; | |
| 647 | 6 | return NULL; | |
| 648 | } | ||
| 649 | |||
| 650 | ✗ | static const AVClass *filter_child_class_iterate(void **iter) | |
| 651 | { | ||
| 652 | const AVFilter *f; | ||
| 653 | |||
| 654 | ✗ | while ((f = av_filter_iterate(iter))) | |
| 655 | ✗ | if (f->priv_class) | |
| 656 | ✗ | return f->priv_class; | |
| 657 | |||
| 658 | ✗ | return NULL; | |
| 659 | } | ||
| 660 | |||
| 661 | #define OFFSET(x) offsetof(AVFilterContext, x) | ||
| 662 | #define FLAGS AV_OPT_FLAG_FILTERING_PARAM | ||
| 663 | #define TFLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM | ||
| 664 | static const AVOption avfilter_options[] = { | ||
| 665 | { "thread_type", "Allowed thread types", OFFSET(thread_type), AV_OPT_TYPE_FLAGS, | ||
| 666 | { .i64 = AVFILTER_THREAD_SLICE }, 0, INT_MAX, FLAGS, .unit = "thread_type" }, | ||
| 667 | { "slice", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AVFILTER_THREAD_SLICE }, .flags = FLAGS, .unit = "thread_type" }, | ||
| 668 | { "enable", "set enable expression", OFFSET(enable_str), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = TFLAGS }, | ||
| 669 | { "threads", "Allowed number of threads", OFFSET(nb_threads), AV_OPT_TYPE_INT, | ||
| 670 | { .i64 = 0 }, 0, INT_MAX, FLAGS, .unit = "threads" }, | ||
| 671 | {"auto", "autodetect a suitable number of threads to use", 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, .flags = FLAGS, .unit = "threads"}, | ||
| 672 | { "extra_hw_frames", "Number of extra hardware frames to allocate for the user", | ||
| 673 | OFFSET(extra_hw_frames), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, FLAGS }, | ||
| 674 | { NULL }, | ||
| 675 | }; | ||
| 676 | |||
| 677 | static const AVClass avfilter_class = { | ||
| 678 | .class_name = "AVFilter", | ||
| 679 | .item_name = default_filter_name, | ||
| 680 | .version = LIBAVUTIL_VERSION_INT, | ||
| 681 | .category = AV_CLASS_CATEGORY_FILTER, | ||
| 682 | .child_next = filter_child_next, | ||
| 683 | .child_class_iterate = filter_child_class_iterate, | ||
| 684 | .option = avfilter_options, | ||
| 685 | .state_flags_offset = offsetof(FFFilterContext, state_flags), | ||
| 686 | }; | ||
| 687 | |||
| 688 | 1277 | static int default_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, | |
| 689 | int *ret, int nb_jobs) | ||
| 690 | { | ||
| 691 | int i; | ||
| 692 | |||
| 693 |
2/2✓ Branch 0 taken 1277 times.
✓ Branch 1 taken 1277 times.
|
2554 | for (i = 0; i < nb_jobs; i++) { |
| 694 | 1277 | int r = func(ctx, arg, i, nb_jobs); | |
| 695 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1277 times.
|
1277 | if (ret) |
| 696 | ✗ | ret[i] = r; | |
| 697 | } | ||
| 698 | 1277 | return 0; | |
| 699 | } | ||
| 700 | |||
| 701 | 63941 | AVFilterContext *ff_filter_alloc(const AVFilter *filter, const char *inst_name) | |
| 702 | { | ||
| 703 | FFFilterContext *ctx; | ||
| 704 | AVFilterContext *ret; | ||
| 705 | 63941 | const FFFilter *const fi = fffilter(filter); | |
| 706 | 63941 | int preinited = 0; | |
| 707 | |||
| 708 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 63941 times.
|
63941 | if (!filter) |
| 709 | ✗ | return NULL; | |
| 710 | |||
| 711 | 63941 | ctx = av_mallocz(sizeof(*ctx)); | |
| 712 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 63941 times.
|
63941 | if (!ctx) |
| 713 | ✗ | return NULL; | |
| 714 | 63941 | ret = &ctx->p; | |
| 715 | |||
| 716 | 63941 | ret->av_class = &avfilter_class; | |
| 717 | 63941 | ret->filter = filter; | |
| 718 |
1/2✓ Branch 0 taken 63941 times.
✗ Branch 1 not taken.
|
63941 | ret->name = inst_name ? av_strdup(inst_name) : NULL; |
| 719 |
2/2✓ Branch 0 taken 57070 times.
✓ Branch 1 taken 6871 times.
|
63941 | if (fi->priv_size) { |
| 720 | 57070 | ret->priv = av_mallocz(fi->priv_size); | |
| 721 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 57070 times.
|
57070 | if (!ret->priv) |
| 722 | ✗ | goto err; | |
| 723 | } | ||
| 724 |
2/2✓ Branch 0 taken 13680 times.
✓ Branch 1 taken 50261 times.
|
63941 | if (fi->preinit) { |
| 725 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 13680 times.
|
13680 | if (fi->preinit(ret) < 0) |
| 726 | ✗ | goto err; | |
| 727 | 13680 | preinited = 1; | |
| 728 | } | ||
| 729 | |||
| 730 | 63941 | av_opt_set_defaults(ret); | |
| 731 |
2/2✓ Branch 0 taken 55811 times.
✓ Branch 1 taken 8130 times.
|
63941 | if (filter->priv_class) { |
| 732 | 55811 | *(const AVClass**)ret->priv = filter->priv_class; | |
| 733 | 55811 | av_opt_set_defaults(ret->priv); | |
| 734 | } | ||
| 735 | |||
| 736 | 63941 | ctx->execute = default_execute; | |
| 737 | |||
| 738 | 63941 | ret->nb_inputs = fi->nb_inputs; | |
| 739 |
2/2✓ Branch 0 taken 54176 times.
✓ Branch 1 taken 9765 times.
|
63941 | if (ret->nb_inputs ) { |
| 740 | 54176 | ret->input_pads = av_memdup(filter->inputs, ret->nb_inputs * sizeof(*filter->inputs)); | |
| 741 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54176 times.
|
54176 | if (!ret->input_pads) |
| 742 | ✗ | goto err; | |
| 743 | 54176 | ret->inputs = av_calloc(ret->nb_inputs, sizeof(*ret->inputs)); | |
| 744 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54176 times.
|
54176 | if (!ret->inputs) |
| 745 | ✗ | goto err; | |
| 746 | } | ||
| 747 | |||
| 748 | 63941 | ret->nb_outputs = fi->nb_outputs; | |
| 749 |
2/2✓ Branch 0 taken 55480 times.
✓ Branch 1 taken 8461 times.
|
63941 | if (ret->nb_outputs) { |
| 750 | 55480 | ret->output_pads = av_memdup(filter->outputs, ret->nb_outputs * sizeof(*filter->outputs)); | |
| 751 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 55480 times.
|
55480 | if (!ret->output_pads) |
| 752 | ✗ | goto err; | |
| 753 | 55480 | ret->outputs = av_calloc(ret->nb_outputs, sizeof(*ret->outputs)); | |
| 754 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 55480 times.
|
55480 | if (!ret->outputs) |
| 755 | ✗ | goto err; | |
| 756 | } | ||
| 757 | |||
| 758 | 63941 | return ret; | |
| 759 | |||
| 760 | ✗ | err: | |
| 761 | ✗ | if (preinited) | |
| 762 | ✗ | fi->uninit(ret); | |
| 763 | ✗ | av_freep(&ret->name); | |
| 764 | ✗ | av_freep(&ret->inputs); | |
| 765 | ✗ | av_freep(&ret->input_pads); | |
| 766 | ✗ | ret->nb_inputs = 0; | |
| 767 | ✗ | av_freep(&ret->outputs); | |
| 768 | ✗ | av_freep(&ret->output_pads); | |
| 769 | ✗ | ret->nb_outputs = 0; | |
| 770 | ✗ | av_freep(&ret->priv); | |
| 771 | ✗ | av_free(ret); | |
| 772 | ✗ | return NULL; | |
| 773 | } | ||
| 774 | |||
| 775 | 110326 | static void free_link(AVFilterLink *link) | |
| 776 | { | ||
| 777 |
2/2✓ Branch 0 taken 62752 times.
✓ Branch 1 taken 47574 times.
|
110326 | if (!link) |
| 778 | 62752 | return; | |
| 779 | |||
| 780 |
2/2✓ Branch 0 taken 47442 times.
✓ Branch 1 taken 132 times.
|
47574 | if (link->src) |
| 781 | 47442 | link->src->outputs[link->srcpad - link->src->output_pads] = NULL; | |
| 782 |
2/2✓ Branch 0 taken 47442 times.
✓ Branch 1 taken 132 times.
|
47574 | if (link->dst) |
| 783 | 47442 | link->dst->inputs[link->dstpad - link->dst->input_pads] = NULL; | |
| 784 | |||
| 785 | 47574 | ff_formats_unref(&link->incfg.formats); | |
| 786 | 47574 | ff_formats_unref(&link->outcfg.formats); | |
| 787 | 47574 | ff_formats_unref(&link->incfg.color_spaces); | |
| 788 | 47574 | ff_formats_unref(&link->outcfg.color_spaces); | |
| 789 | 47574 | ff_formats_unref(&link->incfg.color_ranges); | |
| 790 | 47574 | ff_formats_unref(&link->outcfg.color_ranges); | |
| 791 | 47574 | ff_formats_unref(&link->incfg.alpha_modes); | |
| 792 | 47574 | ff_formats_unref(&link->outcfg.alpha_modes); | |
| 793 | 47574 | ff_formats_unref(&link->incfg.samplerates); | |
| 794 | 47574 | ff_formats_unref(&link->outcfg.samplerates); | |
| 795 | 47574 | ff_channel_layouts_unref(&link->incfg.channel_layouts); | |
| 796 | 47574 | ff_channel_layouts_unref(&link->outcfg.channel_layouts); | |
| 797 | 47574 | link_free(&link); | |
| 798 | } | ||
| 799 | |||
| 800 | 63941 | void avfilter_free(AVFilterContext *filter) | |
| 801 | { | ||
| 802 | FFFilterContext *ctxi; | ||
| 803 | int i; | ||
| 804 | |||
| 805 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 63941 times.
|
63941 | if (!filter) |
| 806 | ✗ | return; | |
| 807 | 63941 | ctxi = fffilterctx(filter); | |
| 808 | |||
| 809 |
1/2✓ Branch 0 taken 63941 times.
✗ Branch 1 not taken.
|
63941 | if (filter->graph) |
| 810 | 63941 | ff_filter_graph_remove_filter(filter->graph, filter); | |
| 811 | |||
| 812 |
2/2✓ Branch 1 taken 49715 times.
✓ Branch 2 taken 14226 times.
|
63941 | if (fffilter(filter->filter)->uninit) |
| 813 | 49715 | fffilter(filter->filter)->uninit(filter); | |
| 814 | |||
| 815 |
2/2✓ Branch 0 taken 54555 times.
✓ Branch 1 taken 63941 times.
|
118496 | for (i = 0; i < filter->nb_inputs; i++) { |
| 816 | 54555 | free_link(filter->inputs[i]); | |
| 817 |
2/2✓ Branch 0 taken 264 times.
✓ Branch 1 taken 54291 times.
|
54555 | if (filter->input_pads[i].flags & AVFILTERPAD_FLAG_FREE_NAME) |
| 818 | 264 | av_freep(&filter->input_pads[i].name); | |
| 819 | } | ||
| 820 |
2/2✓ Branch 0 taken 55771 times.
✓ Branch 1 taken 63941 times.
|
119712 | for (i = 0; i < filter->nb_outputs; i++) { |
| 821 | 55771 | free_link(filter->outputs[i]); | |
| 822 |
2/2✓ Branch 0 taken 282 times.
✓ Branch 1 taken 55489 times.
|
55771 | if (filter->output_pads[i].flags & AVFILTERPAD_FLAG_FREE_NAME) |
| 823 | 282 | av_freep(&filter->output_pads[i].name); | |
| 824 | } | ||
| 825 | |||
| 826 |
2/2✓ Branch 0 taken 55811 times.
✓ Branch 1 taken 8130 times.
|
63941 | if (filter->filter->priv_class) |
| 827 | 55811 | av_opt_free(filter->priv); | |
| 828 | |||
| 829 | 63941 | av_buffer_unref(&filter->hw_device_ctx); | |
| 830 | |||
| 831 | 63941 | av_freep(&filter->name); | |
| 832 | 63941 | av_freep(&filter->input_pads); | |
| 833 | 63941 | av_freep(&filter->output_pads); | |
| 834 | 63941 | av_freep(&filter->inputs); | |
| 835 | 63941 | av_freep(&filter->outputs); | |
| 836 | 63941 | av_freep(&filter->priv); | |
| 837 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 63941 times.
|
63941 | while (ctxi->command_queue) |
| 838 | ✗ | command_queue_pop(filter); | |
| 839 | 63941 | av_opt_free(filter); | |
| 840 | 63941 | av_expr_free(ctxi->enable); | |
| 841 | 63941 | ctxi->enable = NULL; | |
| 842 | 63941 | av_freep(&ctxi->var_values); | |
| 843 | 63941 | av_free(filter); | |
| 844 | } | ||
| 845 | |||
| 846 | 19289 | int ff_filter_get_nb_threads(AVFilterContext *ctx) | |
| 847 | { | ||
| 848 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19289 times.
|
19289 | if (ctx->nb_threads > 0) |
| 849 | ✗ | return FFMIN(ctx->nb_threads, ctx->graph->nb_threads); | |
| 850 | 19289 | return ctx->graph->nb_threads; | |
| 851 | } | ||
| 852 | |||
| 853 | 34218 | int ff_filter_opt_parse(void *logctx, const AVClass *priv_class, | |
| 854 | AVDictionary **options, const char *args) | ||
| 855 | { | ||
| 856 | 34218 | const AVOption *o = NULL; | |
| 857 | int ret; | ||
| 858 | 34218 | int offset= -1; | |
| 859 | |||
| 860 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34218 times.
|
34218 | if (!args) |
| 861 | ✗ | return 0; | |
| 862 | |||
| 863 |
2/2✓ Branch 0 taken 58927 times.
✓ Branch 1 taken 34218 times.
|
93145 | while (*args) { |
| 864 | char *parsed_key, *value; | ||
| 865 | const char *key; | ||
| 866 | 58927 | const char *shorthand = NULL; | |
| 867 | 58927 | int additional_flags = 0; | |
| 868 | |||
| 869 |
4/4✓ Branch 0 taken 45776 times.
✓ Branch 1 taken 13151 times.
✓ Branch 3 taken 44494 times.
✓ Branch 4 taken 1282 times.
|
58927 | if (priv_class && (o = av_opt_next(&priv_class, o))) { |
| 870 |
4/4✓ Branch 0 taken 42724 times.
✓ Branch 1 taken 1770 times.
✓ Branch 2 taken 4564 times.
✓ Branch 3 taken 38160 times.
|
44494 | if (o->type == AV_OPT_TYPE_CONST || o->offset == offset) |
| 871 | 6334 | continue; | |
| 872 | 38160 | offset = o->offset; | |
| 873 | 38160 | shorthand = o->name; | |
| 874 | } | ||
| 875 | |||
| 876 | 52593 | ret = av_opt_get_key_value(&args, "=", ":", | |
| 877 | shorthand ? AV_OPT_FLAG_IMPLICIT_KEY : 0, | ||
| 878 | &parsed_key, &value); | ||
| 879 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 52593 times.
|
52593 | if (ret < 0) { |
| 880 | ✗ | if (ret == AVERROR(EINVAL)) | |
| 881 | ✗ | av_log(logctx, AV_LOG_ERROR, "No option name near '%s'\n", args); | |
| 882 | else | ||
| 883 | ✗ | av_log(logctx, AV_LOG_ERROR, "Unable to parse '%s': %s\n", args, | |
| 884 | ✗ | av_err2str(ret)); | |
| 885 | ✗ | return ret; | |
| 886 | } | ||
| 887 |
2/2✓ Branch 0 taken 27345 times.
✓ Branch 1 taken 25248 times.
|
52593 | if (*args) |
| 888 | 27345 | args++; | |
| 889 |
2/2✓ Branch 0 taken 31588 times.
✓ Branch 1 taken 21005 times.
|
52593 | if (parsed_key) { |
| 890 | 31588 | key = parsed_key; | |
| 891 | 31588 | additional_flags = AV_DICT_DONT_STRDUP_KEY; | |
| 892 | 31588 | priv_class = NULL; /* reject all remaining shorthand */ | |
| 893 | } else { | ||
| 894 | 21005 | key = shorthand; | |
| 895 | } | ||
| 896 | |||
| 897 | 52593 | av_log(logctx, AV_LOG_DEBUG, "Setting '%s' to value '%s'\n", key, value); | |
| 898 | |||
| 899 | 52593 | av_dict_set(options, key, value, | |
| 900 | additional_flags | AV_DICT_DONT_STRDUP_VAL | AV_DICT_MULTIKEY); | ||
| 901 | } | ||
| 902 | |||
| 903 | 34218 | return 0; | |
| 904 | } | ||
| 905 | |||
| 906 | ✗ | int ff_filter_process_command(AVFilterContext *ctx, const char *cmd, | |
| 907 | const char *arg, char *res, int res_len, int flags) | ||
| 908 | { | ||
| 909 | const AVOption *o; | ||
| 910 | |||
| 911 | ✗ | if (!ctx->filter->priv_class) | |
| 912 | ✗ | return 0; | |
| 913 | ✗ | o = av_opt_find2(ctx->priv, cmd, NULL, AV_OPT_FLAG_RUNTIME_PARAM | AV_OPT_FLAG_FILTERING_PARAM, AV_OPT_SEARCH_CHILDREN, NULL); | |
| 914 | ✗ | if (!o) | |
| 915 | ✗ | return AVERROR(ENOSYS); | |
| 916 | ✗ | return av_opt_set(ctx->priv, cmd, arg, 0); | |
| 917 | } | ||
| 918 | |||
| 919 | 63941 | int avfilter_init_dict(AVFilterContext *ctx, AVDictionary **options) | |
| 920 | { | ||
| 921 | 63941 | FFFilterContext *ctxi = fffilterctx(ctx); | |
| 922 | 63941 | int ret = 0; | |
| 923 | |||
| 924 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 63941 times.
|
63941 | if (ctxi->state_flags & AV_CLASS_STATE_INITIALIZED) { |
| 925 | ✗ | av_log(ctx, AV_LOG_ERROR, "Filter already initialized\n"); | |
| 926 | ✗ | return AVERROR(EINVAL); | |
| 927 | } | ||
| 928 | |||
| 929 | 63941 | ret = av_opt_set_dict2(ctx, options, AV_OPT_SEARCH_CHILDREN); | |
| 930 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 63941 times.
|
63941 | if (ret < 0) { |
| 931 | ✗ | av_log(ctx, AV_LOG_ERROR, "Error applying generic filter options.\n"); | |
| 932 | ✗ | return ret; | |
| 933 | } | ||
| 934 | |||
| 935 |
2/2✓ Branch 0 taken 1244 times.
✓ Branch 1 taken 62697 times.
|
63941 | if (ctx->filter->flags & AVFILTER_FLAG_SLICE_THREADS && |
| 936 |
2/2✓ Branch 0 taken 153 times.
✓ Branch 1 taken 1091 times.
|
1244 | ctx->thread_type & ctx->graph->thread_type & AVFILTER_THREAD_SLICE && |
| 937 |
1/2✓ Branch 1 taken 153 times.
✗ Branch 2 not taken.
|
153 | fffiltergraph(ctx->graph)->thread_execute) { |
| 938 | 153 | ctx->thread_type = AVFILTER_THREAD_SLICE; | |
| 939 | 153 | ctxi->execute = fffiltergraph(ctx->graph)->thread_execute; | |
| 940 | } else { | ||
| 941 | 63788 | ctx->thread_type = 0; | |
| 942 | } | ||
| 943 | |||
| 944 |
2/2✓ Branch 1 taken 50542 times.
✓ Branch 2 taken 13399 times.
|
63941 | if (fffilter(ctx->filter)->init) |
| 945 | 50542 | ret = fffilter(ctx->filter)->init(ctx); | |
| 946 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 63941 times.
|
63941 | if (ret < 0) |
| 947 | ✗ | return ret; | |
| 948 | |||
| 949 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 63935 times.
|
63941 | if (ctx->enable_str) { |
| 950 | 6 | ret = set_enable_expr(ctxi, ctx->enable_str); | |
| 951 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (ret < 0) |
| 952 | ✗ | return ret; | |
| 953 | } | ||
| 954 | |||
| 955 | 63941 | ctxi->state_flags |= AV_CLASS_STATE_INITIALIZED; | |
| 956 | |||
| 957 | 63941 | return 0; | |
| 958 | } | ||
| 959 | |||
| 960 | 20943 | int avfilter_init_str(AVFilterContext *filter, const char *args) | |
| 961 | { | ||
| 962 | 20943 | AVDictionary *options = NULL; | |
| 963 | const AVDictionaryEntry *e; | ||
| 964 | 20943 | int ret = 0; | |
| 965 | |||
| 966 |
3/4✓ Branch 0 taken 10457 times.
✓ Branch 1 taken 10486 times.
✓ Branch 2 taken 10457 times.
✗ Branch 3 not taken.
|
20943 | if (args && *args) { |
| 967 | 10457 | ret = ff_filter_opt_parse(filter, filter->filter->priv_class, &options, args); | |
| 968 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10457 times.
|
10457 | if (ret < 0) |
| 969 | ✗ | goto fail; | |
| 970 | } | ||
| 971 | |||
| 972 | 20943 | ret = avfilter_init_dict(filter, &options); | |
| 973 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 20943 times.
|
20943 | if (ret < 0) |
| 974 | ✗ | goto fail; | |
| 975 | |||
| 976 |
1/2✓ Branch 1 taken 20943 times.
✗ Branch 2 not taken.
|
20943 | if ((e = av_dict_iterate(options, NULL))) { |
| 977 | ✗ | av_log(filter, AV_LOG_ERROR, "No such option: %s.\n", e->key); | |
| 978 | ✗ | ret = AVERROR_OPTION_NOT_FOUND; | |
| 979 | ✗ | goto fail; | |
| 980 | } | ||
| 981 | |||
| 982 | 20943 | fail: | |
| 983 | 20943 | av_dict_free(&options); | |
| 984 | |||
| 985 | 20943 | return ret; | |
| 986 | } | ||
| 987 | |||
| 988 | 15274 | const char *avfilter_pad_get_name(const AVFilterPad *pads, int pad_idx) | |
| 989 | { | ||
| 990 | 15274 | return pads[pad_idx].name; | |
| 991 | } | ||
| 992 | |||
| 993 | 30896 | enum AVMediaType avfilter_pad_get_type(const AVFilterPad *pads, int pad_idx) | |
| 994 | { | ||
| 995 | 30896 | return pads[pad_idx].type; | |
| 996 | } | ||
| 997 | |||
| 998 | ✗ | AVBufferRef *avfilter_link_get_hw_frames_ctx(AVFilterLink *link) | |
| 999 | { | ||
| 1000 | ✗ | FilterLink *plink = ff_filter_link(link); | |
| 1001 | ✗ | if (plink->hw_frames_ctx) | |
| 1002 | ✗ | return av_buffer_ref(plink->hw_frames_ctx); | |
| 1003 | |||
| 1004 | ✗ | return NULL; | |
| 1005 | } | ||
| 1006 | |||
| 1007 | 785047 | static int default_filter_frame(AVFilterLink *link, AVFrame *frame) | |
| 1008 | { | ||
| 1009 | 785047 | return ff_filter_frame(link->dst->outputs[0], frame); | |
| 1010 | } | ||
| 1011 | |||
| 1012 | /** | ||
| 1013 | * Evaluate the timeline expression of the link for the time and properties | ||
| 1014 | * of the frame. | ||
| 1015 | * @return >0 if enabled, 0 if disabled | ||
| 1016 | * @note It does not update link->dst->is_disabled. | ||
| 1017 | */ | ||
| 1018 | 2491036 | static int evaluate_timeline_at_frame(AVFilterLink *link, const AVFrame *frame) | |
| 1019 | { | ||
| 1020 | 2491036 | FilterLink *l = ff_filter_link(link); | |
| 1021 | 2491036 | AVFilterContext *dstctx = link->dst; | |
| 1022 | 2491036 | FFFilterContext *dsti = fffilterctx(dstctx); | |
| 1023 | 2491036 | int64_t pts = frame->pts; | |
| 1024 | |||
| 1025 |
2/2✓ Branch 0 taken 2490838 times.
✓ Branch 1 taken 198 times.
|
2491036 | if (!dstctx->enable_str) |
| 1026 | 2490838 | return 1; | |
| 1027 | |||
| 1028 | 198 | dsti->var_values[VAR_N] = l->frame_count_out; | |
| 1029 |
1/2✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
|
198 | dsti->var_values[VAR_T] = pts == AV_NOPTS_VALUE ? NAN : pts * av_q2d(link->time_base); |
| 1030 | 198 | dsti->var_values[VAR_W] = link->w; | |
| 1031 | 198 | dsti->var_values[VAR_H] = link->h; | |
| 1032 | |||
| 1033 | 198 | return fabs(av_expr_eval(dsti->enable, dsti->var_values, NULL)) >= 0.5; | |
| 1034 | } | ||
| 1035 | |||
| 1036 | 805511 | static int filter_frame_framed(AVFilterLink *link, AVFrame *frame) | |
| 1037 | { | ||
| 1038 | 805511 | FilterLink *l = ff_filter_link(link); | |
| 1039 | int (*filter_frame)(AVFilterLink *, AVFrame *); | ||
| 1040 | 805511 | AVFilterContext *dstctx = link->dst; | |
| 1041 | 805511 | AVFilterPad *dst = link->dstpad; | |
| 1042 | int ret; | ||
| 1043 | |||
| 1044 |
2/2✓ Branch 0 taken 785038 times.
✓ Branch 1 taken 20473 times.
|
805511 | if (!(filter_frame = dst->filter_frame)) |
| 1045 | 785038 | filter_frame = default_filter_frame; | |
| 1046 | |||
| 1047 |
2/2✓ Branch 0 taken 2993 times.
✓ Branch 1 taken 802518 times.
|
805511 | if (dst->flags & AVFILTERPAD_FLAG_NEEDS_WRITABLE) { |
| 1048 | 2993 | ret = ff_inlink_make_frame_writable(link, &frame); | |
| 1049 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2993 times.
|
2993 | if (ret < 0) |
| 1050 | ✗ | goto fail; | |
| 1051 | } | ||
| 1052 | |||
| 1053 | 805511 | ff_inlink_process_commands(link, frame); | |
| 1054 | 805511 | dstctx->is_disabled = !evaluate_timeline_at_frame(link, frame); | |
| 1055 | |||
| 1056 |
2/2✓ Branch 0 taken 19 times.
✓ Branch 1 taken 805492 times.
|
805511 | if (dstctx->is_disabled && |
| 1057 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 10 times.
|
19 | (dstctx->filter->flags & AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC)) |
| 1058 | 9 | filter_frame = default_filter_frame; | |
| 1059 | 805511 | ret = filter_frame(link, frame); | |
| 1060 | 805511 | l->frame_count_out++; | |
| 1061 | 805511 | return ret; | |
| 1062 | |||
| 1063 | ✗ | fail: | |
| 1064 | ✗ | av_frame_free(&frame); | |
| 1065 | ✗ | return ret; | |
| 1066 | } | ||
| 1067 | |||
| 1068 | 1690787 | int ff_filter_frame(AVFilterLink *link, AVFrame *frame) | |
| 1069 | { | ||
| 1070 | 1690787 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1071 | int ret; | ||
| 1072 | 1690787 | FF_TPRINTF_START(NULL, filter_frame); ff_tlog_link(NULL, link, 1); ff_tlog(NULL, " "); tlog_ref(NULL, frame, 1); | |
| 1073 | |||
| 1074 | /* Consistency checks */ | ||
| 1075 |
2/2✓ Branch 0 taken 585257 times.
✓ Branch 1 taken 1105530 times.
|
1690787 | if (link->type == AVMEDIA_TYPE_VIDEO) { |
| 1076 |
2/2✓ Branch 0 taken 435383 times.
✓ Branch 1 taken 149874 times.
|
585257 | if (strcmp(link->dst->filter->name, "buffersink") && |
| 1077 |
2/2✓ Branch 0 taken 259372 times.
✓ Branch 1 taken 176011 times.
|
435383 | strcmp(link->dst->filter->name, "format") && |
| 1078 |
2/2✓ Branch 0 taken 259345 times.
✓ Branch 1 taken 27 times.
|
259372 | strcmp(link->dst->filter->name, "idet") && |
| 1079 |
2/2✓ Branch 0 taken 167900 times.
✓ Branch 1 taken 91445 times.
|
259345 | strcmp(link->dst->filter->name, "null") && |
| 1080 |
2/2✓ Branch 0 taken 57464 times.
✓ Branch 1 taken 110436 times.
|
167900 | strcmp(link->dst->filter->name, "scale") && |
| 1081 |
1/2✓ Branch 0 taken 57464 times.
✗ Branch 1 not taken.
|
57464 | strcmp(link->dst->filter->name, "libplacebo")) { |
| 1082 | av_assert1(frame->format == link->format); | ||
| 1083 | av_assert1(frame->width == link->w); | ||
| 1084 | av_assert1(frame->height == link->h); | ||
| 1085 | 57464 | if (av_pix_fmt_desc_get(link->format)->flags & AV_PIX_FMT_FLAG_ALPHA) | |
| 1086 | av_assert1(frame->alpha_mode == link->alpha_mode); | ||
| 1087 | } | ||
| 1088 | } else { | ||
| 1089 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1105530 times.
|
1105530 | if (frame->format != link->format) { |
| 1090 | ✗ | av_log(link->dst, AV_LOG_ERROR, "Format change is not supported\n"); | |
| 1091 | ✗ | goto error; | |
| 1092 | } | ||
| 1093 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1105530 times.
|
1105530 | if (av_channel_layout_compare(&frame->ch_layout, &link->ch_layout)) { |
| 1094 | ✗ | av_log(link->dst, AV_LOG_ERROR, "Channel layout change is not supported\n"); | |
| 1095 | ✗ | goto error; | |
| 1096 | } | ||
| 1097 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1105530 times.
|
1105530 | if (frame->sample_rate != link->sample_rate) { |
| 1098 | ✗ | av_log(link->dst, AV_LOG_ERROR, "Sample rate change is not supported\n"); | |
| 1099 | ✗ | goto error; | |
| 1100 | } | ||
| 1101 | |||
| 1102 | 1105530 | frame->duration = av_rescale_q(frame->nb_samples, (AVRational){ 1, frame->sample_rate }, | |
| 1103 | link->time_base); | ||
| 1104 | } | ||
| 1105 | |||
| 1106 | 1690787 | li->frame_blocked_in = li->frame_wanted_out = 0; | |
| 1107 | 1690787 | li->l.frame_count_in++; | |
| 1108 | 1690787 | li->l.sample_count_in += frame->nb_samples; | |
| 1109 | 1690787 | filter_unblock(link->dst); | |
| 1110 | 1690787 | ret = ff_framequeue_add(&li->fifo, frame); | |
| 1111 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1690787 times.
|
1690787 | if (ret < 0) { |
| 1112 | ✗ | av_frame_free(&frame); | |
| 1113 | ✗ | return ret; | |
| 1114 | } | ||
| 1115 | 1690787 | ff_filter_set_ready(link->dst, 300); | |
| 1116 | 1690787 | return 0; | |
| 1117 | |||
| 1118 | ✗ | error: | |
| 1119 | ✗ | av_frame_free(&frame); | |
| 1120 | ✗ | return AVERROR_PATCHWELCOME; | |
| 1121 | } | ||
| 1122 | |||
| 1123 | 2411728 | static int samples_ready(FilterLinkInternal *link, unsigned min) | |
| 1124 | { | ||
| 1125 |
2/2✓ Branch 1 taken 805645 times.
✓ Branch 2 taken 1606083 times.
|
3217373 | return ff_framequeue_queued_frames(&link->fifo) && |
| 1126 |
2/2✓ Branch 1 taken 135 times.
✓ Branch 2 taken 805510 times.
|
805645 | (ff_framequeue_queued_samples(&link->fifo) >= min || |
| 1127 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 134 times.
|
135 | link->status_in); |
| 1128 | } | ||
| 1129 | |||
| 1130 | 2931 | static int take_samples(FilterLinkInternal *li, unsigned min, unsigned max, | |
| 1131 | AVFrame **rframe) | ||
| 1132 | { | ||
| 1133 | 2931 | FilterLink *l = &li->l; | |
| 1134 | 2931 | AVFilterLink *link = &l->pub; | |
| 1135 | AVFrame *frame0, *frame, *buf; | ||
| 1136 | unsigned nb_samples, nb_frames, i, p; | ||
| 1137 | int ret; | ||
| 1138 | |||
| 1139 | /* Note: this function relies on no format changes and must only be | ||
| 1140 | called with enough samples. */ | ||
| 1141 | av_assert1(samples_ready(li, l->min_samples)); | ||
| 1142 | 2931 | frame0 = frame = ff_framequeue_peek(&li->fifo, 0); | |
| 1143 |
6/6✓ Branch 0 taken 1416 times.
✓ Branch 1 taken 1515 times.
✓ Branch 2 taken 1302 times.
✓ Branch 3 taken 114 times.
✓ Branch 4 taken 1026 times.
✓ Branch 5 taken 276 times.
|
2931 | if (!li->fifo.samples_skipped && frame->nb_samples >= min && frame->nb_samples <= max) { |
| 1144 | 1026 | *rframe = ff_framequeue_take(&li->fifo); | |
| 1145 | 1026 | return 0; | |
| 1146 | } | ||
| 1147 | 1905 | nb_frames = 0; | |
| 1148 | 1905 | nb_samples = 0; | |
| 1149 | while (1) { | ||
| 1150 |
2/2✓ Branch 0 taken 1654 times.
✓ Branch 1 taken 1461 times.
|
3115 | if (nb_samples + frame->nb_samples > max) { |
| 1151 |
2/2✓ Branch 0 taken 1518 times.
✓ Branch 1 taken 136 times.
|
1654 | if (nb_samples < min) |
| 1152 | 1518 | nb_samples = max; | |
| 1153 | 1654 | break; | |
| 1154 | } | ||
| 1155 | 1461 | nb_samples += frame->nb_samples; | |
| 1156 | 1461 | nb_frames++; | |
| 1157 |
2/2✓ Branch 1 taken 251 times.
✓ Branch 2 taken 1210 times.
|
1461 | if (nb_frames == ff_framequeue_queued_frames(&li->fifo)) |
| 1158 | 251 | break; | |
| 1159 | 1210 | frame = ff_framequeue_peek(&li->fifo, nb_frames); | |
| 1160 | } | ||
| 1161 | |||
| 1162 | 1905 | buf = ff_get_audio_buffer(link, nb_samples); | |
| 1163 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1905 times.
|
1905 | if (!buf) |
| 1164 | ✗ | return AVERROR(ENOMEM); | |
| 1165 | 1905 | ret = av_frame_copy_props(buf, frame0); | |
| 1166 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1905 times.
|
1905 | if (ret < 0) { |
| 1167 | ✗ | av_frame_free(&buf); | |
| 1168 | ✗ | return ret; | |
| 1169 | } | ||
| 1170 | |||
| 1171 | 1905 | p = 0; | |
| 1172 |
2/2✓ Branch 0 taken 1461 times.
✓ Branch 1 taken 1905 times.
|
3366 | for (i = 0; i < nb_frames; i++) { |
| 1173 | 1461 | frame = ff_framequeue_take(&li->fifo); | |
| 1174 | 1461 | av_samples_copy(buf->extended_data, frame->extended_data, p, 0, | |
| 1175 | 1461 | frame->nb_samples, link->ch_layout.nb_channels, link->format); | |
| 1176 | 1461 | p += frame->nb_samples; | |
| 1177 | 1461 | av_frame_free(&frame); | |
| 1178 | } | ||
| 1179 |
2/2✓ Branch 0 taken 1518 times.
✓ Branch 1 taken 387 times.
|
1905 | if (p < nb_samples) { |
| 1180 | 1518 | unsigned n = nb_samples - p; | |
| 1181 | 1518 | frame = ff_framequeue_peek(&li->fifo, 0); | |
| 1182 | 1518 | av_samples_copy(buf->extended_data, frame->extended_data, p, 0, n, | |
| 1183 | 1518 | link->ch_layout.nb_channels, link->format); | |
| 1184 | 1518 | ff_framequeue_skip_samples(&li->fifo, n, link->time_base); | |
| 1185 | } | ||
| 1186 | |||
| 1187 | 1905 | *rframe = buf; | |
| 1188 | 1905 | return 0; | |
| 1189 | } | ||
| 1190 | |||
| 1191 | 805511 | static int filter_frame_to_filter(AVFilterLink *link) | |
| 1192 | { | ||
| 1193 | 805511 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1194 | 805511 | AVFrame *frame = NULL; | |
| 1195 | 805511 | AVFilterContext *dst = link->dst; | |
| 1196 | int ret; | ||
| 1197 | |||
| 1198 | av_assert1(ff_framequeue_queued_frames(&li->fifo)); | ||
| 1199 | 1611022 | ret = li->l.min_samples ? | |
| 1200 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 805475 times.
|
805511 | ff_inlink_consume_samples(link, li->l.min_samples, li->l.max_samples, &frame) : |
| 1201 | 805475 | ff_inlink_consume_frame(link, &frame); | |
| 1202 | av_assert1(ret); | ||
| 1203 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 805511 times.
|
805511 | if (ret < 0) { |
| 1204 | av_assert1(!frame); | ||
| 1205 | ✗ | return ret; | |
| 1206 | } | ||
| 1207 | /* The filter will soon have received a new frame, that may allow it to | ||
| 1208 | produce one or more: unblock its outputs. */ | ||
| 1209 | 805511 | filter_unblock(dst); | |
| 1210 | /* AVFilterPad.filter_frame() expect frame_count_out to have the value | ||
| 1211 | before the frame; filter_frame_framed() will re-increment it. */ | ||
| 1212 | 805511 | li->l.frame_count_out--; | |
| 1213 | 805511 | ret = filter_frame_framed(link, frame); | |
| 1214 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 805511 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
805511 | if (ret < 0 && ret != li->status_out) { |
| 1215 | ✗ | link_set_out_status(link, ret, AV_NOPTS_VALUE); | |
| 1216 | } else { | ||
| 1217 | /* Run once again, to see if several frames were available, or if | ||
| 1218 | the input status has also changed, or any other reason. */ | ||
| 1219 | 805511 | ff_filter_set_ready(dst, 300); | |
| 1220 | } | ||
| 1221 | 805511 | return ret; | |
| 1222 | } | ||
| 1223 | |||
| 1224 | 6088 | static int forward_status_change(AVFilterContext *filter, FilterLinkInternal *li_in) | |
| 1225 | { | ||
| 1226 | 6088 | AVFilterLink *in = &li_in->l.pub; | |
| 1227 | 6088 | unsigned out = 0, progress = 0; | |
| 1228 | int ret; | ||
| 1229 | |||
| 1230 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6088 times.
|
6088 | av_assert0(!li_in->status_out); |
| 1231 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6087 times.
|
6088 | if (!filter->nb_outputs) { |
| 1232 | /* not necessary with the current API and sinks */ | ||
| 1233 | 1 | return 0; | |
| 1234 | } | ||
| 1235 |
2/2✓ Branch 0 taken 6087 times.
✓ Branch 1 taken 6087 times.
|
12174 | while (!li_in->status_out) { |
| 1236 | 6087 | FilterLinkInternal *li_out = ff_link_internal(filter->outputs[out]); | |
| 1237 | |||
| 1238 |
1/2✓ Branch 0 taken 6087 times.
✗ Branch 1 not taken.
|
6087 | if (!li_out->status_in) { |
| 1239 | 6087 | progress++; | |
| 1240 | 6087 | ret = request_frame_to_filter(filter->outputs[out]); | |
| 1241 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6087 times.
|
6087 | if (ret < 0) |
| 1242 | ✗ | return ret; | |
| 1243 | } | ||
| 1244 |
1/2✓ Branch 0 taken 6087 times.
✗ Branch 1 not taken.
|
6087 | if (++out == filter->nb_outputs) { |
| 1245 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6087 times.
|
6087 | if (!progress) { |
| 1246 | /* Every output already closed: input no longer interesting | ||
| 1247 | (example: overlay in shortest mode, other input closed). */ | ||
| 1248 | ✗ | link_set_out_status(in, li_in->status_in, li_in->status_in_pts); | |
| 1249 | ✗ | return 0; | |
| 1250 | } | ||
| 1251 | 6087 | progress = 0; | |
| 1252 | 6087 | out = 0; | |
| 1253 | } | ||
| 1254 | } | ||
| 1255 | 6087 | ff_filter_set_ready(filter, 200); | |
| 1256 | 6087 | return 0; | |
| 1257 | } | ||
| 1258 | |||
| 1259 | 2418960 | static int filter_activate_default(AVFilterContext *filter) | |
| 1260 | { | ||
| 1261 | unsigned i; | ||
| 1262 | 2418960 | int nb_eofs = 0; | |
| 1263 | |||
| 1264 |
2/2✓ Branch 0 taken 2418911 times.
✓ Branch 1 taken 2418960 times.
|
4837871 | for (i = 0; i < filter->nb_outputs; i++) |
| 1265 | 2418911 | nb_eofs += ff_outlink_get_status(filter->outputs[i]) == AVERROR_EOF; | |
| 1266 |
4/4✓ Branch 0 taken 2418911 times.
✓ Branch 1 taken 49 times.
✓ Branch 2 taken 6963 times.
✓ Branch 3 taken 2411948 times.
|
2418960 | if (filter->nb_outputs && nb_eofs == filter->nb_outputs) { |
| 1267 |
2/2✓ Branch 0 taken 6963 times.
✓ Branch 1 taken 6963 times.
|
13926 | for (int j = 0; j < filter->nb_inputs; j++) |
| 1268 | 6963 | ff_inlink_set_status(filter->inputs[j], AVERROR_EOF); | |
| 1269 | 6963 | return 0; | |
| 1270 | } | ||
| 1271 | |||
| 1272 |
2/2✓ Branch 0 taken 2411728 times.
✓ Branch 1 taken 1606486 times.
|
4018214 | for (i = 0; i < filter->nb_inputs; i++) { |
| 1273 | 2411728 | FilterLinkInternal *li = ff_link_internal(filter->inputs[i]); | |
| 1274 |
2/2✓ Branch 1 taken 805511 times.
✓ Branch 2 taken 1606217 times.
|
2411728 | if (samples_ready(li, li->l.min_samples)) { |
| 1275 | 805511 | return filter_frame_to_filter(filter->inputs[i]); | |
| 1276 | } | ||
| 1277 | } | ||
| 1278 |
2/2✓ Branch 0 taken 1606217 times.
✓ Branch 1 taken 1600398 times.
|
3206615 | for (i = 0; i < filter->nb_inputs; i++) { |
| 1279 | 1606217 | FilterLinkInternal * const li = ff_link_internal(filter->inputs[i]); | |
| 1280 |
4/4✓ Branch 0 taken 6118 times.
✓ Branch 1 taken 1600099 times.
✓ Branch 2 taken 6088 times.
✓ Branch 3 taken 30 times.
|
1606217 | if (li->status_in && !li->status_out) { |
| 1281 | av_assert1(!ff_framequeue_queued_frames(&li->fifo)); | ||
| 1282 | 6088 | return forward_status_change(filter, li); | |
| 1283 | } | ||
| 1284 | } | ||
| 1285 |
2/2✓ Branch 0 taken 1600374 times.
✓ Branch 1 taken 805349 times.
|
2405723 | for (i = 0; i < filter->nb_outputs; i++) { |
| 1286 | 1600374 | FilterLinkInternal * const li = ff_link_internal(filter->outputs[i]); | |
| 1287 |
2/2✓ Branch 0 taken 799904 times.
✓ Branch 1 taken 800470 times.
|
1600374 | if (li->frame_wanted_out && |
| 1288 |
2/2✓ Branch 0 taken 795049 times.
✓ Branch 1 taken 4855 times.
|
799904 | !li->frame_blocked_in) { |
| 1289 | 795049 | return request_frame_to_filter(filter->outputs[i]); | |
| 1290 | } | ||
| 1291 | } | ||
| 1292 |
2/2✓ Branch 0 taken 805325 times.
✓ Branch 1 taken 800494 times.
|
1605819 | for (i = 0; i < filter->nb_outputs; i++) { |
| 1293 | 805325 | FilterLinkInternal * const li = ff_link_internal(filter->outputs[i]); | |
| 1294 |
2/2✓ Branch 0 taken 4855 times.
✓ Branch 1 taken 800470 times.
|
805325 | if (li->frame_wanted_out) |
| 1295 | 4855 | return request_frame_to_filter(filter->outputs[i]); | |
| 1296 | } | ||
| 1297 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 800470 times.
|
800494 | if (!filter->nb_outputs) { |
| 1298 | 24 | ff_inlink_request_frame(filter->inputs[0]); | |
| 1299 | 24 | return 0; | |
| 1300 | } | ||
| 1301 | 800470 | return FFERROR_NOT_READY; | |
| 1302 | } | ||
| 1303 | |||
| 1304 | /* | ||
| 1305 | Filter scheduling and activation | ||
| 1306 | |||
| 1307 | When a filter is activated, it must: | ||
| 1308 | - if possible, output a frame; | ||
| 1309 | - else, if relevant, forward the input status change; | ||
| 1310 | - else, check outputs for wanted frames and forward the requests. | ||
| 1311 | |||
| 1312 | The following AVFilterLink fields are used for activation: | ||
| 1313 | |||
| 1314 | - frame_wanted_out: | ||
| 1315 | |||
| 1316 | This field indicates if a frame is needed on this input of the | ||
| 1317 | destination filter. A positive value indicates that a frame is needed | ||
| 1318 | to process queued frames or internal data or to satisfy the | ||
| 1319 | application; a zero value indicates that a frame is not especially | ||
| 1320 | needed but could be processed anyway; a negative value indicates that a | ||
| 1321 | frame would just be queued. | ||
| 1322 | |||
| 1323 | It is set by filters using ff_request_frame() or ff_request_no_frame(), | ||
| 1324 | when requested by the application through a specific API or when it is | ||
| 1325 | set on one of the outputs. | ||
| 1326 | |||
| 1327 | It is cleared when a frame is sent from the source using | ||
| 1328 | ff_filter_frame(). | ||
| 1329 | |||
| 1330 | It is also cleared when a status change is sent from the source using | ||
| 1331 | ff_avfilter_link_set_in_status(). | ||
| 1332 | |||
| 1333 | - frame_blocked_in: | ||
| 1334 | |||
| 1335 | This field means that the source filter can not generate a frame as is. | ||
| 1336 | Its goal is to avoid repeatedly calling the request_frame() method on | ||
| 1337 | the same link. | ||
| 1338 | |||
| 1339 | It is set by the framework on all outputs of a filter before activating it. | ||
| 1340 | |||
| 1341 | It is automatically cleared by ff_filter_frame(). | ||
| 1342 | |||
| 1343 | It is also automatically cleared by ff_avfilter_link_set_in_status(). | ||
| 1344 | |||
| 1345 | It is also cleared on all outputs (using filter_unblock()) when | ||
| 1346 | something happens on an input: processing a frame or changing the | ||
| 1347 | status. | ||
| 1348 | |||
| 1349 | - fifo: | ||
| 1350 | |||
| 1351 | Contains the frames queued on a filter input. If it contains frames and | ||
| 1352 | frame_wanted_out is not set, then the filter can be activated. If that | ||
| 1353 | result in the filter not able to use these frames, the filter must set | ||
| 1354 | frame_wanted_out to ask for more frames. | ||
| 1355 | |||
| 1356 | - status_in and status_in_pts: | ||
| 1357 | |||
| 1358 | Status (EOF or error code) of the link and timestamp of the status | ||
| 1359 | change (in link time base, same as frames) as seen from the input of | ||
| 1360 | the link. The status change is considered happening after the frames | ||
| 1361 | queued in fifo. | ||
| 1362 | |||
| 1363 | It is set by the source filter using ff_avfilter_link_set_in_status(). | ||
| 1364 | |||
| 1365 | - status_out: | ||
| 1366 | |||
| 1367 | Status of the link as seen from the output of the link. The status | ||
| 1368 | change is considered having already happened. | ||
| 1369 | |||
| 1370 | It is set by the destination filter using | ||
| 1371 | link_set_out_status(). | ||
| 1372 | |||
| 1373 | Filters are activated according to the ready field, set using the | ||
| 1374 | ff_filter_set_ready(). Eventually, a priority queue will be used. | ||
| 1375 | ff_filter_set_ready() is called whenever anything could cause progress to | ||
| 1376 | be possible. Marking a filter ready when it is not is not a problem, | ||
| 1377 | except for the small overhead it causes. | ||
| 1378 | |||
| 1379 | Conditions that cause a filter to be marked ready are: | ||
| 1380 | |||
| 1381 | - frames added on an input link; | ||
| 1382 | |||
| 1383 | - changes in the input or output status of an input link; | ||
| 1384 | |||
| 1385 | - requests for a frame on an output link; | ||
| 1386 | |||
| 1387 | - after any actual processing using the legacy methods (filter_frame(), | ||
| 1388 | and request_frame() to acknowledge status changes), to run once more | ||
| 1389 | and check if enough input was present for several frames. | ||
| 1390 | |||
| 1391 | Examples of scenarios to consider: | ||
| 1392 | |||
| 1393 | - buffersrc: activate if frame_wanted_out to notify the application; | ||
| 1394 | activate when the application adds a frame to push it immediately. | ||
| 1395 | |||
| 1396 | - testsrc: activate only if frame_wanted_out to produce and push a frame. | ||
| 1397 | |||
| 1398 | - concat (not at stitch points): can process a frame on any output. | ||
| 1399 | Activate if frame_wanted_out on output to forward on the corresponding | ||
| 1400 | input. Activate when a frame is present on input to process it | ||
| 1401 | immediately. | ||
| 1402 | |||
| 1403 | - framesync: needs at least one frame on each input; extra frames on the | ||
| 1404 | wrong input will accumulate. When a frame is first added on one input, | ||
| 1405 | set frame_wanted_out<0 on it to avoid getting more (would trigger | ||
| 1406 | testsrc) and frame_wanted_out>0 on the other to allow processing it. | ||
| 1407 | |||
| 1408 | Activation of old filters: | ||
| 1409 | |||
| 1410 | In order to activate a filter implementing the legacy filter_frame() and | ||
| 1411 | request_frame() methods, perform the first possible of the following | ||
| 1412 | actions: | ||
| 1413 | |||
| 1414 | - If an input has frames in fifo and frame_wanted_out == 0, dequeue a | ||
| 1415 | frame and call filter_frame(). | ||
| 1416 | |||
| 1417 | Rationale: filter frames as soon as possible instead of leaving them | ||
| 1418 | queued; frame_wanted_out < 0 is not possible since the old API does not | ||
| 1419 | set it nor provides any similar feedback; frame_wanted_out > 0 happens | ||
| 1420 | when min_samples > 0 and there are not enough samples queued. | ||
| 1421 | |||
| 1422 | - If an input has status_in set but not status_out, try to call | ||
| 1423 | request_frame() on one of the outputs in the hope that it will trigger | ||
| 1424 | request_frame() on the input with status_in and acknowledge it. This is | ||
| 1425 | awkward and fragile, filters with several inputs or outputs should be | ||
| 1426 | updated to direct activation as soon as possible. | ||
| 1427 | |||
| 1428 | - If an output has frame_wanted_out > 0 and not frame_blocked_in, call | ||
| 1429 | request_frame(). | ||
| 1430 | |||
| 1431 | Rationale: checking frame_blocked_in is necessary to avoid requesting | ||
| 1432 | repeatedly on a blocked input if another is not blocked (example: | ||
| 1433 | [buffersrc1][testsrc1][buffersrc2][testsrc2]concat=v=2). | ||
| 1434 | |||
| 1435 | - If an output has frame_wanted_out > 0 call request_frame(). | ||
| 1436 | |||
| 1437 | Rationale: even if all inputs are blocked an activate callback should | ||
| 1438 | request a frame on some if its inputs if a frame is requested on any of | ||
| 1439 | its output. | ||
| 1440 | |||
| 1441 | - Request a frame on the input for sinks. | ||
| 1442 | |||
| 1443 | Rationale: sinks using the old api have no way to request a frame on their | ||
| 1444 | input, so we need to do it for them. | ||
| 1445 | */ | ||
| 1446 | |||
| 1447 | 4205962 | int ff_filter_activate(AVFilterContext *filter) | |
| 1448 | { | ||
| 1449 | 4205962 | FFFilterContext *ctxi = fffilterctx(filter); | |
| 1450 | 4205962 | const FFFilter *const fi = fffilter(filter->filter); | |
| 1451 | int ret; | ||
| 1452 | |||
| 1453 | /* Generic timeline support is not yet implemented but should be easy */ | ||
| 1454 | av_assert1(!(fi->p.flags & AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC && | ||
| 1455 | fi->activate)); | ||
| 1456 | 4205962 | ctxi->ready = 0; | |
| 1457 |
2/2✓ Branch 0 taken 1787002 times.
✓ Branch 1 taken 2418960 times.
|
4205962 | ret = fi->activate ? fi->activate(filter) : filter_activate_default(filter); |
| 1458 |
2/2✓ Branch 0 taken 801340 times.
✓ Branch 1 taken 3404622 times.
|
4205962 | if (ret == FFERROR_NOT_READY) |
| 1459 | 801340 | ret = 0; | |
| 1460 | 4205962 | return ret; | |
| 1461 | } | ||
| 1462 | |||
| 1463 | 3792912 | int ff_inlink_acknowledge_status(AVFilterLink *link, int *rstatus, int64_t *rpts) | |
| 1464 | { | ||
| 1465 | 3792912 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1466 | 3792912 | *rpts = li->l.current_pts; | |
| 1467 |
2/2✓ Branch 1 taken 2176 times.
✓ Branch 2 taken 3790736 times.
|
3792912 | if (ff_framequeue_queued_frames(&li->fifo)) |
| 1468 | 2176 | return *rstatus = 0; | |
| 1469 |
2/2✓ Branch 0 taken 8005 times.
✓ Branch 1 taken 3782731 times.
|
3790736 | if (li->status_out) |
| 1470 | 8005 | return *rstatus = li->status_out; | |
| 1471 |
2/2✓ Branch 0 taken 3774728 times.
✓ Branch 1 taken 8003 times.
|
3782731 | if (!li->status_in) |
| 1472 | 3774728 | return *rstatus = 0; | |
| 1473 | 8003 | *rstatus = li->status_out = li->status_in; | |
| 1474 | 8003 | update_link_current_pts(li, li->status_in_pts); | |
| 1475 | 8003 | *rpts = li->l.current_pts; | |
| 1476 | 8003 | return 1; | |
| 1477 | } | ||
| 1478 | |||
| 1479 | 1934 | size_t ff_inlink_queued_frames(AVFilterLink *link) | |
| 1480 | { | ||
| 1481 | 1934 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1482 | 1934 | return ff_framequeue_queued_frames(&li->fifo); | |
| 1483 | } | ||
| 1484 | |||
| 1485 | 5470848 | int ff_inlink_check_available_frame(AVFilterLink *link) | |
| 1486 | { | ||
| 1487 | 5470848 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1488 | 5470848 | return ff_framequeue_queued_frames(&li->fifo) > 0; | |
| 1489 | } | ||
| 1490 | |||
| 1491 | 8448 | int ff_inlink_queued_samples(AVFilterLink *link) | |
| 1492 | { | ||
| 1493 | 8448 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1494 | 8448 | return ff_framequeue_queued_samples(&li->fifo); | |
| 1495 | } | ||
| 1496 | |||
| 1497 | 4826 | int ff_inlink_check_available_samples(AVFilterLink *link, unsigned min) | |
| 1498 | { | ||
| 1499 | 4826 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1500 | 4826 | uint64_t samples = ff_framequeue_queued_samples(&li->fifo); | |
| 1501 | av_assert1(min); | ||
| 1502 |
6/6✓ Branch 0 taken 1901 times.
✓ Branch 1 taken 2925 times.
✓ Branch 2 taken 65 times.
✓ Branch 3 taken 1836 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 59 times.
|
4826 | return samples >= min || (li->status_in && samples); |
| 1503 | } | ||
| 1504 | |||
| 1505 | 1688254 | static void consume_update(FilterLinkInternal *li, const AVFrame *frame) | |
| 1506 | { | ||
| 1507 | 1688254 | AVFilterLink *const link = &li->l.pub; | |
| 1508 | 1688254 | update_link_current_pts(li, frame->pts); | |
| 1509 | 1688254 | ff_inlink_process_commands(link, frame); | |
| 1510 |
2/2✓ Branch 0 taken 1685525 times.
✓ Branch 1 taken 2729 times.
|
1688254 | if (link == link->dst->inputs[0]) |
| 1511 | 1685525 | link->dst->is_disabled = !evaluate_timeline_at_frame(link, frame); | |
| 1512 | 1688254 | li->l.frame_count_out++; | |
| 1513 | 1688254 | li->l.sample_count_out += frame->nb_samples; | |
| 1514 | 1688254 | } | |
| 1515 | |||
| 1516 | 5468733 | int ff_inlink_consume_frame(AVFilterLink *link, AVFrame **rframe) | |
| 1517 | { | ||
| 1518 | 5468733 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1519 | AVFrame *frame; | ||
| 1520 | |||
| 1521 | 5468733 | *rframe = NULL; | |
| 1522 |
2/2✓ Branch 1 taken 3783406 times.
✓ Branch 2 taken 1685327 times.
|
5468733 | if (!ff_inlink_check_available_frame(link)) |
| 1523 | 3783406 | return 0; | |
| 1524 | |||
| 1525 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1685323 times.
|
1685327 | if (li->fifo.samples_skipped) { |
| 1526 | 4 | frame = ff_framequeue_peek(&li->fifo, 0); | |
| 1527 | 4 | return ff_inlink_consume_samples(link, frame->nb_samples, frame->nb_samples, rframe); | |
| 1528 | } | ||
| 1529 | |||
| 1530 | 1685323 | frame = ff_framequeue_take(&li->fifo); | |
| 1531 | 1685323 | consume_update(li, frame); | |
| 1532 | 1685323 | *rframe = frame; | |
| 1533 | 1685323 | return 1; | |
| 1534 | } | ||
| 1535 | |||
| 1536 | 4826 | int ff_inlink_consume_samples(AVFilterLink *link, unsigned min, unsigned max, | |
| 1537 | AVFrame **rframe) | ||
| 1538 | { | ||
| 1539 | 4826 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1540 | AVFrame *frame; | ||
| 1541 | int ret; | ||
| 1542 | |||
| 1543 | av_assert1(min); | ||
| 1544 | 4826 | *rframe = NULL; | |
| 1545 |
2/2✓ Branch 1 taken 1895 times.
✓ Branch 2 taken 2931 times.
|
4826 | if (!ff_inlink_check_available_samples(link, min)) |
| 1546 | 1895 | return 0; | |
| 1547 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 2915 times.
|
2931 | if (li->status_in) |
| 1548 |
2/2✓ Branch 1 taken 6 times.
✓ Branch 2 taken 10 times.
|
16 | min = FFMIN(min, ff_framequeue_queued_samples(&li->fifo)); |
| 1549 | 2931 | ret = take_samples(li, min, max, &frame); | |
| 1550 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2931 times.
|
2931 | if (ret < 0) |
| 1551 | ✗ | return ret; | |
| 1552 | 2931 | consume_update(li, frame); | |
| 1553 | 2931 | *rframe = frame; | |
| 1554 | 2931 | return 1; | |
| 1555 | } | ||
| 1556 | |||
| 1557 | 210 | AVFrame *ff_inlink_peek_frame(AVFilterLink *link, size_t idx) | |
| 1558 | { | ||
| 1559 | 210 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1560 | 210 | return ff_framequeue_peek(&li->fifo, idx); | |
| 1561 | } | ||
| 1562 | |||
| 1563 | 5170 | int ff_inlink_make_frame_writable(AVFilterLink *link, AVFrame **rframe) | |
| 1564 | { | ||
| 1565 | 5170 | AVFrame *frame = *rframe; | |
| 1566 | AVFrame *out; | ||
| 1567 | int ret; | ||
| 1568 | |||
| 1569 |
2/2✓ Branch 1 taken 2281 times.
✓ Branch 2 taken 2889 times.
|
5170 | if (av_frame_is_writable(frame)) |
| 1570 | 2281 | return 0; | |
| 1571 | 2889 | av_log(link->dst, AV_LOG_DEBUG, "Copying data in avfilter.\n"); | |
| 1572 | |||
| 1573 |
1/3✓ Branch 0 taken 2889 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
2889 | switch (link->type) { |
| 1574 | 2889 | case AVMEDIA_TYPE_VIDEO: | |
| 1575 | 2889 | out = ff_get_video_buffer(link, link->w, link->h); | |
| 1576 | 2889 | break; | |
| 1577 | ✗ | case AVMEDIA_TYPE_AUDIO: | |
| 1578 | ✗ | out = ff_get_audio_buffer(link, frame->nb_samples); | |
| 1579 | ✗ | break; | |
| 1580 | ✗ | default: | |
| 1581 | ✗ | return AVERROR(EINVAL); | |
| 1582 | } | ||
| 1583 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2889 times.
|
2889 | if (!out) |
| 1584 | ✗ | return AVERROR(ENOMEM); | |
| 1585 | |||
| 1586 | 2889 | ret = av_frame_copy_props(out, frame); | |
| 1587 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2889 times.
|
2889 | if (ret < 0) { |
| 1588 | ✗ | av_frame_free(&out); | |
| 1589 | ✗ | return ret; | |
| 1590 | } | ||
| 1591 | |||
| 1592 | 2889 | ret = av_frame_copy(out, frame); | |
| 1593 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2889 times.
|
2889 | if (ret < 0) { |
| 1594 | ✗ | av_frame_free(&out); | |
| 1595 | ✗ | return ret; | |
| 1596 | } | ||
| 1597 | |||
| 1598 | 2889 | av_frame_free(&frame); | |
| 1599 | 2889 | *rframe = out; | |
| 1600 | 2889 | return 0; | |
| 1601 | } | ||
| 1602 | |||
| 1603 | 2493765 | int ff_inlink_process_commands(AVFilterLink *link, const AVFrame *frame) | |
| 1604 | { | ||
| 1605 | 2493765 | FFFilterContext *ctxi = fffilterctx(link->dst); | |
| 1606 | 2493765 | AVFilterCommand *cmd = ctxi->command_queue; | |
| 1607 | |||
| 1608 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 2493765 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
2493765 | while(cmd && cmd->time <= frame->pts * av_q2d(link->time_base)){ |
| 1609 | ✗ | av_log(link->dst, AV_LOG_DEBUG, | |
| 1610 | "Processing command time:%f command:%s arg:%s\n", | ||
| 1611 | cmd->time, cmd->command, cmd->arg); | ||
| 1612 | ✗ | avfilter_process_command(link->dst, cmd->command, cmd->arg, 0, 0, cmd->flags); | |
| 1613 | ✗ | command_queue_pop(link->dst); | |
| 1614 | ✗ | cmd = ctxi->command_queue; | |
| 1615 | } | ||
| 1616 | 2493765 | return 0; | |
| 1617 | } | ||
| 1618 | |||
| 1619 | 889388 | void ff_inlink_request_frame(AVFilterLink *link) | |
| 1620 | { | ||
| 1621 | 889388 | av_unused FilterLinkInternal *li = ff_link_internal(link); | |
| 1622 | av_assert1(!li->status_in); | ||
| 1623 | av_assert1(!li->status_out); | ||
| 1624 | 889388 | li->frame_wanted_out = 1; | |
| 1625 | 889388 | ff_filter_set_ready(link->src, 100); | |
| 1626 | 889388 | } | |
| 1627 | |||
| 1628 | 11092 | void ff_inlink_set_status(AVFilterLink *link, int status) | |
| 1629 | { | ||
| 1630 | 11092 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1631 |
2/2✓ Branch 0 taken 8578 times.
✓ Branch 1 taken 2514 times.
|
11092 | if (li->status_out) |
| 1632 | 8578 | return; | |
| 1633 | 2514 | li->frame_wanted_out = 0; | |
| 1634 | 2514 | li->frame_blocked_in = 0; | |
| 1635 | 2514 | link_set_out_status(link, status, AV_NOPTS_VALUE); | |
| 1636 |
2/2✓ Branch 1 taken 7 times.
✓ Branch 2 taken 2514 times.
|
2521 | while (ff_framequeue_queued_frames(&li->fifo)) { |
| 1637 | 7 | AVFrame *frame = ff_framequeue_take(&li->fifo); | |
| 1638 | 7 | av_frame_free(&frame); | |
| 1639 | } | ||
| 1640 |
2/2✓ Branch 0 taken 2511 times.
✓ Branch 1 taken 3 times.
|
2514 | if (!li->status_in) |
| 1641 | 2511 | li->status_in = status; | |
| 1642 | } | ||
| 1643 | |||
| 1644 | 4130299 | int ff_outlink_get_status(AVFilterLink *link) | |
| 1645 | { | ||
| 1646 | 4130299 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1647 | 4130299 | return li->status_in; | |
| 1648 | } | ||
| 1649 | |||
| 1650 | 1668 | int ff_inoutlink_check_flow(AVFilterLink *inlink, AVFilterLink *outlink) | |
| 1651 | { | ||
| 1652 | 1668 | FilterLinkInternal * const li_in = ff_link_internal(inlink); | |
| 1653 |
2/2✓ Branch 1 taken 982 times.
✓ Branch 2 taken 70 times.
|
2720 | return ff_outlink_frame_wanted(outlink) || |
| 1654 |
2/2✓ Branch 0 taken 1052 times.
✓ Branch 1 taken 616 times.
|
2720 | ff_inlink_check_available_frame(inlink) || |
| 1655 |
2/2✓ Branch 0 taken 55 times.
✓ Branch 1 taken 927 times.
|
982 | li_in->status_out; |
| 1656 | } | ||
| 1657 | |||
| 1658 | |||
| 1659 | ✗ | const AVClass *avfilter_get_class(void) | |
| 1660 | { | ||
| 1661 | ✗ | return &avfilter_class; | |
| 1662 | } | ||
| 1663 | |||
| 1664 | ✗ | int ff_filter_init_hw_frames(AVFilterContext *avctx, AVFilterLink *link, | |
| 1665 | int default_pool_size) | ||
| 1666 | { | ||
| 1667 | ✗ | FilterLink *l = ff_filter_link(link); | |
| 1668 | AVHWFramesContext *frames; | ||
| 1669 | |||
| 1670 | // Must already be set by caller. | ||
| 1671 | ✗ | av_assert0(l->hw_frames_ctx); | |
| 1672 | |||
| 1673 | ✗ | frames = (AVHWFramesContext*)l->hw_frames_ctx->data; | |
| 1674 | |||
| 1675 | ✗ | if (frames->initial_pool_size == 0) { | |
| 1676 | // Dynamic allocation is necessarily supported. | ||
| 1677 | ✗ | } else if (avctx->extra_hw_frames >= 0) { | |
| 1678 | ✗ | frames->initial_pool_size += avctx->extra_hw_frames; | |
| 1679 | } else { | ||
| 1680 | ✗ | frames->initial_pool_size = default_pool_size; | |
| 1681 | } | ||
| 1682 | |||
| 1683 | ✗ | return 0; | |
| 1684 | } | ||
| 1685 | |||
| 1686 | 484189 | int ff_outlink_frame_wanted(AVFilterLink *link) | |
| 1687 | { | ||
| 1688 | 484189 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1689 | 484189 | return li->frame_wanted_out; | |
| 1690 | } | ||
| 1691 | |||
| 1692 | 4993 | int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, | |
| 1693 | void *arg, int *ret, int nb_jobs) | ||
| 1694 | { | ||
| 1695 | 4993 | return fffilterctx(ctx)->execute(ctx, func, arg, ret, nb_jobs); | |
| 1696 | } | ||
| 1697 |