| 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 | 1720749 | 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 | 1720749 | } | |
| 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 | 579 | static int append_pad(unsigned *count, AVFilterPad **pads, | |
| 101 | AVFilterLink ***links, AVFilterPad *newpad) | ||
| 102 | { | ||
| 103 | AVFilterLink **newlinks; | ||
| 104 | AVFilterPad *newpads; | ||
| 105 | 579 | unsigned idx = *count; | |
| 106 | |||
| 107 | 579 | newpads = av_realloc_array(*pads, idx + 1, sizeof(*newpads)); | |
| 108 | 579 | newlinks = av_realloc_array(*links, idx + 1, sizeof(*newlinks)); | |
| 109 |
1/2✓ Branch 0 taken 579 times.
✗ Branch 1 not taken.
|
579 | if (newpads) |
| 110 | 579 | *pads = newpads; | |
| 111 |
1/2✓ Branch 0 taken 579 times.
✗ Branch 1 not taken.
|
579 | if (newlinks) |
| 112 | 579 | *links = newlinks; | |
| 113 |
2/4✓ Branch 0 taken 579 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 579 times.
|
579 | if (!newpads || !newlinks) { |
| 114 | ✗ | if (newpad->flags & AVFILTERPAD_FLAG_FREE_NAME) | |
| 115 | ✗ | av_freep(&newpad->name); | |
| 116 | ✗ | return AVERROR(ENOMEM); | |
| 117 | } | ||
| 118 | |||
| 119 | 579 | memcpy(*pads + idx, newpad, sizeof(AVFilterPad)); | |
| 120 | 579 | (*links)[idx] = NULL; | |
| 121 | |||
| 122 | 579 | (*count)++; | |
| 123 | |||
| 124 | 579 | return 0; | |
| 125 | } | ||
| 126 | |||
| 127 | 289 | int ff_append_inpad(AVFilterContext *f, AVFilterPad *p) | |
| 128 | { | ||
| 129 | 289 | return append_pad(&f->nb_inputs, &f->input_pads, &f->inputs, p); | |
| 130 | } | ||
| 131 | |||
| 132 | 270 | int ff_append_inpad_free_name(AVFilterContext *f, AVFilterPad *p) | |
| 133 | { | ||
| 134 | 270 | p->flags |= AVFILTERPAD_FLAG_FREE_NAME; | |
| 135 | 270 | return ff_append_inpad(f, p); | |
| 136 | } | ||
| 137 | |||
| 138 | 290 | int ff_append_outpad(AVFilterContext *f, AVFilterPad *p) | |
| 139 | { | ||
| 140 | 290 | return append_pad(&f->nb_outputs, &f->output_pads, &f->outputs, p); | |
| 141 | } | ||
| 142 | |||
| 143 | 149 | int ff_append_outpad_free_name(AVFilterContext *f, AVFilterPad *p) | |
| 144 | { | ||
| 145 | 149 | p->flags |= AVFILTERPAD_FLAG_FREE_NAME; | |
| 146 | 149 | return ff_append_outpad(f, p); | |
| 147 | } | ||
| 148 | |||
| 149 | 47722 | 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 47722 times.
|
47722 | av_assert0(src->graph); |
| 156 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 47722 times.
|
47722 | av_assert0(dst->graph); |
| 157 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 47722 times.
|
47722 | av_assert0(src->graph == dst->graph); |
| 158 | |||
| 159 |
2/4✓ Branch 0 taken 47722 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 47722 times.
✗ Branch 3 not taken.
|
47722 | if (src->nb_outputs <= srcpad || dst->nb_inputs <= dstpad || |
| 160 |
2/4✓ Branch 0 taken 47722 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 47722 times.
|
47722 | src->outputs[srcpad] || dst->inputs[dstpad]) |
| 161 | ✗ | return AVERROR(EINVAL); | |
| 162 | |||
| 163 |
1/2✓ Branch 1 taken 47722 times.
✗ Branch 2 not taken.
|
47722 | if (!(fffilterctx(src)->state_flags & AV_CLASS_STATE_INITIALIZED) || |
| 164 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 47722 times.
|
47722 | !(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 47722 times.
|
47722 | 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 | 47722 | li = av_mallocz(sizeof(*li)); | |
| 178 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 47722 times.
|
47722 | if (!li) |
| 179 | ✗ | return AVERROR(ENOMEM); | |
| 180 | 47722 | link = &li->l.pub; | |
| 181 | |||
| 182 | 47722 | src->outputs[srcpad] = dst->inputs[dstpad] = link; | |
| 183 | |||
| 184 | 47722 | link->src = src; | |
| 185 | 47722 | link->dst = dst; | |
| 186 | 47722 | link->srcpad = &src->output_pads[srcpad]; | |
| 187 | 47722 | link->dstpad = &dst->input_pads[dstpad]; | |
| 188 | 47722 | link->type = src->output_pads[srcpad].type; | |
| 189 | 47722 | li->l.graph = src->graph; | |
| 190 | av_assert0(AV_PIX_FMT_NONE == -1 && AV_SAMPLE_FMT_NONE == -1); | ||
| 191 | 47722 | link->format = -1; | |
| 192 | 47722 | link->colorspace = AVCOL_SPC_UNSPECIFIED; | |
| 193 | 47722 | ff_framequeue_init(&li->fifo, &fffiltergraph(src->graph)->frame_queues); | |
| 194 | |||
| 195 | 47722 | return 0; | |
| 196 | } | ||
| 197 | |||
| 198 | 47854 | static void link_free(AVFilterLink **link) | |
| 199 | { | ||
| 200 | FilterLinkInternal *li; | ||
| 201 | |||
| 202 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 47854 times.
|
47854 | if (!*link) |
| 203 | ✗ | return; | |
| 204 | 47854 | li = ff_link_internal(*link); | |
| 205 | |||
| 206 | 47854 | ff_framequeue_free(&li->fifo); | |
| 207 | 47854 | ff_frame_pool_uninit(&li->frame_pool); | |
| 208 | 47854 | av_channel_layout_uninit(&(*link)->ch_layout); | |
| 209 | 47854 | av_frame_side_data_free(&(*link)->side_data, &(*link)->nb_side_data); | |
| 210 | |||
| 211 | 47854 | av_buffer_unref(&li->l.hw_frames_ctx); | |
| 212 | |||
| 213 | 47854 | av_freep(link); | |
| 214 | } | ||
| 215 | |||
| 216 | 1732527 | static void update_link_current_pts(FilterLinkInternal *li, int64_t pts) | |
| 217 | { | ||
| 218 | 1732527 | AVFilterLink *const link = &li->l.pub; | |
| 219 | |||
| 220 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1732522 times.
|
1732527 | if (pts == AV_NOPTS_VALUE) |
| 221 | 5 | return; | |
| 222 | 1732522 | li->l.current_pts = pts; | |
| 223 | 1732522 | 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 1732522 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 467294 times.
✓ Branch 3 taken 1265228 times.
|
1732522 | if (li->l.graph && li->age_index >= 0) |
| 226 | 467294 | ff_avfilter_graph_update_heap(li->l.graph, li); | |
| 227 | } | ||
| 228 | |||
| 229 | 4294908 | void ff_filter_set_ready(AVFilterContext *filter, unsigned priority) | |
| 230 | { | ||
| 231 | 4294908 | FFFilterContext *ctxi = fffilterctx(filter); | |
| 232 | 4294908 | ctxi->ready = FFMAX(ctxi->ready, priority); | |
| 233 | 4294908 | } | |
| 234 | |||
| 235 | /** | ||
| 236 | * Clear frame_blocked_in on all outputs. | ||
| 237 | * This is necessary whenever something changes on input. | ||
| 238 | */ | ||
| 239 | 2563682 | static void filter_unblock(AVFilterContext *filter) | |
| 240 | { | ||
| 241 | unsigned i; | ||
| 242 | |||
| 243 |
2/2✓ Branch 0 taken 2096488 times.
✓ Branch 1 taken 2563682 times.
|
4660170 | for (i = 0; i < filter->nb_outputs; i++) { |
| 244 | 2096488 | FilterLinkInternal * const li = ff_link_internal(filter->outputs[i]); | |
| 245 | 2096488 | li->frame_blocked_in = 0; | |
| 246 | } | ||
| 247 | 2563682 | } | |
| 248 | |||
| 249 | |||
| 250 | 20027 | void ff_avfilter_link_set_in_status(AVFilterLink *link, int status, int64_t pts) | |
| 251 | { | ||
| 252 | 20027 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 253 | |||
| 254 |
2/2✓ Branch 0 taken 5700 times.
✓ Branch 1 taken 14327 times.
|
20027 | if (li->status_in == status) |
| 255 | 5700 | return; | |
| 256 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14327 times.
|
14327 | av_assert0(!li->status_in); |
| 257 | 14327 | li->status_in = status; | |
| 258 | 14327 | li->status_in_pts = pts; | |
| 259 | 14327 | li->frame_wanted_out = 0; | |
| 260 | 14327 | li->frame_blocked_in = 0; | |
| 261 | 14327 | filter_unblock(link->dst); | |
| 262 | 14327 | 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 | 8738 | static void link_set_out_status(AVFilterLink *link, int status, int64_t pts) | |
| 270 | { | ||
| 271 | 8738 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 272 | |||
| 273 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8738 times.
|
8738 | av_assert0(!li->frame_wanted_out); |
| 274 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8738 times.
|
8738 | av_assert0(!li->status_out); |
| 275 | 8738 | li->status_out = status; | |
| 276 |
2/2✓ Branch 0 taken 6198 times.
✓ Branch 1 taken 2540 times.
|
8738 | if (pts != AV_NOPTS_VALUE) |
| 277 | 6198 | update_link_current_pts(li, pts); | |
| 278 | 8738 | filter_unblock(link->dst); | |
| 279 | 8738 | ff_filter_set_ready(link->src, 200); | |
| 280 | 8738 | } | |
| 281 | |||
| 282 | 1303 | int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt, | |
| 283 | unsigned filt_srcpad_idx, unsigned filt_dstpad_idx) | ||
| 284 | { | ||
| 285 | int ret; | ||
| 286 | 1303 | unsigned dstpad_idx = link->dstpad - link->dst->input_pads; | |
| 287 | |||
| 288 | 1303 | av_log(link->dst, AV_LOG_VERBOSE, "auto-inserting filter '%s' " | |
| 289 | "between the filter '%s' and the filter '%s'\n", | ||
| 290 | 1303 | filt->name, link->src->name, link->dst->name); | |
| 291 | |||
| 292 | 1303 | link->dst->inputs[dstpad_idx] = NULL; | |
| 293 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1303 times.
|
1303 | 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 | 1303 | link->dst = filt; | |
| 301 | 1303 | link->dstpad = &filt->input_pads[filt_srcpad_idx]; | |
| 302 | 1303 | 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 1303 times.
✗ Branch 1 not taken.
|
1303 | if (link->outcfg.formats) |
| 307 | 1303 | ff_formats_changeref(&link->outcfg.formats, | |
| 308 | 1303 | &filt->outputs[filt_dstpad_idx]->outcfg.formats); | |
| 309 |
2/2✓ Branch 0 taken 634 times.
✓ Branch 1 taken 669 times.
|
1303 | if (link->outcfg.color_spaces) |
| 310 | 634 | ff_formats_changeref(&link->outcfg.color_spaces, | |
| 311 | 634 | &filt->outputs[filt_dstpad_idx]->outcfg.color_spaces); | |
| 312 |
2/2✓ Branch 0 taken 634 times.
✓ Branch 1 taken 669 times.
|
1303 | if (link->outcfg.color_ranges) |
| 313 | 634 | ff_formats_changeref(&link->outcfg.color_ranges, | |
| 314 | 634 | &filt->outputs[filt_dstpad_idx]->outcfg.color_ranges); | |
| 315 |
2/2✓ Branch 0 taken 634 times.
✓ Branch 1 taken 669 times.
|
1303 | if (link->outcfg.alpha_modes) |
| 316 | 634 | ff_formats_changeref(&link->outcfg.alpha_modes, | |
| 317 | 634 | &filt->outputs[filt_dstpad_idx]->outcfg.alpha_modes); | |
| 318 |
2/2✓ Branch 0 taken 669 times.
✓ Branch 1 taken 634 times.
|
1303 | if (link->outcfg.samplerates) |
| 319 | 669 | ff_formats_changeref(&link->outcfg.samplerates, | |
| 320 | 669 | &filt->outputs[filt_dstpad_idx]->outcfg.samplerates); | |
| 321 |
2/2✓ Branch 0 taken 669 times.
✓ Branch 1 taken 634 times.
|
1303 | if (link->outcfg.channel_layouts) |
| 322 | 669 | ff_channel_layouts_changeref(&link->outcfg.channel_layouts, | |
| 323 | 669 | &filt->outputs[filt_dstpad_idx]->outcfg.channel_layouts); | |
| 324 | |||
| 325 | 1303 | return 0; | |
| 326 | } | ||
| 327 | |||
| 328 | 45793 | 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 37464 times.
✓ Branch 1 taken 45789 times.
|
83253 | for (i = 0; i < filter->nb_inputs; i ++) { |
| 335 | 37464 | AVFilterLink *link = filter->inputs[i]; | |
| 336 | AVFilterLink *inlink; | ||
| 337 | 37464 | FilterLinkInternal *li = ff_link_internal(link); | |
| 338 | FilterLinkInternal *li_in; | ||
| 339 | |||
| 340 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 37464 times.
|
37464 | if (!link) continue; |
| 341 |
2/4✓ Branch 0 taken 37464 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 37464 times.
|
37464 | 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 28933 times.
✓ Branch 1 taken 8531 times.
|
37464 | inlink = link->src->nb_inputs ? link->src->inputs[0] : NULL; |
| 348 |
2/2✓ Branch 0 taken 28933 times.
✓ Branch 1 taken 8531 times.
|
37464 | li_in = inlink ? ff_link_internal(inlink) : NULL; |
| 349 | 37464 | li->l.current_pts = | |
| 350 | 37464 | 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 37351 times.
✗ Branch 3 not taken.
|
37464 | 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 | 37351 | case AVLINK_UNINIT: | |
| 359 | 37351 | li->init_state = AVLINK_STARTINIT; | |
| 360 | |||
| 361 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 37350 times.
|
37351 | if ((ret = ff_filter_config_links(link->src)) < 0) |
| 362 | 1 | return ret; | |
| 363 | |||
| 364 |
2/2✓ Branch 0 taken 19566 times.
✓ Branch 1 taken 17784 times.
|
37350 | if (!(config_link = link->srcpad->config_props)) { |
| 365 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19566 times.
|
19566 | 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 28853 times.
✓ Branch 1 taken 8497 times.
✓ Branch 2 taken 311 times.
✓ Branch 3 taken 28542 times.
✓ Branch 4 taken 311 times.
✗ Branch 5 not taken.
|
37350 | if (inlink && inlink->nb_side_data && !link->nb_side_data) { |
| 377 |
2/2✓ Branch 0 taken 355 times.
✓ Branch 1 taken 311 times.
|
666 | for (int j = 0; j < inlink->nb_side_data; j++) { |
| 378 | 355 | ret = av_frame_side_data_clone(&link->side_data, &link->nb_side_data, | |
| 379 | 355 | inlink->side_data[j], 0); | |
| 380 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 355 times.
|
355 | if (ret < 0) { |
| 381 | ✗ | av_frame_side_data_free(&link->side_data, &link->nb_side_data); | |
| 382 | ✗ | return ret; | |
| 383 | } | ||
| 384 | } | ||
| 385 | } | ||
| 386 | |||
| 387 |
4/4✓ Branch 0 taken 17784 times.
✓ Branch 1 taken 19566 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 17783 times.
|
37350 | if (config_link && (ret = config_link(link)) < 0) { |
| 388 | 1 | av_log(link->src, AV_LOG_ERROR, | |
| 389 | "Failed to configure output pad on %s\n", | ||
| 390 | 1 | link->src->name); | |
| 391 | 1 | return ret; | |
| 392 | } | ||
| 393 | |||
| 394 |
2/3✓ Branch 0 taken 31111 times.
✓ Branch 1 taken 6238 times.
✗ Branch 2 not taken.
|
37349 | switch (link->type) { |
| 395 | 31111 | case AVMEDIA_TYPE_VIDEO: | |
| 396 |
3/4✓ Branch 0 taken 23806 times.
✓ Branch 1 taken 7305 times.
✓ Branch 2 taken 23806 times.
✗ Branch 3 not taken.
|
31111 | if (!link->time_base.num && !link->time_base.den) |
| 397 |
1/2✓ Branch 0 taken 23806 times.
✗ Branch 1 not taken.
|
23806 | link->time_base = inlink ? inlink->time_base : AV_TIME_BASE_Q; |
| 398 | |||
| 399 |
4/4✓ Branch 0 taken 26590 times.
✓ Branch 1 taken 4521 times.
✓ Branch 2 taken 16926 times.
✓ Branch 3 taken 9664 times.
|
31111 | if (!link->sample_aspect_ratio.num && !link->sample_aspect_ratio.den) |
| 400 | 16926 | link->sample_aspect_ratio = inlink ? | |
| 401 |
2/2✓ Branch 0 taken 16911 times.
✓ Branch 1 taken 15 times.
|
16926 | inlink->sample_aspect_ratio : (AVRational){1,1}; |
| 402 | |||
| 403 |
2/2✓ Branch 0 taken 24070 times.
✓ Branch 1 taken 7041 times.
|
31111 | if (inlink) { |
| 404 |
3/4✓ Branch 0 taken 23849 times.
✓ Branch 1 taken 221 times.
✓ Branch 2 taken 23849 times.
✗ Branch 3 not taken.
|
24070 | if (!li->l.frame_rate.num && !li->l.frame_rate.den) |
| 405 | 23849 | li->l.frame_rate = li_in->l.frame_rate; | |
| 406 |
2/2✓ Branch 0 taken 16423 times.
✓ Branch 1 taken 7647 times.
|
24070 | if (!link->w) |
| 407 | 16423 | link->w = inlink->w; | |
| 408 |
2/2✓ Branch 0 taken 16423 times.
✓ Branch 1 taken 7647 times.
|
24070 | if (!link->h) |
| 409 | 16423 | link->h = inlink->h; | |
| 410 |
2/4✓ Branch 0 taken 7041 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7041 times.
|
7041 | } 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 | 31111 | break; | |
| 417 | |||
| 418 | 6238 | case AVMEDIA_TYPE_AUDIO: | |
| 419 |
2/2✓ Branch 0 taken 4782 times.
✓ Branch 1 taken 1456 times.
|
6238 | if (inlink) { |
| 420 |
3/4✓ Branch 0 taken 3234 times.
✓ Branch 1 taken 1548 times.
✓ Branch 2 taken 3234 times.
✗ Branch 3 not taken.
|
4782 | if (!link->time_base.num && !link->time_base.den) |
| 421 | 3234 | link->time_base = inlink->time_base; | |
| 422 | } | ||
| 423 | |||
| 424 |
3/4✓ Branch 0 taken 84 times.
✓ Branch 1 taken 6154 times.
✓ Branch 2 taken 84 times.
✗ Branch 3 not taken.
|
6238 | if (!link->time_base.num && !link->time_base.den) |
| 425 | 84 | link->time_base = (AVRational) {1, link->sample_rate}; | |
| 426 | } | ||
| 427 | |||
| 428 |
2/2✓ Branch 0 taken 28852 times.
✓ Branch 1 taken 8497 times.
|
37349 | if (link->src->nb_inputs && |
| 429 |
1/2✓ Branch 1 taken 28852 times.
✗ Branch 2 not taken.
|
28852 | !(fffilter(link->src->filter)->flags_internal & FF_FILTER_FLAG_HWFRAME_AWARE)) { |
| 430 | 28852 | FilterLink *l0 = ff_filter_link(link->src->inputs[0]); | |
| 431 | |||
| 432 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 28852 times.
|
28852 | 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 28852 times.
|
28852 | 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 5021 times.
✓ Branch 1 taken 32328 times.
|
37349 | if ((config_link = link->dstpad->config_props)) |
| 443 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 5021 times.
|
5021 | 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 | 37349 | li->init_state = AVLINK_INIT; | |
| 451 | } | ||
| 452 | } | ||
| 453 | |||
| 454 | 45789 | 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 | 820139 | int ff_request_frame(AVFilterLink *link) | |
| 484 | { | ||
| 485 | 820139 | 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 820130 times.
|
820139 | if (li->status_out) |
| 491 | 9 | return li->status_out; | |
| 492 |
2/2✓ Branch 0 taken 6199 times.
✓ Branch 1 taken 813931 times.
|
820130 | if (li->status_in) { |
| 493 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6199 times.
|
6199 | 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 | 6199 | link_set_out_status(link, li->status_in, li->status_in_pts); | |
| 502 | 6199 | return li->status_out; | |
| 503 | } | ||
| 504 | } | ||
| 505 | 813931 | li->frame_wanted_out = 1; | |
| 506 | 813931 | ff_filter_set_ready(link->src, 100); | |
| 507 | 813931 | return 0; | |
| 508 | } | ||
| 509 | |||
| 510 | 6191 | static int64_t guess_status_pts(AVFilterContext *ctx, int status, AVRational link_time_base) | |
| 511 | { | ||
| 512 | unsigned i; | ||
| 513 | 6191 | int64_t r = INT64_MAX; | |
| 514 | |||
| 515 |
2/2✓ Branch 0 taken 6190 times.
✓ Branch 1 taken 6191 times.
|
12381 | for (i = 0; i < ctx->nb_inputs; i++) { |
| 516 | 6190 | FilterLinkInternal * const li = ff_link_internal(ctx->inputs[i]); | |
| 517 |
1/2✓ Branch 0 taken 6190 times.
✗ Branch 1 not taken.
|
6190 | if (li->status_out == status) |
| 518 | 6190 | 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 6190 times.
✓ Branch 1 taken 1 times.
|
6191 | if (r < INT64_MAX) |
| 521 | 6190 | 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 | 820455 | static int request_frame_to_filter(AVFilterLink *link) | |
| 533 | { | ||
| 534 | 820455 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 535 | 820455 | 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 | 820455 | li->frame_blocked_in = 1; | |
| 540 |
2/2✓ Branch 0 taken 2016 times.
✓ Branch 1 taken 818439 times.
|
820455 | if (link->srcpad->request_frame) |
| 541 | 2016 | ret = link->srcpad->request_frame(link); | |
| 542 |
1/2✓ Branch 0 taken 818439 times.
✗ Branch 1 not taken.
|
818439 | else if (link->src->inputs[0]) |
| 543 | 818439 | ret = ff_request_frame(link->src->inputs[0]); | |
| 544 |
2/2✓ Branch 0 taken 6191 times.
✓ Branch 1 taken 814264 times.
|
820455 | if (ret < 0) { |
| 545 |
2/4✓ Branch 0 taken 6191 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6191 times.
✗ Branch 3 not taken.
|
6191 | if (ret != AVERROR(EAGAIN) && ret != li->status_in) |
| 546 | 6191 | ff_avfilter_link_set_in_status(link, ret, guess_status_pts(link->src, ret, link->time_base)); | |
| 547 |
1/2✓ Branch 0 taken 6191 times.
✗ Branch 1 not taken.
|
6191 | if (ret == AVERROR_EOF) |
| 548 | 6191 | ret = 0; | |
| 549 | } | ||
| 550 | 820455 | return ret; | |
| 551 | } | ||
| 552 | |||
| 553 | static const char *const var_names[] = { | ||
| 554 | "t", | ||
| 555 | "n", | ||
| 556 | "w", | ||
| 557 | "h", | ||
| 558 | NULL | ||
| 559 | }; | ||
| 560 | |||
| 561 | enum { | ||
| 562 | VAR_T, | ||
| 563 | VAR_N, | ||
| 564 | VAR_W, | ||
| 565 | VAR_H, | ||
| 566 | VAR_VARS_NB | ||
| 567 | }; | ||
| 568 | |||
| 569 | 6 | static int set_enable_expr(FFFilterContext *ctxi, const char *expr) | |
| 570 | { | ||
| 571 | 6 | AVFilterContext *ctx = &ctxi->p; | |
| 572 | int ret; | ||
| 573 | char *expr_dup; | ||
| 574 | 6 | AVExpr *old = ctxi->enable; | |
| 575 | |||
| 576 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (!(ctx->filter->flags & AVFILTER_FLAG_SUPPORT_TIMELINE)) { |
| 577 | ✗ | av_log(ctx, AV_LOG_ERROR, "Timeline ('enable' option) not supported " | |
| 578 | ✗ | "with filter '%s'\n", ctx->filter->name); | |
| 579 | ✗ | return AVERROR_PATCHWELCOME; | |
| 580 | } | ||
| 581 | |||
| 582 | 6 | expr_dup = av_strdup(expr); | |
| 583 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (!expr_dup) |
| 584 | ✗ | return AVERROR(ENOMEM); | |
| 585 | |||
| 586 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | if (!ctxi->var_values) { |
| 587 | 6 | ctxi->var_values = av_calloc(VAR_VARS_NB, sizeof(*ctxi->var_values)); | |
| 588 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (!ctxi->var_values) { |
| 589 | ✗ | av_free(expr_dup); | |
| 590 | ✗ | return AVERROR(ENOMEM); | |
| 591 | } | ||
| 592 | } | ||
| 593 | |||
| 594 | 6 | ret = av_expr_parse(&ctxi->enable, expr_dup, var_names, | |
| 595 | NULL, NULL, NULL, NULL, 0, ctx->priv); | ||
| 596 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (ret < 0) { |
| 597 | ✗ | av_log(ctx->priv, AV_LOG_ERROR, | |
| 598 | "Error when evaluating the expression '%s' for enable\n", | ||
| 599 | expr_dup); | ||
| 600 | ✗ | av_free(expr_dup); | |
| 601 | ✗ | return ret; | |
| 602 | } | ||
| 603 | |||
| 604 | 6 | av_expr_free(old); | |
| 605 | 6 | av_free(ctx->enable_str); | |
| 606 | 6 | ctx->enable_str = expr_dup; | |
| 607 | 6 | return 0; | |
| 608 | } | ||
| 609 | |||
| 610 | ✗ | int avfilter_process_command(AVFilterContext *filter, const char *cmd, const char *arg, char *res, int res_len, int flags) | |
| 611 | { | ||
| 612 | ✗ | if(!strcmp(cmd, "ping")){ | |
| 613 | ✗ | char local_res[256] = {0}; | |
| 614 | |||
| 615 | ✗ | if (!res) { | |
| 616 | ✗ | res = local_res; | |
| 617 | ✗ | res_len = sizeof(local_res); | |
| 618 | } | ||
| 619 | ✗ | av_strlcatf(res, res_len, "pong from:%s %s\n", filter->filter->name, filter->name); | |
| 620 | ✗ | if (res == local_res) | |
| 621 | ✗ | av_log(filter, AV_LOG_INFO, "%s", res); | |
| 622 | ✗ | return 0; | |
| 623 | ✗ | }else if(!strcmp(cmd, "enable")) { | |
| 624 | ✗ | return set_enable_expr(fffilterctx(filter), arg); | |
| 625 | ✗ | }else if (fffilter(filter->filter)->process_command) { | |
| 626 | ✗ | return fffilter(filter->filter)->process_command(filter, cmd, arg, res, res_len, flags); | |
| 627 | } | ||
| 628 | ✗ | return AVERROR(ENOSYS); | |
| 629 | } | ||
| 630 | |||
| 631 | ✗ | unsigned avfilter_filter_pad_count(const AVFilter *filter, int is_output) | |
| 632 | { | ||
| 633 | ✗ | return is_output ? fffilter(filter)->nb_outputs : fffilter(filter)->nb_inputs; | |
| 634 | } | ||
| 635 | |||
| 636 | 594 | static const char *default_filter_name(void *filter_ctx) | |
| 637 | { | ||
| 638 | 594 | AVFilterContext *ctx = filter_ctx; | |
| 639 |
1/2✓ Branch 0 taken 594 times.
✗ Branch 1 not taken.
|
594 | return ctx->name ? ctx->name : ctx->filter->name; |
| 640 | } | ||
| 641 | |||
| 642 | 57595 | static void *filter_child_next(void *obj, void *prev) | |
| 643 | { | ||
| 644 | 57595 | AVFilterContext *ctx = obj; | |
| 645 |
5/8✓ Branch 0 taken 57589 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 57589 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 57589 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 57589 times.
✗ Branch 7 not taken.
|
57595 | if (!prev && ctx->filter && ctx->filter->priv_class && ctx->priv) |
| 646 | 57589 | 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 | 1373 | 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 1429 times.
✓ Branch 1 taken 1373 times.
|
2802 | for (i = 0; i < nb_jobs; i++) { |
| 694 | 1429 | int r = func(ctx, arg, i, nb_jobs); | |
| 695 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1429 times.
|
1429 | if (ret) |
| 696 | ✗ | ret[i] = r; | |
| 697 | } | ||
| 698 | 1373 | return 0; | |
| 699 | } | ||
| 700 | |||
| 701 | 64357 | AVFilterContext *ff_filter_alloc(const AVFilter *filter, const char *inst_name) | |
| 702 | { | ||
| 703 | FFFilterContext *ctx; | ||
| 704 | AVFilterContext *ret; | ||
| 705 | 64357 | const FFFilter *const fi = fffilter(filter); | |
| 706 | 64357 | int preinited = 0; | |
| 707 | |||
| 708 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 64357 times.
|
64357 | if (!filter) |
| 709 | ✗ | return NULL; | |
| 710 | |||
| 711 | 64357 | ctx = av_mallocz(sizeof(*ctx)); | |
| 712 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 64357 times.
|
64357 | if (!ctx) |
| 713 | ✗ | return NULL; | |
| 714 | 64357 | ret = &ctx->p; | |
| 715 | |||
| 716 | 64357 | ret->av_class = &avfilter_class; | |
| 717 | 64357 | ret->filter = filter; | |
| 718 |
1/2✓ Branch 0 taken 64357 times.
✗ Branch 1 not taken.
|
64357 | ret->name = inst_name ? av_strdup(inst_name) : NULL; |
| 719 |
2/2✓ Branch 0 taken 57405 times.
✓ Branch 1 taken 6952 times.
|
64357 | if (fi->priv_size) { |
| 720 | 57405 | ret->priv = av_mallocz(fi->priv_size); | |
| 721 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 57405 times.
|
57405 | if (!ret->priv) |
| 722 | ✗ | goto err; | |
| 723 | } | ||
| 724 |
2/2✓ Branch 0 taken 13746 times.
✓ Branch 1 taken 50611 times.
|
64357 | if (fi->preinit) { |
| 725 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 13746 times.
|
13746 | if (fi->preinit(ret) < 0) |
| 726 | ✗ | goto err; | |
| 727 | 13746 | preinited = 1; | |
| 728 | } | ||
| 729 | |||
| 730 | 64357 | av_opt_set_defaults(ret); | |
| 731 |
2/2✓ Branch 0 taken 56146 times.
✓ Branch 1 taken 8211 times.
|
64357 | if (filter->priv_class) { |
| 732 | 56146 | *(const AVClass**)ret->priv = filter->priv_class; | |
| 733 | 56146 | av_opt_set_defaults(ret->priv); | |
| 734 | } | ||
| 735 | |||
| 736 | 64357 | ctx->execute = default_execute; | |
| 737 | |||
| 738 | 64357 | ret->nb_inputs = fi->nb_inputs; | |
| 739 |
2/2✓ Branch 0 taken 54511 times.
✓ Branch 1 taken 9846 times.
|
64357 | if (ret->nb_inputs ) { |
| 740 | 54511 | ret->input_pads = av_memdup(filter->inputs, ret->nb_inputs * sizeof(*filter->inputs)); | |
| 741 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54511 times.
|
54511 | if (!ret->input_pads) |
| 742 | ✗ | goto err; | |
| 743 | 54511 | ret->inputs = av_calloc(ret->nb_inputs, sizeof(*ret->inputs)); | |
| 744 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54511 times.
|
54511 | if (!ret->inputs) |
| 745 | ✗ | goto err; | |
| 746 | } | ||
| 747 | |||
| 748 | 64357 | ret->nb_outputs = fi->nb_outputs; | |
| 749 |
2/2✓ Branch 0 taken 55821 times.
✓ Branch 1 taken 8536 times.
|
64357 | if (ret->nb_outputs) { |
| 750 | 55821 | ret->output_pads = av_memdup(filter->outputs, ret->nb_outputs * sizeof(*filter->outputs)); | |
| 751 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 55821 times.
|
55821 | if (!ret->output_pads) |
| 752 | ✗ | goto err; | |
| 753 | 55821 | ret->outputs = av_calloc(ret->nb_outputs, sizeof(*ret->outputs)); | |
| 754 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 55821 times.
|
55821 | if (!ret->outputs) |
| 755 | ✗ | goto err; | |
| 756 | } | ||
| 757 | |||
| 758 | 64357 | return ret; | |
| 759 | |||
| 760 | ✗ | err: | |
| 761 | ✗ | if (preinited) | |
| 762 | ✗ | fi->uninit(ret); | |
| 763 | ✗ | av_freep(&ret->name); | |
| 764 | ✗ | av_freep(&ret->inputs); | |
| 765 | ✗ | av_freep(&ret->input_pads); | |
| 766 | ✗ | ret->nb_inputs = 0; | |
| 767 | ✗ | av_freep(&ret->outputs); | |
| 768 | ✗ | av_freep(&ret->output_pads); | |
| 769 | ✗ | ret->nb_outputs = 0; | |
| 770 | ✗ | av_freep(&ret->priv); | |
| 771 | ✗ | av_free(ret); | |
| 772 | ✗ | return NULL; | |
| 773 | } | ||
| 774 | |||
| 775 | 111011 | static void free_link(AVFilterLink *link) | |
| 776 | { | ||
| 777 |
2/2✓ Branch 0 taken 63157 times.
✓ Branch 1 taken 47854 times.
|
111011 | if (!link) |
| 778 | 63157 | return; | |
| 779 | |||
| 780 |
2/2✓ Branch 0 taken 47722 times.
✓ Branch 1 taken 132 times.
|
47854 | if (link->src) |
| 781 | 47722 | link->src->outputs[link->srcpad - link->src->output_pads] = NULL; | |
| 782 |
2/2✓ Branch 0 taken 47722 times.
✓ Branch 1 taken 132 times.
|
47854 | if (link->dst) |
| 783 | 47722 | link->dst->inputs[link->dstpad - link->dst->input_pads] = NULL; | |
| 784 | |||
| 785 | 47854 | ff_formats_unref(&link->incfg.formats); | |
| 786 | 47854 | ff_formats_unref(&link->outcfg.formats); | |
| 787 | 47854 | ff_formats_unref(&link->incfg.color_spaces); | |
| 788 | 47854 | ff_formats_unref(&link->outcfg.color_spaces); | |
| 789 | 47854 | ff_formats_unref(&link->incfg.color_ranges); | |
| 790 | 47854 | ff_formats_unref(&link->outcfg.color_ranges); | |
| 791 | 47854 | ff_formats_unref(&link->incfg.alpha_modes); | |
| 792 | 47854 | ff_formats_unref(&link->outcfg.alpha_modes); | |
| 793 | 47854 | ff_formats_unref(&link->incfg.samplerates); | |
| 794 | 47854 | ff_formats_unref(&link->outcfg.samplerates); | |
| 795 | 47854 | ff_channel_layouts_unref(&link->incfg.channel_layouts); | |
| 796 | 47854 | ff_channel_layouts_unref(&link->outcfg.channel_layouts); | |
| 797 | 47854 | link_free(&link); | |
| 798 | } | ||
| 799 | |||
| 800 | 64357 | void avfilter_free(AVFilterContext *filter) | |
| 801 | { | ||
| 802 | FFFilterContext *ctxi; | ||
| 803 | int i; | ||
| 804 | |||
| 805 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 64357 times.
|
64357 | if (!filter) |
| 806 | ✗ | return; | |
| 807 | 64357 | ctxi = fffilterctx(filter); | |
| 808 | |||
| 809 |
1/2✓ Branch 0 taken 64357 times.
✗ Branch 1 not taken.
|
64357 | if (filter->graph) |
| 810 | 64357 | ff_filter_graph_remove_filter(filter->graph, filter); | |
| 811 | |||
| 812 |
2/2✓ Branch 1 taken 49987 times.
✓ Branch 2 taken 14370 times.
|
64357 | if (fffilter(filter->filter)->uninit) |
| 813 | 49987 | fffilter(filter->filter)->uninit(filter); | |
| 814 | |||
| 815 |
2/2✓ Branch 0 taken 54896 times.
✓ Branch 1 taken 64357 times.
|
119253 | for (i = 0; i < filter->nb_inputs; i++) { |
| 816 | 54896 | free_link(filter->inputs[i]); | |
| 817 |
2/2✓ Branch 0 taken 270 times.
✓ Branch 1 taken 54626 times.
|
54896 | if (filter->input_pads[i].flags & AVFILTERPAD_FLAG_FREE_NAME) |
| 818 | 270 | av_freep(&filter->input_pads[i].name); | |
| 819 | } | ||
| 820 |
2/2✓ Branch 0 taken 56115 times.
✓ Branch 1 taken 64357 times.
|
120472 | for (i = 0; i < filter->nb_outputs; i++) { |
| 821 | 56115 | free_link(filter->outputs[i]); | |
| 822 |
2/2✓ Branch 0 taken 285 times.
✓ Branch 1 taken 55830 times.
|
56115 | if (filter->output_pads[i].flags & AVFILTERPAD_FLAG_FREE_NAME) |
| 823 | 285 | av_freep(&filter->output_pads[i].name); | |
| 824 | } | ||
| 825 | |||
| 826 |
2/2✓ Branch 0 taken 56146 times.
✓ Branch 1 taken 8211 times.
|
64357 | if (filter->filter->priv_class) |
| 827 | 56146 | av_opt_free(filter->priv); | |
| 828 | |||
| 829 | 64357 | av_buffer_unref(&filter->hw_device_ctx); | |
| 830 | |||
| 831 | 64357 | av_freep(&filter->name); | |
| 832 | 64357 | av_freep(&filter->input_pads); | |
| 833 | 64357 | av_freep(&filter->output_pads); | |
| 834 | 64357 | av_freep(&filter->inputs); | |
| 835 | 64357 | av_freep(&filter->outputs); | |
| 836 | 64357 | av_freep(&filter->priv); | |
| 837 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 64357 times.
|
64357 | while (ctxi->command_queue) |
| 838 | ✗ | command_queue_pop(filter); | |
| 839 | 64357 | av_opt_free(filter); | |
| 840 | 64357 | av_expr_free(ctxi->enable); | |
| 841 | 64357 | ctxi->enable = NULL; | |
| 842 | 64357 | av_freep(&ctxi->var_values); | |
| 843 | 64357 | av_free(filter); | |
| 844 | } | ||
| 845 | |||
| 846 | 19544 | int ff_filter_get_nb_threads(AVFilterContext *ctx) | |
| 847 | { | ||
| 848 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19544 times.
|
19544 | if (ctx->nb_threads > 0) |
| 849 | ✗ | return FFMIN(ctx->nb_threads, ctx->graph->nb_threads); | |
| 850 | 19544 | return ctx->graph->nb_threads; | |
| 851 | } | ||
| 852 | |||
| 853 | 34407 | int ff_filter_opt_parse(void *logctx, const AVClass *priv_class, | |
| 854 | AVDictionary **options, const char *args) | ||
| 855 | { | ||
| 856 | 34407 | const AVOption *o = NULL; | |
| 857 | int ret; | ||
| 858 | 34407 | int offset= -1; | |
| 859 | |||
| 860 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 34407 times.
|
34407 | if (!args) |
| 861 | ✗ | return 0; | |
| 862 | |||
| 863 |
2/2✓ Branch 0 taken 59380 times.
✓ Branch 1 taken 34407 times.
|
93787 | while (*args) { |
| 864 | char *parsed_key, *value; | ||
| 865 | const char *key; | ||
| 866 | 59380 | const char *shorthand = NULL; | |
| 867 | 59380 | int additional_flags = 0; | |
| 868 | |||
| 869 |
4/4✓ Branch 0 taken 46022 times.
✓ Branch 1 taken 13358 times.
✓ Branch 3 taken 44740 times.
✓ Branch 4 taken 1282 times.
|
59380 | if (priv_class && (o = av_opt_next(&priv_class, o))) { |
| 870 |
4/4✓ Branch 0 taken 42970 times.
✓ Branch 1 taken 1770 times.
✓ Branch 2 taken 4592 times.
✓ Branch 3 taken 38378 times.
|
44740 | if (o->type == AV_OPT_TYPE_CONST || o->offset == offset) |
| 871 | 6362 | continue; | |
| 872 | 38378 | offset = o->offset; | |
| 873 | 38378 | shorthand = o->name; | |
| 874 | } | ||
| 875 | |||
| 876 | 53018 | ret = av_opt_get_key_value(&args, "=", ":", | |
| 877 | shorthand ? AV_OPT_FLAG_IMPLICIT_KEY : 0, | ||
| 878 | &parsed_key, &value); | ||
| 879 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 53018 times.
|
53018 | if (ret < 0) { |
| 880 | ✗ | if (ret == AVERROR(EINVAL)) | |
| 881 | ✗ | av_log(logctx, AV_LOG_ERROR, "No option name near '%s'\n", args); | |
| 882 | else | ||
| 883 | ✗ | av_log(logctx, AV_LOG_ERROR, "Unable to parse '%s': %s\n", args, | |
| 884 | ✗ | av_err2str(ret)); | |
| 885 | ✗ | return ret; | |
| 886 | } | ||
| 887 |
2/2✓ Branch 0 taken 27637 times.
✓ Branch 1 taken 25381 times.
|
53018 | if (*args) |
| 888 | 27637 | args++; | |
| 889 |
2/2✓ Branch 0 taken 31938 times.
✓ Branch 1 taken 21080 times.
|
53018 | if (parsed_key) { |
| 890 | 31938 | key = parsed_key; | |
| 891 | 31938 | additional_flags = AV_DICT_DONT_STRDUP_KEY; | |
| 892 | 31938 | priv_class = NULL; /* reject all remaining shorthand */ | |
| 893 | } else { | ||
| 894 | 21080 | key = shorthand; | |
| 895 | } | ||
| 896 | |||
| 897 | 53018 | av_log(logctx, AV_LOG_DEBUG, "Setting '%s' to value '%s'\n", key, value); | |
| 898 | |||
| 899 | 53018 | av_dict_set(options, key, value, | |
| 900 | additional_flags | AV_DICT_DONT_STRDUP_VAL | AV_DICT_MULTIKEY); | ||
| 901 | } | ||
| 902 | |||
| 903 | 34407 | return 0; | |
| 904 | } | ||
| 905 | |||
| 906 | ✗ | int ff_filter_process_command(AVFilterContext *ctx, const char *cmd, | |
| 907 | const char *arg, char *res, int res_len, int flags) | ||
| 908 | { | ||
| 909 | const AVOption *o; | ||
| 910 | |||
| 911 | ✗ | if (!ctx->filter->priv_class) | |
| 912 | ✗ | return 0; | |
| 913 | ✗ | o = av_opt_find2(ctx->priv, cmd, NULL, AV_OPT_FLAG_RUNTIME_PARAM | AV_OPT_FLAG_FILTERING_PARAM, AV_OPT_SEARCH_CHILDREN, NULL); | |
| 914 | ✗ | if (!o) | |
| 915 | ✗ | return AVERROR(ENOSYS); | |
| 916 | ✗ | return av_opt_set(ctx->priv, cmd, arg, 0); | |
| 917 | } | ||
| 918 | |||
| 919 | 64357 | int avfilter_init_dict(AVFilterContext *ctx, AVDictionary **options) | |
| 920 | { | ||
| 921 | 64357 | FFFilterContext *ctxi = fffilterctx(ctx); | |
| 922 | 64357 | int ret = 0; | |
| 923 | |||
| 924 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 64357 times.
|
64357 | if (ctxi->state_flags & AV_CLASS_STATE_INITIALIZED) { |
| 925 | ✗ | av_log(ctx, AV_LOG_ERROR, "Filter already initialized\n"); | |
| 926 | ✗ | return AVERROR(EINVAL); | |
| 927 | } | ||
| 928 | |||
| 929 | 64357 | ret = av_opt_set_dict2(ctx, options, AV_OPT_SEARCH_CHILDREN); | |
| 930 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 64357 times.
|
64357 | if (ret < 0) { |
| 931 | ✗ | av_log(ctx, AV_LOG_ERROR, "Error applying generic filter options.\n"); | |
| 932 | ✗ | return ret; | |
| 933 | } | ||
| 934 | |||
| 935 |
2/2✓ Branch 0 taken 1254 times.
✓ Branch 1 taken 63103 times.
|
64357 | if (ctx->filter->flags & AVFILTER_FLAG_SLICE_THREADS && |
| 936 |
2/2✓ Branch 0 taken 154 times.
✓ Branch 1 taken 1100 times.
|
1254 | ctx->thread_type & ctx->graph->thread_type & AVFILTER_THREAD_SLICE && |
| 937 |
1/2✓ Branch 1 taken 154 times.
✗ Branch 2 not taken.
|
154 | fffiltergraph(ctx->graph)->thread_execute) { |
| 938 | 154 | ctx->thread_type = AVFILTER_THREAD_SLICE; | |
| 939 | 154 | ctxi->execute = fffiltergraph(ctx->graph)->thread_execute; | |
| 940 | } else { | ||
| 941 | 64203 | ctx->thread_type = 0; | |
| 942 | } | ||
| 943 | |||
| 944 |
2/2✓ Branch 1 taken 50819 times.
✓ Branch 2 taken 13538 times.
|
64357 | if (fffilter(ctx->filter)->init) |
| 945 | 50819 | ret = fffilter(ctx->filter)->init(ctx); | |
| 946 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 64357 times.
|
64357 | if (ret < 0) |
| 947 | ✗ | return ret; | |
| 948 | |||
| 949 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 64351 times.
|
64357 | if (ctx->enable_str) { |
| 950 | 6 | ret = set_enable_expr(ctxi, ctx->enable_str); | |
| 951 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (ret < 0) |
| 952 | ✗ | return ret; | |
| 953 | } | ||
| 954 | |||
| 955 | 64357 | ctxi->state_flags |= AV_CLASS_STATE_INITIALIZED; | |
| 956 | |||
| 957 | 64357 | return 0; | |
| 958 | } | ||
| 959 | |||
| 960 | 21151 | int avfilter_init_str(AVFilterContext *filter, const char *args) | |
| 961 | { | ||
| 962 | 21151 | AVDictionary *options = NULL; | |
| 963 | const AVDictionaryEntry *e; | ||
| 964 | 21151 | int ret = 0; | |
| 965 | |||
| 966 |
3/4✓ Branch 0 taken 10564 times.
✓ Branch 1 taken 10587 times.
✓ Branch 2 taken 10564 times.
✗ Branch 3 not taken.
|
21151 | if (args && *args) { |
| 967 | 10564 | ret = ff_filter_opt_parse(filter, filter->filter->priv_class, &options, args); | |
| 968 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10564 times.
|
10564 | if (ret < 0) |
| 969 | ✗ | goto fail; | |
| 970 | } | ||
| 971 | |||
| 972 | 21151 | ret = avfilter_init_dict(filter, &options); | |
| 973 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21151 times.
|
21151 | if (ret < 0) |
| 974 | ✗ | goto fail; | |
| 975 | |||
| 976 |
1/2✓ Branch 1 taken 21151 times.
✗ Branch 2 not taken.
|
21151 | if ((e = av_dict_iterate(options, NULL))) { |
| 977 | ✗ | av_log(filter, AV_LOG_ERROR, "No such option: %s.\n", e->key); | |
| 978 | ✗ | ret = AVERROR_OPTION_NOT_FOUND; | |
| 979 | ✗ | goto fail; | |
| 980 | } | ||
| 981 | |||
| 982 | 21151 | fail: | |
| 983 | 21151 | av_dict_free(&options); | |
| 984 | |||
| 985 | 21151 | return ret; | |
| 986 | } | ||
| 987 | |||
| 988 | 15399 | const char *avfilter_pad_get_name(const AVFilterPad *pads, int pad_idx) | |
| 989 | { | ||
| 990 | 15399 | return pads[pad_idx].name; | |
| 991 | } | ||
| 992 | |||
| 993 | 31155 | enum AVMediaType avfilter_pad_get_type(const AVFilterPad *pads, int pad_idx) | |
| 994 | { | ||
| 995 | 31155 | return pads[pad_idx].type; | |
| 996 | } | ||
| 997 | |||
| 998 | ✗ | AVBufferRef *avfilter_link_get_hw_frames_ctx(AVFilterLink *link) | |
| 999 | { | ||
| 1000 | ✗ | FilterLink *plink = ff_filter_link(link); | |
| 1001 | ✗ | if (plink->hw_frames_ctx) | |
| 1002 | ✗ | return av_buffer_ref(plink->hw_frames_ctx); | |
| 1003 | |||
| 1004 | ✗ | return NULL; | |
| 1005 | } | ||
| 1006 | |||
| 1007 | 799268 | static int default_filter_frame(AVFilterLink *link, AVFrame *frame) | |
| 1008 | { | ||
| 1009 | 799268 | return ff_filter_frame(link->dst->outputs[0], frame); | |
| 1010 | } | ||
| 1011 | |||
| 1012 | /** | ||
| 1013 | * Evaluate the timeline expression of the link for the time and properties | ||
| 1014 | * of the frame. | ||
| 1015 | * @return >0 if enabled, 0 if disabled | ||
| 1016 | * @note It does not update link->dst->is_disabled. | ||
| 1017 | */ | ||
| 1018 | 2535357 | static int evaluate_timeline_at_frame(AVFilterLink *link, const AVFrame *frame) | |
| 1019 | { | ||
| 1020 | 2535357 | FilterLink *l = ff_filter_link(link); | |
| 1021 | 2535357 | AVFilterContext *dstctx = link->dst; | |
| 1022 | 2535357 | FFFilterContext *dsti = fffilterctx(dstctx); | |
| 1023 | 2535357 | int64_t pts = frame->pts; | |
| 1024 | |||
| 1025 |
2/2✓ Branch 0 taken 2535159 times.
✓ Branch 1 taken 198 times.
|
2535357 | if (!dstctx->enable_str) |
| 1026 | 2535159 | return 1; | |
| 1027 | |||
| 1028 | 198 | dsti->var_values[VAR_N] = l->frame_count_out; | |
| 1029 |
1/2✓ Branch 0 taken 198 times.
✗ Branch 1 not taken.
|
198 | dsti->var_values[VAR_T] = pts == AV_NOPTS_VALUE ? NAN : pts * av_q2d(link->time_base); |
| 1030 | 198 | dsti->var_values[VAR_W] = link->w; | |
| 1031 | 198 | dsti->var_values[VAR_H] = link->h; | |
| 1032 | |||
| 1033 | 198 | return fabs(av_expr_eval(dsti->enable, dsti->var_values, NULL)) >= 0.5; | |
| 1034 | } | ||
| 1035 | |||
| 1036 | 819868 | static int filter_frame_framed(AVFilterLink *link, AVFrame *frame) | |
| 1037 | { | ||
| 1038 | 819868 | FilterLink *l = ff_filter_link(link); | |
| 1039 | int (*filter_frame)(AVFilterLink *, AVFrame *); | ||
| 1040 | 819868 | AVFilterContext *dstctx = link->dst; | |
| 1041 | 819868 | AVFilterPad *dst = link->dstpad; | |
| 1042 | int ret; | ||
| 1043 | |||
| 1044 |
2/2✓ Branch 0 taken 799259 times.
✓ Branch 1 taken 20609 times.
|
819868 | if (!(filter_frame = dst->filter_frame)) |
| 1045 | 799259 | filter_frame = default_filter_frame; | |
| 1046 | |||
| 1047 |
2/2✓ Branch 0 taken 2993 times.
✓ Branch 1 taken 816875 times.
|
819868 | if (dst->flags & AVFILTERPAD_FLAG_NEEDS_WRITABLE) { |
| 1048 | 2993 | ret = ff_inlink_make_frame_writable(link, &frame); | |
| 1049 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2993 times.
|
2993 | if (ret < 0) |
| 1050 | ✗ | goto fail; | |
| 1051 | } | ||
| 1052 | |||
| 1053 | 819868 | ff_inlink_process_commands(link, frame); | |
| 1054 | 819868 | dstctx->is_disabled = !evaluate_timeline_at_frame(link, frame); | |
| 1055 | |||
| 1056 |
2/2✓ Branch 0 taken 19 times.
✓ Branch 1 taken 819849 times.
|
819868 | if (dstctx->is_disabled && |
| 1057 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 10 times.
|
19 | (dstctx->filter->flags & AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC)) |
| 1058 | 9 | filter_frame = default_filter_frame; | |
| 1059 | 819868 | ret = filter_frame(link, frame); | |
| 1060 | 819868 | l->frame_count_out++; | |
| 1061 | 819868 | return ret; | |
| 1062 | |||
| 1063 | ✗ | fail: | |
| 1064 | ✗ | av_frame_free(&frame); | |
| 1065 | ✗ | return ret; | |
| 1066 | } | ||
| 1067 | |||
| 1068 | 1720749 | int ff_filter_frame(AVFilterLink *link, AVFrame *frame) | |
| 1069 | { | ||
| 1070 | 1720749 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1071 | int ret; | ||
| 1072 | 1720749 | FF_TPRINTF_START(NULL, filter_frame); ff_tlog_link(NULL, link, 1); ff_tlog(NULL, " "); tlog_ref(NULL, frame, 1); | |
| 1073 | |||
| 1074 | /* Consistency checks */ | ||
| 1075 |
2/2✓ Branch 0 taken 586128 times.
✓ Branch 1 taken 1134621 times.
|
1720749 | if (link->type == AVMEDIA_TYPE_VIDEO) { |
| 1076 |
2/2✓ Branch 0 taken 435960 times.
✓ Branch 1 taken 150168 times.
|
586128 | if (strcmp(link->dst->filter->name, "buffersink") && |
| 1077 |
2/2✓ Branch 0 taken 259737 times.
✓ Branch 1 taken 176223 times.
|
435960 | strcmp(link->dst->filter->name, "format") && |
| 1078 |
2/2✓ Branch 0 taken 259710 times.
✓ Branch 1 taken 27 times.
|
259737 | strcmp(link->dst->filter->name, "idet") && |
| 1079 |
2/2✓ Branch 0 taken 168191 times.
✓ Branch 1 taken 91519 times.
|
259710 | strcmp(link->dst->filter->name, "null") && |
| 1080 |
2/2✓ Branch 0 taken 57611 times.
✓ Branch 1 taken 110580 times.
|
168191 | strcmp(link->dst->filter->name, "scale") && |
| 1081 |
1/2✓ Branch 0 taken 57611 times.
✗ Branch 1 not taken.
|
57611 | strcmp(link->dst->filter->name, "libplacebo")) { |
| 1082 | av_assert1(frame->format == link->format); | ||
| 1083 | av_assert1(frame->width == link->w); | ||
| 1084 | av_assert1(frame->height == link->h); | ||
| 1085 | 57611 | if (av_pix_fmt_desc_get(link->format)->flags & AV_PIX_FMT_FLAG_ALPHA) | |
| 1086 | av_assert1(frame->alpha_mode == link->alpha_mode); | ||
| 1087 | } | ||
| 1088 | } else { | ||
| 1089 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1134621 times.
|
1134621 | if (frame->format != link->format) { |
| 1090 | ✗ | av_log(link->dst, AV_LOG_ERROR, "Format change is not supported\n"); | |
| 1091 | ✗ | goto error; | |
| 1092 | } | ||
| 1093 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1134621 times.
|
1134621 | if (av_channel_layout_compare(&frame->ch_layout, &link->ch_layout)) { |
| 1094 | ✗ | av_log(link->dst, AV_LOG_ERROR, "Channel layout change is not supported\n"); | |
| 1095 | ✗ | goto error; | |
| 1096 | } | ||
| 1097 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1134621 times.
|
1134621 | if (frame->sample_rate != link->sample_rate) { |
| 1098 | ✗ | av_log(link->dst, AV_LOG_ERROR, "Sample rate change is not supported\n"); | |
| 1099 | ✗ | goto error; | |
| 1100 | } | ||
| 1101 | |||
| 1102 | 1134621 | frame->duration = av_rescale_q(frame->nb_samples, (AVRational){ 1, frame->sample_rate }, | |
| 1103 | link->time_base); | ||
| 1104 | } | ||
| 1105 | |||
| 1106 | 1720749 | li->frame_blocked_in = li->frame_wanted_out = 0; | |
| 1107 | 1720749 | li->l.frame_count_in++; | |
| 1108 | 1720749 | li->l.sample_count_in += frame->nb_samples; | |
| 1109 | 1720749 | filter_unblock(link->dst); | |
| 1110 | 1720749 | ret = ff_framequeue_add(&li->fifo, frame); | |
| 1111 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1720749 times.
|
1720749 | if (ret < 0) { |
| 1112 | ✗ | const FFFrameQueueGlobal *global = li->fifo.global; | |
| 1113 | ✗ | if (ret == AVERROR(ENOMEM) && global->queued >= global->max_queued) | |
| 1114 | ✗ | av_log(link->dst, AV_LOG_ERROR, "Exhausted frame queue capacity (%zu frames)\n", global->max_queued); | |
| 1115 | ✗ | av_frame_free(&frame); | |
| 1116 | ✗ | return ret; | |
| 1117 | } | ||
| 1118 | 1720749 | ff_filter_set_ready(link->dst, 300); | |
| 1119 | 1720749 | return 0; | |
| 1120 | |||
| 1121 | ✗ | error: | |
| 1122 | ✗ | av_frame_free(&frame); | |
| 1123 | ✗ | return AVERROR_PATCHWELCOME; | |
| 1124 | } | ||
| 1125 | |||
| 1126 | 2454884 | static int samples_ready(FilterLinkInternal *link, unsigned min) | |
| 1127 | { | ||
| 1128 |
2/2✓ Branch 1 taken 820002 times.
✓ Branch 2 taken 1634882 times.
|
3274886 | return ff_framequeue_queued_frames(&link->fifo) && |
| 1129 |
2/2✓ Branch 1 taken 135 times.
✓ Branch 2 taken 819867 times.
|
820002 | (ff_framequeue_queued_samples(&link->fifo) >= min || |
| 1130 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 134 times.
|
135 | link->status_in); |
| 1131 | } | ||
| 1132 | |||
| 1133 | 2931 | static int take_samples(FilterLinkInternal *li, unsigned min, unsigned max, | |
| 1134 | AVFrame **rframe) | ||
| 1135 | { | ||
| 1136 | 2931 | FilterLink *l = &li->l; | |
| 1137 | 2931 | AVFilterLink *link = &l->pub; | |
| 1138 | AVFrame *frame0, *frame, *buf; | ||
| 1139 | unsigned nb_samples, nb_frames, i, p; | ||
| 1140 | int ret; | ||
| 1141 | |||
| 1142 | /* Note: this function relies on no format changes and must only be | ||
| 1143 | called with enough samples. */ | ||
| 1144 | av_assert1(samples_ready(li, l->min_samples)); | ||
| 1145 | 2931 | frame0 = frame = ff_framequeue_peek(&li->fifo, 0); | |
| 1146 |
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) { |
| 1147 | 1026 | *rframe = ff_framequeue_take(&li->fifo); | |
| 1148 | 1026 | return 0; | |
| 1149 | } | ||
| 1150 | 1905 | nb_frames = 0; | |
| 1151 | 1905 | nb_samples = 0; | |
| 1152 | while (1) { | ||
| 1153 |
2/2✓ Branch 0 taken 1660 times.
✓ Branch 1 taken 1461 times.
|
3121 | if (nb_samples + frame->nb_samples > max) { |
| 1154 |
2/2✓ Branch 0 taken 1518 times.
✓ Branch 1 taken 142 times.
|
1660 | if (nb_samples < min) |
| 1155 | 1518 | nb_samples = max; | |
| 1156 | 1660 | break; | |
| 1157 | } | ||
| 1158 | 1461 | nb_samples += frame->nb_samples; | |
| 1159 | 1461 | nb_frames++; | |
| 1160 |
2/2✓ Branch 1 taken 245 times.
✓ Branch 2 taken 1216 times.
|
1461 | if (nb_frames == ff_framequeue_queued_frames(&li->fifo)) |
| 1161 | 245 | break; | |
| 1162 | 1216 | frame = ff_framequeue_peek(&li->fifo, nb_frames); | |
| 1163 | } | ||
| 1164 | |||
| 1165 | 1905 | buf = ff_get_audio_buffer(link, nb_samples); | |
| 1166 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1905 times.
|
1905 | if (!buf) |
| 1167 | ✗ | return AVERROR(ENOMEM); | |
| 1168 | 1905 | ret = av_frame_copy_props(buf, frame0); | |
| 1169 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1905 times.
|
1905 | if (ret < 0) { |
| 1170 | ✗ | av_frame_free(&buf); | |
| 1171 | ✗ | return ret; | |
| 1172 | } | ||
| 1173 | |||
| 1174 | 1905 | p = 0; | |
| 1175 |
2/2✓ Branch 0 taken 1461 times.
✓ Branch 1 taken 1905 times.
|
3366 | for (i = 0; i < nb_frames; i++) { |
| 1176 | 1461 | frame = ff_framequeue_take(&li->fifo); | |
| 1177 | 1461 | av_samples_copy(buf->extended_data, frame->extended_data, p, 0, | |
| 1178 | 1461 | frame->nb_samples, link->ch_layout.nb_channels, link->format); | |
| 1179 | 1461 | p += frame->nb_samples; | |
| 1180 | 1461 | av_frame_free(&frame); | |
| 1181 | } | ||
| 1182 |
2/2✓ Branch 0 taken 1518 times.
✓ Branch 1 taken 387 times.
|
1905 | if (p < nb_samples) { |
| 1183 | 1518 | unsigned n = nb_samples - p; | |
| 1184 | 1518 | frame = ff_framequeue_peek(&li->fifo, 0); | |
| 1185 | 1518 | av_samples_copy(buf->extended_data, frame->extended_data, p, 0, n, | |
| 1186 | 1518 | link->ch_layout.nb_channels, link->format); | |
| 1187 | 1518 | ff_framequeue_skip_samples(&li->fifo, n, link->time_base); | |
| 1188 | } | ||
| 1189 | |||
| 1190 | 1905 | *rframe = buf; | |
| 1191 | 1905 | return 0; | |
| 1192 | } | ||
| 1193 | |||
| 1194 | 819868 | static int filter_frame_to_filter(AVFilterLink *link) | |
| 1195 | { | ||
| 1196 | 819868 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1197 | 819868 | AVFrame *frame = NULL; | |
| 1198 | 819868 | AVFilterContext *dst = link->dst; | |
| 1199 | int ret; | ||
| 1200 | |||
| 1201 | av_assert1(ff_framequeue_queued_frames(&li->fifo)); | ||
| 1202 | 1639736 | ret = li->l.min_samples ? | |
| 1203 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 819832 times.
|
819868 | ff_inlink_consume_samples(link, li->l.min_samples, li->l.max_samples, &frame) : |
| 1204 | 819832 | ff_inlink_consume_frame(link, &frame); | |
| 1205 | av_assert1(ret); | ||
| 1206 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 819868 times.
|
819868 | if (ret < 0) { |
| 1207 | av_assert1(!frame); | ||
| 1208 | ✗ | return ret; | |
| 1209 | } | ||
| 1210 | /* The filter will soon have received a new frame, that may allow it to | ||
| 1211 | produce one or more: unblock its outputs. */ | ||
| 1212 | 819868 | filter_unblock(dst); | |
| 1213 | /* AVFilterPad.filter_frame() expect frame_count_out to have the value | ||
| 1214 | before the frame; filter_frame_framed() will re-increment it. */ | ||
| 1215 | 819868 | li->l.frame_count_out--; | |
| 1216 | 819868 | ret = filter_frame_framed(link, frame); | |
| 1217 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 819868 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
819868 | if (ret < 0 && ret != li->status_out) { |
| 1218 | ✗ | link_set_out_status(link, ret, AV_NOPTS_VALUE); | |
| 1219 | } else { | ||
| 1220 | /* Run once again, to see if several frames were available, or if | ||
| 1221 | the input status has also changed, or any other reason. */ | ||
| 1222 | 819868 | ff_filter_set_ready(dst, 300); | |
| 1223 | } | ||
| 1224 | 819868 | return ret; | |
| 1225 | } | ||
| 1226 | |||
| 1227 | 6199 | static int forward_status_change(AVFilterContext *filter, FilterLinkInternal *li_in) | |
| 1228 | { | ||
| 1229 | 6199 | AVFilterLink *in = &li_in->l.pub; | |
| 1230 | 6199 | unsigned out = 0, progress = 0; | |
| 1231 | int ret; | ||
| 1232 | |||
| 1233 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6199 times.
|
6199 | av_assert0(!li_in->status_out); |
| 1234 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6198 times.
|
6199 | if (!filter->nb_outputs) { |
| 1235 | /* not necessary with the current API and sinks */ | ||
| 1236 | 1 | return 0; | |
| 1237 | } | ||
| 1238 |
2/2✓ Branch 0 taken 6198 times.
✓ Branch 1 taken 6198 times.
|
12396 | while (!li_in->status_out) { |
| 1239 | 6198 | FilterLinkInternal *li_out = ff_link_internal(filter->outputs[out]); | |
| 1240 | |||
| 1241 |
1/2✓ Branch 0 taken 6198 times.
✗ Branch 1 not taken.
|
6198 | if (!li_out->status_in) { |
| 1242 | 6198 | progress++; | |
| 1243 | 6198 | ret = request_frame_to_filter(filter->outputs[out]); | |
| 1244 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6198 times.
|
6198 | if (ret < 0) |
| 1245 | ✗ | return ret; | |
| 1246 | } | ||
| 1247 |
1/2✓ Branch 0 taken 6198 times.
✗ Branch 1 not taken.
|
6198 | if (++out == filter->nb_outputs) { |
| 1248 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6198 times.
|
6198 | if (!progress) { |
| 1249 | /* Every output already closed: input no longer interesting | ||
| 1250 | (example: overlay in shortest mode, other input closed). */ | ||
| 1251 | ✗ | link_set_out_status(in, li_in->status_in, li_in->status_in_pts); | |
| 1252 | ✗ | return 0; | |
| 1253 | } | ||
| 1254 | 6198 | progress = 0; | |
| 1255 | 6198 | out = 0; | |
| 1256 | } | ||
| 1257 | } | ||
| 1258 | 6198 | ff_filter_set_ready(filter, 200); | |
| 1259 | 6198 | return 0; | |
| 1260 | } | ||
| 1261 | |||
| 1262 | 2462260 | static int filter_activate_default(AVFilterContext *filter) | |
| 1263 | { | ||
| 1264 | unsigned i; | ||
| 1265 | 2462260 | int nb_eofs = 0; | |
| 1266 | |||
| 1267 |
2/2✓ Branch 0 taken 2462227 times.
✓ Branch 1 taken 2462260 times.
|
4924487 | for (i = 0; i < filter->nb_outputs; i++) |
| 1268 | 2462227 | nb_eofs += ff_outlink_get_status(filter->outputs[i]) == AVERROR_EOF; | |
| 1269 |
4/4✓ Branch 0 taken 2462227 times.
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 7108 times.
✓ Branch 3 taken 2455119 times.
|
2462260 | if (filter->nb_outputs && nb_eofs == filter->nb_outputs) { |
| 1270 |
2/2✓ Branch 0 taken 7108 times.
✓ Branch 1 taken 7108 times.
|
14216 | for (int j = 0; j < filter->nb_inputs; j++) |
| 1271 | 7108 | ff_inlink_set_status(filter->inputs[j], AVERROR_EOF); | |
| 1272 | 7108 | return 0; | |
| 1273 | } | ||
| 1274 | |||
| 1275 |
2/2✓ Branch 0 taken 2454884 times.
✓ Branch 1 taken 1635284 times.
|
4090168 | for (i = 0; i < filter->nb_inputs; i++) { |
| 1276 | 2454884 | FilterLinkInternal *li = ff_link_internal(filter->inputs[i]); | |
| 1277 |
2/2✓ Branch 1 taken 819868 times.
✓ Branch 2 taken 1635016 times.
|
2454884 | if (samples_ready(li, li->l.min_samples)) { |
| 1278 | 819868 | return filter_frame_to_filter(filter->inputs[i]); | |
| 1279 | } | ||
| 1280 | } | ||
| 1281 |
2/2✓ Branch 0 taken 1635016 times.
✓ Branch 1 taken 1629085 times.
|
3264101 | for (i = 0; i < filter->nb_inputs; i++) { |
| 1282 | 1635016 | FilterLinkInternal * const li = ff_link_internal(filter->inputs[i]); | |
| 1283 |
4/4✓ Branch 0 taken 6230 times.
✓ Branch 1 taken 1628786 times.
✓ Branch 2 taken 6199 times.
✓ Branch 3 taken 31 times.
|
1635016 | if (li->status_in && !li->status_out) { |
| 1284 | av_assert1(!ff_framequeue_queued_frames(&li->fifo)); | ||
| 1285 | 6199 | return forward_status_change(filter, li); | |
| 1286 | } | ||
| 1287 | } | ||
| 1288 |
2/2✓ Branch 0 taken 1629069 times.
✓ Branch 1 taken 819684 times.
|
2448753 | for (i = 0; i < filter->nb_outputs; i++) { |
| 1289 | 1629069 | FilterLinkInternal * const li = ff_link_internal(filter->outputs[i]); | |
| 1290 |
2/2✓ Branch 0 taken 814257 times.
✓ Branch 1 taken 814812 times.
|
1629069 | if (li->frame_wanted_out && |
| 1291 |
2/2✓ Branch 0 taken 809401 times.
✓ Branch 1 taken 4856 times.
|
814257 | !li->frame_blocked_in) { |
| 1292 | 809401 | return request_frame_to_filter(filter->outputs[i]); | |
| 1293 | } | ||
| 1294 | } | ||
| 1295 |
2/2✓ Branch 0 taken 819668 times.
✓ Branch 1 taken 814828 times.
|
1634496 | for (i = 0; i < filter->nb_outputs; i++) { |
| 1296 | 819668 | FilterLinkInternal * const li = ff_link_internal(filter->outputs[i]); | |
| 1297 |
2/2✓ Branch 0 taken 4856 times.
✓ Branch 1 taken 814812 times.
|
819668 | if (li->frame_wanted_out) |
| 1298 | 4856 | return request_frame_to_filter(filter->outputs[i]); | |
| 1299 | } | ||
| 1300 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 814812 times.
|
814828 | if (!filter->nb_outputs) { |
| 1301 | 16 | ff_inlink_request_frame(filter->inputs[0]); | |
| 1302 | 16 | return 0; | |
| 1303 | } | ||
| 1304 | 814812 | return FFERROR_NOT_READY; | |
| 1305 | } | ||
| 1306 | |||
| 1307 | /* | ||
| 1308 | Filter scheduling and activation | ||
| 1309 | |||
| 1310 | When a filter is activated, it must: | ||
| 1311 | - if possible, output a frame; | ||
| 1312 | - else, if relevant, forward the input status change; | ||
| 1313 | - else, check outputs for wanted frames and forward the requests. | ||
| 1314 | |||
| 1315 | The following AVFilterLink fields are used for activation: | ||
| 1316 | |||
| 1317 | - frame_wanted_out: | ||
| 1318 | |||
| 1319 | This field indicates if a frame is needed on this input of the | ||
| 1320 | destination filter. A positive value indicates that a frame is needed | ||
| 1321 | to process queued frames or internal data or to satisfy the | ||
| 1322 | application; a zero value indicates that a frame is not especially | ||
| 1323 | needed but could be processed anyway; a negative value indicates that a | ||
| 1324 | frame would just be queued. | ||
| 1325 | |||
| 1326 | It is set by filters using ff_request_frame() or ff_request_no_frame(), | ||
| 1327 | when requested by the application through a specific API or when it is | ||
| 1328 | set on one of the outputs. | ||
| 1329 | |||
| 1330 | It is cleared when a frame is sent from the source using | ||
| 1331 | ff_filter_frame(). | ||
| 1332 | |||
| 1333 | It is also cleared when a status change is sent from the source using | ||
| 1334 | ff_avfilter_link_set_in_status(). | ||
| 1335 | |||
| 1336 | - frame_blocked_in: | ||
| 1337 | |||
| 1338 | This field means that the source filter can not generate a frame as is. | ||
| 1339 | Its goal is to avoid repeatedly calling the request_frame() method on | ||
| 1340 | the same link. | ||
| 1341 | |||
| 1342 | It is set by the framework on all outputs of a filter before activating it. | ||
| 1343 | |||
| 1344 | It is automatically cleared by ff_filter_frame(). | ||
| 1345 | |||
| 1346 | It is also automatically cleared by ff_avfilter_link_set_in_status(). | ||
| 1347 | |||
| 1348 | It is also cleared on all outputs (using filter_unblock()) when | ||
| 1349 | something happens on an input: processing a frame or changing the | ||
| 1350 | status. | ||
| 1351 | |||
| 1352 | - fifo: | ||
| 1353 | |||
| 1354 | Contains the frames queued on a filter input. If it contains frames and | ||
| 1355 | frame_wanted_out is not set, then the filter can be activated. If that | ||
| 1356 | result in the filter not able to use these frames, the filter must set | ||
| 1357 | frame_wanted_out to ask for more frames. | ||
| 1358 | |||
| 1359 | - status_in and status_in_pts: | ||
| 1360 | |||
| 1361 | Status (EOF or error code) of the link and timestamp of the status | ||
| 1362 | change (in link time base, same as frames) as seen from the input of | ||
| 1363 | the link. The status change is considered happening after the frames | ||
| 1364 | queued in fifo. | ||
| 1365 | |||
| 1366 | It is set by the source filter using ff_avfilter_link_set_in_status(). | ||
| 1367 | |||
| 1368 | - status_out: | ||
| 1369 | |||
| 1370 | Status of the link as seen from the output of the link. The status | ||
| 1371 | change is considered having already happened. | ||
| 1372 | |||
| 1373 | It is set by the destination filter using | ||
| 1374 | link_set_out_status(). | ||
| 1375 | |||
| 1376 | Filters are activated according to the ready field, set using the | ||
| 1377 | ff_filter_set_ready(). Eventually, a priority queue will be used. | ||
| 1378 | ff_filter_set_ready() is called whenever anything could cause progress to | ||
| 1379 | be possible. Marking a filter ready when it is not is not a problem, | ||
| 1380 | except for the small overhead it causes. | ||
| 1381 | |||
| 1382 | Conditions that cause a filter to be marked ready are: | ||
| 1383 | |||
| 1384 | - frames added on an input link; | ||
| 1385 | |||
| 1386 | - changes in the input or output status of an input link; | ||
| 1387 | |||
| 1388 | - requests for a frame on an output link; | ||
| 1389 | |||
| 1390 | - after any actual processing using the legacy methods (filter_frame(), | ||
| 1391 | and request_frame() to acknowledge status changes), to run once more | ||
| 1392 | and check if enough input was present for several frames. | ||
| 1393 | |||
| 1394 | Examples of scenarios to consider: | ||
| 1395 | |||
| 1396 | - buffersrc: activate if frame_wanted_out to notify the application; | ||
| 1397 | activate when the application adds a frame to push it immediately. | ||
| 1398 | |||
| 1399 | - testsrc: activate only if frame_wanted_out to produce and push a frame. | ||
| 1400 | |||
| 1401 | - concat (not at stitch points): can process a frame on any output. | ||
| 1402 | Activate if frame_wanted_out on output to forward on the corresponding | ||
| 1403 | input. Activate when a frame is present on input to process it | ||
| 1404 | immediately. | ||
| 1405 | |||
| 1406 | - framesync: needs at least one frame on each input; extra frames on the | ||
| 1407 | wrong input will accumulate. When a frame is first added on one input, | ||
| 1408 | set frame_wanted_out<0 on it to avoid getting more (would trigger | ||
| 1409 | testsrc) and frame_wanted_out>0 on the other to allow processing it. | ||
| 1410 | |||
| 1411 | Activation of old filters: | ||
| 1412 | |||
| 1413 | In order to activate a filter implementing the legacy filter_frame() and | ||
| 1414 | request_frame() methods, perform the first possible of the following | ||
| 1415 | actions: | ||
| 1416 | |||
| 1417 | - If an input has frames in fifo and frame_wanted_out == 0, dequeue a | ||
| 1418 | frame and call filter_frame(). | ||
| 1419 | |||
| 1420 | Rationale: filter frames as soon as possible instead of leaving them | ||
| 1421 | queued; frame_wanted_out < 0 is not possible since the old API does not | ||
| 1422 | set it nor provides any similar feedback; frame_wanted_out > 0 happens | ||
| 1423 | when min_samples > 0 and there are not enough samples queued. | ||
| 1424 | |||
| 1425 | - If an input has status_in set but not status_out, try to call | ||
| 1426 | request_frame() on one of the outputs in the hope that it will trigger | ||
| 1427 | request_frame() on the input with status_in and acknowledge it. This is | ||
| 1428 | awkward and fragile, filters with several inputs or outputs should be | ||
| 1429 | updated to direct activation as soon as possible. | ||
| 1430 | |||
| 1431 | - If an output has frame_wanted_out > 0 and not frame_blocked_in, call | ||
| 1432 | request_frame(). | ||
| 1433 | |||
| 1434 | Rationale: checking frame_blocked_in is necessary to avoid requesting | ||
| 1435 | repeatedly on a blocked input if another is not blocked (example: | ||
| 1436 | [buffersrc1][testsrc1][buffersrc2][testsrc2]concat=v=2). | ||
| 1437 | |||
| 1438 | - If an output has frame_wanted_out > 0 call request_frame(). | ||
| 1439 | |||
| 1440 | Rationale: even if all inputs are blocked an activate callback should | ||
| 1441 | request a frame on some if its inputs if a frame is requested on any of | ||
| 1442 | its output. | ||
| 1443 | |||
| 1444 | - Request a frame on the input for sinks. | ||
| 1445 | |||
| 1446 | Rationale: sinks using the old api have no way to request a frame on their | ||
| 1447 | input, so we need to do it for them. | ||
| 1448 | */ | ||
| 1449 | |||
| 1450 | 4280648 | int ff_filter_activate(AVFilterContext *filter) | |
| 1451 | { | ||
| 1452 | 4280648 | FFFilterContext *ctxi = fffilterctx(filter); | |
| 1453 | 4280648 | const FFFilter *const fi = fffilter(filter->filter); | |
| 1454 | int ret; | ||
| 1455 | |||
| 1456 | /* Generic timeline support is not yet implemented but should be easy */ | ||
| 1457 | av_assert1(!(fi->p.flags & AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC && | ||
| 1458 | fi->activate)); | ||
| 1459 | 4280648 | ctxi->ready = 0; | |
| 1460 |
2/2✓ Branch 0 taken 1818388 times.
✓ Branch 1 taken 2462260 times.
|
4280648 | ret = fi->activate ? fi->activate(filter) : filter_activate_default(filter); |
| 1461 |
2/2✓ Branch 0 taken 815684 times.
✓ Branch 1 taken 3464964 times.
|
4280648 | if (ret == FFERROR_NOT_READY) |
| 1462 | 815684 | ret = 0; | |
| 1463 | 4280648 | return ret; | |
| 1464 | } | ||
| 1465 | |||
| 1466 | 3854732 | int ff_inlink_acknowledge_status(AVFilterLink *link, int *rstatus, int64_t *rpts) | |
| 1467 | { | ||
| 1468 | 3854732 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1469 | 3854732 | *rpts = li->l.current_pts; | |
| 1470 |
2/2✓ Branch 1 taken 2162 times.
✓ Branch 2 taken 3852570 times.
|
3854732 | if (ff_framequeue_queued_frames(&li->fifo)) |
| 1471 | 2162 | return *rstatus = 0; | |
| 1472 |
2/2✓ Branch 0 taken 8048 times.
✓ Branch 1 taken 3844522 times.
|
3852570 | if (li->status_out) |
| 1473 | 8048 | return *rstatus = li->status_out; | |
| 1474 |
2/2✓ Branch 0 taken 3836411 times.
✓ Branch 1 taken 8111 times.
|
3844522 | if (!li->status_in) |
| 1475 | 3836411 | return *rstatus = 0; | |
| 1476 | 8111 | *rstatus = li->status_out = li->status_in; | |
| 1477 | 8111 | update_link_current_pts(li, li->status_in_pts); | |
| 1478 | 8111 | *rpts = li->l.current_pts; | |
| 1479 | 8111 | return 1; | |
| 1480 | } | ||
| 1481 | |||
| 1482 | 1934 | size_t ff_inlink_queued_frames(AVFilterLink *link) | |
| 1483 | { | ||
| 1484 | 1934 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1485 | 1934 | return ff_framequeue_queued_frames(&li->fifo); | |
| 1486 | } | ||
| 1487 | |||
| 1488 | 5562677 | int ff_inlink_check_available_frame(AVFilterLink *link) | |
| 1489 | { | ||
| 1490 | 5562677 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1491 | 5562677 | return ff_framequeue_queued_frames(&li->fifo) > 0; | |
| 1492 | } | ||
| 1493 | |||
| 1494 | 8377 | int ff_inlink_queued_samples(AVFilterLink *link) | |
| 1495 | { | ||
| 1496 | 8377 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1497 | 8377 | return ff_framequeue_queued_samples(&li->fifo); | |
| 1498 | } | ||
| 1499 | |||
| 1500 | 4816 | int ff_inlink_check_available_samples(AVFilterLink *link, unsigned min) | |
| 1501 | { | ||
| 1502 | 4816 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1503 | 4816 | uint64_t samples = ff_framequeue_queued_samples(&li->fifo); | |
| 1504 | av_assert1(min); | ||
| 1505 |
6/6✓ Branch 0 taken 1891 times.
✓ Branch 1 taken 2925 times.
✓ Branch 2 taken 65 times.
✓ Branch 3 taken 1826 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 59 times.
|
4816 | return samples >= min || (li->status_in && samples); |
| 1506 | } | ||
| 1507 | |||
| 1508 | 1718218 | static void consume_update(FilterLinkInternal *li, const AVFrame *frame) | |
| 1509 | { | ||
| 1510 | 1718218 | AVFilterLink *const link = &li->l.pub; | |
| 1511 | 1718218 | update_link_current_pts(li, frame->pts); | |
| 1512 | 1718218 | ff_inlink_process_commands(link, frame); | |
| 1513 |
2/2✓ Branch 0 taken 1715489 times.
✓ Branch 1 taken 2729 times.
|
1718218 | if (link == link->dst->inputs[0]) |
| 1514 | 1715489 | link->dst->is_disabled = !evaluate_timeline_at_frame(link, frame); | |
| 1515 | 1718218 | li->l.frame_count_out++; | |
| 1516 | 1718218 | li->l.sample_count_out += frame->nb_samples; | |
| 1517 | 1718218 | } | |
| 1518 | |||
| 1519 | 5560562 | int ff_inlink_consume_frame(AVFilterLink *link, AVFrame **rframe) | |
| 1520 | { | ||
| 1521 | 5560562 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1522 | AVFrame *frame; | ||
| 1523 | |||
| 1524 | 5560562 | *rframe = NULL; | |
| 1525 |
2/2✓ Branch 1 taken 3845271 times.
✓ Branch 2 taken 1715291 times.
|
5560562 | if (!ff_inlink_check_available_frame(link)) |
| 1526 | 3845271 | return 0; | |
| 1527 | |||
| 1528 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1715287 times.
|
1715291 | if (li->fifo.samples_skipped) { |
| 1529 | 4 | frame = ff_framequeue_peek(&li->fifo, 0); | |
| 1530 | 4 | return ff_inlink_consume_samples(link, frame->nb_samples, frame->nb_samples, rframe); | |
| 1531 | } | ||
| 1532 | |||
| 1533 | 1715287 | frame = ff_framequeue_take(&li->fifo); | |
| 1534 | 1715287 | consume_update(li, frame); | |
| 1535 | 1715287 | *rframe = frame; | |
| 1536 | 1715287 | return 1; | |
| 1537 | } | ||
| 1538 | |||
| 1539 | 4816 | int ff_inlink_consume_samples(AVFilterLink *link, unsigned min, unsigned max, | |
| 1540 | AVFrame **rframe) | ||
| 1541 | { | ||
| 1542 | 4816 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1543 | AVFrame *frame; | ||
| 1544 | int ret; | ||
| 1545 | |||
| 1546 | av_assert1(min); | ||
| 1547 | 4816 | *rframe = NULL; | |
| 1548 |
2/2✓ Branch 1 taken 1885 times.
✓ Branch 2 taken 2931 times.
|
4816 | if (!ff_inlink_check_available_samples(link, min)) |
| 1549 | 1885 | return 0; | |
| 1550 |
2/2✓ Branch 0 taken 26 times.
✓ Branch 1 taken 2905 times.
|
2931 | if (li->status_in) |
| 1551 |
2/2✓ Branch 1 taken 6 times.
✓ Branch 2 taken 20 times.
|
26 | min = FFMIN(min, ff_framequeue_queued_samples(&li->fifo)); |
| 1552 | 2931 | ret = take_samples(li, min, max, &frame); | |
| 1553 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2931 times.
|
2931 | if (ret < 0) |
| 1554 | ✗ | return ret; | |
| 1555 | 2931 | consume_update(li, frame); | |
| 1556 | 2931 | *rframe = frame; | |
| 1557 | 2931 | return 1; | |
| 1558 | } | ||
| 1559 | |||
| 1560 | 210 | AVFrame *ff_inlink_peek_frame(AVFilterLink *link, size_t idx) | |
| 1561 | { | ||
| 1562 | 210 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1563 | 210 | return ff_framequeue_peek(&li->fifo, idx); | |
| 1564 | } | ||
| 1565 | |||
| 1566 | 5178 | int ff_inlink_make_frame_writable(AVFilterLink *link, AVFrame **rframe) | |
| 1567 | { | ||
| 1568 | 5178 | AVFrame *frame = *rframe; | |
| 1569 | AVFrame *out; | ||
| 1570 | int ret; | ||
| 1571 | |||
| 1572 |
2/2✓ Branch 1 taken 2284 times.
✓ Branch 2 taken 2894 times.
|
5178 | if (av_frame_is_writable(frame)) |
| 1573 | 2284 | return 0; | |
| 1574 | 2894 | av_log(link->dst, AV_LOG_DEBUG, "Copying data in avfilter.\n"); | |
| 1575 | |||
| 1576 |
1/3✓ Branch 0 taken 2894 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
2894 | switch (link->type) { |
| 1577 | 2894 | case AVMEDIA_TYPE_VIDEO: | |
| 1578 | 2894 | out = ff_get_video_buffer(link, link->w, link->h); | |
| 1579 | 2894 | break; | |
| 1580 | ✗ | case AVMEDIA_TYPE_AUDIO: | |
| 1581 | ✗ | out = ff_get_audio_buffer(link, frame->nb_samples); | |
| 1582 | ✗ | break; | |
| 1583 | ✗ | default: | |
| 1584 | ✗ | return AVERROR(EINVAL); | |
| 1585 | } | ||
| 1586 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2894 times.
|
2894 | if (!out) |
| 1587 | ✗ | return AVERROR(ENOMEM); | |
| 1588 | |||
| 1589 | 2894 | ret = av_frame_copy_props(out, frame); | |
| 1590 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2894 times.
|
2894 | if (ret < 0) { |
| 1591 | ✗ | av_frame_free(&out); | |
| 1592 | ✗ | return ret; | |
| 1593 | } | ||
| 1594 | |||
| 1595 | 2894 | ret = av_frame_copy(out, frame); | |
| 1596 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2894 times.
|
2894 | if (ret < 0) { |
| 1597 | ✗ | av_frame_free(&out); | |
| 1598 | ✗ | return ret; | |
| 1599 | } | ||
| 1600 | |||
| 1601 | 2894 | av_frame_free(&frame); | |
| 1602 | 2894 | *rframe = out; | |
| 1603 | 2894 | return 0; | |
| 1604 | } | ||
| 1605 | |||
| 1606 | 2538086 | int ff_inlink_process_commands(AVFilterLink *link, const AVFrame *frame) | |
| 1607 | { | ||
| 1608 | 2538086 | FFFilterContext *ctxi = fffilterctx(link->dst); | |
| 1609 | 2538086 | AVFilterCommand *cmd = ctxi->command_queue; | |
| 1610 | |||
| 1611 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 2538086 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
2538086 | while(cmd && cmd->time <= frame->pts * av_q2d(link->time_base)){ |
| 1612 | ✗ | av_log(link->dst, AV_LOG_DEBUG, | |
| 1613 | "Processing command time:%f command:%s arg:%s\n", | ||
| 1614 | cmd->time, cmd->command, cmd->arg); | ||
| 1615 | ✗ | avfilter_process_command(link->dst, cmd->command, cmd->arg, 0, 0, cmd->flags); | |
| 1616 | ✗ | command_queue_pop(link->dst); | |
| 1617 | ✗ | cmd = ctxi->command_queue; | |
| 1618 | } | ||
| 1619 | 2538086 | return 0; | |
| 1620 | } | ||
| 1621 | |||
| 1622 | 904985 | void ff_inlink_request_frame(AVFilterLink *link) | |
| 1623 | { | ||
| 1624 | 904985 | av_unused FilterLinkInternal *li = ff_link_internal(link); | |
| 1625 | av_assert1(!li->status_in); | ||
| 1626 | av_assert1(!li->status_out); | ||
| 1627 | 904985 | li->frame_wanted_out = 1; | |
| 1628 | 904985 | ff_filter_set_ready(link->src, 100); | |
| 1629 | 904985 | } | |
| 1630 | |||
| 1631 | 11284 | void ff_inlink_set_status(AVFilterLink *link, int status) | |
| 1632 | { | ||
| 1633 | 11284 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1634 |
2/2✓ Branch 0 taken 8745 times.
✓ Branch 1 taken 2539 times.
|
11284 | if (li->status_out) |
| 1635 | 8745 | return; | |
| 1636 | 2539 | li->frame_wanted_out = 0; | |
| 1637 | 2539 | li->frame_blocked_in = 0; | |
| 1638 | 2539 | link_set_out_status(link, status, AV_NOPTS_VALUE); | |
| 1639 |
2/2✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2539 times.
|
2545 | while (ff_framequeue_queued_frames(&li->fifo)) { |
| 1640 | 6 | AVFrame *frame = ff_framequeue_take(&li->fifo); | |
| 1641 | 6 | av_frame_free(&frame); | |
| 1642 | } | ||
| 1643 |
2/2✓ Branch 0 taken 2535 times.
✓ Branch 1 taken 4 times.
|
2539 | if (!li->status_in) |
| 1644 | 2535 | li->status_in = status; | |
| 1645 | } | ||
| 1646 | |||
| 1647 | 4204168 | int ff_outlink_get_status(AVFilterLink *link) | |
| 1648 | { | ||
| 1649 | 4204168 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1650 | 4204168 | return li->status_in; | |
| 1651 | } | ||
| 1652 | |||
| 1653 | 1668 | int ff_inoutlink_check_flow(AVFilterLink *inlink, AVFilterLink *outlink) | |
| 1654 | { | ||
| 1655 | 1668 | FilterLinkInternal * const li_in = ff_link_internal(inlink); | |
| 1656 |
2/2✓ Branch 1 taken 982 times.
✓ Branch 2 taken 70 times.
|
2720 | return ff_outlink_frame_wanted(outlink) || |
| 1657 |
2/2✓ Branch 0 taken 1052 times.
✓ Branch 1 taken 616 times.
|
2720 | ff_inlink_check_available_frame(inlink) || |
| 1658 |
2/2✓ Branch 0 taken 55 times.
✓ Branch 1 taken 927 times.
|
982 | li_in->status_out; |
| 1659 | } | ||
| 1660 | |||
| 1661 | |||
| 1662 | ✗ | const AVClass *avfilter_get_class(void) | |
| 1663 | { | ||
| 1664 | ✗ | return &avfilter_class; | |
| 1665 | } | ||
| 1666 | |||
| 1667 | ✗ | int ff_filter_init_hw_frames(AVFilterContext *avctx, AVFilterLink *link, | |
| 1668 | int default_pool_size) | ||
| 1669 | { | ||
| 1670 | ✗ | FilterLink *l = ff_filter_link(link); | |
| 1671 | AVHWFramesContext *frames; | ||
| 1672 | |||
| 1673 | // Must already be set by caller. | ||
| 1674 | ✗ | av_assert0(l->hw_frames_ctx); | |
| 1675 | |||
| 1676 | ✗ | frames = (AVHWFramesContext*)l->hw_frames_ctx->data; | |
| 1677 | |||
| 1678 | ✗ | if (frames->initial_pool_size == 0) { | |
| 1679 | // Dynamic allocation is necessarily supported. | ||
| 1680 | ✗ | } else if (avctx->extra_hw_frames >= 0) { | |
| 1681 | ✗ | frames->initial_pool_size += avctx->extra_hw_frames; | |
| 1682 | } else { | ||
| 1683 | ✗ | frames->initial_pool_size = default_pool_size; | |
| 1684 | } | ||
| 1685 | |||
| 1686 | ✗ | return 0; | |
| 1687 | } | ||
| 1688 | |||
| 1689 | 492048 | int ff_outlink_frame_wanted(AVFilterLink *link) | |
| 1690 | { | ||
| 1691 | 492048 | FilterLinkInternal * const li = ff_link_internal(link); | |
| 1692 | 492048 | return li->frame_wanted_out; | |
| 1693 | } | ||
| 1694 | |||
| 1695 | 5102 | int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, | |
| 1696 | void *arg, int *ret, int nb_jobs) | ||
| 1697 | { | ||
| 1698 | 5102 | return fffilterctx(ctx)->execute(ctx, func, arg, ret, nb_jobs); | |
| 1699 | } | ||
| 1700 |