| 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 | 1546102 | 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 | 1546102 | } | |
| 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 | 47192 | 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 47192 times.
|
47192 | av_assert0(src->graph); |
| 156 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 47192 times.
|
47192 | av_assert0(dst->graph); |
| 157 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 47192 times.
|
47192 | av_assert0(src->graph == dst->graph); |
| 158 | |||
| 159 |
2/4✓ Branch 0 taken 47192 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 47192 times.
✗ Branch 3 not taken.
|
47192 | if (src->nb_outputs <= srcpad || dst->nb_inputs <= dstpad || |
| 160 |
2/4✓ Branch 0 taken 47192 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 47192 times.
|
47192 | src->outputs[srcpad] || dst->inputs[dstpad]) |
| 161 | ✗ | return AVERROR(EINVAL); | |
| 162 | |||
| 163 |
1/2✓ Branch 1 taken 47192 times.
✗ Branch 2 not taken.
|
47192 | if (!(fffilterctx(src)->state_flags & AV_CLASS_STATE_INITIALIZED) || |
| 164 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 47192 times.
|
47192 | !(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 47192 times.
|
47192 | 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 | 47192 | li = av_mallocz(sizeof(*li)); | |
| 178 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 47192 times.
|
47192 | if (!li) |
| 179 | ✗ | return AVERROR(ENOMEM); | |
| 180 | 47192 | link = &li->l.pub; | |
| 181 | |||
| 182 | 47192 | src->outputs[srcpad] = dst->inputs[dstpad] = link; | |
| 183 | |||
| 184 | 47192 | link->src = src; | |
| 185 | 47192 | link->dst = dst; | |
| 186 | 47192 | link->srcpad = &src->output_pads[srcpad]; | |
| 187 | 47192 | link->dstpad = &dst->input_pads[dstpad]; | |
| 188 | 47192 | link->type = src->output_pads[srcpad].type; | |
| 189 | 47192 | li->l.graph = src->graph; | |
| 190 | av_assert0(AV_PIX_FMT_NONE == -1 && AV_SAMPLE_FMT_NONE == -1); | ||
| 191 | 47192 | link->format = -1; | |
| 192 | 47192 | link->colorspace = AVCOL_SPC_UNSPECIFIED; | |
| 193 | 47192 | ff_framequeue_init(&li->fifo, &fffiltergraph(src->graph)->frame_queues); | |
| 194 | |||
| 195 | 47192 | return 0; | |
| 196 | } | ||
| 197 | |||
| 198 | 47324 | static void link_free(AVFilterLink **link) | |
| 199 | { | ||
| 200 | FilterLinkInternal *li; | ||
| 201 | |||
| 202 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 47324 times.
|
47324 | if (!*link) |
| 203 | ✗ | return; | |
| 204 | 47324 | li = ff_link_internal(*link); | |
| 205 | |||
| 206 | 47324 | ff_framequeue_free(&li->fifo); | |
| 207 | 47324 | ff_frame_pool_uninit(&li->frame_pool); | |
| 208 | 47324 | av_channel_layout_uninit(&(*link)->ch_layout); | |
| 209 | 47324 | av_frame_side_data_free(&(*link)->side_data, &(*link)->nb_side_data); | |
| 210 | |||
| 211 | 47324 | av_buffer_unref(&li->l.hw_frames_ctx); | |
| 212 | |||
| 213 | 47324 | av_freep(link); | |
| 214 | } | ||
| 215 | |||
| 216 | 1557490 | static void update_link_current_pts(FilterLinkInternal *li, int64_t pts) | |
| 217 | { | ||
| 218 | 1557490 | AVFilterLink *const link = &li->l.pub; | |
| 219 | |||
| 220 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1557485 times.
|
1557490 | if (pts == AV_NOPTS_VALUE) |
| 221 | 5 | return; | |
| 222 | 1557485 | li->l.current_pts = pts; | |
| 223 | 1557485 | 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 1557485 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 422056 times.
✓ Branch 3 taken 1135429 times.
|
1557485 | if (li->l.graph && li->age_index >= 0) |
| 226 | 422056 | ff_avfilter_graph_update_heap(li->l.graph, li); | |
| 227 | } | ||
| 228 | |||
| 229 | 3858947 | void ff_filter_set_ready(AVFilterContext *filter, unsigned priority) | |
| 230 | { | ||
| 231 | 3858947 | FFFilterContext *ctxi = fffilterctx(filter); | |
| 232 | 3858947 | ctxi->ready = FFMAX(ctxi->ready, priority); | |
| 233 | 3858947 | } | |
| 234 | |||
| 235 | /** | ||
| 236 | * Clear frame_blocked_in on all outputs. | ||
| 237 | * This is necessary whenever something changes on input. | ||
| 238 | */ | ||
| 239 | 2301962 | static void filter_unblock(AVFilterContext *filter) | |
| 240 | { | ||
| 241 | unsigned i; | ||
| 242 | |||
| 243 |
2/2✓ Branch 0 taken 1880018 times.
✓ Branch 1 taken 2301962 times.
|
4181980 | for (i = 0; i < filter->nb_outputs; i++) { |
| 244 | 1880018 | FilterLinkInternal * const li = ff_link_internal(filter->outputs[i]); | |
| 245 | 1880018 | li->frame_blocked_in = 0; | |
| 246 | } | ||
| 247 | 2301962 | } | |
| 248 | |||
| 249 | |||
| 250 | 19501 | void ff_avfilter_link_set_in_status(AVFilterLink *link, int status, int64_t pts) | |
| 251 | { | ||
| 252 | 19501 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 253 | |||
| 254 |
2/2✓ Branch 0 taken 5574 times.
✓ Branch 1 taken 13927 times.
|
19501 | if (li->status_in == status) |
| 255 | 5574 | return; | |
| 256 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13927 times.
|
13927 | av_assert0(!li->status_in); |
| 257 | 13927 | li->status_in = status; | |
| 258 | 13927 | li->status_in_pts = pts; | |
| 259 | 13927 | li->frame_wanted_out = 0; | |
| 260 | 13927 | li->frame_blocked_in = 0; | |
| 261 | 13927 | filter_unblock(link->dst); | |
| 262 | 13927 | 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 | 8471 | static void link_set_out_status(AVFilterLink *link, int status, int64_t pts) | |
| 270 | { | ||
| 271 | 8471 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 272 | |||
| 273 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8471 times.
|
8471 | av_assert0(!li->frame_wanted_out); |
| 274 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8471 times.
|
8471 | av_assert0(!li->status_out); |
| 275 | 8471 | li->status_out = status; | |
| 276 |
2/2✓ Branch 0 taken 5994 times.
✓ Branch 1 taken 2477 times.
|
8471 | if (pts != AV_NOPTS_VALUE) |
| 277 | 5994 | update_link_current_pts(li, pts); | |
| 278 | 8471 | filter_unblock(link->dst); | |
| 279 | 8471 | ff_filter_set_ready(link->src, 200); | |
| 280 | 8471 | } | |
| 281 | |||
| 282 | 1265 | int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt, | |
| 283 | unsigned filt_srcpad_idx, unsigned filt_dstpad_idx) | ||
| 284 | { | ||
| 285 | int ret; | ||
| 286 | 1265 | unsigned dstpad_idx = link->dstpad - link->dst->input_pads; | |
| 287 | |||
| 288 | 1265 | av_log(link->dst, AV_LOG_VERBOSE, "auto-inserting filter '%s' " | |
| 289 | "between the filter '%s' and the filter '%s'\n", | ||
| 290 | 1265 | filt->name, link->src->name, link->dst->name); | |
| 291 | |||
| 292 | 1265 | link->dst->inputs[dstpad_idx] = NULL; | |
| 293 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1265 times.
|
1265 | 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 | 1265 | link->dst = filt; | |
| 301 | 1265 | link->dstpad = &filt->input_pads[filt_srcpad_idx]; | |
| 302 | 1265 | 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 1265 times.
✗ Branch 1 not taken.
|
1265 | if (link->outcfg.formats) |
| 307 | 1265 | ff_formats_changeref(&link->outcfg.formats, | |
| 308 | 1265 | &filt->outputs[filt_dstpad_idx]->outcfg.formats); | |
| 309 |
2/2✓ Branch 0 taken 626 times.
✓ Branch 1 taken 639 times.
|
1265 | if (link->outcfg.color_spaces) |
| 310 | 626 | ff_formats_changeref(&link->outcfg.color_spaces, | |
| 311 | 626 | &filt->outputs[filt_dstpad_idx]->outcfg.color_spaces); | |
| 312 |
2/2✓ Branch 0 taken 626 times.
✓ Branch 1 taken 639 times.
|
1265 | if (link->outcfg.color_ranges) |
| 313 | 626 | ff_formats_changeref(&link->outcfg.color_ranges, | |
| 314 | 626 | &filt->outputs[filt_dstpad_idx]->outcfg.color_ranges); | |
| 315 |
2/2✓ Branch 0 taken 626 times.
✓ Branch 1 taken 639 times.
|
1265 | if (link->outcfg.alpha_modes) |
| 316 | 626 | ff_formats_changeref(&link->outcfg.alpha_modes, | |
| 317 | 626 | &filt->outputs[filt_dstpad_idx]->outcfg.alpha_modes); | |
| 318 |
2/2✓ Branch 0 taken 639 times.
✓ Branch 1 taken 626 times.
|
1265 | if (link->outcfg.samplerates) |
| 319 | 639 | ff_formats_changeref(&link->outcfg.samplerates, | |
| 320 | 639 | &filt->outputs[filt_dstpad_idx]->outcfg.samplerates); | |
| 321 |
2/2✓ Branch 0 taken 639 times.
✓ Branch 1 taken 626 times.
|
1265 | if (link->outcfg.channel_layouts) |
| 322 | 639 | ff_channel_layouts_changeref(&link->outcfg.channel_layouts, | |
| 323 | 639 | &filt->outputs[filt_dstpad_idx]->outcfg.channel_layouts); | |
| 324 | |||
| 325 | 1265 | return 0; | |
| 326 | } | ||
| 327 | |||
| 328 | 45145 | 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 36965 times.
✓ Branch 1 taken 45143 times.
|
82108 | for (i = 0; i < filter->nb_inputs; i ++) { |
| 335 | 36965 | AVFilterLink *link = filter->inputs[i]; | |
| 336 | AVFilterLink *inlink; | ||
| 337 | 36965 | FilterLinkInternal *li = ff_link_internal(link); | |
| 338 | FilterLinkInternal *li_in; | ||
| 339 | |||
| 340 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 36965 times.
|
36965 | if (!link) continue; |
| 341 |
2/4✓ Branch 0 taken 36965 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 36965 times.
|
36965 | 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 28585 times.
✓ Branch 1 taken 8380 times.
|
36965 | inlink = link->src->nb_inputs ? link->src->inputs[0] : NULL; |
| 348 |
2/2✓ Branch 0 taken 28585 times.
✓ Branch 1 taken 8380 times.
|
36965 | li_in = inlink ? ff_link_internal(inlink) : NULL; |
| 349 | 36965 | li->l.current_pts = | |
| 350 | 36965 | 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 36852 times.
✗ Branch 3 not taken.
|
36965 | 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 | 36852 | case AVLINK_UNINIT: | |
| 359 | 36852 | li->init_state = AVLINK_STARTINIT; | |
| 360 | |||
| 361 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 36852 times.
|
36852 | if ((ret = ff_filter_config_links(link->src)) < 0) |
| 362 | ✗ | return ret; | |
| 363 | |||
| 364 |
2/2✓ Branch 0 taken 19300 times.
✓ Branch 1 taken 17552 times.
|
36852 | if (!(config_link = link->srcpad->config_props)) { |
| 365 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19300 times.
|
19300 | 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 28506 times.
✓ Branch 1 taken 8346 times.
✓ Branch 2 taken 261 times.
✓ Branch 3 taken 28245 times.
✓ Branch 4 taken 261 times.
✗ Branch 5 not taken.
|
36852 | 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 |
3/4✓ Branch 0 taken 17552 times.
✓ Branch 1 taken 19300 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 17552 times.
|
36852 | if (config_link && (ret = config_link(link)) < 0) { |
| 388 | ✗ | av_log(link->src, AV_LOG_ERROR, | |
| 389 | "Failed to configure output pad on %s\n", | ||
| 390 | ✗ | link->src->name); | |
| 391 | ✗ | return ret; | |
| 392 | } | ||
| 393 | |||
| 394 |
2/3✓ Branch 0 taken 30885 times.
✓ Branch 1 taken 5967 times.
✗ Branch 2 not taken.
|
36852 | switch (link->type) { |
| 395 | 30885 | case AVMEDIA_TYPE_VIDEO: | |
| 396 |
3/4✓ Branch 0 taken 23662 times.
✓ Branch 1 taken 7223 times.
✓ Branch 2 taken 23662 times.
✗ Branch 3 not taken.
|
30885 | if (!link->time_base.num && !link->time_base.den) |
| 397 |
1/2✓ Branch 0 taken 23662 times.
✗ Branch 1 not taken.
|
23662 | link->time_base = inlink ? inlink->time_base : AV_TIME_BASE_Q; |
| 398 | |||
| 399 |
4/4✓ Branch 0 taken 26441 times.
✓ Branch 1 taken 4444 times.
✓ Branch 2 taken 16816 times.
✓ Branch 3 taken 9625 times.
|
30885 | if (!link->sample_aspect_ratio.num && !link->sample_aspect_ratio.den) |
| 400 | 16816 | link->sample_aspect_ratio = inlink ? | |
| 401 |
2/2✓ Branch 0 taken 16801 times.
✓ Branch 1 taken 15 times.
|
16816 | inlink->sample_aspect_ratio : (AVRational){1,1}; |
| 402 | |||
| 403 |
2/2✓ Branch 0 taken 23920 times.
✓ Branch 1 taken 6965 times.
|
30885 | if (inlink) { |
| 404 |
3/4✓ Branch 0 taken 23705 times.
✓ Branch 1 taken 215 times.
✓ Branch 2 taken 23705 times.
✗ Branch 3 not taken.
|
23920 | if (!li->l.frame_rate.num && !li->l.frame_rate.den) |
| 405 | 23705 | li->l.frame_rate = li_in->l.frame_rate; | |
| 406 |
2/2✓ Branch 0 taken 16313 times.
✓ Branch 1 taken 7607 times.
|
23920 | if (!link->w) |
| 407 | 16313 | link->w = inlink->w; | |
| 408 |
2/2✓ Branch 0 taken 16313 times.
✓ Branch 1 taken 7607 times.
|
23920 | if (!link->h) |
| 409 | 16313 | link->h = inlink->h; | |
| 410 |
2/4✓ Branch 0 taken 6965 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6965 times.
|
6965 | } 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 | 30885 | break; | |
| 417 | |||
| 418 | 5967 | case AVMEDIA_TYPE_AUDIO: | |
| 419 |
2/2✓ Branch 0 taken 4586 times.
✓ Branch 1 taken 1381 times.
|
5967 | if (inlink) { |
| 420 |
3/4✓ Branch 0 taken 3074 times.
✓ Branch 1 taken 1512 times.
✓ Branch 2 taken 3074 times.
✗ Branch 3 not taken.
|
4586 | if (!link->time_base.num && !link->time_base.den) |
| 421 | 3074 | link->time_base = inlink->time_base; | |
| 422 | } | ||
| 423 | |||
| 424 |
3/4✓ Branch 0 taken 83 times.
✓ Branch 1 taken 5884 times.
✓ Branch 2 taken 83 times.
✗ Branch 3 not taken.
|
5967 | if (!link->time_base.num && !link->time_base.den) |
| 425 | 83 | link->time_base = (AVRational) {1, link->sample_rate}; | |
| 426 | } | ||
| 427 | |||
| 428 |
2/2✓ Branch 0 taken 28506 times.
✓ Branch 1 taken 8346 times.
|
36852 | if (link->src->nb_inputs && |
| 429 |
1/2✓ Branch 1 taken 28506 times.
✗ Branch 2 not taken.
|
28506 | !(fffilter(link->src->filter)->flags_internal & FF_FILTER_FLAG_HWFRAME_AWARE)) { |
| 430 | 28506 | FilterLink *l0 = ff_filter_link(link->src->inputs[0]); | |
| 431 | |||
| 432 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 28506 times.
|
28506 | 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 28506 times.
|
28506 | 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 4903 times.
✓ Branch 1 taken 31949 times.
|
36852 | if ((config_link = link->dstpad->config_props)) |
| 443 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4903 times.
|
4903 | 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 | 36852 | li->init_state = AVLINK_INIT; | |
| 451 | } | ||
| 452 | } | ||
| 453 | |||
| 454 | 45143 | 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 | 733991 | int ff_request_frame(AVFilterLink *link) | |
| 484 | { | ||
| 485 | 733991 | 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 733982 times.
|
733991 | if (li->status_out) |
| 491 | 9 | return li->status_out; | |
| 492 |
2/2✓ Branch 0 taken 5995 times.
✓ Branch 1 taken 727987 times.
|
733982 | if (li->status_in) { |
| 493 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 5995 times.
|
5995 | 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 | 5995 | link_set_out_status(link, li->status_in, li->status_in_pts); | |
| 502 | 5995 | return li->status_out; | |
| 503 | } | ||
| 504 | } | ||
| 505 | 727987 | li->frame_wanted_out = 1; | |
| 506 | 727987 | ff_filter_set_ready(link->src, 100); | |
| 507 | 727987 | return 0; | |
| 508 | } | ||
| 509 | |||
| 510 | 5989 | static int64_t guess_status_pts(AVFilterContext *ctx, int status, AVRational link_time_base) | |
| 511 | { | ||
| 512 | unsigned i; | ||
| 513 | 5989 | int64_t r = INT64_MAX; | |
| 514 | |||
| 515 |
2/2✓ Branch 0 taken 5988 times.
✓ Branch 1 taken 5989 times.
|
11977 | for (i = 0; i < ctx->nb_inputs; i++) { |
| 516 | 5988 | FilterLinkInternal * const li = ff_link_internal(ctx->inputs[i]); | |
| 517 |
1/2✓ Branch 0 taken 5988 times.
✗ Branch 1 not taken.
|
5988 | if (li->status_out == status) |
| 518 | 5988 | 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 5988 times.
✓ Branch 1 taken 1 times.
|
5989 | if (r < INT64_MAX) |
| 521 | 5988 | 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 | 734306 | static int request_frame_to_filter(AVFilterLink *link) | |
| 533 | { | ||
| 534 | 734306 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 535 | 734306 | 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 | 734306 | li->frame_blocked_in = 1; | |
| 540 |
2/2✓ Branch 0 taken 2053 times.
✓ Branch 1 taken 732253 times.
|
734306 | if (link->srcpad->request_frame) |
| 541 | 2053 | ret = link->srcpad->request_frame(link); | |
| 542 |
1/2✓ Branch 0 taken 732253 times.
✗ Branch 1 not taken.
|
732253 | else if (link->src->inputs[0]) |
| 543 | 732253 | ret = ff_request_frame(link->src->inputs[0]); | |
| 544 |
2/2✓ Branch 0 taken 5989 times.
✓ Branch 1 taken 728317 times.
|
734306 | if (ret < 0) { |
| 545 |
2/4✓ Branch 0 taken 5989 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5989 times.
✗ Branch 3 not taken.
|
5989 | if (ret != AVERROR(EAGAIN) && ret != li->status_in) |
| 546 | 5989 | ff_avfilter_link_set_in_status(link, ret, guess_status_pts(link->src, ret, link->time_base)); | |
| 547 |
1/2✓ Branch 0 taken 5989 times.
✗ Branch 1 not taken.
|
5989 | if (ret == AVERROR_EOF) |
| 548 | 5989 | ret = 0; | |
| 549 | } | ||
| 550 | 734306 | 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 | 14913 | unsigned avfilter_filter_pad_count(const AVFilter *filter, int is_output) | |
| 632 | { | ||
| 633 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14913 times.
|
14913 | return is_output ? fffilter(filter)->nb_outputs : fffilter(filter)->nb_inputs; |
| 634 | } | ||
| 635 | |||
| 636 | 540 | static const char *default_filter_name(void *filter_ctx) | |
| 637 | { | ||
| 638 | 540 | AVFilterContext *ctx = filter_ctx; | |
| 639 |
1/2✓ Branch 0 taken 540 times.
✗ Branch 1 not taken.
|
540 | return ctx->name ? ctx->name : ctx->filter->name; |
| 640 | } | ||
| 641 | |||
| 642 | 56807 | static void *filter_child_next(void *obj, void *prev) | |
| 643 | { | ||
| 644 | 56807 | AVFilterContext *ctx = obj; | |
| 645 |
5/8✓ Branch 0 taken 56801 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 56801 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 56801 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 56801 times.
✗ Branch 7 not taken.
|
56807 | if (!prev && ctx->filter && ctx->filter->priv_class && ctx->priv) |
| 646 | 56801 | 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 | 63545 | AVFilterContext *ff_filter_alloc(const AVFilter *filter, const char *inst_name) | |
| 702 | { | ||
| 703 | FFFilterContext *ctx; | ||
| 704 | AVFilterContext *ret; | ||
| 705 | 63545 | const FFFilter *const fi = fffilter(filter); | |
| 706 | 63545 | int preinited = 0; | |
| 707 | |||
| 708 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 63545 times.
|
63545 | if (!filter) |
| 709 | ✗ | return NULL; | |
| 710 | |||
| 711 | 63545 | ctx = av_mallocz(sizeof(*ctx)); | |
| 712 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 63545 times.
|
63545 | if (!ctx) |
| 713 | ✗ | return NULL; | |
| 714 | 63545 | ret = &ctx->p; | |
| 715 | |||
| 716 | 63545 | ret->av_class = &avfilter_class; | |
| 717 | 63545 | ret->filter = filter; | |
| 718 |
1/2✓ Branch 0 taken 63545 times.
✗ Branch 1 not taken.
|
63545 | ret->name = inst_name ? av_strdup(inst_name) : NULL; |
| 719 |
2/2✓ Branch 0 taken 56788 times.
✓ Branch 1 taken 6757 times.
|
63545 | if (fi->priv_size) { |
| 720 | 56788 | ret->priv = av_mallocz(fi->priv_size); | |
| 721 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 56788 times.
|
56788 | if (!ret->priv) |
| 722 | ✗ | goto err; | |
| 723 | } | ||
| 724 |
2/2✓ Branch 0 taken 13653 times.
✓ Branch 1 taken 49892 times.
|
63545 | if (fi->preinit) { |
| 725 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 13653 times.
|
13653 | if (fi->preinit(ret) < 0) |
| 726 | ✗ | goto err; | |
| 727 | 13653 | preinited = 1; | |
| 728 | } | ||
| 729 | |||
| 730 | 63545 | av_opt_set_defaults(ret); | |
| 731 |
2/2✓ Branch 0 taken 55529 times.
✓ Branch 1 taken 8016 times.
|
63545 | if (filter->priv_class) { |
| 732 | 55529 | *(const AVClass**)ret->priv = filter->priv_class; | |
| 733 | 55529 | av_opt_set_defaults(ret->priv); | |
| 734 | } | ||
| 735 | |||
| 736 | 63545 | ctx->execute = default_execute; | |
| 737 | |||
| 738 | 63545 | ret->nb_inputs = fi->nb_inputs; | |
| 739 |
2/2✓ Branch 0 taken 53862 times.
✓ Branch 1 taken 9683 times.
|
63545 | if (ret->nb_inputs ) { |
| 740 | 53862 | ret->input_pads = av_memdup(filter->inputs, ret->nb_inputs * sizeof(*filter->inputs)); | |
| 741 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 53862 times.
|
53862 | if (!ret->input_pads) |
| 742 | ✗ | goto err; | |
| 743 | 53862 | ret->inputs = av_calloc(ret->nb_inputs, sizeof(*ret->inputs)); | |
| 744 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 53862 times.
|
53862 | if (!ret->inputs) |
| 745 | ✗ | goto err; | |
| 746 | } | ||
| 747 | |||
| 748 | 63545 | ret->nb_outputs = fi->nb_outputs; | |
| 749 |
2/2✓ Branch 0 taken 55161 times.
✓ Branch 1 taken 8384 times.
|
63545 | if (ret->nb_outputs) { |
| 750 | 55161 | ret->output_pads = av_memdup(filter->outputs, ret->nb_outputs * sizeof(*filter->outputs)); | |
| 751 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 55161 times.
|
55161 | if (!ret->output_pads) |
| 752 | ✗ | goto err; | |
| 753 | 55161 | ret->outputs = av_calloc(ret->nb_outputs, sizeof(*ret->outputs)); | |
| 754 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 55161 times.
|
55161 | if (!ret->outputs) |
| 755 | ✗ | goto err; | |
| 756 | } | ||
| 757 | |||
| 758 | 63545 | return ret; | |
| 759 | |||
| 760 | ✗ | err: | |
| 761 | ✗ | if (preinited) | |
| 762 | ✗ | fi->uninit(ret); | |
| 763 | ✗ | av_freep(&ret->inputs); | |
| 764 | ✗ | av_freep(&ret->input_pads); | |
| 765 | ✗ | ret->nb_inputs = 0; | |
| 766 | ✗ | av_freep(&ret->outputs); | |
| 767 | ✗ | av_freep(&ret->output_pads); | |
| 768 | ✗ | ret->nb_outputs = 0; | |
| 769 | ✗ | av_freep(&ret->priv); | |
| 770 | ✗ | av_free(ret); | |
| 771 | ✗ | return NULL; | |
| 772 | } | ||
| 773 | |||
| 774 | 109693 | static void free_link(AVFilterLink *link) | |
| 775 | { | ||
| 776 |
2/2✓ Branch 0 taken 62369 times.
✓ Branch 1 taken 47324 times.
|
109693 | if (!link) |
| 777 | 62369 | return; | |
| 778 | |||
| 779 |
2/2✓ Branch 0 taken 47192 times.
✓ Branch 1 taken 132 times.
|
47324 | if (link->src) |
| 780 | 47192 | link->src->outputs[link->srcpad - link->src->output_pads] = NULL; | |
| 781 |
2/2✓ Branch 0 taken 47192 times.
✓ Branch 1 taken 132 times.
|
47324 | if (link->dst) |
| 782 | 47192 | link->dst->inputs[link->dstpad - link->dst->input_pads] = NULL; | |
| 783 | |||
| 784 | 47324 | ff_formats_unref(&link->incfg.formats); | |
| 785 | 47324 | ff_formats_unref(&link->outcfg.formats); | |
| 786 | 47324 | ff_formats_unref(&link->incfg.color_spaces); | |
| 787 | 47324 | ff_formats_unref(&link->outcfg.color_spaces); | |
| 788 | 47324 | ff_formats_unref(&link->incfg.color_ranges); | |
| 789 | 47324 | ff_formats_unref(&link->outcfg.color_ranges); | |
| 790 | 47324 | ff_formats_unref(&link->incfg.alpha_modes); | |
| 791 | 47324 | ff_formats_unref(&link->outcfg.alpha_modes); | |
| 792 | 47324 | ff_formats_unref(&link->incfg.samplerates); | |
| 793 | 47324 | ff_formats_unref(&link->outcfg.samplerates); | |
| 794 | 47324 | ff_channel_layouts_unref(&link->incfg.channel_layouts); | |
| 795 | 47324 | ff_channel_layouts_unref(&link->outcfg.channel_layouts); | |
| 796 | 47324 | link_free(&link); | |
| 797 | } | ||
| 798 | |||
| 799 | 63545 | void avfilter_free(AVFilterContext *filter) | |
| 800 | { | ||
| 801 | FFFilterContext *ctxi; | ||
| 802 | int i; | ||
| 803 | |||
| 804 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 63545 times.
|
63545 | if (!filter) |
| 805 | ✗ | return; | |
| 806 | 63545 | ctxi = fffilterctx(filter); | |
| 807 | |||
| 808 |
1/2✓ Branch 0 taken 63545 times.
✗ Branch 1 not taken.
|
63545 | if (filter->graph) |
| 809 | 63545 | ff_filter_graph_remove_filter(filter->graph, filter); | |
| 810 | |||
| 811 |
2/2✓ Branch 1 taken 49486 times.
✓ Branch 2 taken 14059 times.
|
63545 | if (fffilter(filter->filter)->uninit) |
| 812 | 49486 | fffilter(filter->filter)->uninit(filter); | |
| 813 | |||
| 814 |
2/2✓ Branch 0 taken 54241 times.
✓ Branch 1 taken 63545 times.
|
117786 | for (i = 0; i < filter->nb_inputs; i++) { |
| 815 | 54241 | free_link(filter->inputs[i]); | |
| 816 |
2/2✓ Branch 0 taken 264 times.
✓ Branch 1 taken 53977 times.
|
54241 | if (filter->input_pads[i].flags & AVFILTERPAD_FLAG_FREE_NAME) |
| 817 | 264 | av_freep(&filter->input_pads[i].name); | |
| 818 | } | ||
| 819 |
2/2✓ Branch 0 taken 55452 times.
✓ Branch 1 taken 63545 times.
|
118997 | for (i = 0; i < filter->nb_outputs; i++) { |
| 820 | 55452 | free_link(filter->outputs[i]); | |
| 821 |
2/2✓ Branch 0 taken 282 times.
✓ Branch 1 taken 55170 times.
|
55452 | if (filter->output_pads[i].flags & AVFILTERPAD_FLAG_FREE_NAME) |
| 822 | 282 | av_freep(&filter->output_pads[i].name); | |
| 823 | } | ||
| 824 | |||
| 825 |
2/2✓ Branch 0 taken 55529 times.
✓ Branch 1 taken 8016 times.
|
63545 | if (filter->filter->priv_class) |
| 826 | 55529 | av_opt_free(filter->priv); | |
| 827 | |||
| 828 | 63545 | av_buffer_unref(&filter->hw_device_ctx); | |
| 829 | |||
| 830 | 63545 | av_freep(&filter->name); | |
| 831 | 63545 | av_freep(&filter->input_pads); | |
| 832 | 63545 | av_freep(&filter->output_pads); | |
| 833 | 63545 | av_freep(&filter->inputs); | |
| 834 | 63545 | av_freep(&filter->outputs); | |
| 835 | 63545 | av_freep(&filter->priv); | |
| 836 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 63545 times.
|
63545 | while (ctxi->command_queue) |
| 837 | ✗ | command_queue_pop(filter); | |
| 838 | 63545 | av_opt_free(filter); | |
| 839 | 63545 | av_expr_free(ctxi->enable); | |
| 840 | 63545 | ctxi->enable = NULL; | |
| 841 | 63545 | av_freep(&ctxi->var_values); | |
| 842 | 63545 | av_free(filter); | |
| 843 | } | ||
| 844 | |||
| 845 | 19267 | int ff_filter_get_nb_threads(AVFilterContext *ctx) | |
| 846 | { | ||
| 847 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19267 times.
|
19267 | if (ctx->nb_threads > 0) |
| 848 | ✗ | return FFMIN(ctx->nb_threads, ctx->graph->nb_threads); | |
| 849 | 19267 | return ctx->graph->nb_threads; | |
| 850 | } | ||
| 851 | |||
| 852 | 34074 | int ff_filter_opt_parse(void *logctx, const AVClass *priv_class, | |
| 853 | AVDictionary **options, const char *args) | ||
| 854 | { | ||
| 855 | 34074 | const AVOption *o = NULL; | |
| 856 | int ret; | ||
| 857 | 34074 | int offset= -1; | |
| 858 | |||
| 859 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34074 times.
|
34074 | if (!args) |
| 860 | ✗ | return 0; | |
| 861 | |||
| 862 |
2/2✓ Branch 0 taken 58602 times.
✓ Branch 1 taken 34074 times.
|
92676 | while (*args) { |
| 863 | char *parsed_key, *value; | ||
| 864 | const char *key; | ||
| 865 | 58602 | const char *shorthand = NULL; | |
| 866 | 58602 | int additional_flags = 0; | |
| 867 | |||
| 868 |
4/4✓ Branch 0 taken 45619 times.
✓ Branch 1 taken 12983 times.
✓ Branch 3 taken 44337 times.
✓ Branch 4 taken 1282 times.
|
58602 | if (priv_class && (o = av_opt_next(&priv_class, o))) { |
| 869 |
4/4✓ Branch 0 taken 42567 times.
✓ Branch 1 taken 1770 times.
✓ Branch 2 taken 4558 times.
✓ Branch 3 taken 38009 times.
|
44337 | if (o->type == AV_OPT_TYPE_CONST || o->offset == offset) |
| 870 | 6328 | continue; | |
| 871 | 38009 | offset = o->offset; | |
| 872 | 38009 | shorthand = o->name; | |
| 873 | } | ||
| 874 | |||
| 875 | 52274 | ret = av_opt_get_key_value(&args, "=", ":", | |
| 876 | shorthand ? AV_OPT_FLAG_IMPLICIT_KEY : 0, | ||
| 877 | &parsed_key, &value); | ||
| 878 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 52274 times.
|
52274 | if (ret < 0) { |
| 879 | ✗ | if (ret == AVERROR(EINVAL)) | |
| 880 | ✗ | av_log(logctx, AV_LOG_ERROR, "No option name near '%s'\n", args); | |
| 881 | else | ||
| 882 | ✗ | av_log(logctx, AV_LOG_ERROR, "Unable to parse '%s': %s\n", args, | |
| 883 | ✗ | av_err2str(ret)); | |
| 884 | ✗ | return ret; | |
| 885 | } | ||
| 886 |
2/2✓ Branch 0 taken 27112 times.
✓ Branch 1 taken 25162 times.
|
52274 | if (*args) |
| 887 | 27112 | args++; | |
| 888 |
2/2✓ Branch 0 taken 31294 times.
✓ Branch 1 taken 20980 times.
|
52274 | if (parsed_key) { |
| 889 | 31294 | key = parsed_key; | |
| 890 | 31294 | additional_flags = AV_DICT_DONT_STRDUP_KEY; | |
| 891 | 31294 | priv_class = NULL; /* reject all remaining shorthand */ | |
| 892 | } else { | ||
| 893 | 20980 | key = shorthand; | |
| 894 | } | ||
| 895 | |||
| 896 | 52274 | av_log(logctx, AV_LOG_DEBUG, "Setting '%s' to value '%s'\n", key, value); | |
| 897 | |||
| 898 | 52274 | av_dict_set(options, key, value, | |
| 899 | additional_flags | AV_DICT_DONT_STRDUP_VAL | AV_DICT_MULTIKEY); | ||
| 900 | } | ||
| 901 | |||
| 902 | 34074 | return 0; | |
| 903 | } | ||
| 904 | |||
| 905 | ✗ | int ff_filter_process_command(AVFilterContext *ctx, const char *cmd, | |
| 906 | const char *arg, char *res, int res_len, int flags) | ||
| 907 | { | ||
| 908 | const AVOption *o; | ||
| 909 | |||
| 910 | ✗ | if (!ctx->filter->priv_class) | |
| 911 | ✗ | return 0; | |
| 912 | ✗ | o = av_opt_find2(ctx->priv, cmd, NULL, AV_OPT_FLAG_RUNTIME_PARAM | AV_OPT_FLAG_FILTERING_PARAM, AV_OPT_SEARCH_CHILDREN, NULL); | |
| 913 | ✗ | if (!o) | |
| 914 | ✗ | return AVERROR(ENOSYS); | |
| 915 | ✗ | return av_opt_set(ctx->priv, cmd, arg, 0); | |
| 916 | } | ||
| 917 | |||
| 918 | 63545 | int avfilter_init_dict(AVFilterContext *ctx, AVDictionary **options) | |
| 919 | { | ||
| 920 | 63545 | FFFilterContext *ctxi = fffilterctx(ctx); | |
| 921 | 63545 | int ret = 0; | |
| 922 | |||
| 923 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 63545 times.
|
63545 | if (ctxi->state_flags & AV_CLASS_STATE_INITIALIZED) { |
| 924 | ✗ | av_log(ctx, AV_LOG_ERROR, "Filter already initialized\n"); | |
| 925 | ✗ | return AVERROR(EINVAL); | |
| 926 | } | ||
| 927 | |||
| 928 | 63545 | ret = av_opt_set_dict2(ctx, options, AV_OPT_SEARCH_CHILDREN); | |
| 929 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 63545 times.
|
63545 | if (ret < 0) { |
| 930 | ✗ | av_log(ctx, AV_LOG_ERROR, "Error applying generic filter options.\n"); | |
| 931 | ✗ | return ret; | |
| 932 | } | ||
| 933 | |||
| 934 |
2/2✓ Branch 0 taken 1244 times.
✓ Branch 1 taken 62301 times.
|
63545 | if (ctx->filter->flags & AVFILTER_FLAG_SLICE_THREADS && |
| 935 |
2/2✓ Branch 0 taken 153 times.
✓ Branch 1 taken 1091 times.
|
1244 | ctx->thread_type & ctx->graph->thread_type & AVFILTER_THREAD_SLICE && |
| 936 |
1/2✓ Branch 1 taken 153 times.
✗ Branch 2 not taken.
|
153 | fffiltergraph(ctx->graph)->thread_execute) { |
| 937 | 153 | ctx->thread_type = AVFILTER_THREAD_SLICE; | |
| 938 | 153 | ctxi->execute = fffiltergraph(ctx->graph)->thread_execute; | |
| 939 | } else { | ||
| 940 | 63392 | ctx->thread_type = 0; | |
| 941 | } | ||
| 942 | |||
| 943 |
2/2✓ Branch 1 taken 50267 times.
✓ Branch 2 taken 13278 times.
|
63545 | if (fffilter(ctx->filter)->init) |
| 944 | 50267 | ret = fffilter(ctx->filter)->init(ctx); | |
| 945 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 63545 times.
|
63545 | if (ret < 0) |
| 946 | ✗ | return ret; | |
| 947 | |||
| 948 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 63539 times.
|
63545 | if (ctx->enable_str) { |
| 949 | 6 | ret = set_enable_expr(ctxi, ctx->enable_str); | |
| 950 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (ret < 0) |
| 951 | ✗ | return ret; | |
| 952 | } | ||
| 953 | |||
| 954 | 63545 | ctxi->state_flags |= AV_CLASS_STATE_INITIALIZED; | |
| 955 | |||
| 956 | 63545 | return 0; | |
| 957 | } | ||
| 958 | |||
| 959 | 20744 | int avfilter_init_str(AVFilterContext *filter, const char *args) | |
| 960 | { | ||
| 961 | 20744 | AVDictionary *options = NULL; | |
| 962 | const AVDictionaryEntry *e; | ||
| 963 | 20744 | int ret = 0; | |
| 964 | |||
| 965 |
3/4✓ Branch 0 taken 10359 times.
✓ Branch 1 taken 10385 times.
✓ Branch 2 taken 10359 times.
✗ Branch 3 not taken.
|
20744 | if (args && *args) { |
| 966 | 10359 | ret = ff_filter_opt_parse(filter, filter->filter->priv_class, &options, args); | |
| 967 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10359 times.
|
10359 | if (ret < 0) |
| 968 | ✗ | goto fail; | |
| 969 | } | ||
| 970 | |||
| 971 | 20744 | ret = avfilter_init_dict(filter, &options); | |
| 972 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 20744 times.
|
20744 | if (ret < 0) |
| 973 | ✗ | goto fail; | |
| 974 | |||
| 975 |
1/2✓ Branch 1 taken 20744 times.
✗ Branch 2 not taken.
|
20744 | if ((e = av_dict_iterate(options, NULL))) { |
| 976 | ✗ | av_log(filter, AV_LOG_ERROR, "No such option: %s.\n", e->key); | |
| 977 | ✗ | ret = AVERROR_OPTION_NOT_FOUND; | |
| 978 | ✗ | goto fail; | |
| 979 | } | ||
| 980 | |||
| 981 | 20744 | fail: | |
| 982 | 20744 | av_dict_free(&options); | |
| 983 | |||
| 984 | 20744 | return ret; | |
| 985 | } | ||
| 986 | |||
| 987 | 15141 | const char *avfilter_pad_get_name(const AVFilterPad *pads, int pad_idx) | |
| 988 | { | ||
| 989 | 15141 | return pads[pad_idx].name; | |
| 990 | } | ||
| 991 | |||
| 992 | 30622 | enum AVMediaType avfilter_pad_get_type(const AVFilterPad *pads, int pad_idx) | |
| 993 | { | ||
| 994 | 30622 | return pads[pad_idx].type; | |
| 995 | } | ||
| 996 | |||
| 997 | ✗ | AVBufferRef *avfilter_link_get_hw_frames_ctx(AVFilterLink *link) | |
| 998 | { | ||
| 999 | ✗ | FilterLink *plink = ff_filter_link(link); | |
| 1000 | ✗ | if (plink->hw_frames_ctx) | |
| 1001 | ✗ | return av_buffer_ref(plink->hw_frames_ctx); | |
| 1002 | |||
| 1003 | ✗ | return NULL; | |
| 1004 | } | ||
| 1005 | |||
| 1006 | 713289 | static int default_filter_frame(AVFilterLink *link, AVFrame *frame) | |
| 1007 | { | ||
| 1008 | 713289 | return ff_filter_frame(link->dst->outputs[0], frame); | |
| 1009 | } | ||
| 1010 | |||
| 1011 | /** | ||
| 1012 | * Evaluate the timeline expression of the link for the time and properties | ||
| 1013 | * of the frame. | ||
| 1014 | * @return >0 if enabled, 0 if disabled | ||
| 1015 | * @note It does not update link->dst->is_disabled. | ||
| 1016 | */ | ||
| 1017 | 2274309 | static int evaluate_timeline_at_frame(AVFilterLink *link, const AVFrame *frame) | |
| 1018 | { | ||
| 1019 | 2274309 | FilterLink *l = ff_filter_link(link); | |
| 1020 | 2274309 | AVFilterContext *dstctx = link->dst; | |
| 1021 | 2274309 | FFFilterContext *dsti = fffilterctx(dstctx); | |
| 1022 | 2274309 | int64_t pts = frame->pts; | |
| 1023 | |||
| 1024 |
2/2✓ Branch 0 taken 2274111 times.
✓ Branch 1 taken 198 times.
|
2274309 | if (!dstctx->enable_str) |
| 1025 | 2274111 | return 1; | |
| 1026 | |||
| 1027 | 198 | dsti->var_values[VAR_N] = l->frame_count_out; | |
| 1028 |
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); |
| 1029 | 198 | dsti->var_values[VAR_W] = link->w; | |
| 1030 | 198 | dsti->var_values[VAR_H] = link->h; | |
| 1031 | |||
| 1032 | 198 | return fabs(av_expr_eval(dsti->enable, dsti->var_values, NULL)) >= 0.5; | |
| 1033 | } | ||
| 1034 | |||
| 1035 | 733462 | static int filter_frame_framed(AVFilterLink *link, AVFrame *frame) | |
| 1036 | { | ||
| 1037 | 733462 | FilterLink *l = ff_filter_link(link); | |
| 1038 | int (*filter_frame)(AVFilterLink *, AVFrame *); | ||
| 1039 | 733462 | AVFilterContext *dstctx = link->dst; | |
| 1040 | 733462 | AVFilterPad *dst = link->dstpad; | |
| 1041 | int ret; | ||
| 1042 | |||
| 1043 |
2/2✓ Branch 0 taken 713280 times.
✓ Branch 1 taken 20182 times.
|
733462 | if (!(filter_frame = dst->filter_frame)) |
| 1044 | 713280 | filter_frame = default_filter_frame; | |
| 1045 | |||
| 1046 |
2/2✓ Branch 0 taken 2993 times.
✓ Branch 1 taken 730469 times.
|
733462 | if (dst->flags & AVFILTERPAD_FLAG_NEEDS_WRITABLE) { |
| 1047 | 2993 | ret = ff_inlink_make_frame_writable(link, &frame); | |
| 1048 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2993 times.
|
2993 | if (ret < 0) |
| 1049 | ✗ | goto fail; | |
| 1050 | } | ||
| 1051 | |||
| 1052 | 733462 | ff_inlink_process_commands(link, frame); | |
| 1053 | 733462 | dstctx->is_disabled = !evaluate_timeline_at_frame(link, frame); | |
| 1054 | |||
| 1055 |
2/2✓ Branch 0 taken 19 times.
✓ Branch 1 taken 733443 times.
|
733462 | if (dstctx->is_disabled && |
| 1056 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 10 times.
|
19 | (dstctx->filter->flags & AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC)) |
| 1057 | 9 | filter_frame = default_filter_frame; | |
| 1058 | 733462 | ret = filter_frame(link, frame); | |
| 1059 | 733462 | l->frame_count_out++; | |
| 1060 | 733462 | return ret; | |
| 1061 | |||
| 1062 | ✗ | fail: | |
| 1063 | ✗ | av_frame_free(&frame); | |
| 1064 | ✗ | return ret; | |
| 1065 | } | ||
| 1066 | |||
| 1067 | 1546102 | int ff_filter_frame(AVFilterLink *link, AVFrame *frame) | |
| 1068 | { | ||
| 1069 | 1546102 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1070 | int ret; | ||
| 1071 | 1546102 | FF_TPRINTF_START(NULL, filter_frame); ff_tlog_link(NULL, link, 1); ff_tlog(NULL, " "); tlog_ref(NULL, frame, 1); | |
| 1072 | |||
| 1073 | /* Consistency checks */ | ||
| 1074 |
2/2✓ Branch 0 taken 583342 times.
✓ Branch 1 taken 962760 times.
|
1546102 | if (link->type == AVMEDIA_TYPE_VIDEO) { |
| 1075 |
2/2✓ Branch 0 taken 434111 times.
✓ Branch 1 taken 149231 times.
|
583342 | if (strcmp(link->dst->filter->name, "buffersink") && |
| 1076 |
2/2✓ Branch 0 taken 258428 times.
✓ Branch 1 taken 175683 times.
|
434111 | strcmp(link->dst->filter->name, "format") && |
| 1077 |
2/2✓ Branch 0 taken 258401 times.
✓ Branch 1 taken 27 times.
|
258428 | strcmp(link->dst->filter->name, "idet") && |
| 1078 |
2/2✓ Branch 0 taken 167478 times.
✓ Branch 1 taken 90923 times.
|
258401 | strcmp(link->dst->filter->name, "null") && |
| 1079 |
2/2✓ Branch 0 taken 57159 times.
✓ Branch 1 taken 110319 times.
|
167478 | strcmp(link->dst->filter->name, "scale") && |
| 1080 |
1/2✓ Branch 0 taken 57159 times.
✗ Branch 1 not taken.
|
57159 | strcmp(link->dst->filter->name, "libplacebo")) { |
| 1081 | av_assert1(frame->format == link->format); | ||
| 1082 | av_assert1(frame->width == link->w); | ||
| 1083 | av_assert1(frame->height == link->h); | ||
| 1084 | 57159 | if (av_pix_fmt_desc_get(link->format)->flags & AV_PIX_FMT_FLAG_ALPHA) | |
| 1085 | av_assert1(frame->alpha_mode == link->alpha_mode); | ||
| 1086 | } | ||
| 1087 | |||
| 1088 | 583342 | frame->sample_aspect_ratio = link->sample_aspect_ratio; | |
| 1089 | } else { | ||
| 1090 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 962760 times.
|
962760 | if (frame->format != link->format) { |
| 1091 | ✗ | av_log(link->dst, AV_LOG_ERROR, "Format change is not supported\n"); | |
| 1092 | ✗ | goto error; | |
| 1093 | } | ||
| 1094 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 962760 times.
|
962760 | if (av_channel_layout_compare(&frame->ch_layout, &link->ch_layout)) { |
| 1095 | ✗ | av_log(link->dst, AV_LOG_ERROR, "Channel layout change is not supported\n"); | |
| 1096 | ✗ | goto error; | |
| 1097 | } | ||
| 1098 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 962760 times.
|
962760 | if (frame->sample_rate != link->sample_rate) { |
| 1099 | ✗ | av_log(link->dst, AV_LOG_ERROR, "Sample rate change is not supported\n"); | |
| 1100 | ✗ | goto error; | |
| 1101 | } | ||
| 1102 | |||
| 1103 | 962760 | frame->duration = av_rescale_q(frame->nb_samples, (AVRational){ 1, frame->sample_rate }, | |
| 1104 | link->time_base); | ||
| 1105 | } | ||
| 1106 | |||
| 1107 | 1546102 | li->frame_blocked_in = li->frame_wanted_out = 0; | |
| 1108 | 1546102 | li->l.frame_count_in++; | |
| 1109 | 1546102 | li->l.sample_count_in += frame->nb_samples; | |
| 1110 | 1546102 | filter_unblock(link->dst); | |
| 1111 | 1546102 | ret = ff_framequeue_add(&li->fifo, frame); | |
| 1112 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1546102 times.
|
1546102 | if (ret < 0) { |
| 1113 | ✗ | av_frame_free(&frame); | |
| 1114 | ✗ | return ret; | |
| 1115 | } | ||
| 1116 | 1546102 | ff_filter_set_ready(link->dst, 300); | |
| 1117 | 1546102 | return 0; | |
| 1118 | |||
| 1119 | ✗ | error: | |
| 1120 | ✗ | av_frame_free(&frame); | |
| 1121 | ✗ | return AVERROR_PATCHWELCOME; | |
| 1122 | } | ||
| 1123 | |||
| 1124 | 2196032 | static int samples_ready(FilterLinkInternal *link, unsigned min) | |
| 1125 | { | ||
| 1126 |
2/2✓ Branch 1 taken 733596 times.
✓ Branch 2 taken 1462436 times.
|
2929628 | return ff_framequeue_queued_frames(&link->fifo) && |
| 1127 |
2/2✓ Branch 1 taken 135 times.
✓ Branch 2 taken 733461 times.
|
733596 | (ff_framequeue_queued_samples(&link->fifo) >= min || |
| 1128 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 134 times.
|
135 | link->status_in); |
| 1129 | } | ||
| 1130 | |||
| 1131 | 2931 | static int take_samples(FilterLinkInternal *li, unsigned min, unsigned max, | |
| 1132 | AVFrame **rframe) | ||
| 1133 | { | ||
| 1134 | 2931 | FilterLink *l = &li->l; | |
| 1135 | 2931 | AVFilterLink *link = &l->pub; | |
| 1136 | AVFrame *frame0, *frame, *buf; | ||
| 1137 | unsigned nb_samples, nb_frames, i, p; | ||
| 1138 | int ret; | ||
| 1139 | |||
| 1140 | /* Note: this function relies on no format changes and must only be | ||
| 1141 | called with enough samples. */ | ||
| 1142 | av_assert1(samples_ready(li, l->min_samples)); | ||
| 1143 | 2931 | frame0 = frame = ff_framequeue_peek(&li->fifo, 0); | |
| 1144 |
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) { |
| 1145 | 1026 | *rframe = ff_framequeue_take(&li->fifo); | |
| 1146 | 1026 | return 0; | |
| 1147 | } | ||
| 1148 | 1905 | nb_frames = 0; | |
| 1149 | 1905 | nb_samples = 0; | |
| 1150 | while (1) { | ||
| 1151 |
2/2✓ Branch 0 taken 1519 times.
✓ Branch 1 taken 1461 times.
|
2980 | if (nb_samples + frame->nb_samples > max) { |
| 1152 |
2/2✓ Branch 0 taken 1518 times.
✓ Branch 1 taken 1 times.
|
1519 | if (nb_samples < min) |
| 1153 | 1518 | nb_samples = max; | |
| 1154 | 1519 | break; | |
| 1155 | } | ||
| 1156 | 1461 | nb_samples += frame->nb_samples; | |
| 1157 | 1461 | nb_frames++; | |
| 1158 |
2/2✓ Branch 1 taken 386 times.
✓ Branch 2 taken 1075 times.
|
1461 | if (nb_frames == ff_framequeue_queued_frames(&li->fifo)) |
| 1159 | 386 | break; | |
| 1160 | 1075 | frame = ff_framequeue_peek(&li->fifo, nb_frames); | |
| 1161 | } | ||
| 1162 | |||
| 1163 | 1905 | buf = ff_get_audio_buffer(link, nb_samples); | |
| 1164 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1905 times.
|
1905 | if (!buf) |
| 1165 | ✗ | return AVERROR(ENOMEM); | |
| 1166 | 1905 | ret = av_frame_copy_props(buf, frame0); | |
| 1167 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1905 times.
|
1905 | if (ret < 0) { |
| 1168 | ✗ | av_frame_free(&buf); | |
| 1169 | ✗ | return ret; | |
| 1170 | } | ||
| 1171 | |||
| 1172 | 1905 | p = 0; | |
| 1173 |
2/2✓ Branch 0 taken 1461 times.
✓ Branch 1 taken 1905 times.
|
3366 | for (i = 0; i < nb_frames; i++) { |
| 1174 | 1461 | frame = ff_framequeue_take(&li->fifo); | |
| 1175 | 1461 | av_samples_copy(buf->extended_data, frame->extended_data, p, 0, | |
| 1176 | 1461 | frame->nb_samples, link->ch_layout.nb_channels, link->format); | |
| 1177 | 1461 | p += frame->nb_samples; | |
| 1178 | 1461 | av_frame_free(&frame); | |
| 1179 | } | ||
| 1180 |
2/2✓ Branch 0 taken 1518 times.
✓ Branch 1 taken 387 times.
|
1905 | if (p < nb_samples) { |
| 1181 | 1518 | unsigned n = nb_samples - p; | |
| 1182 | 1518 | frame = ff_framequeue_peek(&li->fifo, 0); | |
| 1183 | 1518 | av_samples_copy(buf->extended_data, frame->extended_data, p, 0, n, | |
| 1184 | 1518 | link->ch_layout.nb_channels, link->format); | |
| 1185 | 1518 | ff_framequeue_skip_samples(&li->fifo, n, link->time_base); | |
| 1186 | } | ||
| 1187 | |||
| 1188 | 1905 | *rframe = buf; | |
| 1189 | 1905 | return 0; | |
| 1190 | } | ||
| 1191 | |||
| 1192 | 733462 | static int filter_frame_to_filter(AVFilterLink *link) | |
| 1193 | { | ||
| 1194 | 733462 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1195 | 733462 | AVFrame *frame = NULL; | |
| 1196 | 733462 | AVFilterContext *dst = link->dst; | |
| 1197 | int ret; | ||
| 1198 | |||
| 1199 | av_assert1(ff_framequeue_queued_frames(&li->fifo)); | ||
| 1200 | 1466924 | ret = li->l.min_samples ? | |
| 1201 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 733426 times.
|
733462 | ff_inlink_consume_samples(link, li->l.min_samples, li->l.max_samples, &frame) : |
| 1202 | 733426 | ff_inlink_consume_frame(link, &frame); | |
| 1203 | av_assert1(ret); | ||
| 1204 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 733462 times.
|
733462 | if (ret < 0) { |
| 1205 | av_assert1(!frame); | ||
| 1206 | ✗ | return ret; | |
| 1207 | } | ||
| 1208 | /* The filter will soon have received a new frame, that may allow it to | ||
| 1209 | produce one or more: unblock its outputs. */ | ||
| 1210 | 733462 | filter_unblock(dst); | |
| 1211 | /* AVFilterPad.filter_frame() expect frame_count_out to have the value | ||
| 1212 | before the frame; filter_frame_framed() will re-increment it. */ | ||
| 1213 | 733462 | li->l.frame_count_out--; | |
| 1214 | 733462 | ret = filter_frame_framed(link, frame); | |
| 1215 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 733462 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
733462 | if (ret < 0 && ret != li->status_out) { |
| 1216 | ✗ | link_set_out_status(link, ret, AV_NOPTS_VALUE); | |
| 1217 | } else { | ||
| 1218 | /* Run once again, to see if several frames were available, or if | ||
| 1219 | the input status has also changed, or any other reason. */ | ||
| 1220 | 733462 | ff_filter_set_ready(dst, 300); | |
| 1221 | } | ||
| 1222 | 733462 | return ret; | |
| 1223 | } | ||
| 1224 | |||
| 1225 | 5995 | static int forward_status_change(AVFilterContext *filter, FilterLinkInternal *li_in) | |
| 1226 | { | ||
| 1227 | 5995 | AVFilterLink *in = &li_in->l.pub; | |
| 1228 | 5995 | unsigned out = 0, progress = 0; | |
| 1229 | int ret; | ||
| 1230 | |||
| 1231 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5995 times.
|
5995 | av_assert0(!li_in->status_out); |
| 1232 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5994 times.
|
5995 | if (!filter->nb_outputs) { |
| 1233 | /* not necessary with the current API and sinks */ | ||
| 1234 | 1 | return 0; | |
| 1235 | } | ||
| 1236 |
2/2✓ Branch 0 taken 5994 times.
✓ Branch 1 taken 5994 times.
|
11988 | while (!li_in->status_out) { |
| 1237 | 5994 | FilterLinkInternal *li_out = ff_link_internal(filter->outputs[out]); | |
| 1238 | |||
| 1239 |
1/2✓ Branch 0 taken 5994 times.
✗ Branch 1 not taken.
|
5994 | if (!li_out->status_in) { |
| 1240 | 5994 | progress++; | |
| 1241 | 5994 | ret = request_frame_to_filter(filter->outputs[out]); | |
| 1242 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5994 times.
|
5994 | if (ret < 0) |
| 1243 | ✗ | return ret; | |
| 1244 | } | ||
| 1245 |
1/2✓ Branch 0 taken 5994 times.
✗ Branch 1 not taken.
|
5994 | if (++out == filter->nb_outputs) { |
| 1246 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5994 times.
|
5994 | if (!progress) { |
| 1247 | /* Every output already closed: input no longer interesting | ||
| 1248 | (example: overlay in shortest mode, other input closed). */ | ||
| 1249 | ✗ | link_set_out_status(in, li_in->status_in, li_in->status_in_pts); | |
| 1250 | ✗ | return 0; | |
| 1251 | } | ||
| 1252 | 5994 | progress = 0; | |
| 1253 | 5994 | out = 0; | |
| 1254 | } | ||
| 1255 | } | ||
| 1256 | 5994 | ff_filter_set_ready(filter, 200); | |
| 1257 | 5994 | return 0; | |
| 1258 | } | ||
| 1259 | |||
| 1260 | 2203134 | static int filter_activate_default(AVFilterContext *filter) | |
| 1261 | { | ||
| 1262 | unsigned i; | ||
| 1263 | 2203134 | int nb_eofs = 0; | |
| 1264 | |||
| 1265 |
2/2✓ Branch 0 taken 2203085 times.
✓ Branch 1 taken 2203134 times.
|
4406219 | for (i = 0; i < filter->nb_outputs; i++) |
| 1266 | 2203085 | nb_eofs += ff_outlink_get_status(filter->outputs[i]) == AVERROR_EOF; | |
| 1267 |
4/4✓ Branch 0 taken 2203085 times.
✓ Branch 1 taken 49 times.
✓ Branch 2 taken 6827 times.
✓ Branch 3 taken 2196258 times.
|
2203134 | if (filter->nb_outputs && nb_eofs == filter->nb_outputs) { |
| 1268 |
2/2✓ Branch 0 taken 6827 times.
✓ Branch 1 taken 6827 times.
|
13654 | for (int j = 0; j < filter->nb_inputs; j++) |
| 1269 | 6827 | ff_inlink_set_status(filter->inputs[j], AVERROR_EOF); | |
| 1270 | 6827 | return 0; | |
| 1271 | } | ||
| 1272 | |||
| 1273 |
2/2✓ Branch 0 taken 2196032 times.
✓ Branch 1 taken 1462845 times.
|
3658877 | for (i = 0; i < filter->nb_inputs; i++) { |
| 1274 | 2196032 | FilterLinkInternal *li = ff_link_internal(filter->inputs[i]); | |
| 1275 |
2/2✓ Branch 1 taken 733462 times.
✓ Branch 2 taken 1462570 times.
|
2196032 | if (samples_ready(li, li->l.min_samples)) { |
| 1276 | 733462 | return filter_frame_to_filter(filter->inputs[i]); | |
| 1277 | } | ||
| 1278 | } | ||
| 1279 |
2/2✓ Branch 0 taken 1462570 times.
✓ Branch 1 taken 1456850 times.
|
2919420 | for (i = 0; i < filter->nb_inputs; i++) { |
| 1280 | 1462570 | FilterLinkInternal * const li = ff_link_internal(filter->inputs[i]); | |
| 1281 |
4/4✓ Branch 0 taken 6024 times.
✓ Branch 1 taken 1456546 times.
✓ Branch 2 taken 5995 times.
✓ Branch 3 taken 29 times.
|
1462570 | if (li->status_in && !li->status_out) { |
| 1282 | av_assert1(!ff_framequeue_queued_frames(&li->fifo)); | ||
| 1283 | 5995 | return forward_status_change(filter, li); | |
| 1284 | } | ||
| 1285 | } | ||
| 1286 |
2/2✓ Branch 0 taken 1456826 times.
✓ Branch 1 taken 733397 times.
|
2190223 | for (i = 0; i < filter->nb_outputs; i++) { |
| 1287 | 1456826 | FilterLinkInternal * const li = ff_link_internal(filter->outputs[i]); | |
| 1288 |
2/2✓ Branch 0 taken 728312 times.
✓ Branch 1 taken 728514 times.
|
1456826 | if (li->frame_wanted_out && |
| 1289 |
2/2✓ Branch 0 taken 723453 times.
✓ Branch 1 taken 4859 times.
|
728312 | !li->frame_blocked_in) { |
| 1290 | 723453 | return request_frame_to_filter(filter->outputs[i]); | |
| 1291 | } | ||
| 1292 | } | ||
| 1293 |
2/2✓ Branch 0 taken 733373 times.
✓ Branch 1 taken 728538 times.
|
1461911 | for (i = 0; i < filter->nb_outputs; i++) { |
| 1294 | 733373 | FilterLinkInternal * const li = ff_link_internal(filter->outputs[i]); | |
| 1295 |
2/2✓ Branch 0 taken 4859 times.
✓ Branch 1 taken 728514 times.
|
733373 | if (li->frame_wanted_out) |
| 1296 | 4859 | return request_frame_to_filter(filter->outputs[i]); | |
| 1297 | } | ||
| 1298 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 728514 times.
|
728538 | if (!filter->nb_outputs) { |
| 1299 | 24 | ff_inlink_request_frame(filter->inputs[0]); | |
| 1300 | 24 | return 0; | |
| 1301 | } | ||
| 1302 | 728514 | return FFERROR_NOT_READY; | |
| 1303 | } | ||
| 1304 | |||
| 1305 | /* | ||
| 1306 | Filter scheduling and activation | ||
| 1307 | |||
| 1308 | When a filter is activated, it must: | ||
| 1309 | - if possible, output a frame; | ||
| 1310 | - else, if relevant, forward the input status change; | ||
| 1311 | - else, check outputs for wanted frames and forward the requests. | ||
| 1312 | |||
| 1313 | The following AVFilterLink fields are used for activation: | ||
| 1314 | |||
| 1315 | - frame_wanted_out: | ||
| 1316 | |||
| 1317 | This field indicates if a frame is needed on this input of the | ||
| 1318 | destination filter. A positive value indicates that a frame is needed | ||
| 1319 | to process queued frames or internal data or to satisfy the | ||
| 1320 | application; a zero value indicates that a frame is not especially | ||
| 1321 | needed but could be processed anyway; a negative value indicates that a | ||
| 1322 | frame would just be queued. | ||
| 1323 | |||
| 1324 | It is set by filters using ff_request_frame() or ff_request_no_frame(), | ||
| 1325 | when requested by the application through a specific API or when it is | ||
| 1326 | set on one of the outputs. | ||
| 1327 | |||
| 1328 | It is cleared when a frame is sent from the source using | ||
| 1329 | ff_filter_frame(). | ||
| 1330 | |||
| 1331 | It is also cleared when a status change is sent from the source using | ||
| 1332 | ff_avfilter_link_set_in_status(). | ||
| 1333 | |||
| 1334 | - frame_blocked_in: | ||
| 1335 | |||
| 1336 | This field means that the source filter can not generate a frame as is. | ||
| 1337 | Its goal is to avoid repeatedly calling the request_frame() method on | ||
| 1338 | the same link. | ||
| 1339 | |||
| 1340 | It is set by the framework on all outputs of a filter before activating it. | ||
| 1341 | |||
| 1342 | It is automatically cleared by ff_filter_frame(). | ||
| 1343 | |||
| 1344 | It is also automatically cleared by ff_avfilter_link_set_in_status(). | ||
| 1345 | |||
| 1346 | It is also cleared on all outputs (using filter_unblock()) when | ||
| 1347 | something happens on an input: processing a frame or changing the | ||
| 1348 | status. | ||
| 1349 | |||
| 1350 | - fifo: | ||
| 1351 | |||
| 1352 | Contains the frames queued on a filter input. If it contains frames and | ||
| 1353 | frame_wanted_out is not set, then the filter can be activated. If that | ||
| 1354 | result in the filter not able to use these frames, the filter must set | ||
| 1355 | frame_wanted_out to ask for more frames. | ||
| 1356 | |||
| 1357 | - status_in and status_in_pts: | ||
| 1358 | |||
| 1359 | Status (EOF or error code) of the link and timestamp of the status | ||
| 1360 | change (in link time base, same as frames) as seen from the input of | ||
| 1361 | the link. The status change is considered happening after the frames | ||
| 1362 | queued in fifo. | ||
| 1363 | |||
| 1364 | It is set by the source filter using ff_avfilter_link_set_in_status(). | ||
| 1365 | |||
| 1366 | - status_out: | ||
| 1367 | |||
| 1368 | Status of the link as seen from the output of the link. The status | ||
| 1369 | change is considered having already happened. | ||
| 1370 | |||
| 1371 | It is set by the destination filter using | ||
| 1372 | link_set_out_status(). | ||
| 1373 | |||
| 1374 | Filters are activated according to the ready field, set using the | ||
| 1375 | ff_filter_set_ready(). Eventually, a priority queue will be used. | ||
| 1376 | ff_filter_set_ready() is called whenever anything could cause progress to | ||
| 1377 | be possible. Marking a filter ready when it is not is not a problem, | ||
| 1378 | except for the small overhead it causes. | ||
| 1379 | |||
| 1380 | Conditions that cause a filter to be marked ready are: | ||
| 1381 | |||
| 1382 | - frames added on an input link; | ||
| 1383 | |||
| 1384 | - changes in the input or output status of an input link; | ||
| 1385 | |||
| 1386 | - requests for a frame on an output link; | ||
| 1387 | |||
| 1388 | - after any actual processing using the legacy methods (filter_frame(), | ||
| 1389 | and request_frame() to acknowledge status changes), to run once more | ||
| 1390 | and check if enough input was present for several frames. | ||
| 1391 | |||
| 1392 | Examples of scenarios to consider: | ||
| 1393 | |||
| 1394 | - buffersrc: activate if frame_wanted_out to notify the application; | ||
| 1395 | activate when the application adds a frame to push it immediately. | ||
| 1396 | |||
| 1397 | - testsrc: activate only if frame_wanted_out to produce and push a frame. | ||
| 1398 | |||
| 1399 | - concat (not at stitch points): can process a frame on any output. | ||
| 1400 | Activate if frame_wanted_out on output to forward on the corresponding | ||
| 1401 | input. Activate when a frame is present on input to process it | ||
| 1402 | immediately. | ||
| 1403 | |||
| 1404 | - framesync: needs at least one frame on each input; extra frames on the | ||
| 1405 | wrong input will accumulate. When a frame is first added on one input, | ||
| 1406 | set frame_wanted_out<0 on it to avoid getting more (would trigger | ||
| 1407 | testsrc) and frame_wanted_out>0 on the other to allow processing it. | ||
| 1408 | |||
| 1409 | Activation of old filters: | ||
| 1410 | |||
| 1411 | In order to activate a filter implementing the legacy filter_frame() and | ||
| 1412 | request_frame() methods, perform the first possible of the following | ||
| 1413 | actions: | ||
| 1414 | |||
| 1415 | - If an input has frames in fifo and frame_wanted_out == 0, dequeue a | ||
| 1416 | frame and call filter_frame(). | ||
| 1417 | |||
| 1418 | Rationale: filter frames as soon as possible instead of leaving them | ||
| 1419 | queued; frame_wanted_out < 0 is not possible since the old API does not | ||
| 1420 | set it nor provides any similar feedback; frame_wanted_out > 0 happens | ||
| 1421 | when min_samples > 0 and there are not enough samples queued. | ||
| 1422 | |||
| 1423 | - If an input has status_in set but not status_out, try to call | ||
| 1424 | request_frame() on one of the outputs in the hope that it will trigger | ||
| 1425 | request_frame() on the input with status_in and acknowledge it. This is | ||
| 1426 | awkward and fragile, filters with several inputs or outputs should be | ||
| 1427 | updated to direct activation as soon as possible. | ||
| 1428 | |||
| 1429 | - If an output has frame_wanted_out > 0 and not frame_blocked_in, call | ||
| 1430 | request_frame(). | ||
| 1431 | |||
| 1432 | Rationale: checking frame_blocked_in is necessary to avoid requesting | ||
| 1433 | repeatedly on a blocked input if another is not blocked (example: | ||
| 1434 | [buffersrc1][testsrc1][buffersrc2][testsrc2]concat=v=2). | ||
| 1435 | |||
| 1436 | - If an output has frame_wanted_out > 0 call request_frame(). | ||
| 1437 | |||
| 1438 | Rationale: even if all inputs are blocked an activate callback should | ||
| 1439 | request a frame on some if its inputs if a frame is requested on any of | ||
| 1440 | its output. | ||
| 1441 | |||
| 1442 | - Request a frame on the input for sinks. | ||
| 1443 | |||
| 1444 | Rationale: sinks using the old api have no way to request a frame on their | ||
| 1445 | input, so we need to do it for them. | ||
| 1446 | */ | ||
| 1447 | |||
| 1448 | 3844842 | int ff_filter_activate(AVFilterContext *filter) | |
| 1449 | { | ||
| 1450 | 3844842 | FFFilterContext *ctxi = fffilterctx(filter); | |
| 1451 | 3844842 | const FFFilter *const fi = fffilter(filter->filter); | |
| 1452 | int ret; | ||
| 1453 | |||
| 1454 | /* Generic timeline support is not yet implemented but should be easy */ | ||
| 1455 | av_assert1(!(fi->p.flags & AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC && | ||
| 1456 | fi->activate)); | ||
| 1457 | 3844842 | ctxi->ready = 0; | |
| 1458 |
2/2✓ Branch 0 taken 1641708 times.
✓ Branch 1 taken 2203134 times.
|
3844842 | ret = fi->activate ? fi->activate(filter) : filter_activate_default(filter); |
| 1459 |
2/2✓ Branch 0 taken 729386 times.
✓ Branch 1 taken 3115456 times.
|
3844842 | if (ret == FFERROR_NOT_READY) |
| 1460 | 729386 | ret = 0; | |
| 1461 | 3844842 | return ret; | |
| 1462 | } | ||
| 1463 | |||
| 1464 | 3533415 | int ff_inlink_acknowledge_status(AVFilterLink *link, int *rstatus, int64_t *rpts) | |
| 1465 | { | ||
| 1466 | 3533415 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1467 | 3533415 | *rpts = li->l.current_pts; | |
| 1468 |
2/2✓ Branch 1 taken 2170 times.
✓ Branch 2 taken 3531245 times.
|
3533415 | if (ff_framequeue_queued_frames(&li->fifo)) |
| 1469 | 2170 | return *rstatus = 0; | |
| 1470 |
2/2✓ Branch 0 taken 7937 times.
✓ Branch 1 taken 3523308 times.
|
3531245 | if (li->status_out) |
| 1471 | 7937 | return *rstatus = li->status_out; | |
| 1472 |
2/2✓ Branch 0 taken 3515388 times.
✓ Branch 1 taken 7920 times.
|
3523308 | if (!li->status_in) |
| 1473 | 3515388 | return *rstatus = 0; | |
| 1474 | 7920 | *rstatus = li->status_out = li->status_in; | |
| 1475 | 7920 | update_link_current_pts(li, li->status_in_pts); | |
| 1476 | 7920 | *rpts = li->l.current_pts; | |
| 1477 | 7920 | return 1; | |
| 1478 | } | ||
| 1479 | |||
| 1480 | 1934 | size_t ff_inlink_queued_frames(AVFilterLink *link) | |
| 1481 | { | ||
| 1482 | 1934 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1483 | 1934 | return ff_framequeue_queued_frames(&li->fifo); | |
| 1484 | } | ||
| 1485 | |||
| 1486 | 5066276 | int ff_inlink_check_available_frame(AVFilterLink *link) | |
| 1487 | { | ||
| 1488 | 5066276 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1489 | 5066276 | return ff_framequeue_queued_frames(&li->fifo) > 0; | |
| 1490 | } | ||
| 1491 | |||
| 1492 | 8543 | int ff_inlink_queued_samples(AVFilterLink *link) | |
| 1493 | { | ||
| 1494 | 8543 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1495 | 8543 | return ff_framequeue_queued_samples(&li->fifo); | |
| 1496 | } | ||
| 1497 | |||
| 1498 | 5035 | int ff_inlink_check_available_samples(AVFilterLink *link, unsigned min) | |
| 1499 | { | ||
| 1500 | 5035 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1501 | 5035 | uint64_t samples = ff_framequeue_queued_samples(&li->fifo); | |
| 1502 | av_assert1(min); | ||
| 1503 |
6/6✓ Branch 0 taken 2110 times.
✓ Branch 1 taken 2925 times.
✓ Branch 2 taken 65 times.
✓ Branch 3 taken 2045 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 59 times.
|
5035 | return samples >= min || (li->status_in && samples); |
| 1504 | } | ||
| 1505 | |||
| 1506 | 1543576 | static void consume_update(FilterLinkInternal *li, const AVFrame *frame) | |
| 1507 | { | ||
| 1508 | 1543576 | AVFilterLink *const link = &li->l.pub; | |
| 1509 | 1543576 | update_link_current_pts(li, frame->pts); | |
| 1510 | 1543576 | ff_inlink_process_commands(link, frame); | |
| 1511 |
2/2✓ Branch 0 taken 1540847 times.
✓ Branch 1 taken 2729 times.
|
1543576 | if (link == link->dst->inputs[0]) |
| 1512 | 1540847 | link->dst->is_disabled = !evaluate_timeline_at_frame(link, frame); | |
| 1513 | 1543576 | li->l.frame_count_out++; | |
| 1514 | 1543576 | li->l.sample_count_out += frame->nb_samples; | |
| 1515 | 1543576 | } | |
| 1516 | |||
| 1517 | 5064391 | int ff_inlink_consume_frame(AVFilterLink *link, AVFrame **rframe) | |
| 1518 | { | ||
| 1519 | 5064391 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1520 | AVFrame *frame; | ||
| 1521 | |||
| 1522 | 5064391 | *rframe = NULL; | |
| 1523 |
2/2✓ Branch 1 taken 3523742 times.
✓ Branch 2 taken 1540649 times.
|
5064391 | if (!ff_inlink_check_available_frame(link)) |
| 1524 | 3523742 | return 0; | |
| 1525 | |||
| 1526 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1540645 times.
|
1540649 | if (li->fifo.samples_skipped) { |
| 1527 | 4 | frame = ff_framequeue_peek(&li->fifo, 0); | |
| 1528 | 4 | return ff_inlink_consume_samples(link, frame->nb_samples, frame->nb_samples, rframe); | |
| 1529 | } | ||
| 1530 | |||
| 1531 | 1540645 | frame = ff_framequeue_take(&li->fifo); | |
| 1532 | 1540645 | consume_update(li, frame); | |
| 1533 | 1540645 | *rframe = frame; | |
| 1534 | 1540645 | return 1; | |
| 1535 | } | ||
| 1536 | |||
| 1537 | 5035 | int ff_inlink_consume_samples(AVFilterLink *link, unsigned min, unsigned max, | |
| 1538 | AVFrame **rframe) | ||
| 1539 | { | ||
| 1540 | 5035 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1541 | AVFrame *frame; | ||
| 1542 | int ret; | ||
| 1543 | |||
| 1544 | av_assert1(min); | ||
| 1545 | 5035 | *rframe = NULL; | |
| 1546 |
2/2✓ Branch 1 taken 2104 times.
✓ Branch 2 taken 2931 times.
|
5035 | if (!ff_inlink_check_available_samples(link, min)) |
| 1547 | 2104 | return 0; | |
| 1548 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 2919 times.
|
2931 | if (li->status_in) |
| 1549 |
2/2✓ Branch 1 taken 6 times.
✓ Branch 2 taken 6 times.
|
12 | min = FFMIN(min, ff_framequeue_queued_samples(&li->fifo)); |
| 1550 | 2931 | ret = take_samples(li, min, max, &frame); | |
| 1551 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2931 times.
|
2931 | if (ret < 0) |
| 1552 | ✗ | return ret; | |
| 1553 | 2931 | consume_update(li, frame); | |
| 1554 | 2931 | *rframe = frame; | |
| 1555 | 2931 | return 1; | |
| 1556 | } | ||
| 1557 | |||
| 1558 | 210 | AVFrame *ff_inlink_peek_frame(AVFilterLink *link, size_t idx) | |
| 1559 | { | ||
| 1560 | 210 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1561 | 210 | return ff_framequeue_peek(&li->fifo, idx); | |
| 1562 | } | ||
| 1563 | |||
| 1564 | 5159 | int ff_inlink_make_frame_writable(AVFilterLink *link, AVFrame **rframe) | |
| 1565 | { | ||
| 1566 | 5159 | AVFrame *frame = *rframe; | |
| 1567 | AVFrame *out; | ||
| 1568 | int ret; | ||
| 1569 | |||
| 1570 |
2/2✓ Branch 1 taken 2288 times.
✓ Branch 2 taken 2871 times.
|
5159 | if (av_frame_is_writable(frame)) |
| 1571 | 2288 | return 0; | |
| 1572 | 2871 | av_log(link->dst, AV_LOG_DEBUG, "Copying data in avfilter.\n"); | |
| 1573 | |||
| 1574 |
1/3✓ Branch 0 taken 2871 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
2871 | switch (link->type) { |
| 1575 | 2871 | case AVMEDIA_TYPE_VIDEO: | |
| 1576 | 2871 | out = ff_get_video_buffer(link, link->w, link->h); | |
| 1577 | 2871 | break; | |
| 1578 | ✗ | case AVMEDIA_TYPE_AUDIO: | |
| 1579 | ✗ | out = ff_get_audio_buffer(link, frame->nb_samples); | |
| 1580 | ✗ | break; | |
| 1581 | ✗ | default: | |
| 1582 | ✗ | return AVERROR(EINVAL); | |
| 1583 | } | ||
| 1584 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2871 times.
|
2871 | if (!out) |
| 1585 | ✗ | return AVERROR(ENOMEM); | |
| 1586 | |||
| 1587 | 2871 | ret = av_frame_copy_props(out, frame); | |
| 1588 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2871 times.
|
2871 | if (ret < 0) { |
| 1589 | ✗ | av_frame_free(&out); | |
| 1590 | ✗ | return ret; | |
| 1591 | } | ||
| 1592 | |||
| 1593 | 2871 | ret = av_frame_copy(out, frame); | |
| 1594 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2871 times.
|
2871 | if (ret < 0) { |
| 1595 | ✗ | av_frame_free(&out); | |
| 1596 | ✗ | return ret; | |
| 1597 | } | ||
| 1598 | |||
| 1599 | 2871 | av_frame_free(&frame); | |
| 1600 | 2871 | *rframe = out; | |
| 1601 | 2871 | return 0; | |
| 1602 | } | ||
| 1603 | |||
| 1604 | 2277038 | int ff_inlink_process_commands(AVFilterLink *link, const AVFrame *frame) | |
| 1605 | { | ||
| 1606 | 2277038 | FFFilterContext *ctxi = fffilterctx(link->dst); | |
| 1607 | 2277038 | AVFilterCommand *cmd = ctxi->command_queue; | |
| 1608 | |||
| 1609 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 2277038 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
2277038 | while(cmd && cmd->time <= frame->pts * av_q2d(link->time_base)){ |
| 1610 | ✗ | av_log(link->dst, AV_LOG_DEBUG, | |
| 1611 | "Processing command time:%f command:%s arg:%s\n", | ||
| 1612 | cmd->time, cmd->command, cmd->arg); | ||
| 1613 | ✗ | avfilter_process_command(link->dst, cmd->command, cmd->arg, 0, 0, cmd->flags); | |
| 1614 | ✗ | command_queue_pop(link->dst); | |
| 1615 | ✗ | cmd = ctxi->command_queue; | |
| 1616 | } | ||
| 1617 | 2277038 | return 0; | |
| 1618 | } | ||
| 1619 | |||
| 1620 | 817024 | void ff_inlink_request_frame(AVFilterLink *link) | |
| 1621 | { | ||
| 1622 | 817024 | av_unused FilterLinkInternal *li = ff_link_internal(link); | |
| 1623 | av_assert1(!li->status_in); | ||
| 1624 | av_assert1(!li->status_out); | ||
| 1625 | 817024 | li->frame_wanted_out = 1; | |
| 1626 | 817024 | ff_filter_set_ready(link->src, 100); | |
| 1627 | 817024 | } | |
| 1628 | |||
| 1629 | 10927 | void ff_inlink_set_status(AVFilterLink *link, int status) | |
| 1630 | { | ||
| 1631 | 10927 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1632 |
2/2✓ Branch 0 taken 8451 times.
✓ Branch 1 taken 2476 times.
|
10927 | if (li->status_out) |
| 1633 | 8451 | return; | |
| 1634 | 2476 | li->frame_wanted_out = 0; | |
| 1635 | 2476 | li->frame_blocked_in = 0; | |
| 1636 | 2476 | link_set_out_status(link, status, AV_NOPTS_VALUE); | |
| 1637 |
2/2✓ Branch 1 taken 7 times.
✓ Branch 2 taken 2476 times.
|
2483 | while (ff_framequeue_queued_frames(&li->fifo)) { |
| 1638 | 7 | AVFrame *frame = ff_framequeue_take(&li->fifo); | |
| 1639 | 7 | av_frame_free(&frame); | |
| 1640 | } | ||
| 1641 |
2/2✓ Branch 0 taken 2473 times.
✓ Branch 1 taken 3 times.
|
2476 | if (!li->status_in) |
| 1642 | 2473 | li->status_in = status; | |
| 1643 | } | ||
| 1644 | |||
| 1645 | 3769890 | int ff_outlink_get_status(AVFilterLink *link) | |
| 1646 | { | ||
| 1647 | 3769890 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1648 | 3769890 | return li->status_in; | |
| 1649 | } | ||
| 1650 | |||
| 1651 | 1478 | int ff_inoutlink_check_flow(AVFilterLink *inlink, AVFilterLink *outlink) | |
| 1652 | { | ||
| 1653 | 1478 | FilterLinkInternal * const li_in = ff_link_internal(inlink); | |
| 1654 |
1/2✓ Branch 1 taken 887 times.
✗ Branch 2 not taken.
|
2365 | return ff_outlink_frame_wanted(outlink) || |
| 1655 |
2/2✓ Branch 0 taken 887 times.
✓ Branch 1 taken 591 times.
|
2365 | ff_inlink_check_available_frame(inlink) || |
| 1656 |
2/2✓ Branch 0 taken 27 times.
✓ Branch 1 taken 860 times.
|
887 | li_in->status_out; |
| 1657 | } | ||
| 1658 | |||
| 1659 | |||
| 1660 | ✗ | const AVClass *avfilter_get_class(void) | |
| 1661 | { | ||
| 1662 | ✗ | return &avfilter_class; | |
| 1663 | } | ||
| 1664 | |||
| 1665 | ✗ | int ff_filter_init_hw_frames(AVFilterContext *avctx, AVFilterLink *link, | |
| 1666 | int default_pool_size) | ||
| 1667 | { | ||
| 1668 | ✗ | FilterLink *l = ff_filter_link(link); | |
| 1669 | AVHWFramesContext *frames; | ||
| 1670 | |||
| 1671 | // Must already be set by caller. | ||
| 1672 | ✗ | av_assert0(l->hw_frames_ctx); | |
| 1673 | |||
| 1674 | ✗ | frames = (AVHWFramesContext*)l->hw_frames_ctx->data; | |
| 1675 | |||
| 1676 | ✗ | if (frames->initial_pool_size == 0) { | |
| 1677 | // Dynamic allocation is necessarily supported. | ||
| 1678 | ✗ | } else if (avctx->extra_hw_frames >= 0) { | |
| 1679 | ✗ | frames->initial_pool_size += avctx->extra_hw_frames; | |
| 1680 | } else { | ||
| 1681 | ✗ | frames->initial_pool_size = default_pool_size; | |
| 1682 | } | ||
| 1683 | |||
| 1684 | ✗ | return 0; | |
| 1685 | } | ||
| 1686 | |||
| 1687 | 447396 | int ff_outlink_frame_wanted(AVFilterLink *link) | |
| 1688 | { | ||
| 1689 | 447396 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1690 | 447396 | return li->frame_wanted_out; | |
| 1691 | } | ||
| 1692 | |||
| 1693 | 4989 | int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, | |
| 1694 | void *arg, int *ret, int nb_jobs) | ||
| 1695 | { | ||
| 1696 | 4989 | return fffilterctx(ctx)->execute(ctx, func, arg, ret, nb_jobs); | |
| 1697 | } | ||
| 1698 |