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 
67  AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
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 
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 
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)
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 
616 static void copy_field(PullupContext *s,
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 
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 
687  pullup_release_buffer(b, 2);
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)
714  pullup_pack_frame(s, f);
715 
716  out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
717  if (!out) {
718  ret = AVERROR(ENOMEM);
719  goto end;
720  }
721  av_frame_copy_props(out, in);
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 
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,
774  .inputs = pullup_inputs,
775  .outputs = pullup_outputs,
776 };
#define NULL
Definition: coverity.c:32
PullupFrame frame
Definition: vf_pullup.h:62
#define FLAGS
Definition: vf_pullup.c:38
static int alloc_metrics(PullupContext *s, PullupField *f)
Definition: vf_pullup.c:117
int parity
Definition: vf_pullup.h:44
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2522
This structure describes decoded (raw) audio or video data.
Definition: frame.h:295
static PullupBuffer * pullup_lock_buffer(PullupBuffer *b, int parity)
Definition: vf_pullup.c:223
PullupBuffer * buffer
Definition: vf_pullup.h:46
AVOption.
Definition: opt.h:246
int(* diff)(const uint8_t *a, const uint8_t *b, ptrdiff_t s)
Definition: vf_pullup.h:64
static const AVOption pullup_options[]
Definition: vf_pullup.c:40
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:71
misc image utilities
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2562
Main libavfilter public API header.
PullupBuffer * buffer
Definition: vf_pullup.h:31
const char * desc
Definition: nvenc.c:68
unsigned flags
Definition: vf_pullup.h:32
int repeat_pict
When decoding, this signals how much the picture must be delayed.
Definition: frame.h:437
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:36
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:236
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
#define F_HAVE_AFFINITY
Definition: vf_pullup.c:32
#define src
Definition: vp8dsp.c:254
int strict_breaks
Definition: vf_pullup.h:53
uint8_t log2_chroma_w
Amount to shift the luma width right to find the chroma width.
Definition: pixdesc.h:92
static void pullup_submit_field(PullupContext *s, PullupBuffer *b, int parity)
Definition: vf_pullup.c:584
void * av_calloc(size_t nmemb, size_t size)
Non-inlined equivalent of av_mallocz_array().
Definition: mem.c:244
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:283
AVFilter ff_vf_pullup
Definition: vf_pullup.c:767
const char * name
Pad name.
Definition: internal.h:60
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1093
uint8_t
#define av_cold
Definition: attributes.h:82
#define av_malloc(s)
int junk_bottom
Definition: vf_pullup.h:51
AVOptions.
static PullupBuffer * pullup_get_buffer(PullupContext *s, int parity)
Definition: vf_pullup.c:262
#define f(width, name)
Definition: cbs_vp9.c:255
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
static av_cold void uninit(AVFilterContext *ctx)
Definition: vf_pullup.c:734
static void compute_breaks(PullupContext *s, PullupField *f0)
Definition: vf_pullup.c:326
int metric_offset
Definition: vf_pullup.h:56
planar YUV 4:4:0 full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV440P and setting color_range...
Definition: pixfmt.h:100
planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV422P and setting col...
Definition: pixfmt.h:79
int interlaced_frame
The content of the picture is interlaced.
Definition: frame.h:442
void ff_pullup_init_x86(PullupContext *s)
#define max(a, b)
Definition: cuda_runtime.h:33
#define FFALIGN(x, a)
Definition: macros.h:48
#define av_log(a,...)
A filter pad used for either input or output.
Definition: internal.h:54
int breaks
Definition: vf_pullup.h:33
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
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:569
uint8_t log2_chroma_h
Amount to shift the luma height right to find the chroma height.
Definition: pixdesc.h:101
PullupField * head
Definition: vf_pullup.h:60
PullupBuffer * ifields[4]
Definition: vf_pullup.h:45
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:202
int lock[2]
Definition: vf_pullup.h:25
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
PullupField * last
Definition: vf_pullup.h:60
void * priv
private data for use by the filter
Definition: avfilter.h:353
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
simple assert() macros that are a bit more flexible than ISO C assert().
static void copy_field(PullupContext *s, PullupBuffer *dst, PullupBuffer *src, int parity)
Definition: vf_pullup.c:616
#define BREAK_RIGHT
Definition: vf_pullup.c:35
GLsizei count
Definition: opengl_enc.c:108
#define FFMAX(a, b)
Definition: common.h:94
PullupField * first
Definition: vf_pullup.h:60
int planewidth[4]
Definition: vf_pullup.h:58
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:387
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:70
int * diffs
Definition: vf_pullup.h:35
#define ss(width, name, subs,...)
Definition: cbs_vp9.c:261
int * combs
Definition: vf_pullup.h:36
#define b
Definition: input.c:41
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition: avassert.h:53
#define fb(width, name)
Definition: cbs_av1.c:549
planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting col...
Definition: pixfmt.h:78
int strict_pairs
Definition: vf_pullup.h:54
static void free_field_queue(PullupField *head)
Definition: vf_pullup.c:132
static PullupFrame * pullup_get_frame(PullupContext *s)
Definition: vf_pullup.c:467
uint8_t w
Definition: llviddspenc.c:38
int planeheight[4]
Definition: vf_pullup.h:59
AVFormatContext * ctx
Definition: movenc.c:48
int parity
Definition: vf_pullup.h:30
#define s(width, name)
Definition: cbs_vp9.c:257
mcdeint parity
Definition: vf_mcdeint.c:274
static const AVFilterPad pullup_inputs[]
Definition: vf_pullup.c:749
int affinity
Definition: vf_pullup.h:34
int n
Definition: avisynth_c.h:760
static int var_c(const uint8_t *a, const uint8_t *b, ptrdiff_t s)
Definition: vf_pullup.c:104
int metric_plane
Definition: vf_pullup.h:52
static int find_first_break(PullupField *f, int max)
Definition: vf_pullup.c:313
static int diff_c(const uint8_t *a, const uint8_t *b, ptrdiff_t s)
Definition: vf_pullup.c:75
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
#define FF_ARRAY_ELEMS(a)
PullupBuffer * ofields[2]
Definition: vf_pullup.h:45
struct PullupField * next
Definition: vf_pullup.h:38
static void compute_affinity(PullupContext *s, PullupField *f)
Definition: vf_pullup.c:367
static int queue_length(PullupField *begin, PullupField *end)
Definition: vf_pullup.c:299
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:326
int(* comb)(const uint8_t *a, const uint8_t *b, ptrdiff_t s)
Definition: vf_pullup.h:65
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:81
static void pullup_release_frame(PullupFrame *f)
Definition: vf_pullup.c:514
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
#define ABS(a)
Definition: vf_pullup.c:73
#define OFFSET(x)
Definition: vf_pullup.c:37
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
planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
Definition: pixfmt.h:72
int(* func)(AVBPrint *dst, const char *in, const char *arg)
Definition: jacosubdec.c:67
Filter definition.
Definition: avfilter.h:144
static int check_field_queue(PullupContext *s)
Definition: vf_pullup.c:560
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
Definition: vf_pullup.c:658
#define BREAK_LEFT
Definition: vf_pullup.c:34
const char * name
Filter name.
Definition: avfilter.h:148
static const AVFilterPad pullup_outputs[]
Definition: vf_pullup.c:759
static void pullup_release_buffer(PullupBuffer *b, int parity)
Definition: vf_pullup.c:236
uint8_t * planes[4]
Definition: vf_pullup.h:26
struct PullupField * prev
Definition: vf_pullup.h:38
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:350
AVFILTER_DEFINE_CLASS(pullup)
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:275
static int config_input(AVFilterLink *inlink)
Definition: vf_pullup.c:183
static int alloc_buffer(PullupContext *s, PullupBuffer *b)
Definition: vf_pullup.c:247
int(* var)(const uint8_t *a, const uint8_t *b, ptrdiff_t s)
Definition: vf_pullup.h:66
static int comb_c(const uint8_t *a, const uint8_t *b, ptrdiff_t s)
Definition: vf_pullup.c:89
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:309
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
GLint GLenum GLboolean GLsizei stride
Definition: opengl_enc.c:104
int length
Definition: vf_pullup.h:43
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:66
int junk_right
Definition: vf_pullup.h:51
Y , 8bpp.
Definition: pixfmt.h:74
int * vars
Definition: vf_pullup.h:37
static void pullup_pack_frame(PullupContext *s, PullupFrame *fr)
Definition: vf_pullup.c:632
planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting col...
Definition: pixfmt.h:80
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
Definition: pixfmt.h:73
int metric_length
Definition: vf_pullup.h:55
static av_always_inline int diff(const uint32_t a, const uint32_t b)
#define av_free(p)
int top_field_first
If the content is interlaced, is top field displayed first.
Definition: frame.h:447
int len
PullupBuffer buffers[10]
Definition: vf_pullup.h:61
A list of supported formats for one end of a filter link.
Definition: formats.h:64
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) full scale (JPEG), deprecated in favor ...
Definition: pixfmt.h:258
An instance of a filter.
Definition: avfilter.h:338
FILE * out
Definition: movenc.c:54
#define av_freep(p)
#define F_HAVE_BREAKS
Definition: vf_pullup.c:31
planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
Definition: pixfmt.h:99
static int decide_frame_length(PullupContext *s)
Definition: vf_pullup.c:411
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:338
static int query_formats(AVFilterContext *ctx)
Definition: vf_pullup.c:55
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
internal API functions
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
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
static PullupField * make_field_queue(PullupContext *s, int len)
Definition: vf_pullup.c:149
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:654
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:58