| 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 | 1759266 | 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 | 1759266 | } | |
| 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 | 814 | static int append_pad(unsigned *count, AVFilterPad **pads, | |
| 101 | AVFilterLink ***links, AVFilterPad *newpad) | ||
| 102 | { | ||
| 103 | AVFilterLink **newlinks; | ||
| 104 | AVFilterPad *newpads; | ||
| 105 | 814 | unsigned idx = *count; | |
| 106 | |||
| 107 | 814 | newpads = av_realloc_array(*pads, idx + 1, sizeof(*newpads)); | |
| 108 | 814 | newlinks = av_realloc_array(*links, idx + 1, sizeof(*newlinks)); | |
| 109 |
1/2✓ Branch 0 taken 814 times.
✗ Branch 1 not taken.
|
814 | if (newpads) |
| 110 | 814 | *pads = newpads; | |
| 111 |
1/2✓ Branch 0 taken 814 times.
✗ Branch 1 not taken.
|
814 | if (newlinks) |
| 112 | 814 | *links = newlinks; | |
| 113 |
2/4✓ Branch 0 taken 814 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 814 times.
|
814 | if (!newpads || !newlinks) { |
| 114 | ✗ | if (newpad->flags & AVFILTERPAD_FLAG_FREE_NAME) | |
| 115 | ✗ | av_freep(&newpad->name); | |
| 116 | ✗ | return AVERROR(ENOMEM); | |
| 117 | } | ||
| 118 | |||
| 119 | 814 | memcpy(*pads + idx, newpad, sizeof(AVFilterPad)); | |
| 120 | 814 | (*links)[idx] = NULL; | |
| 121 | |||
| 122 | 814 | (*count)++; | |
| 123 | |||
| 124 | 814 | return 0; | |
| 125 | } | ||
| 126 | |||
| 127 | 295 | int ff_append_inpad(AVFilterContext *f, AVFilterPad *p) | |
| 128 | { | ||
| 129 | 295 | return append_pad(&f->nb_inputs, &f->input_pads, &f->inputs, p); | |
| 130 | } | ||
| 131 | |||
| 132 | 272 | int ff_append_inpad_free_name(AVFilterContext *f, AVFilterPad *p) | |
| 133 | { | ||
| 134 | 272 | p->flags |= AVFILTERPAD_FLAG_FREE_NAME; | |
| 135 | 272 | return ff_append_inpad(f, p); | |
| 136 | } | ||
| 137 | |||
| 138 | 519 | int ff_append_outpad(AVFilterContext *f, AVFilterPad *p) | |
| 139 | { | ||
| 140 | 519 | return append_pad(&f->nb_outputs, &f->output_pads, &f->outputs, p); | |
| 141 | } | ||
| 142 | |||
| 143 | 377 | int ff_append_outpad_free_name(AVFilterContext *f, AVFilterPad *p) | |
| 144 | { | ||
| 145 | 377 | p->flags |= AVFILTERPAD_FLAG_FREE_NAME; | |
| 146 | 377 | return ff_append_outpad(f, p); | |
| 147 | } | ||
| 148 | |||
| 149 | 48821 | 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 48821 times.
|
48821 | av_assert0(src->graph); |
| 156 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 48821 times.
|
48821 | av_assert0(dst->graph); |
| 157 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 48821 times.
|
48821 | av_assert0(src->graph == dst->graph); |
| 158 | |||
| 159 |
2/4✓ Branch 0 taken 48821 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 48821 times.
✗ Branch 3 not taken.
|
48821 | if (src->nb_outputs <= srcpad || dst->nb_inputs <= dstpad || |
| 160 |
2/4✓ Branch 0 taken 48821 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 48821 times.
|
48821 | src->outputs[srcpad] || dst->inputs[dstpad]) |
| 161 | ✗ | return AVERROR(EINVAL); | |
| 162 | |||
| 163 |
1/2✓ Branch 1 taken 48821 times.
✗ Branch 2 not taken.
|
48821 | if (!(fffilterctx(src)->state_flags & AV_CLASS_STATE_INITIALIZED) || |
| 164 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 48821 times.
|
48821 | !(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 48821 times.
|
48821 | 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 | 48821 | li = av_mallocz(sizeof(*li)); | |
| 178 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 48821 times.
|
48821 | if (!li) |
| 179 | ✗ | return AVERROR(ENOMEM); | |
| 180 | 48821 | link = &li->l.pub; | |
| 181 | |||
| 182 | 48821 | src->outputs[srcpad] = dst->inputs[dstpad] = link; | |
| 183 | |||
| 184 | 48821 | link->src = src; | |
| 185 | 48821 | link->dst = dst; | |
| 186 | 48821 | link->srcpad = &src->output_pads[srcpad]; | |
| 187 | 48821 | link->dstpad = &dst->input_pads[dstpad]; | |
| 188 | 48821 | link->type = src->output_pads[srcpad].type; | |
| 189 | 48821 | li->l.graph = src->graph; | |
| 190 | av_assert0(AV_PIX_FMT_NONE == -1 && AV_SAMPLE_FMT_NONE == -1); | ||
| 191 | 48821 | link->format = -1; | |
| 192 | 48821 | link->colorspace = AVCOL_SPC_UNSPECIFIED; | |
| 193 | 48821 | ff_framequeue_init(&li->fifo, &fffiltergraph(src->graph)->frame_queues); | |
| 194 | |||
| 195 | 48821 | return 0; | |
| 196 | } | ||
| 197 | |||
| 198 | 48953 | static void link_free(AVFilterLink **link) | |
| 199 | { | ||
| 200 | FilterLinkInternal *li; | ||
| 201 | |||
| 202 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 48953 times.
|
48953 | if (!*link) |
| 203 | ✗ | return; | |
| 204 | 48953 | li = ff_link_internal(*link); | |
| 205 | |||
| 206 | 48953 | ff_framequeue_free(&li->fifo); | |
| 207 | 48953 | ff_frame_pool_uninit(&li->frame_pool); | |
| 208 | 48953 | av_channel_layout_uninit(&(*link)->ch_layout); | |
| 209 | 48953 | av_frame_side_data_free(&(*link)->side_data, &(*link)->nb_side_data); | |
| 210 | |||
| 211 | 48953 | av_buffer_unref(&li->l.hw_frames_ctx); | |
| 212 | |||
| 213 | 48953 | av_freep(link); | |
| 214 | } | ||
| 215 | |||
| 216 | 1771789 | static void update_link_current_pts(FilterLinkInternal *li, int64_t pts) | |
| 217 | { | ||
| 218 | 1771789 | AVFilterLink *const link = &li->l.pub; | |
| 219 | |||
| 220 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1771784 times.
|
1771789 | if (pts == AV_NOPTS_VALUE) |
| 221 | 5 | return; | |
| 222 | 1771784 | li->l.current_pts = pts; | |
| 223 | 1771784 | 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 1771784 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 476519 times.
✓ Branch 3 taken 1295265 times.
|
1771784 | if (li->l.graph && li->age_index >= 0) |
| 226 | 476519 | ff_avfilter_graph_update_heap(li->l.graph, li); | |
| 227 | } | ||
| 228 | |||
| 229 | 4377416 | void ff_filter_set_ready(AVFilterContext *filter, unsigned priority) | |
| 230 | { | ||
| 231 | 4377416 | FFFilterContext *ctxi = fffilterctx(filter); | |
| 232 | 4377416 | ctxi->ready = FFMAX(ctxi->ready, priority); | |
| 233 | 4377416 | } | |
| 234 | |||
| 235 | /** | ||
| 236 | * Clear frame_blocked_in on all outputs. | ||
| 237 | * This is necessary whenever something changes on input. | ||
| 238 | */ | ||
| 239 | 2616704 | static void filter_unblock(AVFilterContext *filter) | |
| 240 | { | ||
| 241 | unsigned i; | ||
| 242 | |||
| 243 |
2/2✓ Branch 0 taken 2143544 times.
✓ Branch 1 taken 2616704 times.
|
4760248 | for (i = 0; i < filter->nb_outputs; i++) { |
| 244 | 2143544 | FilterLinkInternal * const li = ff_link_internal(filter->outputs[i]); | |
| 245 | 2143544 | li->frame_blocked_in = 0; | |
| 246 | } | ||
| 247 | 2616704 | } | |
| 248 | |||
| 249 | |||
| 250 | 21026 | void ff_avfilter_link_set_in_status(AVFilterLink *link, int status, int64_t pts) | |
| 251 | { | ||
| 252 | 21026 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 253 | |||
| 254 |
2/2✓ Branch 0 taken 5912 times.
✓ Branch 1 taken 15114 times.
|
21026 | if (li->status_in == status) |
| 255 | 5912 | return; | |
| 256 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15114 times.
|
15114 | av_assert0(!li->status_in); |
| 257 | 15114 | li->status_in = status; | |
| 258 | 15114 | li->status_in_pts = pts; | |
| 259 | 15114 | li->frame_wanted_out = 0; | |
| 260 | 15114 | li->frame_blocked_in = 0; | |
| 261 | 15114 | filter_unblock(link->dst); | |
| 262 | 15114 | 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 | 9009 | static void link_set_out_status(AVFilterLink *link, int status, int64_t pts) | |
| 270 | { | ||
| 271 | 9009 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 272 | |||
| 273 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9009 times.
|
9009 | av_assert0(!li->frame_wanted_out); |
| 274 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9009 times.
|
9009 | av_assert0(!li->status_out); |
| 275 | 9009 | li->status_out = status; | |
| 276 |
2/2✓ Branch 0 taken 6447 times.
✓ Branch 1 taken 2562 times.
|
9009 | if (pts != AV_NOPTS_VALUE) |
| 277 | 6447 | update_link_current_pts(li, pts); | |
| 278 | 9009 | filter_unblock(link->dst); | |
| 279 | 9009 | ff_filter_set_ready(link->src, 200); | |
| 280 | 9009 | } | |
| 281 | |||
| 282 | 1577 | int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt, | |
| 283 | unsigned filt_srcpad_idx, unsigned filt_dstpad_idx) | ||
| 284 | { | ||
| 285 | int ret; | ||
| 286 | 1577 | unsigned dstpad_idx = link->dstpad - link->dst->input_pads; | |
| 287 | |||
| 288 | 1577 | av_log(link->dst, AV_LOG_VERBOSE, "auto-inserting filter '%s' " | |
| 289 | "between the filter '%s' and the filter '%s'\n", | ||
| 290 | 1577 | filt->name, link->src->name, link->dst->name); | |
| 291 | |||
| 292 | 1577 | link->dst->inputs[dstpad_idx] = NULL; | |
| 293 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1577 times.
|
1577 | 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 | 1577 | link->dst = filt; | |
| 301 | 1577 | link->dstpad = &filt->input_pads[filt_srcpad_idx]; | |
| 302 | 1577 | 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 1577 times.
✗ Branch 1 not taken.
|
1577 | if (link->outcfg.formats) |
| 307 | 1577 | ff_formats_changeref(&link->outcfg.formats, | |
| 308 | 1577 | &filt->outputs[filt_dstpad_idx]->outcfg.formats); | |
| 309 |
2/2✓ Branch 0 taken 765 times.
✓ Branch 1 taken 812 times.
|
1577 | if (link->outcfg.color_spaces) |
| 310 | 765 | ff_formats_changeref(&link->outcfg.color_spaces, | |
| 311 | 765 | &filt->outputs[filt_dstpad_idx]->outcfg.color_spaces); | |
| 312 |
2/2✓ Branch 0 taken 765 times.
✓ Branch 1 taken 812 times.
|
1577 | if (link->outcfg.color_ranges) |
| 313 | 765 | ff_formats_changeref(&link->outcfg.color_ranges, | |
| 314 | 765 | &filt->outputs[filt_dstpad_idx]->outcfg.color_ranges); | |
| 315 |
2/2✓ Branch 0 taken 765 times.
✓ Branch 1 taken 812 times.
|
1577 | if (link->outcfg.alpha_modes) |
| 316 | 765 | ff_formats_changeref(&link->outcfg.alpha_modes, | |
| 317 | 765 | &filt->outputs[filt_dstpad_idx]->outcfg.alpha_modes); | |
| 318 |
2/2✓ Branch 0 taken 765 times.
✓ Branch 1 taken 812 times.
|
1577 | if (link->outcfg.chroma_locations) |
| 319 | 765 | ff_formats_changeref(&link->outcfg.chroma_locations, | |
| 320 | 765 | &filt->outputs[filt_dstpad_idx]->outcfg.chroma_locations); | |
| 321 |
2/2✓ Branch 0 taken 812 times.
✓ Branch 1 taken 765 times.
|
1577 | if (link->outcfg.samplerates) |
| 322 | 812 | ff_formats_changeref(&link->outcfg.samplerates, | |
| 323 | 812 | &filt->outputs[filt_dstpad_idx]->outcfg.samplerates); | |
| 324 |
2/2✓ Branch 0 taken 812 times.
✓ Branch 1 taken 765 times.
|
1577 | if (link->outcfg.channel_layouts) |
| 325 | 812 | ff_channel_layouts_changeref(&link->outcfg.channel_layouts, | |
| 326 | 812 | &filt->outputs[filt_dstpad_idx]->outcfg.channel_layouts); | |
| 327 | |||
| 328 | 1577 | return 0; | |
| 329 | } | ||
| 330 | |||
| 331 | 46947 | int ff_filter_config_links(AVFilterContext *filter) | |
| 332 | { | ||
| 333 | int (*config_link)(AVFilterLink *); | ||
| 334 | unsigned i; | ||
| 335 | int ret; | ||
| 336 | |||
| 337 |
2/2✓ Branch 0 taken 38497 times.
✓ Branch 1 taken 46943 times.
|
85440 | for (i = 0; i < filter->nb_inputs; i ++) { |
| 338 | 38497 | AVFilterLink *link = filter->inputs[i]; | |
| 339 | AVFilterLink *inlink; | ||
| 340 | 38497 | FilterLinkInternal *li = ff_link_internal(link); | |
| 341 | FilterLinkInternal *li_in; | ||
| 342 | |||
| 343 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 38497 times.
|
38497 | if (!link) continue; |
| 344 |
2/4✓ Branch 0 taken 38497 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 38497 times.
|
38497 | if (!link->src || !link->dst) { |
| 345 | ✗ | av_log(filter, AV_LOG_ERROR, | |
| 346 | "Not all input and output are properly linked (%d).\n", i); | ||
| 347 | ✗ | return AVERROR(EINVAL); | |
| 348 | } | ||
| 349 | |||
| 350 |
2/2✓ Branch 0 taken 29730 times.
✓ Branch 1 taken 8767 times.
|
38497 | inlink = link->src->nb_inputs ? link->src->inputs[0] : NULL; |
| 351 |
2/2✓ Branch 0 taken 29730 times.
✓ Branch 1 taken 8767 times.
|
38497 | li_in = inlink ? ff_link_internal(inlink) : NULL; |
| 352 | 38497 | li->l.current_pts = | |
| 353 | 38497 | li->l.current_pts_us = AV_NOPTS_VALUE; | |
| 354 | |||
| 355 |
3/4✓ Branch 0 taken 217 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 38278 times.
✗ Branch 3 not taken.
|
38497 | switch (li->init_state) { |
| 356 | 217 | case AVLINK_INIT: | |
| 357 | 217 | continue; | |
| 358 | 2 | case AVLINK_STARTINIT: | |
| 359 | 2 | av_log(filter, AV_LOG_INFO, "circular filter chain detected\n"); | |
| 360 | 2 | return 0; | |
| 361 | 38278 | case AVLINK_UNINIT: | |
| 362 | 38278 | li->init_state = AVLINK_STARTINIT; | |
| 363 | |||
| 364 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 38277 times.
|
38278 | if ((ret = ff_filter_config_links(link->src)) < 0) |
| 365 | 1 | return ret; | |
| 366 | |||
| 367 |
2/2✓ Branch 0 taken 19998 times.
✓ Branch 1 taken 18279 times.
|
38277 | if (!(config_link = link->srcpad->config_props)) { |
| 368 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19998 times.
|
19998 | if (link->src->nb_inputs != 1) { |
| 369 | ✗ | av_log(link->src, AV_LOG_ERROR, "Source filters and filters " | |
| 370 | "with more than one input " | ||
| 371 | "must set config_props() " | ||
| 372 | "callbacks on all outputs\n"); | ||
| 373 | ✗ | return AVERROR(EINVAL); | |
| 374 | } | ||
| 375 | } | ||
| 376 | |||
| 377 | /* Copy side data before link->srcpad->config_props() is called, so the filter | ||
| 378 | * may remove it for the next filter in the chain */ | ||
| 379 |
5/6✓ Branch 0 taken 29643 times.
✓ Branch 1 taken 8634 times.
✓ Branch 2 taken 332 times.
✓ Branch 3 taken 29311 times.
✓ Branch 4 taken 332 times.
✗ Branch 5 not taken.
|
38277 | if (inlink && inlink->nb_side_data && !link->nb_side_data) { |
| 380 |
2/2✓ Branch 0 taken 377 times.
✓ Branch 1 taken 332 times.
|
709 | for (int j = 0; j < inlink->nb_side_data; j++) { |
| 381 | 377 | ret = av_frame_side_data_clone(&link->side_data, &link->nb_side_data, | |
| 382 | 377 | inlink->side_data[j], 0); | |
| 383 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 377 times.
|
377 | if (ret < 0) { |
| 384 | ✗ | av_frame_side_data_free(&link->side_data, &link->nb_side_data); | |
| 385 | ✗ | return ret; | |
| 386 | } | ||
| 387 | } | ||
| 388 | } | ||
| 389 | |||
| 390 |
4/4✓ Branch 0 taken 18279 times.
✓ Branch 1 taken 19998 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 18278 times.
|
38277 | if (config_link && (ret = config_link(link)) < 0) { |
| 391 | 1 | av_log(link->src, AV_LOG_ERROR, | |
| 392 | "Failed to configure output pad on %s\n", | ||
| 393 | 1 | link->src->name); | |
| 394 | 1 | return ret; | |
| 395 | } | ||
| 396 | |||
| 397 |
2/3✓ Branch 0 taken 31528 times.
✓ Branch 1 taken 6748 times.
✗ Branch 2 not taken.
|
38276 | switch (link->type) { |
| 398 | 31528 | case AVMEDIA_TYPE_VIDEO: | |
| 399 |
3/4✓ Branch 0 taken 24128 times.
✓ Branch 1 taken 7400 times.
✓ Branch 2 taken 24128 times.
✗ Branch 3 not taken.
|
31528 | if (!link->time_base.num && !link->time_base.den) |
| 400 |
1/2✓ Branch 0 taken 24128 times.
✗ Branch 1 not taken.
|
24128 | link->time_base = inlink ? inlink->time_base : AV_TIME_BASE_Q; |
| 401 | |||
| 402 |
4/4✓ Branch 0 taken 26828 times.
✓ Branch 1 taken 4700 times.
✓ Branch 2 taken 17082 times.
✓ Branch 3 taken 9746 times.
|
31528 | if (!link->sample_aspect_ratio.num && !link->sample_aspect_ratio.den) |
| 403 | 17082 | link->sample_aspect_ratio = inlink ? | |
| 404 |
2/2✓ Branch 0 taken 17067 times.
✓ Branch 1 taken 15 times.
|
17082 | inlink->sample_aspect_ratio : (AVRational){1,1}; |
| 405 | |||
| 406 |
2/2✓ Branch 0 taken 24409 times.
✓ Branch 1 taken 7119 times.
|
31528 | if (inlink) { |
| 407 |
3/4✓ Branch 0 taken 24171 times.
✓ Branch 1 taken 238 times.
✓ Branch 2 taken 24171 times.
✗ Branch 3 not taken.
|
24409 | if (!li->l.frame_rate.num && !li->l.frame_rate.den) |
| 408 | 24171 | li->l.frame_rate = li_in->l.frame_rate; | |
| 409 |
2/2✓ Branch 0 taken 16572 times.
✓ Branch 1 taken 7837 times.
|
24409 | if (!link->w) |
| 410 | 16572 | link->w = inlink->w; | |
| 411 |
2/2✓ Branch 0 taken 16572 times.
✓ Branch 1 taken 7837 times.
|
24409 | if (!link->h) |
| 412 | 16572 | link->h = inlink->h; | |
| 413 |
2/4✓ Branch 0 taken 7119 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7119 times.
|
7119 | } else if (!link->w || !link->h) { |
| 414 | ✗ | av_log(link->src, AV_LOG_ERROR, | |
| 415 | "Video source filters must set their output link's " | ||
| 416 | "width and height\n"); | ||
| 417 | ✗ | return AVERROR(EINVAL); | |
| 418 | } | ||
| 419 | 31528 | break; | |
| 420 | |||
| 421 | 6748 | case AVMEDIA_TYPE_AUDIO: | |
| 422 |
2/2✓ Branch 0 taken 5233 times.
✓ Branch 1 taken 1515 times.
|
6748 | if (inlink) { |
| 423 |
3/4✓ Branch 0 taken 3533 times.
✓ Branch 1 taken 1700 times.
✓ Branch 2 taken 3533 times.
✗ Branch 3 not taken.
|
5233 | if (!link->time_base.num && !link->time_base.den) |
| 424 | 3533 | link->time_base = inlink->time_base; | |
| 425 | } | ||
| 426 | |||
| 427 |
3/4✓ Branch 0 taken 88 times.
✓ Branch 1 taken 6660 times.
✓ Branch 2 taken 88 times.
✗ Branch 3 not taken.
|
6748 | if (!link->time_base.num && !link->time_base.den) |
| 428 | 88 | link->time_base = (AVRational) {1, link->sample_rate}; | |
| 429 | } | ||
| 430 | |||
| 431 |
2/2✓ Branch 0 taken 29642 times.
✓ Branch 1 taken 8634 times.
|
38276 | if (link->src->nb_inputs && |
| 432 |
1/2✓ Branch 1 taken 29642 times.
✗ Branch 2 not taken.
|
29642 | !(fffilter(link->src->filter)->flags_internal & FF_FILTER_FLAG_HWFRAME_AWARE)) { |
| 433 | 29642 | FilterLink *l0 = ff_filter_link(link->src->inputs[0]); | |
| 434 | |||
| 435 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 29642 times.
|
29642 | av_assert0(!li->l.hw_frames_ctx && |
| 436 | "should not be set by non-hwframe-aware filter"); | ||
| 437 | |||
| 438 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 29642 times.
|
29642 | if (l0->hw_frames_ctx) { |
| 439 | ✗ | li->l.hw_frames_ctx = av_buffer_ref(l0->hw_frames_ctx); | |
| 440 | ✗ | if (!li->l.hw_frames_ctx) | |
| 441 | ✗ | return AVERROR(ENOMEM); | |
| 442 | } | ||
| 443 | } | ||
| 444 | |||
| 445 |
2/2✓ Branch 0 taken 5202 times.
✓ Branch 1 taken 33074 times.
|
38276 | if ((config_link = link->dstpad->config_props)) |
| 446 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 5202 times.
|
5202 | if ((ret = config_link(link)) < 0) { |
| 447 | ✗ | av_log(link->dst, AV_LOG_ERROR, | |
| 448 | "Failed to configure input pad on %s\n", | ||
| 449 | ✗ | link->dst->name); | |
| 450 | ✗ | return ret; | |
| 451 | } | ||
| 452 | |||
| 453 | 38276 | li->init_state = AVLINK_INIT; | |
| 454 | } | ||
| 455 | } | ||
| 456 | |||
| 457 | 46943 | return 0; | |
| 458 | } | ||
| 459 | |||
| 460 | #ifdef TRACE | ||
| 461 | void ff_tlog_link(void *ctx, AVFilterLink *link, int end) | ||
| 462 | { | ||
| 463 | if (link->type == AVMEDIA_TYPE_VIDEO) { | ||
| 464 | ff_tlog(ctx, | ||
| 465 | "link[%p s:%dx%d fmt:%s %s->%s]%s", | ||
| 466 | link, link->w, link->h, | ||
| 467 | av_get_pix_fmt_name(link->format), | ||
| 468 | link->src ? link->src->filter->name : "", | ||
| 469 | link->dst ? link->dst->filter->name : "", | ||
| 470 | end ? "\n" : ""); | ||
| 471 | } else { | ||
| 472 | char buf[128]; | ||
| 473 | av_channel_layout_describe(&link->ch_layout, buf, sizeof(buf)); | ||
| 474 | |||
| 475 | ff_tlog(ctx, | ||
| 476 | "link[%p r:%d cl:%s fmt:%s %s->%s]%s", | ||
| 477 | link, (int)link->sample_rate, buf, | ||
| 478 | av_get_sample_fmt_name(link->format), | ||
| 479 | link->src ? link->src->filter->name : "", | ||
| 480 | link->dst ? link->dst->filter->name : "", | ||
| 481 | end ? "\n" : ""); | ||
| 482 | } | ||
| 483 | } | ||
| 484 | #endif | ||
| 485 | |||
| 486 | 830886 | int ff_request_frame(AVFilterLink *link) | |
| 487 | { | ||
| 488 | 830886 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 489 | |||
| 490 | FF_TPRINTF_START(NULL, request_frame); ff_tlog_link(NULL, link, 1); | ||
| 491 | |||
| 492 | av_assert1(!fffilter(link->dst->filter)->activate); | ||
| 493 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 830875 times.
|
830886 | if (li->status_out) |
| 494 | 11 | return li->status_out; | |
| 495 |
2/2✓ Branch 0 taken 6448 times.
✓ Branch 1 taken 824427 times.
|
830875 | if (li->status_in) { |
| 496 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6448 times.
|
6448 | if (ff_framequeue_queued_frames(&li->fifo)) { |
| 497 | av_assert1(!li->frame_wanted_out); | ||
| 498 | av_assert1(fffilterctx(link->dst)->ready >= 300); | ||
| 499 | ✗ | return 0; | |
| 500 | } else { | ||
| 501 | /* Acknowledge status change. Filters using ff_request_frame() will | ||
| 502 | handle the change automatically. Filters can also check the | ||
| 503 | status directly but none do yet. */ | ||
| 504 | 6448 | link_set_out_status(link, li->status_in, li->status_in_pts); | |
| 505 | 6448 | return li->status_out; | |
| 506 | } | ||
| 507 | } | ||
| 508 | 824427 | li->frame_wanted_out = 1; | |
| 509 | 824427 | ff_filter_set_ready(link->src, 100); | |
| 510 | 824427 | return 0; | |
| 511 | } | ||
| 512 | |||
| 513 | 6440 | static int64_t guess_status_pts(AVFilterContext *ctx, int status, AVRational link_time_base) | |
| 514 | { | ||
| 515 | unsigned i; | ||
| 516 | 6440 | int64_t r = INT64_MAX; | |
| 517 | |||
| 518 |
2/2✓ Branch 0 taken 6439 times.
✓ Branch 1 taken 6440 times.
|
12879 | for (i = 0; i < ctx->nb_inputs; i++) { |
| 519 | 6439 | FilterLinkInternal * const li = ff_link_internal(ctx->inputs[i]); | |
| 520 |
1/2✓ Branch 0 taken 6439 times.
✗ Branch 1 not taken.
|
6439 | if (li->status_out == status) |
| 521 | 6439 | r = FFMIN(r, av_rescale_q(li->l.current_pts, ctx->inputs[i]->time_base, link_time_base)); | |
| 522 | } | ||
| 523 |
2/2✓ Branch 0 taken 6439 times.
✓ Branch 1 taken 1 times.
|
6440 | if (r < INT64_MAX) |
| 524 | 6439 | return r; | |
| 525 | 1 | av_log(ctx, AV_LOG_WARNING, "EOF timestamp not reliable\n"); | |
| 526 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | for (i = 0; i < ctx->nb_inputs; i++) { |
| 527 | ✗ | FilterLinkInternal * const li = ff_link_internal(ctx->inputs[i]); | |
| 528 | ✗ | r = FFMIN(r, av_rescale_q(li->status_in_pts, ctx->inputs[i]->time_base, link_time_base)); | |
| 529 | } | ||
| 530 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (r < INT64_MAX) |
| 531 | ✗ | return r; | |
| 532 | 1 | return AV_NOPTS_VALUE; | |
| 533 | } | ||
| 534 | |||
| 535 | 831206 | static int request_frame_to_filter(AVFilterLink *link) | |
| 536 | { | ||
| 537 | 831206 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 538 | 831206 | int ret = -1; | |
| 539 | |||
| 540 | FF_TPRINTF_START(NULL, request_frame_to_filter); ff_tlog_link(NULL, link, 1); | ||
| 541 | /* Assume the filter is blocked, let the method clear it if not */ | ||
| 542 | 831206 | li->frame_blocked_in = 1; | |
| 543 |
2/2✓ Branch 0 taken 2037 times.
✓ Branch 1 taken 829169 times.
|
831206 | if (link->srcpad->request_frame) |
| 544 | 2037 | ret = link->srcpad->request_frame(link); | |
| 545 |
1/2✓ Branch 0 taken 829169 times.
✗ Branch 1 not taken.
|
829169 | else if (link->src->inputs[0]) |
| 546 | 829169 | ret = ff_request_frame(link->src->inputs[0]); | |
| 547 |
2/2✓ Branch 0 taken 6440 times.
✓ Branch 1 taken 824766 times.
|
831206 | if (ret < 0) { |
| 548 |
2/4✓ Branch 0 taken 6440 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6440 times.
✗ Branch 3 not taken.
|
6440 | if (ret != AVERROR(EAGAIN) && ret != li->status_in) |
| 549 | 6440 | ff_avfilter_link_set_in_status(link, ret, guess_status_pts(link->src, ret, link->time_base)); | |
| 550 |
1/2✓ Branch 0 taken 6440 times.
✗ Branch 1 not taken.
|
6440 | if (ret == AVERROR_EOF) |
| 551 | 6440 | ret = 0; | |
| 552 | } | ||
| 553 | 831206 | return ret; | |
| 554 | } | ||
| 555 | |||
| 556 | static const char *const var_names[] = { | ||
| 557 | "t", | ||
| 558 | "n", | ||
| 559 | "w", | ||
| 560 | "h", | ||
| 561 | NULL | ||
| 562 | }; | ||
| 563 | |||
| 564 | enum { | ||
| 565 | VAR_T, | ||
| 566 | VAR_N, | ||
| 567 | VAR_W, | ||
| 568 | VAR_H, | ||
| 569 | VAR_VARS_NB | ||
| 570 | }; | ||
| 571 | |||
| 572 | 6 | static int set_enable_expr(FFFilterContext *ctxi, const char *expr) | |
| 573 | { | ||
| 574 | 6 | AVFilterContext *ctx = &ctxi->p; | |
| 575 | int ret; | ||
| 576 | char *expr_dup; | ||
| 577 | 6 | AVExpr *old = ctxi->enable; | |
| 578 | |||
| 579 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (!(ctx->filter->flags & AVFILTER_FLAG_SUPPORT_TIMELINE)) { |
| 580 | ✗ | av_log(ctx, AV_LOG_ERROR, "Timeline ('enable' option) not supported " | |
| 581 | ✗ | "with filter '%s'\n", ctx->filter->name); | |
| 582 | ✗ | return AVERROR_PATCHWELCOME; | |
| 583 | } | ||
| 584 | |||
| 585 | 6 | expr_dup = av_strdup(expr); | |
| 586 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (!expr_dup) |
| 587 | ✗ | return AVERROR(ENOMEM); | |
| 588 | |||
| 589 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | if (!ctxi->var_values) { |
| 590 | 6 | ctxi->var_values = av_calloc(VAR_VARS_NB, sizeof(*ctxi->var_values)); | |
| 591 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (!ctxi->var_values) { |
| 592 | ✗ | av_free(expr_dup); | |
| 593 | ✗ | return AVERROR(ENOMEM); | |
| 594 | } | ||
| 595 | } | ||
| 596 | |||
| 597 | 6 | ret = av_expr_parse(&ctxi->enable, expr_dup, var_names, | |
| 598 | NULL, NULL, NULL, NULL, 0, ctx->priv); | ||
| 599 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (ret < 0) { |
| 600 | ✗ | av_log(ctx->priv, AV_LOG_ERROR, | |
| 601 | "Error when evaluating the expression '%s' for enable\n", | ||
| 602 | expr_dup); | ||
| 603 | ✗ | av_free(expr_dup); | |
| 604 | ✗ | return ret; | |
| 605 | } | ||
| 606 | |||
| 607 | 6 | av_expr_free(old); | |
| 608 | 6 | av_free(ctx->enable_str); | |
| 609 | 6 | ctx->enable_str = expr_dup; | |
| 610 | 6 | return 0; | |
| 611 | } | ||
| 612 | |||
| 613 | ✗ | int avfilter_process_command(AVFilterContext *filter, const char *cmd, const char *arg, char *res, int res_len, int flags) | |
| 614 | { | ||
| 615 | ✗ | if(!strcmp(cmd, "ping")){ | |
| 616 | ✗ | char local_res[256] = {0}; | |
| 617 | |||
| 618 | ✗ | if (!res) { | |
| 619 | ✗ | res = local_res; | |
| 620 | ✗ | res_len = sizeof(local_res); | |
| 621 | } | ||
| 622 | ✗ | av_strlcatf(res, res_len, "pong from:%s %s\n", filter->filter->name, filter->name); | |
| 623 | ✗ | if (res == local_res) | |
| 624 | ✗ | av_log(filter, AV_LOG_INFO, "%s", res); | |
| 625 | ✗ | return 0; | |
| 626 | ✗ | }else if(!strcmp(cmd, "enable")) { | |
| 627 | ✗ | return set_enable_expr(fffilterctx(filter), arg); | |
| 628 | ✗ | }else if (fffilter(filter->filter)->process_command) { | |
| 629 | ✗ | return fffilter(filter->filter)->process_command(filter, cmd, arg, res, res_len, flags); | |
| 630 | } | ||
| 631 | ✗ | return AVERROR(ENOSYS); | |
| 632 | } | ||
| 633 | |||
| 634 | ✗ | unsigned avfilter_filter_pad_count(const AVFilter *filter, int is_output) | |
| 635 | { | ||
| 636 | ✗ | return is_output ? fffilter(filter)->nb_outputs : fffilter(filter)->nb_inputs; | |
| 637 | } | ||
| 638 | |||
| 639 | 787 | static const char *default_filter_name(void *filter_ctx) | |
| 640 | { | ||
| 641 | 787 | AVFilterContext *ctx = filter_ctx; | |
| 642 |
1/2✓ Branch 0 taken 787 times.
✗ Branch 1 not taken.
|
787 | return ctx->name ? ctx->name : ctx->filter->name; |
| 643 | } | ||
| 644 | |||
| 645 | 59926 | static void *filter_child_next(void *obj, void *prev) | |
| 646 | { | ||
| 647 | 59926 | AVFilterContext *ctx = obj; | |
| 648 |
5/8✓ Branch 0 taken 59920 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 59920 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 59920 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 59920 times.
✗ Branch 7 not taken.
|
59926 | if (!prev && ctx->filter && ctx->filter->priv_class && ctx->priv) |
| 649 | 59920 | return ctx->priv; | |
| 650 | 6 | return NULL; | |
| 651 | } | ||
| 652 | |||
| 653 | ✗ | static const AVClass *filter_child_class_iterate(void **iter) | |
| 654 | { | ||
| 655 | const AVFilter *f; | ||
| 656 | |||
| 657 | ✗ | while ((f = av_filter_iterate(iter))) | |
| 658 | ✗ | if (f->priv_class) | |
| 659 | ✗ | return f->priv_class; | |
| 660 | |||
| 661 | ✗ | return NULL; | |
| 662 | } | ||
| 663 | |||
| 664 | #define OFFSET(x) offsetof(AVFilterContext, x) | ||
| 665 | #define FLAGS AV_OPT_FLAG_FILTERING_PARAM | ||
| 666 | #define TFLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM | ||
| 667 | static const AVOption avfilter_options[] = { | ||
| 668 | { "thread_type", "Allowed thread types", OFFSET(thread_type), AV_OPT_TYPE_FLAGS, | ||
| 669 | { .i64 = AVFILTER_THREAD_SLICE }, 0, INT_MAX, FLAGS, .unit = "thread_type" }, | ||
| 670 | { "slice", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AVFILTER_THREAD_SLICE }, .flags = FLAGS, .unit = "thread_type" }, | ||
| 671 | { "enable", "set enable expression", OFFSET(enable_str), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = TFLAGS }, | ||
| 672 | { "threads", "Allowed number of threads", OFFSET(nb_threads), AV_OPT_TYPE_INT, | ||
| 673 | { .i64 = 0 }, 0, INT_MAX, FLAGS, .unit = "threads" }, | ||
| 674 | {"auto", "autodetect a suitable number of threads to use", 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, .flags = FLAGS, .unit = "threads"}, | ||
| 675 | { "extra_hw_frames", "Number of extra hardware frames to allocate for the user", | ||
| 676 | OFFSET(extra_hw_frames), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, FLAGS }, | ||
| 677 | { NULL }, | ||
| 678 | }; | ||
| 679 | |||
| 680 | static const AVClass avfilter_class = { | ||
| 681 | .class_name = "AVFilter", | ||
| 682 | .item_name = default_filter_name, | ||
| 683 | .version = LIBAVUTIL_VERSION_INT, | ||
| 684 | .category = AV_CLASS_CATEGORY_FILTER, | ||
| 685 | .child_next = filter_child_next, | ||
| 686 | .child_class_iterate = filter_child_class_iterate, | ||
| 687 | .option = avfilter_options, | ||
| 688 | .state_flags_offset = offsetof(FFFilterContext, state_flags), | ||
| 689 | }; | ||
| 690 | |||
| 691 | 1374 | static int default_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, | |
| 692 | int *ret, int nb_jobs) | ||
| 693 | { | ||
| 694 | int i; | ||
| 695 | |||
| 696 |
2/2✓ Branch 0 taken 1430 times.
✓ Branch 1 taken 1374 times.
|
2804 | for (i = 0; i < nb_jobs; i++) { |
| 697 | 1430 | int r = func(ctx, arg, i, nb_jobs); | |
| 698 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1430 times.
|
1430 | if (ret) |
| 699 | ✗ | ret[i] = r; | |
| 700 | } | ||
| 701 | 1374 | return 0; | |
| 702 | } | ||
| 703 | |||
| 704 | 65689 | AVFilterContext *ff_filter_alloc(const AVFilter *filter, const char *inst_name) | |
| 705 | { | ||
| 706 | FFFilterContext *ctx; | ||
| 707 | AVFilterContext *ret; | ||
| 708 | 65689 | const FFFilter *const fi = fffilter(filter); | |
| 709 | 65689 | int preinited = 0; | |
| 710 | |||
| 711 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 65689 times.
|
65689 | if (!filter) |
| 712 | ✗ | return NULL; | |
| 713 | |||
| 714 | 65689 | ctx = av_mallocz(sizeof(*ctx)); | |
| 715 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 65689 times.
|
65689 | if (!ctx) |
| 716 | ✗ | return NULL; | |
| 717 | 65689 | ret = &ctx->p; | |
| 718 | |||
| 719 | 65689 | ret->av_class = &avfilter_class; | |
| 720 | 65689 | ret->filter = filter; | |
| 721 |
1/2✓ Branch 0 taken 65689 times.
✗ Branch 1 not taken.
|
65689 | ret->name = inst_name ? av_strdup(inst_name) : NULL; |
| 722 |
2/2✓ Branch 0 taken 58622 times.
✓ Branch 1 taken 7067 times.
|
65689 | if (fi->priv_size) { |
| 723 | 58622 | ret->priv = av_mallocz(fi->priv_size); | |
| 724 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 58622 times.
|
58622 | if (!ret->priv) |
| 725 | ✗ | goto err; | |
| 726 | } | ||
| 727 |
2/2✓ Branch 0 taken 14125 times.
✓ Branch 1 taken 51564 times.
|
65689 | if (fi->preinit) { |
| 728 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 14125 times.
|
14125 | if (fi->preinit(ret) < 0) |
| 729 | ✗ | goto err; | |
| 730 | 14125 | preinited = 1; | |
| 731 | } | ||
| 732 | |||
| 733 | 65689 | av_opt_set_defaults(ret); | |
| 734 |
2/2✓ Branch 0 taken 57363 times.
✓ Branch 1 taken 8326 times.
|
65689 | if (filter->priv_class) { |
| 735 | 57363 | *(const AVClass**)ret->priv = filter->priv_class; | |
| 736 | 57363 | av_opt_set_defaults(ret->priv); | |
| 737 | } | ||
| 738 | |||
| 739 | 65689 | ctx->execute = default_execute; | |
| 740 | |||
| 741 | 65689 | ret->nb_inputs = fi->nb_inputs; | |
| 742 |
2/2✓ Branch 0 taken 55651 times.
✓ Branch 1 taken 10038 times.
|
65689 | if (ret->nb_inputs ) { |
| 743 | 55651 | ret->input_pads = av_memdup(filter->inputs, ret->nb_inputs * sizeof(*filter->inputs)); | |
| 744 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 55651 times.
|
55651 | if (!ret->input_pads) |
| 745 | ✗ | goto err; | |
| 746 | 55651 | ret->inputs = av_calloc(ret->nb_inputs, sizeof(*ret->inputs)); | |
| 747 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 55651 times.
|
55651 | if (!ret->inputs) |
| 748 | ✗ | goto err; | |
| 749 | } | ||
| 750 | |||
| 751 | 65689 | ret->nb_outputs = fi->nb_outputs; | |
| 752 |
2/2✓ Branch 0 taken 56909 times.
✓ Branch 1 taken 8780 times.
|
65689 | if (ret->nb_outputs) { |
| 753 | 56909 | ret->output_pads = av_memdup(filter->outputs, ret->nb_outputs * sizeof(*filter->outputs)); | |
| 754 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 56909 times.
|
56909 | if (!ret->output_pads) |
| 755 | ✗ | goto err; | |
| 756 | 56909 | ret->outputs = av_calloc(ret->nb_outputs, sizeof(*ret->outputs)); | |
| 757 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 56909 times.
|
56909 | if (!ret->outputs) |
| 758 | ✗ | goto err; | |
| 759 | } | ||
| 760 | |||
| 761 | 65689 | return ret; | |
| 762 | |||
| 763 | ✗ | err: | |
| 764 | ✗ | if (preinited) | |
| 765 | ✗ | fi->uninit(ret); | |
| 766 | ✗ | av_freep(&ret->name); | |
| 767 | ✗ | av_freep(&ret->inputs); | |
| 768 | ✗ | av_freep(&ret->input_pads); | |
| 769 | ✗ | ret->nb_inputs = 0; | |
| 770 | ✗ | av_freep(&ret->outputs); | |
| 771 | ✗ | av_freep(&ret->output_pads); | |
| 772 | ✗ | ret->nb_outputs = 0; | |
| 773 | ✗ | av_freep(&ret->priv); | |
| 774 | ✗ | av_free(ret); | |
| 775 | ✗ | return NULL; | |
| 776 | } | ||
| 777 | |||
| 778 | 113502 | static void free_link(AVFilterLink *link) | |
| 779 | { | ||
| 780 |
2/2✓ Branch 0 taken 64549 times.
✓ Branch 1 taken 48953 times.
|
113502 | if (!link) |
| 781 | 64549 | return; | |
| 782 | |||
| 783 |
2/2✓ Branch 0 taken 48821 times.
✓ Branch 1 taken 132 times.
|
48953 | if (link->src) |
| 784 | 48821 | link->src->outputs[link->srcpad - link->src->output_pads] = NULL; | |
| 785 |
2/2✓ Branch 0 taken 48821 times.
✓ Branch 1 taken 132 times.
|
48953 | if (link->dst) |
| 786 | 48821 | link->dst->inputs[link->dstpad - link->dst->input_pads] = NULL; | |
| 787 | |||
| 788 | 48953 | ff_formats_unref(&link->incfg.formats); | |
| 789 | 48953 | ff_formats_unref(&link->outcfg.formats); | |
| 790 | 48953 | ff_formats_unref(&link->incfg.color_spaces); | |
| 791 | 48953 | ff_formats_unref(&link->outcfg.color_spaces); | |
| 792 | 48953 | ff_formats_unref(&link->incfg.color_ranges); | |
| 793 | 48953 | ff_formats_unref(&link->outcfg.color_ranges); | |
| 794 | 48953 | ff_formats_unref(&link->incfg.alpha_modes); | |
| 795 | 48953 | ff_formats_unref(&link->outcfg.alpha_modes); | |
| 796 | 48953 | ff_formats_unref(&link->incfg.chroma_locations); | |
| 797 | 48953 | ff_formats_unref(&link->outcfg.chroma_locations); | |
| 798 | 48953 | ff_formats_unref(&link->incfg.samplerates); | |
| 799 | 48953 | ff_formats_unref(&link->outcfg.samplerates); | |
| 800 | 48953 | ff_channel_layouts_unref(&link->incfg.channel_layouts); | |
| 801 | 48953 | ff_channel_layouts_unref(&link->outcfg.channel_layouts); | |
| 802 | 48953 | link_free(&link); | |
| 803 | } | ||
| 804 | |||
| 805 | 65689 | void avfilter_free(AVFilterContext *filter) | |
| 806 | { | ||
| 807 | FFFilterContext *ctxi; | ||
| 808 | int i; | ||
| 809 | |||
| 810 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 65689 times.
|
65689 | if (!filter) |
| 811 | ✗ | return; | |
| 812 | 65689 | ctxi = fffilterctx(filter); | |
| 813 | |||
| 814 |
1/2✓ Branch 0 taken 65689 times.
✗ Branch 1 not taken.
|
65689 | if (filter->graph) |
| 815 | 65689 | ff_filter_graph_remove_filter(filter->graph, filter); | |
| 816 | |||
| 817 |
2/2✓ Branch 1 taken 50991 times.
✓ Branch 2 taken 14698 times.
|
65689 | if (fffilter(filter->filter)->uninit) |
| 818 | 50991 | fffilter(filter->filter)->uninit(filter); | |
| 819 | |||
| 820 |
2/2✓ Branch 0 taken 56070 times.
✓ Branch 1 taken 65689 times.
|
121759 | for (i = 0; i < filter->nb_inputs; i++) { |
| 821 | 56070 | free_link(filter->inputs[i]); | |
| 822 |
2/2✓ Branch 0 taken 272 times.
✓ Branch 1 taken 55798 times.
|
56070 | if (filter->input_pads[i].flags & AVFILTERPAD_FLAG_FREE_NAME) |
| 823 | 272 | av_freep(&filter->input_pads[i].name); | |
| 824 | } | ||
| 825 |
2/2✓ Branch 0 taken 57432 times.
✓ Branch 1 taken 65689 times.
|
123121 | for (i = 0; i < filter->nb_outputs; i++) { |
| 826 | 57432 | free_link(filter->outputs[i]); | |
| 827 |
2/2✓ Branch 0 taken 513 times.
✓ Branch 1 taken 56919 times.
|
57432 | if (filter->output_pads[i].flags & AVFILTERPAD_FLAG_FREE_NAME) |
| 828 | 513 | av_freep(&filter->output_pads[i].name); | |
| 829 | } | ||
| 830 | |||
| 831 |
2/2✓ Branch 0 taken 57363 times.
✓ Branch 1 taken 8326 times.
|
65689 | if (filter->filter->priv_class) |
| 832 | 57363 | av_opt_free(filter->priv); | |
| 833 | |||
| 834 | 65689 | av_buffer_unref(&filter->hw_device_ctx); | |
| 835 | |||
| 836 | 65689 | av_freep(&filter->name); | |
| 837 | 65689 | av_freep(&filter->input_pads); | |
| 838 | 65689 | av_freep(&filter->output_pads); | |
| 839 | 65689 | av_freep(&filter->inputs); | |
| 840 | 65689 | av_freep(&filter->outputs); | |
| 841 | 65689 | av_freep(&filter->priv); | |
| 842 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 65689 times.
|
65689 | while (ctxi->command_queue) |
| 843 | ✗ | command_queue_pop(filter); | |
| 844 | 65689 | av_opt_free(filter); | |
| 845 | 65689 | av_expr_free(ctxi->enable); | |
| 846 | 65689 | ctxi->enable = NULL; | |
| 847 | 65689 | av_freep(&ctxi->var_values); | |
| 848 | 65689 | av_free(filter); | |
| 849 | } | ||
| 850 | |||
| 851 | 19900 | int ff_filter_get_nb_threads(AVFilterContext *ctx) | |
| 852 | { | ||
| 853 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19900 times.
|
19900 | if (ctx->nb_threads > 0) |
| 854 | ✗ | return FFMIN(ctx->nb_threads, ctx->graph->nb_threads); | |
| 855 | 19900 | return ctx->graph->nb_threads; | |
| 856 | } | ||
| 857 | |||
| 858 | 35164 | int ff_filter_opt_parse(void *logctx, const AVClass *priv_class, | |
| 859 | AVDictionary **options, const char *args) | ||
| 860 | { | ||
| 861 | 35164 | const AVOption *o = NULL; | |
| 862 | int ret; | ||
| 863 | 35164 | int offset= -1; | |
| 864 | |||
| 865 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 35164 times.
|
35164 | if (!args) |
| 866 | ✗ | return 0; | |
| 867 | |||
| 868 |
2/2✓ Branch 0 taken 61755 times.
✓ Branch 1 taken 35164 times.
|
96919 | while (*args) { |
| 869 | char *parsed_key, *value; | ||
| 870 | const char *key; | ||
| 871 | 61755 | const char *shorthand = NULL; | |
| 872 | 61755 | int additional_flags = 0; | |
| 873 | |||
| 874 |
4/4✓ Branch 0 taken 46912 times.
✓ Branch 1 taken 14843 times.
✓ Branch 3 taken 45630 times.
✓ Branch 4 taken 1282 times.
|
61755 | if (priv_class && (o = av_opt_next(&priv_class, o))) { |
| 875 |
4/4✓ Branch 0 taken 43860 times.
✓ Branch 1 taken 1770 times.
✓ Branch 2 taken 4646 times.
✓ Branch 3 taken 39214 times.
|
45630 | if (o->type == AV_OPT_TYPE_CONST || o->offset == offset) |
| 876 | 6416 | continue; | |
| 877 | 39214 | offset = o->offset; | |
| 878 | 39214 | shorthand = o->name; | |
| 879 | } | ||
| 880 | |||
| 881 | 55339 | ret = av_opt_get_key_value(&args, "=", ":", | |
| 882 | shorthand ? AV_OPT_FLAG_IMPLICIT_KEY : 0, | ||
| 883 | &parsed_key, &value); | ||
| 884 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 55339 times.
|
55339 | if (ret < 0) { |
| 885 | ✗ | if (ret == AVERROR(EINVAL)) | |
| 886 | ✗ | av_log(logctx, AV_LOG_ERROR, "No option name near '%s'\n", args); | |
| 887 | else | ||
| 888 | ✗ | av_log(logctx, AV_LOG_ERROR, "Unable to parse '%s': %s\n", args, | |
| 889 | ✗ | av_err2str(ret)); | |
| 890 | ✗ | return ret; | |
| 891 | } | ||
| 892 |
2/2✓ Branch 0 taken 29375 times.
✓ Branch 1 taken 25964 times.
|
55339 | if (*args) |
| 893 | 29375 | args++; | |
| 894 |
2/2✓ Branch 0 taken 34037 times.
✓ Branch 1 taken 21302 times.
|
55339 | if (parsed_key) { |
| 895 | 34037 | key = parsed_key; | |
| 896 | 34037 | additional_flags = AV_DICT_DONT_STRDUP_KEY; | |
| 897 | 34037 | priv_class = NULL; /* reject all remaining shorthand */ | |
| 898 | } else { | ||
| 899 | 21302 | key = shorthand; | |
| 900 | } | ||
| 901 | |||
| 902 | 55339 | av_log(logctx, AV_LOG_DEBUG, "Setting '%s' to value '%s'\n", key, value); | |
| 903 | |||
| 904 | 55339 | av_dict_set(options, key, value, | |
| 905 | additional_flags | AV_DICT_DONT_STRDUP_VAL | AV_DICT_MULTIKEY); | ||
| 906 | } | ||
| 907 | |||
| 908 | 35164 | return 0; | |
| 909 | } | ||
| 910 | |||
| 911 | ✗ | int ff_filter_process_command(AVFilterContext *ctx, const char *cmd, | |
| 912 | const char *arg, char *res, int res_len, int flags) | ||
| 913 | { | ||
| 914 | const AVOption *o; | ||
| 915 | |||
| 916 | ✗ | if (!ctx->filter->priv_class) | |
| 917 | ✗ | return 0; | |
| 918 | ✗ | o = av_opt_find2(ctx->priv, cmd, NULL, AV_OPT_FLAG_RUNTIME_PARAM | AV_OPT_FLAG_FILTERING_PARAM, AV_OPT_SEARCH_CHILDREN, NULL); | |
| 919 | ✗ | if (!o) | |
| 920 | ✗ | return AVERROR(ENOSYS); | |
| 921 | ✗ | return av_opt_set(ctx->priv, cmd, arg, 0); | |
| 922 | } | ||
| 923 | |||
| 924 | 65689 | int avfilter_init_dict(AVFilterContext *ctx, AVDictionary **options) | |
| 925 | { | ||
| 926 | 65689 | FFFilterContext *ctxi = fffilterctx(ctx); | |
| 927 | 65689 | int ret = 0; | |
| 928 | |||
| 929 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 65689 times.
|
65689 | if (ctxi->state_flags & AV_CLASS_STATE_INITIALIZED) { |
| 930 | ✗ | av_log(ctx, AV_LOG_ERROR, "Filter already initialized\n"); | |
| 931 | ✗ | return AVERROR(EINVAL); | |
| 932 | } | ||
| 933 | |||
| 934 | 65689 | ret = av_opt_set_dict2(ctx, options, AV_OPT_SEARCH_CHILDREN); | |
| 935 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 65689 times.
|
65689 | if (ret < 0) { |
| 936 | ✗ | av_log(ctx, AV_LOG_ERROR, "Error applying generic filter options.\n"); | |
| 937 | ✗ | return ret; | |
| 938 | } | ||
| 939 | |||
| 940 |
2/2✓ Branch 0 taken 1290 times.
✓ Branch 1 taken 64399 times.
|
65689 | if (ctx->filter->flags & AVFILTER_FLAG_SLICE_THREADS && |
| 941 |
2/2✓ Branch 0 taken 172 times.
✓ Branch 1 taken 1118 times.
|
1290 | ctx->thread_type & ctx->graph->thread_type & AVFILTER_THREAD_SLICE && |
| 942 |
1/2✓ Branch 1 taken 172 times.
✗ Branch 2 not taken.
|
172 | fffiltergraph(ctx->graph)->thread_execute) { |
| 943 | 172 | ctx->thread_type = AVFILTER_THREAD_SLICE; | |
| 944 | 172 | ctxi->execute = fffiltergraph(ctx->graph)->thread_execute; | |
| 945 | } else { | ||
| 946 | 65517 | ctx->thread_type = 0; | |
| 947 | } | ||
| 948 | |||
| 949 |
2/2✓ Branch 1 taken 51818 times.
✓ Branch 2 taken 13871 times.
|
65689 | if (fffilter(ctx->filter)->init) |
| 950 | 51818 | ret = fffilter(ctx->filter)->init(ctx); | |
| 951 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 65688 times.
|
65689 | if (ret < 0) |
| 952 | 1 | return ret; | |
| 953 | |||
| 954 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 65682 times.
|
65688 | if (ctx->enable_str) { |
| 955 | 6 | ret = set_enable_expr(ctxi, ctx->enable_str); | |
| 956 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (ret < 0) |
| 957 | ✗ | return ret; | |
| 958 | } | ||
| 959 | |||
| 960 | 65688 | ctxi->state_flags |= AV_CLASS_STATE_INITIALIZED; | |
| 961 | |||
| 962 | 65688 | return 0; | |
| 963 | } | ||
| 964 | |||
| 965 | 21871 | int avfilter_init_str(AVFilterContext *filter, const char *args) | |
| 966 | { | ||
| 967 | 21871 | AVDictionary *options = NULL; | |
| 968 | const AVDictionaryEntry *e; | ||
| 969 | 21871 | int ret = 0; | |
| 970 | |||
| 971 |
3/4✓ Branch 0 taken 10919 times.
✓ Branch 1 taken 10952 times.
✓ Branch 2 taken 10919 times.
✗ Branch 3 not taken.
|
21871 | if (args && *args) { |
| 972 | 10919 | ret = ff_filter_opt_parse(filter, filter->filter->priv_class, &options, args); | |
| 973 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10919 times.
|
10919 | if (ret < 0) |
| 974 | ✗ | goto fail; | |
| 975 | } | ||
| 976 | |||
| 977 | 21871 | ret = avfilter_init_dict(filter, &options); | |
| 978 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21871 times.
|
21871 | if (ret < 0) |
| 979 | ✗ | goto fail; | |
| 980 | |||
| 981 |
1/2✓ Branch 1 taken 21871 times.
✗ Branch 2 not taken.
|
21871 | if ((e = av_dict_iterate(options, NULL))) { |
| 982 | ✗ | av_log(filter, AV_LOG_ERROR, "No such option: %s.\n", e->key); | |
| 983 | ✗ | ret = AVERROR_OPTION_NOT_FOUND; | |
| 984 | ✗ | goto fail; | |
| 985 | } | ||
| 986 | |||
| 987 | 21871 | fail: | |
| 988 | 21871 | av_dict_free(&options); | |
| 989 | |||
| 990 | 21871 | return ret; | |
| 991 | } | ||
| 992 | |||
| 993 | 15589 | const char *avfilter_pad_get_name(const AVFilterPad *pads, int pad_idx) | |
| 994 | { | ||
| 995 | 15589 | return pads[pad_idx].name; | |
| 996 | } | ||
| 997 | |||
| 998 | 31746 | enum AVMediaType avfilter_pad_get_type(const AVFilterPad *pads, int pad_idx) | |
| 999 | { | ||
| 1000 | 31746 | return pads[pad_idx].type; | |
| 1001 | } | ||
| 1002 | |||
| 1003 | ✗ | AVBufferRef *avfilter_link_get_hw_frames_ctx(AVFilterLink *link) | |
| 1004 | { | ||
| 1005 | ✗ | FilterLink *plink = ff_filter_link(link); | |
| 1006 | ✗ | if (plink->hw_frames_ctx) | |
| 1007 | ✗ | return av_buffer_ref(plink->hw_frames_ctx); | |
| 1008 | |||
| 1009 | ✗ | return NULL; | |
| 1010 | } | ||
| 1011 | |||
| 1012 | 812524 | static int default_filter_frame(AVFilterLink *link, AVFrame *frame) | |
| 1013 | { | ||
| 1014 | 812524 | return ff_filter_frame(link->dst->outputs[0], frame); | |
| 1015 | } | ||
| 1016 | |||
| 1017 | /** | ||
| 1018 | * Evaluate the timeline expression of the link for the time and properties | ||
| 1019 | * of the frame. | ||
| 1020 | * @return >0 if enabled, 0 if disabled | ||
| 1021 | * @note It does not update link->dst->is_disabled. | ||
| 1022 | */ | ||
| 1023 | 2587011 | static int evaluate_timeline_at_frame(AVFilterLink *link, const AVFrame *frame) | |
| 1024 | { | ||
| 1025 | 2587011 | FilterLink *l = ff_filter_link(link); | |
| 1026 | 2587011 | AVFilterContext *dstctx = link->dst; | |
| 1027 | 2587011 | FFFilterContext *dsti = fffilterctx(dstctx); | |
| 1028 | 2587011 | int64_t pts = frame->pts; | |
| 1029 | |||
| 1030 |
2/2✓ Branch 0 taken 2586813 times.
✓ Branch 1 taken 198 times.
|
2587011 | if (!dstctx->enable_str) |
| 1031 | 2586813 | return 1; | |
| 1032 | |||
| 1033 | 198 | dsti->var_values[VAR_N] = l->frame_count_out; | |
| 1034 |
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); |
| 1035 | 198 | dsti->var_values[VAR_W] = link->w; | |
| 1036 | 198 | dsti->var_values[VAR_H] = link->h; | |
| 1037 | |||
| 1038 | 198 | return fabs(av_expr_eval(dsti->enable, dsti->var_values, NULL)) >= 0.5; | |
| 1039 | } | ||
| 1040 | |||
| 1041 | 833315 | static int filter_frame_framed(AVFilterLink *link, AVFrame *frame) | |
| 1042 | { | ||
| 1043 | 833315 | FilterLink *l = ff_filter_link(link); | |
| 1044 | int (*filter_frame)(AVFilterLink *, AVFrame *); | ||
| 1045 | 833315 | AVFilterContext *dstctx = link->dst; | |
| 1046 | 833315 | AVFilterPad *dst = link->dstpad; | |
| 1047 | int ret; | ||
| 1048 | |||
| 1049 |
2/2✓ Branch 0 taken 812515 times.
✓ Branch 1 taken 20800 times.
|
833315 | if (!(filter_frame = dst->filter_frame)) |
| 1050 | 812515 | filter_frame = default_filter_frame; | |
| 1051 | |||
| 1052 |
2/2✓ Branch 0 taken 2993 times.
✓ Branch 1 taken 830322 times.
|
833315 | if (dst->flags & AVFILTERPAD_FLAG_NEEDS_WRITABLE) { |
| 1053 | 2993 | ret = ff_inlink_make_frame_writable(link, &frame); | |
| 1054 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2993 times.
|
2993 | if (ret < 0) |
| 1055 | ✗ | goto fail; | |
| 1056 | } | ||
| 1057 | |||
| 1058 | 833315 | ff_inlink_process_commands(link, frame); | |
| 1059 | 833315 | dstctx->is_disabled = !evaluate_timeline_at_frame(link, frame); | |
| 1060 | |||
| 1061 |
2/2✓ Branch 0 taken 19 times.
✓ Branch 1 taken 833296 times.
|
833315 | if (dstctx->is_disabled && |
| 1062 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 10 times.
|
19 | (dstctx->filter->flags & AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC)) |
| 1063 | 9 | filter_frame = default_filter_frame; | |
| 1064 | 833315 | ret = filter_frame(link, frame); | |
| 1065 | 833315 | l->frame_count_out++; | |
| 1066 | 833315 | return ret; | |
| 1067 | |||
| 1068 | ✗ | fail: | |
| 1069 | ✗ | av_frame_free(&frame); | |
| 1070 | ✗ | return ret; | |
| 1071 | } | ||
| 1072 | |||
| 1073 | 1759266 | int ff_filter_frame(AVFilterLink *link, AVFrame *frame) | |
| 1074 | { | ||
| 1075 | 1759266 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1076 | int ret; | ||
| 1077 | 1759266 | FF_TPRINTF_START(NULL, filter_frame); ff_tlog_link(NULL, link, 1); ff_tlog(NULL, " "); tlog_ref(NULL, frame, 1); | |
| 1078 | |||
| 1079 | /* Consistency checks */ | ||
| 1080 |
2/2✓ Branch 0 taken 595387 times.
✓ Branch 1 taken 1163879 times.
|
1759266 | if (link->type == AVMEDIA_TYPE_VIDEO) { |
| 1081 |
2/2✓ Branch 0 taken 444504 times.
✓ Branch 1 taken 150883 times.
|
595387 | if (strcmp(link->dst->filter->name, "buffersink") && |
| 1082 |
2/2✓ Branch 0 taken 267410 times.
✓ Branch 1 taken 177094 times.
|
444504 | strcmp(link->dst->filter->name, "format") && |
| 1083 |
2/2✓ Branch 0 taken 267383 times.
✓ Branch 1 taken 27 times.
|
267410 | strcmp(link->dst->filter->name, "idet") && |
| 1084 |
2/2✓ Branch 0 taken 175588 times.
✓ Branch 1 taken 91795 times.
|
267383 | strcmp(link->dst->filter->name, "null") && |
| 1085 |
2/2✓ Branch 0 taken 58364 times.
✓ Branch 1 taken 117224 times.
|
175588 | strcmp(link->dst->filter->name, "scale") && |
| 1086 |
1/2✓ Branch 0 taken 58364 times.
✗ Branch 1 not taken.
|
58364 | strcmp(link->dst->filter->name, "libplacebo") && |
| 1087 |
2/2✓ Branch 0 taken 58241 times.
✓ Branch 1 taken 123 times.
|
58364 | strcmp(link->dst->filter->name, "hqdn3d")) { |
| 1088 | av_assert1(frame->format == link->format); | ||
| 1089 | av_assert1(frame->width == link->w); | ||
| 1090 | av_assert1(frame->height == link->h); | ||
| 1091 | 58241 | if (av_pix_fmt_desc_get(link->format)->flags & AV_PIX_FMT_FLAG_ALPHA) | |
| 1092 | av_assert1(frame->alpha_mode == link->alpha_mode); | ||
| 1093 | } | ||
| 1094 | } else { | ||
| 1095 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1163879 times.
|
1163879 | if (frame->format != link->format) { |
| 1096 | ✗ | av_log(link->dst, AV_LOG_ERROR, "Format change is not supported\n"); | |
| 1097 | ✗ | goto error; | |
| 1098 | } | ||
| 1099 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1163879 times.
|
1163879 | if (av_channel_layout_compare(&frame->ch_layout, &link->ch_layout)) { |
| 1100 | ✗ | av_log(link->dst, AV_LOG_ERROR, "Channel layout change is not supported\n"); | |
| 1101 | ✗ | goto error; | |
| 1102 | } | ||
| 1103 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1163879 times.
|
1163879 | if (frame->sample_rate != link->sample_rate) { |
| 1104 | ✗ | av_log(link->dst, AV_LOG_ERROR, "Sample rate change is not supported\n"); | |
| 1105 | ✗ | goto error; | |
| 1106 | } | ||
| 1107 | |||
| 1108 | 1163879 | frame->duration = av_rescale_q(frame->nb_samples, (AVRational){ 1, frame->sample_rate }, | |
| 1109 | link->time_base); | ||
| 1110 | } | ||
| 1111 | |||
| 1112 | 1759266 | li->frame_blocked_in = li->frame_wanted_out = 0; | |
| 1113 | 1759266 | li->l.frame_count_in++; | |
| 1114 | 1759266 | li->l.sample_count_in += frame->nb_samples; | |
| 1115 | 1759266 | filter_unblock(link->dst); | |
| 1116 | 1759266 | ret = ff_framequeue_add(&li->fifo, frame); | |
| 1117 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1759266 times.
|
1759266 | if (ret < 0) { |
| 1118 | ✗ | const FFFrameQueueGlobal *global = li->fifo.global; | |
| 1119 | ✗ | if (ret == AVERROR(ENOMEM) && global->queued >= global->max_queued) | |
| 1120 | ✗ | av_log(link->dst, AV_LOG_ERROR, "Exhausted frame queue capacity (%zu frames)\n", global->max_queued); | |
| 1121 | ✗ | av_frame_free(&frame); | |
| 1122 | ✗ | return ret; | |
| 1123 | } | ||
| 1124 | 1759266 | ff_filter_set_ready(link->dst, 300); | |
| 1125 | 1759266 | return 0; | |
| 1126 | |||
| 1127 | ✗ | error: | |
| 1128 | ✗ | av_frame_free(&frame); | |
| 1129 | ✗ | return AVERROR_PATCHWELCOME; | |
| 1130 | } | ||
| 1131 | |||
| 1132 | 2492344 | static int samples_ready(FilterLinkInternal *link, unsigned min) | |
| 1133 | { | ||
| 1134 |
2/2✓ Branch 1 taken 833449 times.
✓ Branch 2 taken 1658895 times.
|
3325793 | return ff_framequeue_queued_frames(&link->fifo) && |
| 1135 |
2/2✓ Branch 1 taken 135 times.
✓ Branch 2 taken 833314 times.
|
833449 | (ff_framequeue_queued_samples(&link->fifo) >= min || |
| 1136 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 134 times.
|
135 | link->status_in); |
| 1137 | } | ||
| 1138 | |||
| 1139 | 2935 | static int take_samples(FilterLinkInternal *li, unsigned min, unsigned max, | |
| 1140 | AVFrame **rframe) | ||
| 1141 | { | ||
| 1142 | 2935 | FilterLink *l = &li->l; | |
| 1143 | 2935 | AVFilterLink *link = &l->pub; | |
| 1144 | AVFrame *frame0, *frame, *buf; | ||
| 1145 | unsigned nb_samples, nb_frames, i, p; | ||
| 1146 | int ret; | ||
| 1147 | |||
| 1148 | /* Note: this function relies on no format changes and must only be | ||
| 1149 | called with enough samples. */ | ||
| 1150 | av_assert1(samples_ready(li, l->min_samples)); | ||
| 1151 | 2935 | frame0 = frame = ff_framequeue_peek(&li->fifo, 0); | |
| 1152 |
6/6✓ Branch 0 taken 1417 times.
✓ Branch 1 taken 1518 times.
✓ Branch 2 taken 1301 times.
✓ Branch 3 taken 116 times.
✓ Branch 4 taken 1025 times.
✓ Branch 5 taken 276 times.
|
2935 | if (!li->fifo.samples_skipped && frame->nb_samples >= min && frame->nb_samples <= max) { |
| 1153 | 1025 | *rframe = ff_framequeue_take(&li->fifo); | |
| 1154 | 1025 | return 0; | |
| 1155 | } | ||
| 1156 | 1910 | nb_frames = 0; | |
| 1157 | 1910 | nb_samples = 0; | |
| 1158 | while (1) { | ||
| 1159 |
2/2✓ Branch 0 taken 1643 times.
✓ Branch 1 taken 1482 times.
|
3125 | if (nb_samples + frame->nb_samples > max) { |
| 1160 |
2/2✓ Branch 0 taken 1521 times.
✓ Branch 1 taken 122 times.
|
1643 | if (nb_samples < min) |
| 1161 | 1521 | nb_samples = max; | |
| 1162 | 1643 | break; | |
| 1163 | } | ||
| 1164 | 1482 | nb_samples += frame->nb_samples; | |
| 1165 | 1482 | nb_frames++; | |
| 1166 |
2/2✓ Branch 1 taken 267 times.
✓ Branch 2 taken 1215 times.
|
1482 | if (nb_frames == ff_framequeue_queued_frames(&li->fifo)) |
| 1167 | 267 | break; | |
| 1168 | 1215 | frame = ff_framequeue_peek(&li->fifo, nb_frames); | |
| 1169 | } | ||
| 1170 | |||
| 1171 | 1910 | buf = ff_get_audio_buffer(link, nb_samples); | |
| 1172 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1910 times.
|
1910 | if (!buf) |
| 1173 | ✗ | return AVERROR(ENOMEM); | |
| 1174 | 1910 | ret = av_frame_copy_props(buf, frame0); | |
| 1175 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1910 times.
|
1910 | if (ret < 0) { |
| 1176 | ✗ | av_frame_free(&buf); | |
| 1177 | ✗ | return ret; | |
| 1178 | } | ||
| 1179 | |||
| 1180 | 1910 | p = 0; | |
| 1181 |
2/2✓ Branch 0 taken 1482 times.
✓ Branch 1 taken 1910 times.
|
3392 | for (i = 0; i < nb_frames; i++) { |
| 1182 | 1482 | frame = ff_framequeue_take(&li->fifo); | |
| 1183 | 1482 | av_samples_copy(buf->extended_data, frame->extended_data, p, 0, | |
| 1184 | 1482 | frame->nb_samples, link->ch_layout.nb_channels, link->format); | |
| 1185 | 1482 | p += frame->nb_samples; | |
| 1186 | 1482 | av_frame_free(&frame); | |
| 1187 | } | ||
| 1188 |
2/2✓ Branch 0 taken 1521 times.
✓ Branch 1 taken 389 times.
|
1910 | if (p < nb_samples) { |
| 1189 | 1521 | unsigned n = nb_samples - p; | |
| 1190 | 1521 | frame = ff_framequeue_peek(&li->fifo, 0); | |
| 1191 | 1521 | av_samples_copy(buf->extended_data, frame->extended_data, p, 0, n, | |
| 1192 | 1521 | link->ch_layout.nb_channels, link->format); | |
| 1193 | 1521 | ff_framequeue_skip_samples(&li->fifo, n, link->time_base); | |
| 1194 | } | ||
| 1195 | |||
| 1196 | 1910 | *rframe = buf; | |
| 1197 | 1910 | return 0; | |
| 1198 | } | ||
| 1199 | |||
| 1200 | 833315 | static int filter_frame_to_filter(AVFilterLink *link) | |
| 1201 | { | ||
| 1202 | 833315 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1203 | 833315 | AVFrame *frame = NULL; | |
| 1204 | 833315 | AVFilterContext *dst = link->dst; | |
| 1205 | int ret; | ||
| 1206 | |||
| 1207 | av_assert1(ff_framequeue_queued_frames(&li->fifo)); | ||
| 1208 | 1666630 | ret = li->l.min_samples ? | |
| 1209 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 833279 times.
|
833315 | ff_inlink_consume_samples(link, li->l.min_samples, li->l.max_samples, &frame) : |
| 1210 | 833279 | ff_inlink_consume_frame(link, &frame); | |
| 1211 | av_assert1(ret); | ||
| 1212 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 833315 times.
|
833315 | if (ret < 0) { |
| 1213 | av_assert1(!frame); | ||
| 1214 | ✗ | return ret; | |
| 1215 | } | ||
| 1216 | /* The filter will soon have received a new frame, that may allow it to | ||
| 1217 | produce one or more: unblock its outputs. */ | ||
| 1218 | 833315 | filter_unblock(dst); | |
| 1219 | /* AVFilterPad.filter_frame() expect frame_count_out to have the value | ||
| 1220 | before the frame; filter_frame_framed() will re-increment it. */ | ||
| 1221 | 833315 | li->l.frame_count_out--; | |
| 1222 | 833315 | ret = filter_frame_framed(link, frame); | |
| 1223 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 833315 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
833315 | if (ret < 0 && ret != li->status_out) { |
| 1224 | ✗ | link_set_out_status(link, ret, AV_NOPTS_VALUE); | |
| 1225 | } else { | ||
| 1226 | /* Run once again, to see if several frames were available, or if | ||
| 1227 | the input status has also changed, or any other reason. */ | ||
| 1228 | 833315 | ff_filter_set_ready(dst, 300); | |
| 1229 | } | ||
| 1230 | 833315 | return ret; | |
| 1231 | } | ||
| 1232 | |||
| 1233 | 6448 | static int forward_status_change(AVFilterContext *filter, FilterLinkInternal *li_in) | |
| 1234 | { | ||
| 1235 | 6448 | AVFilterLink *in = &li_in->l.pub; | |
| 1236 | 6448 | unsigned out = 0, progress = 0; | |
| 1237 | int ret; | ||
| 1238 | |||
| 1239 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6448 times.
|
6448 | av_assert0(!li_in->status_out); |
| 1240 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6447 times.
|
6448 | if (!filter->nb_outputs) { |
| 1241 | /* not necessary with the current API and sinks */ | ||
| 1242 | 1 | return 0; | |
| 1243 | } | ||
| 1244 |
2/2✓ Branch 0 taken 6447 times.
✓ Branch 1 taken 6447 times.
|
12894 | while (!li_in->status_out) { |
| 1245 | 6447 | FilterLinkInternal *li_out = ff_link_internal(filter->outputs[out]); | |
| 1246 | |||
| 1247 |
1/2✓ Branch 0 taken 6447 times.
✗ Branch 1 not taken.
|
6447 | if (!li_out->status_in) { |
| 1248 | 6447 | progress++; | |
| 1249 | 6447 | ret = request_frame_to_filter(filter->outputs[out]); | |
| 1250 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6447 times.
|
6447 | if (ret < 0) |
| 1251 | ✗ | return ret; | |
| 1252 | } | ||
| 1253 |
1/2✓ Branch 0 taken 6447 times.
✗ Branch 1 not taken.
|
6447 | if (++out == filter->nb_outputs) { |
| 1254 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6447 times.
|
6447 | if (!progress) { |
| 1255 | /* Every output already closed: input no longer interesting | ||
| 1256 | (example: overlay in shortest mode, other input closed). */ | ||
| 1257 | ✗ | link_set_out_status(in, li_in->status_in, li_in->status_in_pts); | |
| 1258 | ✗ | return 0; | |
| 1259 | } | ||
| 1260 | 6447 | progress = 0; | |
| 1261 | 6447 | out = 0; | |
| 1262 | } | ||
| 1263 | } | ||
| 1264 | 6447 | ff_filter_set_ready(filter, 200); | |
| 1265 | 6447 | return 0; | |
| 1266 | } | ||
| 1267 | |||
| 1268 | 2499819 | static int filter_activate_default(AVFilterContext *filter) | |
| 1269 | { | ||
| 1270 | unsigned i; | ||
| 1271 | 2499819 | int nb_eofs = 0; | |
| 1272 | |||
| 1273 |
2/2✓ Branch 0 taken 2499800 times.
✓ Branch 1 taken 2499819 times.
|
4999619 | for (i = 0; i < filter->nb_outputs; i++) |
| 1274 | 2499800 | nb_eofs += ff_outlink_get_status(filter->outputs[i]) == AVERROR_EOF; | |
| 1275 |
4/4✓ Branch 0 taken 2499800 times.
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 7210 times.
✓ Branch 3 taken 2492590 times.
|
2499819 | if (filter->nb_outputs && nb_eofs == filter->nb_outputs) { |
| 1276 |
2/2✓ Branch 0 taken 7210 times.
✓ Branch 1 taken 7210 times.
|
14420 | for (int j = 0; j < filter->nb_inputs; j++) |
| 1277 | 7210 | ff_inlink_set_status(filter->inputs[j], AVERROR_EOF); | |
| 1278 | 7210 | return 0; | |
| 1279 | } | ||
| 1280 | |||
| 1281 |
2/2✓ Branch 0 taken 2492344 times.
✓ Branch 1 taken 1659294 times.
|
4151638 | for (i = 0; i < filter->nb_inputs; i++) { |
| 1282 | 2492344 | FilterLinkInternal *li = ff_link_internal(filter->inputs[i]); | |
| 1283 |
2/2✓ Branch 1 taken 833315 times.
✓ Branch 2 taken 1659029 times.
|
2492344 | if (samples_ready(li, li->l.min_samples)) { |
| 1284 | 833315 | return filter_frame_to_filter(filter->inputs[i]); | |
| 1285 | } | ||
| 1286 | } | ||
| 1287 |
2/2✓ Branch 0 taken 1659029 times.
✓ Branch 1 taken 1652846 times.
|
3311875 | for (i = 0; i < filter->nb_inputs; i++) { |
| 1288 | 1659029 | FilterLinkInternal * const li = ff_link_internal(filter->inputs[i]); | |
| 1289 |
4/4✓ Branch 0 taken 6483 times.
✓ Branch 1 taken 1652546 times.
✓ Branch 2 taken 6448 times.
✓ Branch 3 taken 35 times.
|
1659029 | if (li->status_in && !li->status_out) { |
| 1290 | av_assert1(!ff_framequeue_queued_frames(&li->fifo)); | ||
| 1291 | 6448 | return forward_status_change(filter, li); | |
| 1292 | } | ||
| 1293 | } | ||
| 1294 |
2/2✓ Branch 0 taken 1652837 times.
✓ Branch 1 taken 833110 times.
|
2485947 | for (i = 0; i < filter->nb_outputs; i++) { |
| 1295 | 1652837 | FilterLinkInternal * const li = ff_link_internal(filter->outputs[i]); | |
| 1296 |
2/2✓ Branch 0 taken 824759 times.
✓ Branch 1 taken 828078 times.
|
1652837 | if (li->frame_wanted_out && |
| 1297 |
2/2✓ Branch 0 taken 819736 times.
✓ Branch 1 taken 5023 times.
|
824759 | !li->frame_blocked_in) { |
| 1298 | 819736 | return request_frame_to_filter(filter->outputs[i]); | |
| 1299 | } | ||
| 1300 | } | ||
| 1301 |
2/2✓ Branch 0 taken 833101 times.
✓ Branch 1 taken 828087 times.
|
1661188 | for (i = 0; i < filter->nb_outputs; i++) { |
| 1302 | 833101 | FilterLinkInternal * const li = ff_link_internal(filter->outputs[i]); | |
| 1303 |
2/2✓ Branch 0 taken 5023 times.
✓ Branch 1 taken 828078 times.
|
833101 | if (li->frame_wanted_out) |
| 1304 | 5023 | return request_frame_to_filter(filter->outputs[i]); | |
| 1305 | } | ||
| 1306 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 828078 times.
|
828087 | if (!filter->nb_outputs) { |
| 1307 | 9 | ff_inlink_request_frame(filter->inputs[0]); | |
| 1308 | 9 | return 0; | |
| 1309 | } | ||
| 1310 | 828078 | return FFERROR_NOT_READY; | |
| 1311 | } | ||
| 1312 | |||
| 1313 | /* | ||
| 1314 | Filter scheduling and activation | ||
| 1315 | |||
| 1316 | When a filter is activated, it must: | ||
| 1317 | - if possible, output a frame; | ||
| 1318 | - else, if relevant, forward the input status change; | ||
| 1319 | - else, check outputs for wanted frames and forward the requests. | ||
| 1320 | |||
| 1321 | The following AVFilterLink fields are used for activation: | ||
| 1322 | |||
| 1323 | - frame_wanted_out: | ||
| 1324 | |||
| 1325 | This field indicates if a frame is needed on this input of the | ||
| 1326 | destination filter. A positive value indicates that a frame is needed | ||
| 1327 | to process queued frames or internal data or to satisfy the | ||
| 1328 | application; a zero value indicates that a frame is not especially | ||
| 1329 | needed but could be processed anyway; a negative value indicates that a | ||
| 1330 | frame would just be queued. | ||
| 1331 | |||
| 1332 | It is set by filters using ff_request_frame() or ff_request_no_frame(), | ||
| 1333 | when requested by the application through a specific API or when it is | ||
| 1334 | set on one of the outputs. | ||
| 1335 | |||
| 1336 | It is cleared when a frame is sent from the source using | ||
| 1337 | ff_filter_frame(). | ||
| 1338 | |||
| 1339 | It is also cleared when a status change is sent from the source using | ||
| 1340 | ff_avfilter_link_set_in_status(). | ||
| 1341 | |||
| 1342 | - frame_blocked_in: | ||
| 1343 | |||
| 1344 | This field means that the source filter can not generate a frame as is. | ||
| 1345 | Its goal is to avoid repeatedly calling the request_frame() method on | ||
| 1346 | the same link. | ||
| 1347 | |||
| 1348 | It is set by the framework on all outputs of a filter before activating it. | ||
| 1349 | |||
| 1350 | It is automatically cleared by ff_filter_frame(). | ||
| 1351 | |||
| 1352 | It is also automatically cleared by ff_avfilter_link_set_in_status(). | ||
| 1353 | |||
| 1354 | It is also cleared on all outputs (using filter_unblock()) when | ||
| 1355 | something happens on an input: processing a frame or changing the | ||
| 1356 | status. | ||
| 1357 | |||
| 1358 | - fifo: | ||
| 1359 | |||
| 1360 | Contains the frames queued on a filter input. If it contains frames and | ||
| 1361 | frame_wanted_out is not set, then the filter can be activated. If that | ||
| 1362 | result in the filter not able to use these frames, the filter must set | ||
| 1363 | frame_wanted_out to ask for more frames. | ||
| 1364 | |||
| 1365 | - status_in and status_in_pts: | ||
| 1366 | |||
| 1367 | Status (EOF or error code) of the link and timestamp of the status | ||
| 1368 | change (in link time base, same as frames) as seen from the input of | ||
| 1369 | the link. The status change is considered happening after the frames | ||
| 1370 | queued in fifo. | ||
| 1371 | |||
| 1372 | It is set by the source filter using ff_avfilter_link_set_in_status(). | ||
| 1373 | |||
| 1374 | - status_out: | ||
| 1375 | |||
| 1376 | Status of the link as seen from the output of the link. The status | ||
| 1377 | change is considered having already happened. | ||
| 1378 | |||
| 1379 | It is set by the destination filter using | ||
| 1380 | link_set_out_status(). | ||
| 1381 | |||
| 1382 | Filters are activated according to the ready field, set using the | ||
| 1383 | ff_filter_set_ready(). Eventually, a priority queue will be used. | ||
| 1384 | ff_filter_set_ready() is called whenever anything could cause progress to | ||
| 1385 | be possible. Marking a filter ready when it is not is not a problem, | ||
| 1386 | except for the small overhead it causes. | ||
| 1387 | |||
| 1388 | Conditions that cause a filter to be marked ready are: | ||
| 1389 | |||
| 1390 | - frames added on an input link; | ||
| 1391 | |||
| 1392 | - changes in the input or output status of an input link; | ||
| 1393 | |||
| 1394 | - requests for a frame on an output link; | ||
| 1395 | |||
| 1396 | - after any actual processing using the legacy methods (filter_frame(), | ||
| 1397 | and request_frame() to acknowledge status changes), to run once more | ||
| 1398 | and check if enough input was present for several frames. | ||
| 1399 | |||
| 1400 | Examples of scenarios to consider: | ||
| 1401 | |||
| 1402 | - buffersrc: activate if frame_wanted_out to notify the application; | ||
| 1403 | activate when the application adds a frame to push it immediately. | ||
| 1404 | |||
| 1405 | - testsrc: activate only if frame_wanted_out to produce and push a frame. | ||
| 1406 | |||
| 1407 | - concat (not at stitch points): can process a frame on any output. | ||
| 1408 | Activate if frame_wanted_out on output to forward on the corresponding | ||
| 1409 | input. Activate when a frame is present on input to process it | ||
| 1410 | immediately. | ||
| 1411 | |||
| 1412 | - framesync: needs at least one frame on each input; extra frames on the | ||
| 1413 | wrong input will accumulate. When a frame is first added on one input, | ||
| 1414 | set frame_wanted_out<0 on it to avoid getting more (would trigger | ||
| 1415 | testsrc) and frame_wanted_out>0 on the other to allow processing it. | ||
| 1416 | |||
| 1417 | Activation of old filters: | ||
| 1418 | |||
| 1419 | In order to activate a filter implementing the legacy filter_frame() and | ||
| 1420 | request_frame() methods, perform the first possible of the following | ||
| 1421 | actions: | ||
| 1422 | |||
| 1423 | - If an input has frames in fifo and frame_wanted_out == 0, dequeue a | ||
| 1424 | frame and call filter_frame(). | ||
| 1425 | |||
| 1426 | Rationale: filter frames as soon as possible instead of leaving them | ||
| 1427 | queued; frame_wanted_out < 0 is not possible since the old API does not | ||
| 1428 | set it nor provides any similar feedback; frame_wanted_out > 0 happens | ||
| 1429 | when min_samples > 0 and there are not enough samples queued. | ||
| 1430 | |||
| 1431 | - If an input has status_in set but not status_out, try to call | ||
| 1432 | request_frame() on one of the outputs in the hope that it will trigger | ||
| 1433 | request_frame() on the input with status_in and acknowledge it. This is | ||
| 1434 | awkward and fragile, filters with several inputs or outputs should be | ||
| 1435 | updated to direct activation as soon as possible. | ||
| 1436 | |||
| 1437 | - If an output has frame_wanted_out > 0 and not frame_blocked_in, call | ||
| 1438 | request_frame(). | ||
| 1439 | |||
| 1440 | Rationale: checking frame_blocked_in is necessary to avoid requesting | ||
| 1441 | repeatedly on a blocked input if another is not blocked (example: | ||
| 1442 | [buffersrc1][testsrc1][buffersrc2][testsrc2]concat=v=2). | ||
| 1443 | |||
| 1444 | - If an output has frame_wanted_out > 0 call request_frame(). | ||
| 1445 | |||
| 1446 | Rationale: even if all inputs are blocked an activate callback should | ||
| 1447 | request a frame on some if its inputs if a frame is requested on any of | ||
| 1448 | its output. | ||
| 1449 | |||
| 1450 | - Request a frame on the input for sinks. | ||
| 1451 | |||
| 1452 | Rationale: sinks using the old api have no way to request a frame on their | ||
| 1453 | input, so we need to do it for them. | ||
| 1454 | */ | ||
| 1455 | |||
| 1456 | 4362752 | int ff_filter_activate(AVFilterContext *filter) | |
| 1457 | { | ||
| 1458 | 4362752 | FFFilterContext *ctxi = fffilterctx(filter); | |
| 1459 | 4362752 | const FFFilter *const fi = fffilter(filter->filter); | |
| 1460 | int ret; | ||
| 1461 | |||
| 1462 | /* Generic timeline support is not yet implemented but should be easy */ | ||
| 1463 | av_assert1(!(fi->p.flags & AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC && | ||
| 1464 | fi->activate)); | ||
| 1465 | 4362752 | ctxi->ready = 0; | |
| 1466 |
2/2✓ Branch 0 taken 1862933 times.
✓ Branch 1 taken 2499819 times.
|
4362752 | ret = fi->activate ? fi->activate(filter) : filter_activate_default(filter); |
| 1467 |
2/2✓ Branch 0 taken 828985 times.
✓ Branch 1 taken 3533767 times.
|
4362752 | if (ret == FFERROR_NOT_READY) |
| 1468 | 828985 | ret = 0; | |
| 1469 | 4362752 | return ret; | |
| 1470 | } | ||
| 1471 | |||
| 1472 | 3945686 | int ff_inlink_acknowledge_status(AVFilterLink *link, int *rstatus, int64_t *rpts) | |
| 1473 | { | ||
| 1474 | 3945686 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1475 | 3945686 | *rpts = li->l.current_pts; | |
| 1476 |
2/2✓ Branch 1 taken 2185 times.
✓ Branch 2 taken 3943501 times.
|
3945686 | if (ff_framequeue_queued_frames(&li->fifo)) |
| 1477 | 2185 | return *rstatus = 0; | |
| 1478 |
2/2✓ Branch 0 taken 8065 times.
✓ Branch 1 taken 3935436 times.
|
3943501 | if (li->status_out) |
| 1479 | 8065 | return *rstatus = li->status_out; | |
| 1480 |
2/2✓ Branch 0 taken 3926784 times.
✓ Branch 1 taken 8652 times.
|
3935436 | if (!li->status_in) |
| 1481 | 3926784 | return *rstatus = 0; | |
| 1482 | 8652 | *rstatus = li->status_out = li->status_in; | |
| 1483 | 8652 | update_link_current_pts(li, li->status_in_pts); | |
| 1484 | 8652 | *rpts = li->l.current_pts; | |
| 1485 | 8652 | return 1; | |
| 1486 | } | ||
| 1487 | |||
| 1488 | 1934 | size_t ff_inlink_queued_frames(AVFilterLink *link) | |
| 1489 | { | ||
| 1490 | 1934 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1491 | 1934 | return ff_framequeue_queued_frames(&li->fifo); | |
| 1492 | } | ||
| 1493 | |||
| 1494 | 5692565 | int ff_inlink_check_available_frame(AVFilterLink *link) | |
| 1495 | { | ||
| 1496 | 5692565 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1497 | 5692565 | return ff_framequeue_queued_frames(&li->fifo) > 0; | |
| 1498 | } | ||
| 1499 | |||
| 1500 | 8237 | int ff_inlink_queued_samples(AVFilterLink *link) | |
| 1501 | { | ||
| 1502 | 8237 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1503 | 8237 | return ff_framequeue_queued_samples(&li->fifo); | |
| 1504 | } | ||
| 1505 | |||
| 1506 | 4877 | int ff_inlink_check_available_samples(AVFilterLink *link, unsigned min) | |
| 1507 | { | ||
| 1508 | 4877 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1509 | 4877 | uint64_t samples = ff_framequeue_queued_samples(&li->fifo); | |
| 1510 | av_assert1(min); | ||
| 1511 |
6/6✓ Branch 0 taken 1948 times.
✓ Branch 1 taken 2929 times.
✓ Branch 2 taken 67 times.
✓ Branch 3 taken 1881 times.
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 60 times.
|
4877 | return samples >= min || (li->status_in && samples); |
| 1512 | } | ||
| 1513 | |||
| 1514 | 1756690 | static void consume_update(FilterLinkInternal *li, const AVFrame *frame) | |
| 1515 | { | ||
| 1516 | 1756690 | AVFilterLink *const link = &li->l.pub; | |
| 1517 | 1756690 | update_link_current_pts(li, frame->pts); | |
| 1518 | 1756690 | ff_inlink_process_commands(link, frame); | |
| 1519 |
2/2✓ Branch 0 taken 1753696 times.
✓ Branch 1 taken 2994 times.
|
1756690 | if (link == link->dst->inputs[0]) |
| 1520 | 1753696 | link->dst->is_disabled = !evaluate_timeline_at_frame(link, frame); | |
| 1521 | 1756690 | li->l.frame_count_out++; | |
| 1522 | 1756690 | li->l.sample_count_out += frame->nb_samples; | |
| 1523 | 1756690 | } | |
| 1524 | |||
| 1525 | 5689508 | int ff_inlink_consume_frame(AVFilterLink *link, AVFrame **rframe) | |
| 1526 | { | ||
| 1527 | 5689508 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1528 | AVFrame *frame; | ||
| 1529 | |||
| 1530 | 5689508 | *rframe = NULL; | |
| 1531 |
2/2✓ Branch 1 taken 3935749 times.
✓ Branch 2 taken 1753759 times.
|
5689508 | if (!ff_inlink_check_available_frame(link)) |
| 1532 | 3935749 | return 0; | |
| 1533 | |||
| 1534 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1753755 times.
|
1753759 | if (li->fifo.samples_skipped) { |
| 1535 | 4 | frame = ff_framequeue_peek(&li->fifo, 0); | |
| 1536 | 4 | return ff_inlink_consume_samples(link, frame->nb_samples, frame->nb_samples, rframe); | |
| 1537 | } | ||
| 1538 | |||
| 1539 | 1753755 | frame = ff_framequeue_take(&li->fifo); | |
| 1540 | 1753755 | consume_update(li, frame); | |
| 1541 | 1753755 | *rframe = frame; | |
| 1542 | 1753755 | return 1; | |
| 1543 | } | ||
| 1544 | |||
| 1545 | 4873 | int ff_inlink_consume_samples(AVFilterLink *link, unsigned min, unsigned max, | |
| 1546 | AVFrame **rframe) | ||
| 1547 | { | ||
| 1548 | 4873 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1549 | AVFrame *frame; | ||
| 1550 | int ret; | ||
| 1551 | |||
| 1552 | av_assert1(min); | ||
| 1553 | 4873 | *rframe = NULL; | |
| 1554 |
2/2✓ Branch 1 taken 1938 times.
✓ Branch 2 taken 2935 times.
|
4873 | if (!ff_inlink_check_available_samples(link, min)) |
| 1555 | 1938 | return 0; | |
| 1556 |
2/2✓ Branch 0 taken 21 times.
✓ Branch 1 taken 2914 times.
|
2935 | if (li->status_in) |
| 1557 |
2/2✓ Branch 1 taken 6 times.
✓ Branch 2 taken 15 times.
|
21 | min = FFMIN(min, ff_framequeue_queued_samples(&li->fifo)); |
| 1558 | 2935 | ret = take_samples(li, min, max, &frame); | |
| 1559 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2935 times.
|
2935 | if (ret < 0) |
| 1560 | ✗ | return ret; | |
| 1561 | 2935 | consume_update(li, frame); | |
| 1562 | 2935 | *rframe = frame; | |
| 1563 | 2935 | return 1; | |
| 1564 | } | ||
| 1565 | |||
| 1566 | 532 | AVFrame *ff_inlink_peek_frame(AVFilterLink *link, size_t idx) | |
| 1567 | { | ||
| 1568 | 532 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1569 | 532 | return ff_framequeue_peek(&li->fifo, idx); | |
| 1570 | } | ||
| 1571 | |||
| 1572 | 5176 | int ff_inlink_make_frame_writable(AVFilterLink *link, AVFrame **rframe) | |
| 1573 | { | ||
| 1574 | 5176 | AVFrame *frame = *rframe; | |
| 1575 | AVFrame *out; | ||
| 1576 | int ret; | ||
| 1577 | |||
| 1578 |
2/2✓ Branch 1 taken 2302 times.
✓ Branch 2 taken 2874 times.
|
5176 | if (av_frame_is_writable(frame)) |
| 1579 | 2302 | return 0; | |
| 1580 | 2874 | av_log(link->dst, AV_LOG_DEBUG, "Copying data in avfilter.\n"); | |
| 1581 | |||
| 1582 |
1/3✓ Branch 0 taken 2874 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
2874 | switch (link->type) { |
| 1583 | 2874 | case AVMEDIA_TYPE_VIDEO: | |
| 1584 | 2874 | out = ff_get_video_buffer(link, link->w, link->h); | |
| 1585 | 2874 | break; | |
| 1586 | ✗ | case AVMEDIA_TYPE_AUDIO: | |
| 1587 | ✗ | out = ff_get_audio_buffer(link, frame->nb_samples); | |
| 1588 | ✗ | break; | |
| 1589 | ✗ | default: | |
| 1590 | ✗ | return AVERROR(EINVAL); | |
| 1591 | } | ||
| 1592 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2874 times.
|
2874 | if (!out) |
| 1593 | ✗ | return AVERROR(ENOMEM); | |
| 1594 | |||
| 1595 | 2874 | ret = av_frame_copy_props(out, frame); | |
| 1596 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2874 times.
|
2874 | if (ret < 0) { |
| 1597 | ✗ | av_frame_free(&out); | |
| 1598 | ✗ | return ret; | |
| 1599 | } | ||
| 1600 | |||
| 1601 | 2874 | ret = av_frame_copy(out, frame); | |
| 1602 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2874 times.
|
2874 | if (ret < 0) { |
| 1603 | ✗ | av_frame_free(&out); | |
| 1604 | ✗ | return ret; | |
| 1605 | } | ||
| 1606 | |||
| 1607 | 2874 | av_frame_free(&frame); | |
| 1608 | 2874 | *rframe = out; | |
| 1609 | 2874 | return 0; | |
| 1610 | } | ||
| 1611 | |||
| 1612 | 2590005 | int ff_inlink_process_commands(AVFilterLink *link, const AVFrame *frame) | |
| 1613 | { | ||
| 1614 | 2590005 | FFFilterContext *ctxi = fffilterctx(link->dst); | |
| 1615 | 2590005 | AVFilterCommand *cmd = ctxi->command_queue; | |
| 1616 | |||
| 1617 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 2590005 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
2590005 | while(cmd && cmd->time <= frame->pts * av_q2d(link->time_base)){ |
| 1618 | ✗ | av_log(link->dst, AV_LOG_DEBUG, | |
| 1619 | "Processing command time:%f command:%s arg:%s\n", | ||
| 1620 | cmd->time, cmd->command, cmd->arg); | ||
| 1621 | ✗ | avfilter_process_command(link->dst, cmd->command, cmd->arg, 0, 0, cmd->flags); | |
| 1622 | ✗ | command_queue_pop(link->dst); | |
| 1623 | ✗ | cmd = ctxi->command_queue; | |
| 1624 | } | ||
| 1625 | 2590005 | return 0; | |
| 1626 | } | ||
| 1627 | |||
| 1628 | 923680 | void ff_inlink_request_frame(AVFilterLink *link) | |
| 1629 | { | ||
| 1630 | 923680 | av_unused FilterLinkInternal *li = ff_link_internal(link); | |
| 1631 | av_assert1(!li->status_in); | ||
| 1632 | av_assert1(!li->status_out); | ||
| 1633 | 923680 | li->frame_wanted_out = 1; | |
| 1634 | 923680 | ff_filter_set_ready(link->src, 100); | |
| 1635 | 923680 | } | |
| 1636 | |||
| 1637 | 11679 | void ff_inlink_set_status(AVFilterLink *link, int status) | |
| 1638 | { | ||
| 1639 | 11679 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1640 |
2/2✓ Branch 0 taken 9118 times.
✓ Branch 1 taken 2561 times.
|
11679 | if (li->status_out) |
| 1641 | 9118 | return; | |
| 1642 | 2561 | li->frame_wanted_out = 0; | |
| 1643 | 2561 | li->frame_blocked_in = 0; | |
| 1644 | 2561 | link_set_out_status(link, status, AV_NOPTS_VALUE); | |
| 1645 |
2/2✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2561 times.
|
2567 | while (ff_framequeue_queued_frames(&li->fifo)) { |
| 1646 | 6 | AVFrame *frame = ff_framequeue_take(&li->fifo); | |
| 1647 | 6 | av_frame_free(&frame); | |
| 1648 | } | ||
| 1649 |
2/2✓ Branch 0 taken 2558 times.
✓ Branch 1 taken 3 times.
|
2561 | if (!li->status_in) |
| 1650 | 2558 | li->status_in = status; | |
| 1651 | } | ||
| 1652 | |||
| 1653 | 4291061 | int ff_outlink_get_status(AVFilterLink *link) | |
| 1654 | { | ||
| 1655 | 4291061 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1656 | 4291061 | return li->status_in; | |
| 1657 | } | ||
| 1658 | |||
| 1659 | 1784 | int ff_inoutlink_check_flow(AVFilterLink *inlink, AVFilterLink *outlink) | |
| 1660 | { | ||
| 1661 | 1784 | FilterLinkInternal * const li_in = ff_link_internal(inlink); | |
| 1662 |
2/2✓ Branch 1 taken 1059 times.
✓ Branch 2 taken 70 times.
|
2913 | return ff_outlink_frame_wanted(outlink) || |
| 1663 |
2/2✓ Branch 0 taken 1129 times.
✓ Branch 1 taken 655 times.
|
2913 | ff_inlink_check_available_frame(inlink) || |
| 1664 |
2/2✓ Branch 0 taken 62 times.
✓ Branch 1 taken 997 times.
|
1059 | li_in->status_out; |
| 1665 | } | ||
| 1666 | |||
| 1667 | |||
| 1668 | ✗ | const AVClass *avfilter_get_class(void) | |
| 1669 | { | ||
| 1670 | ✗ | return &avfilter_class; | |
| 1671 | } | ||
| 1672 | |||
| 1673 | ✗ | int ff_filter_init_hw_frames(AVFilterContext *avctx, AVFilterLink *link, | |
| 1674 | int default_pool_size) | ||
| 1675 | { | ||
| 1676 | ✗ | FilterLink *l = ff_filter_link(link); | |
| 1677 | AVHWFramesContext *frames; | ||
| 1678 | |||
| 1679 | // Must already be set by caller. | ||
| 1680 | ✗ | av_assert0(l->hw_frames_ctx); | |
| 1681 | |||
| 1682 | ✗ | frames = (AVHWFramesContext*)l->hw_frames_ctx->data; | |
| 1683 | |||
| 1684 | ✗ | if (frames->initial_pool_size == 0) { | |
| 1685 | // Dynamic allocation is necessarily supported. | ||
| 1686 | ✗ | } else if (avctx->extra_hw_frames >= 0) { | |
| 1687 | ✗ | frames->initial_pool_size += avctx->extra_hw_frames; | |
| 1688 | } else { | ||
| 1689 | ✗ | frames->initial_pool_size = default_pool_size; | |
| 1690 | } | ||
| 1691 | |||
| 1692 | ✗ | return 0; | |
| 1693 | } | ||
| 1694 | |||
| 1695 | 505746 | int ff_outlink_frame_wanted(AVFilterLink *link) | |
| 1696 | { | ||
| 1697 | 505746 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1698 | 505746 | return li->frame_wanted_out; | |
| 1699 | } | ||
| 1700 | |||
| 1701 | 5252 | int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, | |
| 1702 | void *arg, int *ret, int nb_jobs) | ||
| 1703 | { | ||
| 1704 | 5252 | return fffilterctx(ctx)->execute(ctx, func, arg, ret, nb_jobs); | |
| 1705 | } | ||
| 1706 |