FFmpeg
vf_pullup.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2003 Rich Felker
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include "libavutil/avassert.h"
22 #include "libavutil/imgutils.h"
23 #include "libavutil/opt.h"
24 #include "libavutil/pixdesc.h"
25 #include "avfilter.h"
26 #include "formats.h"
27 #include "internal.h"
28 #include "video.h"
29 #include "vf_pullup.h"
30 
31 #define F_HAVE_BREAKS 1
32 #define F_HAVE_AFFINITY 2
33 
34 #define BREAK_LEFT 1
35 #define BREAK_RIGHT 2
36 
37 #define OFFSET(x) offsetof(PullupContext, x)
38 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
39 
40 static const AVOption pullup_options[] = {
41  { "jl", "set left junk size", OFFSET(junk_left), AV_OPT_TYPE_INT, {.i64=1}, 0, INT_MAX, FLAGS },
42  { "jr", "set right junk size", OFFSET(junk_right), AV_OPT_TYPE_INT, {.i64=1}, 0, INT_MAX, FLAGS },
43  { "jt", "set top junk size", OFFSET(junk_top), AV_OPT_TYPE_INT, {.i64=4}, 1, INT_MAX, FLAGS },
44  { "jb", "set bottom junk size", OFFSET(junk_bottom), AV_OPT_TYPE_INT, {.i64=4}, 1, INT_MAX, FLAGS },
45  { "sb", "set strict breaks", OFFSET(strict_breaks), AV_OPT_TYPE_BOOL,{.i64=0},-1, 1, FLAGS },
46  { "mp", "set metric plane", OFFSET(metric_plane), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGS, "mp" },
47  { "y", "luma", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "mp" },
48  { "u", "chroma blue", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "mp" },
49  { "v", "chroma red", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "mp" },
50  { NULL }
51 };
52 
53 AVFILTER_DEFINE_CLASS(pullup);
54 
56 {
57  static const enum AVPixelFormat pix_fmts[] = {
65  };
66 
68  if (!fmts_list)
69  return AVERROR(ENOMEM);
70  return ff_set_common_formats(ctx, fmts_list);
71 }
72 
73 #define ABS(a) (((a) ^ ((a) >> 31)) - ((a) >> 31))
74 
75 static int diff_c(const uint8_t *a, const uint8_t *b, ptrdiff_t s)
76 {
77  int i, j, diff = 0;
78 
79  for (i = 0; i < 4; i++) {
80  for (j = 0; j < 8; j++)
81  diff += ABS(a[j] - b[j]);
82  a += s;
83  b += s;
84  }
85 
86  return diff;
87 }
88 
89 static int comb_c(const uint8_t *a, const uint8_t *b, ptrdiff_t s)
90 {
91  int i, j, comb = 0;
92 
93  for (i = 0; i < 4; i++) {
94  for (j = 0; j < 8; j++)
95  comb += ABS((a[j] << 1) - b[j - s] - b[j ]) +
96  ABS((b[j] << 1) - a[j ] - a[j + s]);
97  a += s;
98  b += s;
99  }
100 
101  return comb;
102 }
103 
104 static int var_c(const uint8_t *a, const uint8_t *b, ptrdiff_t s)
105 {
106  int i, j, var = 0;
107 
108  for (i = 0; i < 3; i++) {
109  for (j = 0; j < 8; j++)
110  var += ABS(a[j] - a[j + s]);
111  a += s;
112  }
113 
114  return 4 * var; /* match comb scaling */
115 }
116 
118 {
119  f->diffs = av_calloc(FFALIGN(s->metric_length, 16), sizeof(*f->diffs));
120  f->combs = av_calloc(FFALIGN(s->metric_length, 16), sizeof(*f->combs));
121  f->vars = av_calloc(FFALIGN(s->metric_length, 16), sizeof(*f->vars));
122 
123  if (!f->diffs || !f->combs || !f->vars) {
124  av_freep(&f->diffs);
125  av_freep(&f->combs);
126  av_freep(&f->vars);
127  return AVERROR(ENOMEM);
128  }
129  return 0;
130 }
131 
132 static void free_field_queue(PullupField *head)
133 {
134  PullupField *f = head;
135  do {
136  PullupField *next;
137  if (!f)
138  break;
139  av_free(f->diffs);
140  av_free(f->combs);
141  av_free(f->vars);
142  next = f->next;
143  memset(f, 0, sizeof(*f)); // clear all pointers to avoid stale ones
144  av_free(f);
145  f = next;
146  } while (f != head);
147 }
148 
150 {
151  PullupField *head, *f;
152 
153  f = head = av_mallocz(sizeof(*head));
154  if (!f)
155  return NULL;
156 
157  if (alloc_metrics(s, f) < 0) {
158  av_free(f);
159  return NULL;
160  }
161 
162  for (; len > 0; len--) {
163  f->next = av_mallocz(sizeof(*f->next));
164  if (!f->next) {
165  free_field_queue(head);
166  return NULL;
167  }
168 
169  f->next->prev = f;
170  f = f->next;
171  if (alloc_metrics(s, f) < 0) {
172  free_field_queue(head);
173  return NULL;
174  }
175  }
176 
177  f->next = head;
178  head->prev = f;
179 
180  return head;
181 }
182 
184 {
185  AVFilterContext *ctx = inlink->dst;
186  PullupContext *s = ctx->priv;
188  int mp = s->metric_plane;
189 
190  s->nb_planes = av_pix_fmt_count_planes(inlink->format);
191 
192  if (mp + 1 > s->nb_planes) {
193  av_log(ctx, AV_LOG_ERROR, "input format does not have such plane\n");
194  return AVERROR(EINVAL);
195  }
196 
197  s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
198  s->planeheight[0] = s->planeheight[3] = inlink->h;
199  s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w);
200  s->planewidth[0] = s->planewidth[3] = inlink->w;
201 
202  s->metric_w = (s->planewidth[mp] - ((s->junk_left + s->junk_right) << 3)) >> 3;
203  s->metric_h = (s->planeheight[mp] - ((s->junk_top + s->junk_bottom) << 1)) >> 3;
204  s->metric_offset = (s->junk_left << 3) + (s->junk_top << 1) * s->planewidth[mp];
205  s->metric_length = s->metric_w * s->metric_h;
206 
207  av_log(ctx, AV_LOG_DEBUG, "w: %d h: %d\n", s->metric_w, s->metric_h);
208  av_log(ctx, AV_LOG_DEBUG, "offset: %d length: %d\n", s->metric_offset, s->metric_length);
209 
210  s->head = make_field_queue(s, 8);
211  if (!s->head)
212  return AVERROR(ENOMEM);
213 
214  s->diff = diff_c;
215  s->comb = comb_c;
216  s->var = var_c;
217 
218  if (ARCH_X86)
220  return 0;
221 }
222 
224 {
225  if (!b)
226  return NULL;
227 
228  if ((parity + 1) & 1)
229  b->lock[0]++;
230  if ((parity + 1) & 2)
231  b->lock[1]++;
232 
233  return b;
234 }
235 
237 {
238  if (!b)
239  return;
240 
241  if ((parity + 1) & 1)
242  b->lock[0]--;
243  if ((parity + 1) & 2)
244  b->lock[1]--;
245 }
246 
248 {
249  int i;
250 
251  if (b->planes[0])
252  return 0;
253  for (i = 0; i < s->nb_planes; i++) {
254  b->planes[i] = av_malloc(s->planeheight[i] * s->planewidth[i]);
255  }
256  if (s->nb_planes == 1)
257  b->planes[1] = av_malloc(4*256);
258 
259  return 0;
260 }
261 
263 {
264  int i;
265 
266  /* Try first to get the sister buffer for the previous field */
267  if (parity < 2 && s->last && parity != s->last->parity
268  && !s->last->buffer->lock[parity]) {
269  alloc_buffer(s, s->last->buffer);
270  return pullup_lock_buffer(s->last->buffer, parity);
271  }
272 
273  /* Prefer a buffer with both fields open */
274  for (i = 0; i < FF_ARRAY_ELEMS(s->buffers); i++) {
275  if (s->buffers[i].lock[0])
276  continue;
277  if (s->buffers[i].lock[1])
278  continue;
279  alloc_buffer(s, &s->buffers[i]);
280  return pullup_lock_buffer(&s->buffers[i], parity);
281  }
282 
283  if (parity == 2)
284  return 0;
285 
286  /* Search for any half-free buffer */
287  for (i = 0; i < FF_ARRAY_ELEMS(s->buffers); i++) {
288  if (((parity + 1) & 1) && s->buffers[i].lock[0])
289  continue;
290  if (((parity + 1) & 2) && s->buffers[i].lock[1])
291  continue;
292  alloc_buffer(s, &s->buffers[i]);
293  return pullup_lock_buffer(&s->buffers[i], parity);
294  }
295 
296  return NULL;
297 }
298 
299 static int queue_length(PullupField *begin, PullupField *end)
300 {
301  PullupField *f;
302  int count = 1;
303 
304  if (!begin || !end)
305  return 0;
306 
307  for (f = begin; f != end; f = f->next)
308  count++;
309 
310  return count;
311 }
312 
314 {
315  int i;
316 
317  for (i = 0; i < max; i++) {
318  if (f->breaks & BREAK_RIGHT || f->next->breaks & BREAK_LEFT)
319  return i + 1;
320  f = f->next;
321  }
322 
323  return 0;
324 }
325 
327 {
328  PullupField *f1 = f0->next;
329  PullupField *f2 = f1->next;
330  PullupField *f3 = f2->next;
331  int i, l, max_l = 0, max_r = 0;
332 
333  if (f0->flags & F_HAVE_BREAKS)
334  return;
335 
336  f0->flags |= F_HAVE_BREAKS;
337 
338  /* Special case when fields are 100% identical */
339  if (f0->buffer == f2->buffer && f1->buffer != f3->buffer) {
340  f2->breaks |= BREAK_RIGHT;
341  return;
342  }
343 
344  if (f0->buffer != f2->buffer && f1->buffer == f3->buffer) {
345  f1->breaks |= BREAK_LEFT;
346  return;
347  }
348 
349  for (i = 0; i < s->metric_length; i++) {
350  l = f2->diffs[i] - f3->diffs[i];
351 
352  if ( l > max_l)
353  max_l = l;
354  if (-l > max_r)
355  max_r = -l;
356  }
357 
358  /* Don't get tripped up when differences are mostly quant error */
359  if (max_l + max_r < 128)
360  return;
361  if (max_l > 4 * max_r)
362  f1->breaks |= BREAK_LEFT;
363  if (max_r > 4 * max_l)
364  f2->breaks |= BREAK_RIGHT;
365 }
366 
368 {
369  int i, max_l = 0, max_r = 0, l;
370 
371  if (f->flags & F_HAVE_AFFINITY)
372  return;
373 
374  f->flags |= F_HAVE_AFFINITY;
375 
376  if (f->buffer == f->next->next->buffer) {
377  f->affinity = 1;
378  f->next->affinity = 0;
379  f->next->next->affinity = -1;
380  f->next->flags |= F_HAVE_AFFINITY;
381  f->next->next->flags |= F_HAVE_AFFINITY;
382  return;
383  }
384 
385  for (i = 0; i < s->metric_length; i++) {
386  int v = f->vars[i];
387  int lv = f->prev->vars[i];
388  int rv = f->next->vars[i];
389  int lc = f-> combs[i] - 2*(v < lv ? v : lv);
390  int rc = f->next->combs[i] - 2*(v < rv ? v : rv);
391 
392  lc = FFMAX(lc, 0);
393  rc = FFMAX(rc, 0);
394  l = lc - rc;
395 
396  if ( l > max_l)
397  max_l = l;
398  if (-l > max_r)
399  max_r = -l;
400  }
401 
402  if (max_l + max_r < 64)
403  return;
404 
405  if (max_r > 6 * max_l)
406  f->affinity = -1;
407  else if (max_l > 6 * max_r)
408  f->affinity = 1;
409 }
410 
412 {
413  PullupField *f0 = s->first;
414  PullupField *f1 = f0->next;
415  PullupField *f2 = f1->next;
416  PullupField *f;
417  int i, l, n;
418 
419  if (queue_length(s->first, s->last) < 4)
420  return 0;
421 
422  f = s->first;
423  n = queue_length(f, s->last);
424  for (i = 0; i < n - 1; i++) {
425  if (i < n - 3)
426  compute_breaks(s, f);
427 
428  compute_affinity(s, f);
429 
430  f = f->next;
431  }
432 
433  if (f0->affinity == -1)
434  return 1;
435 
436  l = find_first_break(f0, 3);
437 
438  if (l == 1 && s->strict_breaks < 0)
439  l = 0;
440 
441  switch (l) {
442  case 1:
443  return 1 + (s->strict_breaks < 1 && f0->affinity == 1 && f1->affinity == -1);
444  case 2:
445  /* FIXME: strictly speaking, f0->prev is no longer valid... :) */
446  if (s->strict_pairs
447  && (f0->prev->breaks & BREAK_RIGHT) && (f2->breaks & BREAK_LEFT)
448  && (f0->affinity != 1 || f1->affinity != -1) )
449  return 1;
450  return 1 + (f1->affinity != 1);
451  case 3:
452  return 2 + (f2->affinity != 1);
453  default:
454  /* 9 possibilities covered before switch */
455  if (f1->affinity == 1)
456  return 1; /* covers 6 */
457  else if (f1->affinity == -1)
458  return 2; /* covers 6 */
459  else if (f2->affinity == -1) { /* covers 2 */
460  return (f0->affinity == 1) ? 3 : 1;
461  } else {
462  return 2; /* the remaining 6 */
463  }
464  }
465 }
466 
468 {
469  PullupFrame *fr = &s->frame;
470  int i, n = decide_frame_length(s);
471  int aff = s->first->next->affinity;
472 
474  if (!n || fr->lock)
475  return NULL;
476 
477  fr->lock++;
478  fr->length = n;
479  fr->parity = s->first->parity;
480  fr->buffer = 0;
481 
482  for (i = 0; i < n; i++) {
483  /* We cheat and steal the buffer without release+relock */
484  fr->ifields[i] = s->first->buffer;
485  s->first->buffer = 0;
486  s->first = s->first->next;
487  }
488 
489  if (n == 1) {
490  fr->ofields[fr->parity ] = fr->ifields[0];
491  fr->ofields[fr->parity ^ 1] = 0;
492  } else if (n == 2) {
493  fr->ofields[fr->parity ] = fr->ifields[0];
494  fr->ofields[fr->parity ^ 1] = fr->ifields[1];
495  } else if (n == 3) {
496  if (!aff)
497  aff = (fr->ifields[0] == fr->ifields[1]) ? -1 : 1;
498  fr->ofields[fr->parity ] = fr->ifields[1 + aff];
499  fr->ofields[fr->parity ^ 1] = fr->ifields[1 ];
500  }
501 
502  pullup_lock_buffer(fr->ofields[0], 0);
503  pullup_lock_buffer(fr->ofields[1], 1);
504 
505  if (fr->ofields[0] == fr->ofields[1]) {
506  fr->buffer = fr->ofields[0];
507  pullup_lock_buffer(fr->buffer, 2);
508  return fr;
509  }
510 
511  return fr;
512 }
513 
515 {
516  int i;
517 
518  for (i = 0; i < f->length; i++)
519  pullup_release_buffer(f->ifields[i], f->parity ^ (i & 1));
520 
521  pullup_release_buffer(f->ofields[0], 0);
522  pullup_release_buffer(f->ofields[1], 1);
523 
524  if (f->buffer)
525  pullup_release_buffer(f->buffer, 2);
526  f->lock--;
527 }
528 
529 static void compute_metric(PullupContext *s, int *dest,
530  PullupField *fa, int pa, PullupField *fb, int pb,
531  int (*func)(const uint8_t *, const uint8_t *, ptrdiff_t))
532 {
533  int mp = s->metric_plane;
534  int xstep = 8;
535  int ystep = s->planewidth[mp] << 3;
536  int stride = s->planewidth[mp] << 1; /* field stride */
537  int w = s->metric_w * xstep;
538  uint8_t *a, *b;
539  int x, y;
540 
541  if (!fa->buffer || !fb->buffer)
542  return;
543 
544  /* Shortcut for duplicate fields (e.g. from RFF flag) */
545  if (fa->buffer == fb->buffer && pa == pb) {
546  memset(dest, 0, s->metric_length * sizeof(*dest));
547  return;
548  }
549 
550  a = fa->buffer->planes[mp] + pa * s->planewidth[mp] + s->metric_offset;
551  b = fb->buffer->planes[mp] + pb * s->planewidth[mp] + s->metric_offset;
552 
553  for (y = 0; y < s->metric_h; y++) {
554  for (x = 0; x < w; x += xstep)
555  *dest++ = func(a + x, b + x, stride);
556  a += ystep; b += ystep;
557  }
558 }
559 
561 {
562  int ret;
563 
564  if (s->head->next == s->first) {
565  PullupField *f = av_mallocz(sizeof(*f));
566 
567  if (!f)
568  return AVERROR(ENOMEM);
569 
570  if ((ret = alloc_metrics(s, f)) < 0) {
571  av_free(f);
572  return ret;
573  }
574 
575  f->prev = s->head;
576  f->next = s->first;
577  s->head->next = f;
578  s->first->prev = f;
579  }
580 
581  return 0;
582 }
583 
585 {
586  PullupField *f;
587 
588  /* Grow the circular list if needed */
589  if (check_field_queue(s) < 0)
590  return;
591 
592  /* Cannot have two fields of same parity in a row; drop the new one */
593  if (s->last && s->last->parity == parity)
594  return;
595 
596  f = s->head;
597  f->parity = parity;
598  f->buffer = pullup_lock_buffer(b, parity);
599  f->flags = 0;
600  f->breaks = 0;
601  f->affinity = 0;
602 
603  compute_metric(s, f->diffs, f, parity, f->prev->prev, parity, s->diff);
604  compute_metric(s, f->combs, parity ? f->prev : f, 0, parity ? f : f->prev, 1, s->comb);
605  compute_metric(s, f->vars, f, parity, f, -1, s->var);
606  emms_c();
607 
608  /* Advance the circular list */
609  if (!s->first)
610  s->first = s->head;
611 
612  s->last = s->head;
613  s->head = s->head->next;
614 }
615 
617  PullupBuffer *dst, PullupBuffer *src, int parity)
618 {
619  uint8_t *dd, *ss;
620  int i;
621 
622  for (i = 0; i < s->nb_planes; i++) {
623  ss = src->planes[i] + parity * s->planewidth[i];
624  dd = dst->planes[i] + parity * s->planewidth[i];
625 
626  av_image_copy_plane(dd, s->planewidth[i] << 1,
627  ss, s->planewidth[i] << 1,
628  s->planewidth[i], s->planeheight[i] >> 1);
629  }
630 }
631 
633 {
634  int i;
635 
636  if (fr->buffer)
637  return;
638 
639  if (fr->length < 2)
640  return; /* FIXME: deal with this */
641 
642  for (i = 0; i < 2; i++) {
643  if (fr->ofields[i]->lock[i^1])
644  continue;
645 
646  fr->buffer = fr->ofields[i];
647  pullup_lock_buffer(fr->buffer, 2);
648  copy_field(s, fr->buffer, fr->ofields[i^1], i^1);
649  return;
650  }
651 
652  fr->buffer = pullup_get_buffer(s, 2);
653 
654  copy_field(s, fr->buffer, fr->ofields[0], 0);
655  copy_field(s, fr->buffer, fr->ofields[1], 1);
656 }
657 
659 {
660  AVFilterContext *ctx = inlink->dst;
661  AVFilterLink *outlink = ctx->outputs[0];
662  PullupContext *s = ctx->priv;
663  PullupBuffer *b;
664  PullupFrame *f;
665  AVFrame *out;
666  int p, ret = 0;
667 
668  b = pullup_get_buffer(s, 2);
669  if (!b) {
670  av_log(ctx, AV_LOG_WARNING, "Could not get buffer!\n");
671  f = pullup_get_frame(s);
673  goto end;
674  }
675 
676  av_image_copy(b->planes, s->planewidth,
677  (const uint8_t**)in->data, in->linesize,
678  inlink->format, inlink->w, inlink->h);
679 
680  p = in->interlaced_frame ? !in->top_field_first : 0;
681  pullup_submit_field(s, b, p );
682  pullup_submit_field(s, b, p^1);
683 
684  if (in->repeat_pict)
685  pullup_submit_field(s, b, p);
686 
688 
689  f = pullup_get_frame(s);
690  if (!f)
691  goto end;
692 
693  if (f->length < 2) {
695  f = pullup_get_frame(s);
696  if (!f)
697  goto end;
698  if (f->length < 2) {
700  if (!in->repeat_pict)
701  goto end;
702  f = pullup_get_frame(s);
703  if (!f)
704  goto end;
705  if (f->length < 2) {
707  goto end;
708  }
709  }
710  }
711 
712  /* If the frame isn't already exportable... */
713  if (!f->buffer)
715 
716  out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
717  if (!out) {
718  ret = AVERROR(ENOMEM);
719  goto end;
720  }
722 
723  av_image_copy(out->data, out->linesize,
724  (const uint8_t**)f->buffer->planes, s->planewidth,
725  inlink->format, inlink->w, inlink->h);
726 
727  ret = ff_filter_frame(outlink, out);
729 end:
730  av_frame_free(&in);
731  return ret;
732 }
733 
735 {
736  PullupContext *s = ctx->priv;
737  int i;
738 
739  free_field_queue(s->head);
740  s->last = NULL;
741 
742  for (i = 0; i < FF_ARRAY_ELEMS(s->buffers); i++) {
743  av_freep(&s->buffers[i].planes[0]);
744  av_freep(&s->buffers[i].planes[1]);
745  av_freep(&s->buffers[i].planes[2]);
746  }
747 }
748 
749 static const AVFilterPad pullup_inputs[] = {
750  {
751  .name = "default",
752  .type = AVMEDIA_TYPE_VIDEO,
753  .filter_frame = filter_frame,
754  .config_props = config_input,
755  },
756  { NULL }
757 };
758 
759 static const AVFilterPad pullup_outputs[] = {
760  {
761  .name = "default",
762  .type = AVMEDIA_TYPE_VIDEO,
763  },
764  { NULL }
765 };
766 
768  .name = "pullup",
769  .description = NULL_IF_CONFIG_SMALL("Pullup from field sequence to frames."),
770  .priv_size = sizeof(PullupContext),
771  .priv_class = &pullup_class,
772  .uninit = uninit,
776 };
ff_get_video_buffer
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:99
func
int(* func)(AVBPrint *dst, const char *in, const char *arg)
Definition: jacosubdec.c:67
stride
int stride
Definition: mace.c:144
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:200
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
pullup_options
static const AVOption pullup_options[]
Definition: vf_pullup.c:40
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
ff_make_format_list
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:286
out
FILE * out
Definition: movenc.c:54
pullup_get_frame
static PullupFrame * pullup_get_frame(PullupContext *s)
Definition: vf_pullup.c:467
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1096
pullup_get_buffer
static PullupBuffer * pullup_get_buffer(PullupContext *s, int parity)
Definition: vf_pullup.c:262
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2573
inlink
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
Definition: filter_design.txt:212
config_input
static int config_input(AVFilterLink *inlink)
Definition: vf_pullup.c:183
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:203
alloc_buffer
static int alloc_buffer(PullupContext *s, PullupBuffer *b)
Definition: vf_pullup.c:247
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:318
pixdesc.h
w
uint8_t w
Definition: llviddspenc.c:39
AVOption
AVOption.
Definition: opt.h:248
b
#define b
Definition: input.c:41
pullup_outputs
static const AVFilterPad pullup_outputs[]
Definition: vf_pullup.c:759
AV_PIX_FMT_YUV440P
@ AV_PIX_FMT_YUV440P
planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
Definition: pixfmt.h:99
vf_pullup.h
max
#define max(a, b)
Definition: cuda_runtime.h:33
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:149
pullup_pack_frame
static void pullup_pack_frame(PullupContext *s, PullupFrame *fr)
Definition: vf_pullup.c:632
queue_length
static int queue_length(PullupField *begin, PullupField *end)
Definition: vf_pullup.c:299
video.h
var_c
static int var_c(const uint8_t *a, const uint8_t *b, ptrdiff_t s)
Definition: vf_pullup.c:104
FLAGS
#define FLAGS
Definition: vf_pullup.c:38
PullupField
Definition: vf_pullup.h:29
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:31
av_image_copy_plane
void av_image_copy_plane(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_linesize, int bytewidth, int height)
Copy image plane from src to dst.
Definition: imgutils.c:373
AVFilterFormats
A list of supported formats for one end of a filter link.
Definition: formats.h:65
formats.h
comb_c
static int comb_c(const uint8_t *a, const uint8_t *b, ptrdiff_t s)
Definition: vf_pullup.c:89
av_pix_fmt_count_planes
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2613
ABS
#define ABS(a)
Definition: vf_pullup.c:73
filter_frame
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
Definition: vf_pullup.c:658
F_HAVE_BREAKS
#define F_HAVE_BREAKS
Definition: vf_pullup.c:31
compute_metric
static void compute_metric(PullupContext *s, int *dest, PullupField *fa, int pa, PullupField *fb, int pb, int(*func)(const uint8_t *, const uint8_t *, ptrdiff_t))
Definition: vf_pullup.c:529
ss
#define ss(width, name, subs,...)
Definition: cbs_vp9.c:261
AVFilterPad
A filter pad used for either input or output.
Definition: internal.h:54
AV_PIX_FMT_YUVJ411P
@ AV_PIX_FMT_YUVJ411P
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) full scale (JPEG), deprecated in favor ...
Definition: pixfmt.h:258
avassert.h
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
PullupField::affinity
int affinity
Definition: vf_pullup.h:34
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
av_cold
#define av_cold
Definition: attributes.h:90
pullup_inputs
static const AVFilterPad pullup_inputs[]
Definition: vf_pullup.c:749
ff_set_common_formats
int ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
A helper for query_formats() which sets all links to the same list of formats.
Definition: formats.c:587
PullupBuffer::planes
uint8_t * planes[4]
Definition: vf_pullup.h:26
OFFSET
#define OFFSET(x)
Definition: vf_pullup.c:37
AV_PIX_FMT_YUVJ422P
@ AV_PIX_FMT_YUVJ422P
planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV422P and setting col...
Definition: pixfmt.h:79
BREAK_LEFT
#define BREAK_LEFT
Definition: vf_pullup.c:34
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(pullup)
pullup_release_buffer
static void pullup_release_buffer(PullupBuffer *b, int parity)
Definition: vf_pullup.c:236
s
#define s(width, name)
Definition: cbs_vp9.c:257
AV_CEIL_RSHIFT
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:58
pullup_lock_buffer
static PullupBuffer * pullup_lock_buffer(PullupBuffer *b, int parity)
Definition: vf_pullup.c:223
outputs
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
pix_fmts
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:309
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:215
ctx
AVFormatContext * ctx
Definition: movenc.c:48
PullupContext
Definition: vf_pullup.h:49
AV_PIX_FMT_YUV420P
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:66
f
#define f(width, name)
Definition: cbs_vp9.c:255
AV_PIX_FMT_YUVJ444P
@ AV_PIX_FMT_YUVJ444P
planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting col...
Definition: pixfmt.h:80
check_field_queue
static int check_field_queue(PullupContext *s)
Definition: vf_pullup.c:560
decide_frame_length
static int decide_frame_length(PullupContext *s)
Definition: vf_pullup.c:411
ff_vf_pullup
AVFilter ff_vf_pullup
Definition: vf_pullup.c:767
PullupFrame::length
int length
Definition: vf_pullup.h:43
NULL
#define NULL
Definition: coverity.c:32
rv
int32_t rv
Definition: input.c:405
av_frame_copy_props
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:658
AV_PIX_FMT_YUVJ420P
@ AV_PIX_FMT_YUVJ420P
planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting col...
Definition: pixfmt.h:78
src
#define src
Definition: vp8dsp.c:255
PullupFrame::ifields
PullupBuffer * ifields[4]
Definition: vf_pullup.h:45
F_HAVE_AFFINITY
#define F_HAVE_AFFINITY
Definition: vf_pullup.c:32
inputs
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several inputs
Definition: filter_design.txt:243
AV_PIX_FMT_GRAY8
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition: pixfmt.h:74
PullupFrame::buffer
PullupBuffer * buffer
Definition: vf_pullup.h:46
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:117
FFMAX
#define FFMAX(a, b)
Definition: common.h:103
parity
mcdeint parity
Definition: vf_mcdeint.c:277
PullupField::buffer
PullupBuffer * buffer
Definition: vf_pullup.h:31
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
PullupFrame::lock
int lock
Definition: vf_pullup.h:42
pullup_submit_field
static void pullup_submit_field(PullupContext *s, PullupBuffer *b, int parity)
Definition: vf_pullup.c:584
internal.h
alloc_metrics
static int alloc_metrics(PullupContext *s, PullupField *f)
Definition: vf_pullup.c:117
compute_breaks
static void compute_breaks(PullupContext *s, PullupField *f0)
Definition: vf_pullup.c:326
PullupFrame::parity
int parity
Definition: vf_pullup.h:44
in
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi - 0x80) *(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi - 0x80) *(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31)))) #define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac) { } void ff_audio_convert_free(AudioConvert **ac) { if(! *ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);} AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map) { AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method !=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt) > 2) { ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc) { av_free(ac);return NULL;} return ac;} in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar) { ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar ? ac->channels :1;} else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);return ac;} int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in) { int use_generic=1;int len=in->nb_samples;int p;if(ac->dc) { av_log(ac->avr, AV_LOG_TRACE, "%d samples - audio_convert: %s to %s (dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> in
Definition: audio_convert.c:326
compute_affinity
static void compute_affinity(PullupContext *s, PullupField *f)
Definition: vf_pullup.c:367
i
int i
Definition: input.c:407
av_assert1
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition: avassert.h:53
fb
#define fb(width, name)
Definition: cbs_av1.c:549
find_first_break
static int find_first_break(PullupField *f, int max)
Definition: vf_pullup.c:313
AV_PIX_FMT_YUVJ440P
@ AV_PIX_FMT_YUVJ440P
planar YUV 4:4:0 full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV440P and setting color_range
Definition: pixfmt.h:100
uint8_t
uint8_t
Definition: audio_convert.c:194
copy_field
static void copy_field(PullupContext *s, PullupBuffer *dst, PullupBuffer *src, int parity)
Definition: vf_pullup.c:616
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:237
BREAK_RIGHT
#define BREAK_RIGHT
Definition: vf_pullup.c:35
query_formats
static int query_formats(AVFilterContext *ctx)
Definition: vf_pullup.c:55
len
int len
Definition: vorbis_enc_data.h:452
uninit
static av_cold void uninit(AVFilterContext *ctx)
Definition: vf_pullup.c:734
AVFilterPad::name
const char * name
Pad name.
Definition: internal.h:60
AVFilter
Filter definition.
Definition: avfilter.h:145
ret
ret
Definition: filter_design.txt:187
PullupFrame::ofields
PullupBuffer * ofields[2]
Definition: vf_pullup.h:45
free_field_queue
static void free_field_queue(PullupField *head)
Definition: vf_pullup.c:132
PullupField::next
struct PullupField * next
Definition: vf_pullup.h:38
make_field_queue
static PullupField * make_field_queue(PullupContext *s, int len)
Definition: vf_pullup.c:149
PullupBuffer::lock
int lock[2]
Definition: vf_pullup.h:25
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Non-inlined equivalent of av_mallocz_array().
Definition: mem.c:245
av_image_copy
void av_image_copy(uint8_t *dst_data[4], int dst_linesizes[4], const uint8_t *src_data[4], const int src_linesizes[4], enum AVPixelFormat pix_fmt, int width, int height)
Copy image in src_data to dst_data.
Definition: imgutils.c:422
PullupField::prev
struct PullupField * prev
Definition: vf_pullup.h:38
PullupBuffer
Definition: vf_pullup.h:24
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:225
avfilter.h
diff_c
static int diff_c(const uint8_t *a, const uint8_t *b, ptrdiff_t s)
Definition: vf_pullup.c:75
AV_PIX_FMT_YUV444P
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:71
AVFilterContext
An instance of a filter.
Definition: avfilter.h:341
desc
const char * desc
Definition: libsvtav1.c:79
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
PullupField::flags
unsigned flags
Definition: vf_pullup.h:32
AV_PIX_FMT_YUV422P
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:70
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:81
ff_pullup_init_x86
void ff_pullup_init_x86(PullupContext *s)
Definition: vf_pullup_init.c:30
diff
static av_always_inline int diff(const uint32_t a, const uint32_t b)
Definition: vf_palettegen.c:136
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:48
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Definition: opt.h:242
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
AV_PIX_FMT_YUV411P
@ AV_PIX_FMT_YUV411P
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
Definition: pixfmt.h:73
PullupField::diffs
int * diffs
Definition: vf_pullup.h:35
imgutils.h
AV_PIX_FMT_YUV410P
@ AV_PIX_FMT_YUV410P
planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
Definition: pixfmt.h:72
PullupFrame
Definition: vf_pullup.h:41
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
pullup_release_frame
static void pullup_release_frame(PullupFrame *f)
Definition: vf_pullup.c:514
PullupField::breaks
int breaks
Definition: vf_pullup.h:33
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Definition: opt.h:234