FFmpeg
vf_fillborders.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Paul B Mahol
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 Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 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 GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along 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/colorspace.h"
23 #include "libavutil/common.h"
24 #include "libavutil/opt.h"
25 #include "libavutil/pixdesc.h"
26 #include "avfilter.h"
27 #include "drawutils.h"
28 #include "formats.h"
29 #include "internal.h"
30 #include "video.h"
31 
32 enum { Y, U, V, A };
33 enum { R, G, B };
34 
36 
37 typedef struct Borders {
38  int left, right, top, bottom;
39 } Borders;
40 
41 typedef struct FillBordersContext {
42  const AVClass *class;
43  int left, right, top, bottom;
44  int mode;
45 
46  int nb_planes;
47  int depth;
48  Borders borders[4];
49  int planewidth[4];
50  int planeheight[4];
51  uint8_t fill[4];
52  uint8_t yuv_color[4];
53  uint8_t rgba_color[4];
54 
55  void (*fillborders)(struct FillBordersContext *s, AVFrame *frame);
57 
59 {
60  static const enum AVPixelFormat pix_fmts[] = {
80  };
81  AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
82  if (!fmts_list)
83  return AVERROR(ENOMEM);
84  return ff_set_common_formats(ctx, fmts_list);
85 }
86 
88 {
89  int p, y;
90 
91  for (p = 0; p < s->nb_planes; p++) {
92  uint8_t *ptr = frame->data[p];
93  int linesize = frame->linesize[p];
94 
95  for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) {
96  memset(ptr + y * linesize,
97  *(ptr + y * linesize + s->borders[p].left),
98  s->borders[p].left);
99  memset(ptr + y * linesize + s->planewidth[p] - s->borders[p].right,
100  *(ptr + y * linesize + s->planewidth[p] - s->borders[p].right - 1),
101  s->borders[p].right);
102  }
103 
104  for (y = 0; y < s->borders[p].top; y++) {
105  memcpy(ptr + y * linesize,
106  ptr + s->borders[p].top * linesize, s->planewidth[p]);
107  }
108 
109  for (y = s->planeheight[p] - s->borders[p].bottom; y < s->planeheight[p]; y++) {
110  memcpy(ptr + y * linesize,
111  ptr + (s->planeheight[p] - s->borders[p].bottom - 1) * linesize,
112  s->planewidth[p]);
113  }
114  }
115 }
116 
118 {
119  int p, y, x;
120 
121  for (p = 0; p < s->nb_planes; p++) {
122  uint16_t *ptr = (uint16_t *)frame->data[p];
123  int linesize = frame->linesize[p] / 2;
124 
125  for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) {
126  for (x = 0; x < s->borders[p].left; x++) {
127  ptr[y * linesize + x] = *(ptr + y * linesize + s->borders[p].left);
128  }
129 
130  for (x = 0; x < s->borders[p].right; x++) {
131  ptr[y * linesize + s->planewidth[p] - s->borders[p].right + x] =
132  *(ptr + y * linesize + s->planewidth[p] - s->borders[p].right - 1);
133  }
134  }
135 
136  for (y = 0; y < s->borders[p].top; y++) {
137  memcpy(ptr + y * linesize,
138  ptr + s->borders[p].top * linesize, s->planewidth[p] * 2);
139  }
140 
141  for (y = s->planeheight[p] - s->borders[p].bottom; y < s->planeheight[p]; y++) {
142  memcpy(ptr + y * linesize,
143  ptr + (s->planeheight[p] - s->borders[p].bottom - 1) * linesize,
144  s->planewidth[p] * 2);
145  }
146  }
147 }
148 
150 {
151  int p, y, x;
152 
153  for (p = 0; p < s->nb_planes; p++) {
154  uint8_t *ptr = frame->data[p];
155  int linesize = frame->linesize[p];
156 
157  for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) {
158  for (x = 0; x < s->borders[p].left; x++) {
159  ptr[y * linesize + x] = ptr[y * linesize + s->borders[p].left * 2 - 1 - x];
160  }
161 
162  for (x = 0; x < s->borders[p].right; x++) {
163  ptr[y * linesize + s->planewidth[p] - s->borders[p].right + x] =
164  ptr[y * linesize + s->planewidth[p] - s->borders[p].right - 1 - x];
165  }
166  }
167 
168  for (y = 0; y < s->borders[p].top; y++) {
169  memcpy(ptr + y * linesize,
170  ptr + (s->borders[p].top * 2 - 1 - y) * linesize,
171  s->planewidth[p]);
172  }
173 
174  for (y = 0; y < s->borders[p].bottom; y++) {
175  memcpy(ptr + (s->planeheight[p] - s->borders[p].bottom + y) * linesize,
176  ptr + (s->planeheight[p] - s->borders[p].bottom - 1 - y) * linesize,
177  s->planewidth[p]);
178  }
179  }
180 }
181 
183 {
184  int p, y, x;
185 
186  for (p = 0; p < s->nb_planes; p++) {
187  uint16_t *ptr = (uint16_t *)frame->data[p];
188  int linesize = frame->linesize[p] / 2;
189 
190  for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) {
191  for (x = 0; x < s->borders[p].left; x++) {
192  ptr[y * linesize + x] = ptr[y * linesize + s->borders[p].left * 2 - 1 - x];
193  }
194 
195  for (x = 0; x < s->borders[p].right; x++) {
196  ptr[y * linesize + s->planewidth[p] - s->borders[p].right + x] =
197  ptr[y * linesize + s->planewidth[p] - s->borders[p].right - 1 - x];
198  }
199  }
200 
201  for (y = 0; y < s->borders[p].top; y++) {
202  memcpy(ptr + y * linesize,
203  ptr + (s->borders[p].top * 2 - 1 - y) * linesize,
204  s->planewidth[p] * 2);
205  }
206 
207  for (y = 0; y < s->borders[p].bottom; y++) {
208  memcpy(ptr + (s->planeheight[p] - s->borders[p].bottom + y) * linesize,
209  ptr + (s->planeheight[p] - s->borders[p].bottom - 1 - y) * linesize,
210  s->planewidth[p] * 2);
211  }
212  }
213 }
214 
216 {
217  int p, y;
218 
219  for (p = 0; p < s->nb_planes; p++) {
220  uint8_t *ptr = frame->data[p];
221  uint8_t fill = s->fill[p];
222  int linesize = frame->linesize[p];
223 
224  for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) {
225  memset(ptr + y * linesize, fill, s->borders[p].left);
226  memset(ptr + y * linesize + s->planewidth[p] - s->borders[p].right, fill,
227  s->borders[p].right);
228  }
229 
230  for (y = 0; y < s->borders[p].top; y++) {
231  memset(ptr + y * linesize, fill, s->planewidth[p]);
232  }
233 
234  for (y = s->planeheight[p] - s->borders[p].bottom; y < s->planeheight[p]; y++) {
235  memset(ptr + y * linesize, fill, s->planewidth[p]);
236  }
237  }
238 }
239 
241 {
242  int p, y, x;
243 
244  for (p = 0; p < s->nb_planes; p++) {
245  uint16_t *ptr = (uint16_t *)frame->data[p];
246  uint16_t fill = s->fill[p] << (s->depth - 8);
247  int linesize = frame->linesize[p] / 2;
248 
249  for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) {
250  for (x = 0; x < s->borders[p].left; x++) {
251  ptr[y * linesize + x] = fill;
252  }
253 
254  for (x = 0; x < s->borders[p].right; x++) {
255  ptr[y * linesize + s->planewidth[p] - s->borders[p].right + x] = fill;
256  }
257  }
258 
259  for (y = 0; y < s->borders[p].top; y++) {
260  for (x = 0; x < s->planewidth[p]; x++) {
261  ptr[y * linesize + x] = fill;
262  }
263  }
264 
265  for (y = s->planeheight[p] - s->borders[p].bottom; y < s->planeheight[p]; y++) {
266  for (x = 0; x < s->planewidth[p]; x++) {
267  ptr[y * linesize + x] = fill;
268  }
269  }
270  }
271 }
272 
274 {
275  int p, y, x;
276 
277  for (p = 0; p < s->nb_planes; p++) {
278  uint8_t *ptr = frame->data[p];
279  int linesize = frame->linesize[p];
280 
281  for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) {
282  for (x = 0; x < s->borders[p].left; x++) {
283  ptr[y * linesize + x] = ptr[y * linesize + s->borders[p].left * 2 - x];
284  }
285 
286  for (x = 0; x < s->borders[p].right; x++) {
287  ptr[y * linesize + s->planewidth[p] - s->borders[p].right + x] =
288  ptr[y * linesize + s->planewidth[p] - s->borders[p].right - 2 - x];
289  }
290  }
291 
292  for (y = 0; y < s->borders[p].top; y++) {
293  memcpy(ptr + y * linesize,
294  ptr + (s->borders[p].top * 2 - y) * linesize,
295  s->planewidth[p]);
296  }
297 
298  for (y = 0; y < s->borders[p].bottom; y++) {
299  memcpy(ptr + (s->planeheight[p] - s->borders[p].bottom + y) * linesize,
300  ptr + (s->planeheight[p] - s->borders[p].bottom - 2 - y) * linesize,
301  s->planewidth[p]);
302  }
303  }
304 }
305 
307 {
308  int p, y, x;
309 
310  for (p = 0; p < s->nb_planes; p++) {
311  uint16_t *ptr = (uint16_t *)frame->data[p];
312  int linesize = frame->linesize[p] / 2;
313 
314  for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) {
315  for (x = 0; x < s->borders[p].left; x++) {
316  ptr[y * linesize + x] = ptr[y * linesize + s->borders[p].left * 2 - x];
317  }
318 
319  for (x = 0; x < s->borders[p].right; x++) {
320  ptr[y * linesize + s->planewidth[p] - s->borders[p].right + x] =
321  ptr[y * linesize + s->planewidth[p] - s->borders[p].right - 2 - x];
322  }
323  }
324 
325  for (y = 0; y < s->borders[p].top; y++) {
326  memcpy(ptr + y * linesize,
327  ptr + (s->borders[p].top * 2 - y) * linesize,
328  s->planewidth[p] * 2);
329  }
330 
331  for (y = 0; y < s->borders[p].bottom; y++) {
332  memcpy(ptr + (s->planeheight[p] - s->borders[p].bottom + y) * linesize,
333  ptr + (s->planeheight[p] - s->borders[p].bottom - 2 - y) * linesize,
334  s->planewidth[p] * 2);
335  }
336  }
337 }
338 
340 {
341  int p, y, x;
342 
343  for (p = 0; p < s->nb_planes; p++) {
344  uint8_t *ptr = frame->data[p];
345  int linesize = frame->linesize[p];
346 
347  for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) {
348  for (x = 0; x < s->borders[p].left; x++) {
349  ptr[y * linesize + x] = ptr[y * linesize + s->planewidth[p] - s->borders[p].right - s->borders[p].left + x];
350  }
351 
352  for (x = 0; x < s->borders[p].right; x++) {
353  ptr[y * linesize + s->planewidth[p] - s->borders[p].right + x] =
354  ptr[y * linesize + s->borders[p].left + x];
355  }
356  }
357 
358  for (y = 0; y < s->borders[p].top; y++) {
359  memcpy(ptr + y * linesize,
360  ptr + (s->planeheight[p] - s->borders[p].bottom - s->borders[p].top + y) * linesize,
361  s->planewidth[p]);
362  }
363 
364  for (y = 0; y < s->borders[p].bottom; y++) {
365  memcpy(ptr + (s->planeheight[p] - s->borders[p].bottom + y) * linesize,
366  ptr + (s->borders[p].top + y) * linesize,
367  s->planewidth[p]);
368  }
369  }
370 }
371 
373 {
374  int p, y, x;
375 
376  for (p = 0; p < s->nb_planes; p++) {
377  uint16_t *ptr = (uint16_t *)frame->data[p];
378  int linesize = frame->linesize[p] / 2;
379 
380  for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) {
381  for (x = 0; x < s->borders[p].left; x++) {
382  ptr[y * linesize + x] = ptr[y * linesize + s->planewidth[p] - s->borders[p].right - s->borders[p].left + x];
383  }
384 
385  for (x = 0; x < s->borders[p].right; x++) {
386  ptr[y * linesize + s->planewidth[p] - s->borders[p].right + x] =
387  ptr[y * linesize + s->borders[p].left + x];
388  }
389  }
390 
391  for (y = 0; y < s->borders[p].top; y++) {
392  memcpy(ptr + y * linesize,
393  ptr + (s->planeheight[p] - s->borders[p].bottom - s->borders[p].top + y) * linesize,
394  s->planewidth[p] * 2);
395  }
396 
397  for (y = 0; y < s->borders[p].bottom; y++) {
398  memcpy(ptr + (s->planeheight[p] - s->borders[p].bottom + y) * linesize,
399  ptr + (s->borders[p].top + y) * linesize,
400  s->planewidth[p] * 2);
401  }
402  }
403 }
404 
405 static int lerp8(int fill, int src, int pos, int size)
406 {
407  return av_clip_uint8(((fill * 256 * pos / size) + (src * 256 * (size - pos) / size)) >> 8);
408 }
409 
410 static int lerp16(int fill, int src, int pos, int size, int depth)
411 {
412  return av_clip_uintp2_c(((fill * (1LL << depth) * pos / size) + (src * (1LL << depth) * (size - pos) / size)) >> depth, depth);
413 }
414 
416 {
417  int p, y, x;
418 
419  for (p = 0; p < s->nb_planes; p++) {
420  uint8_t *ptr = frame->data[p];
421  const uint8_t fill = s->fill[p];
422  const int linesize = frame->linesize[p];
423  const int start_left = s->borders[p].left;
424  const int start_right = s->planewidth[p] - s->borders[p].right;
425  const int start_top = s->borders[p].top;
426  const int start_bottom = s->planeheight[p] - s->borders[p].bottom;
427 
428  for (y = 0; y < start_top; y++) {
429  for (x = 0; x < s->planewidth[p]; x++) {
430  int src = ptr[y * linesize + x];
431  ptr[y * linesize + x] = lerp8(fill, src, start_top - y, start_top);
432  }
433  }
434 
435  for (y = start_bottom; y < s->planeheight[p]; y++) {
436  for (x = 0; x < s->planewidth[p]; x++) {
437  int src = ptr[y * linesize + x];
438  ptr[y * linesize + x] = lerp8(fill, src, y - start_bottom, s->borders[p].bottom);
439  }
440  }
441 
442  for (y = 0; y < s->planeheight[p]; y++) {
443  for (x = 0; x < start_left; x++) {
444  int src = ptr[y * linesize + x];
445  ptr[y * linesize + x] = lerp8(fill, src, start_left - x, start_left);
446  }
447 
448  for (x = 0; x < s->borders[p].right; x++) {
449  int src = ptr[y * linesize + start_right + x];
450  ptr[y * linesize + start_right + x] = lerp8(fill, src, x, s->borders[p].right);
451  }
452  }
453  }
454 }
455 
457 {
458  const int depth = s->depth;
459  int p, y, x;
460 
461  for (p = 0; p < s->nb_planes; p++) {
462  uint16_t *ptr = (uint16_t *)frame->data[p];
463  const uint16_t fill = s->fill[p] << (depth - 8);
464  const int linesize = frame->linesize[p] / 2;
465  const int start_left = s->borders[p].left;
466  const int start_right = s->planewidth[p] - s->borders[p].right;
467  const int start_top = s->borders[p].top;
468  const int start_bottom = s->planeheight[p] - s->borders[p].bottom;
469 
470  for (y = 0; y < start_top; y++) {
471  for (x = 0; x < s->planewidth[p]; x++) {
472  int src = ptr[y * linesize + x];
473  ptr[y * linesize + x] = lerp16(fill, src, start_top - y, start_top, depth);
474  }
475  }
476 
477  for (y = start_bottom; y < s->planeheight[p]; y++) {
478  for (x = 0; x < s->planewidth[p]; x++) {
479  int src = ptr[y * linesize + x];
480  ptr[y * linesize + x] = lerp16(fill, src, y - start_bottom, s->borders[p].bottom, depth);
481  }
482  }
483 
484  for (y = 0; y < s->planeheight[p]; y++) {
485  for (x = 0; x < start_left; x++) {
486  int src = ptr[y * linesize + x];
487  ptr[y * linesize + x] = lerp16(fill, src, start_left - x, start_left, depth);
488  }
489 
490  for (x = 0; x < s->borders[p].right; x++) {
491  int src = ptr[y * linesize + start_right + x];
492  ptr[y * linesize + start_right + x] = lerp16(fill, src, x, s->borders[p].right, depth);
493  }
494  }
495  }
496 }
497 
499 {
500  FillBordersContext *s = inlink->dst->priv;
501 
502  s->fillborders(s, frame);
503 
504  return ff_filter_frame(inlink->dst->outputs[0], frame);
505 }
506 
508 {
509  AVFilterContext *ctx = inlink->dst;
510  FillBordersContext *s = ctx->priv;
512 
513  s->nb_planes = desc->nb_components;
514  s->depth = desc->comp[0].depth;
515 
516  s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
517  s->planeheight[0] = s->planeheight[3] = inlink->h;
518  s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w);
519  s->planewidth[0] = s->planewidth[3] = inlink->w;
520 
521  if (inlink->w < s->left + s->right ||
522  inlink->w <= s->left ||
523  inlink->w <= s->right ||
524  inlink->h < s->top + s->bottom ||
525  inlink->h <= s->top ||
526  inlink->h <= s->bottom ||
527  inlink->w < s->left * 2 ||
528  inlink->w < s->right * 2 ||
529  inlink->h < s->top * 2 ||
530  inlink->h < s->bottom * 2) {
531  av_log(ctx, AV_LOG_ERROR, "Borders are bigger than input frame size.\n");
532  return AVERROR(EINVAL);
533  }
534 
535  s->borders[0].left = s->borders[3].left = s->left;
536  s->borders[0].right = s->borders[3].right = s->right;
537  s->borders[0].top = s->borders[3].top = s->top;
538  s->borders[0].bottom = s->borders[3].bottom = s->bottom;
539 
540  s->borders[1].left = s->left >> desc->log2_chroma_w;
541  s->borders[1].right = s->right >> desc->log2_chroma_w;
542  s->borders[1].top = s->top >> desc->log2_chroma_h;
543  s->borders[1].bottom = s->bottom >> desc->log2_chroma_h;
544 
545  s->borders[2].left = s->left >> desc->log2_chroma_w;
546  s->borders[2].right = s->right >> desc->log2_chroma_w;
547  s->borders[2].top = s->top >> desc->log2_chroma_h;
548  s->borders[2].bottom = s->bottom >> desc->log2_chroma_h;
549 
550  switch (s->mode) {
551  case FM_SMEAR: s->fillborders = s->depth <= 8 ? smear_borders8 : smear_borders16; break;
552  case FM_MIRROR: s->fillborders = s->depth <= 8 ? mirror_borders8 : mirror_borders16; break;
553  case FM_FIXED: s->fillborders = s->depth <= 8 ? fixed_borders8 : fixed_borders16; break;
555  case FM_WRAP: s->fillborders = s->depth <= 8 ? wrap_borders8 : wrap_borders16; break;
556  case FM_FADE: s->fillborders = s->depth <= 8 ? fade_borders8 : fade_borders16; break;
557  default: av_assert0(0);
558  }
559 
561  s->yuv_color[U] = RGB_TO_U_CCIR(s->rgba_color[R], s->rgba_color[G], s->rgba_color[B], 0);
562  s->yuv_color[V] = RGB_TO_V_CCIR(s->rgba_color[R], s->rgba_color[G], s->rgba_color[B], 0);
563  s->yuv_color[A] = s->rgba_color[A];
564 
565  if (desc->flags & AV_PIX_FMT_FLAG_RGB) {
566  uint8_t rgba_map[4];
567  int i;
568 
569  ff_fill_rgba_map(rgba_map, inlink->format);
570  for (i = 0; i < 4; i++)
571  s->fill[rgba_map[i]] = s->rgba_color[i];
572  } else {
573  memcpy(s->fill, s->yuv_color, sizeof(s->yuv_color));
574  }
575 
576  return 0;
577 }
578 
579 static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
580  char *res, int res_len, int flags)
581 {
582  int ret;
583 
584  ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags);
585  if (ret < 0)
586  return ret;
587 
588  return config_input(ctx->inputs[0]);
589 }
590 
591 #define OFFSET(x) offsetof(FillBordersContext, x)
592 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
593 
594 static const AVOption fillborders_options[] = {
595  { "left", "set the left fill border", OFFSET(left), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS },
596  { "right", "set the right fill border", OFFSET(right), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS },
597  { "top", "set the top fill border", OFFSET(top), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS },
598  { "bottom", "set the bottom fill border", OFFSET(bottom), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS },
599  { "mode", "set the fill borders mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=FM_SMEAR}, 0, FM_NB_MODES-1, FLAGS, "mode" },
600  { "smear", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FM_SMEAR}, 0, 0, FLAGS, "mode" },
601  { "mirror", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FM_MIRROR}, 0, 0, FLAGS, "mode" },
602  { "fixed", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FM_FIXED}, 0, 0, FLAGS, "mode" },
603  { "reflect",NULL, 0, AV_OPT_TYPE_CONST, {.i64=FM_REFLECT},0, 0, FLAGS, "mode" },
604  { "wrap", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FM_WRAP}, 0, 0, FLAGS, "mode" },
605  { "fade", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FM_FADE}, 0, 0, FLAGS, "mode" },
606  { "color", "set the color for the fixed/fade mode", OFFSET(rgba_color), AV_OPT_TYPE_COLOR, {.str = "black"}, .flags = FLAGS },
607  { NULL }
608 };
609 
611 
612 static const AVFilterPad fillborders_inputs[] = {
613  {
614  .name = "default",
615  .type = AVMEDIA_TYPE_VIDEO,
616  .config_props = config_input,
617  .filter_frame = filter_frame,
618  .needs_writable = 1,
619  },
620  { NULL }
621 };
622 
624  {
625  .name = "default",
626  .type = AVMEDIA_TYPE_VIDEO,
627  },
628  { NULL }
629 };
630 
632  .name = "fillborders",
633  .description = NULL_IF_CONFIG_SMALL("Fill borders of the input video."),
634  .priv_size = sizeof(FillBordersContext),
635  .priv_class = &fillborders_class,
637  .inputs = fillborders_inputs,
638  .outputs = fillborders_outputs,
641 };
static int lerp16(int fill, int src, int pos, int size, int depth)
AVFILTER_DEFINE_CLASS(fillborders)
#define NULL
Definition: coverity.c:32
#define AV_PIX_FMT_YUVA422P16
Definition: pixfmt.h:442
#define AV_PIX_FMT_YUVA422P9
Definition: pixfmt.h:434
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2573
This structure describes decoded (raw) audio or video data.
Definition: frame.h:314
static const AVOption fillborders_options[]
AVOption.
Definition: opt.h:248
#define AV_PIX_FMT_YUVA420P10
Definition: pixfmt.h:436
#define AV_PIX_FMT_YUV444P14
Definition: pixfmt.h:409
#define AV_PIX_FMT_GBRAP10
Definition: pixfmt.h:419
#define AV_PIX_FMT_YUVA422P10
Definition: pixfmt.h:437
const char * desc
Definition: libsvtav1.c:79
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:71
Main libavfilter public API header.
planar GBR 4:4:4 24bpp
Definition: pixfmt.h:168
#define AV_PIX_FMT_GBRP10
Definition: pixfmt.h:415
#define AV_PIX_FMT_GRAY9
Definition: pixfmt.h:379
#define AV_PIX_FMT_YUV420P12
Definition: pixfmt.h:403
static void fixed_borders16(FillBordersContext *s, AVFrame *frame)
static const AVFilterPad fillborders_inputs[]
static void mirror_borders8(FillBordersContext *s, AVFrame *frame)
uint8_t log2_chroma_w
Amount to shift the luma width right to find the chroma width.
Definition: pixdesc.h:92
static void fade_borders16(FillBordersContext *s, AVFrame *frame)
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:287
#define AV_PIX_FMT_GRAY10
Definition: pixfmt.h:380
#define AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
Some filters support a generic "enable" expression option that can be used to enable or disable a fil...
Definition: avfilter.h:126
const char * name
Pad name.
Definition: internal.h:60
#define AV_PIX_FMT_GRAY12
Definition: pixfmt.h:381
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:349
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1091
static void mirror_borders16(FillBordersContext *s, AVFrame *frame)
planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
Definition: pixfmt.h:101
AVComponentDescriptor comp[4]
Parameters that describe how pixels are packed.
Definition: pixdesc.h:117
uint8_t
static void fade_borders8(FillBordersContext *s, AVFrame *frame)
AVOptions.
#define FLAGS
#define AV_PIX_FMT_YUVA420P9
Definition: pixfmt.h:433
#define AV_PIX_FMT_GBRP9
Definition: pixfmt.h:414
static void smear_borders16(FillBordersContext *s, AVFrame *frame)
static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags)
static void fixed_borders8(FillBordersContext *s, AVFrame *frame)
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
#define AV_PIX_FMT_YUV444P16
Definition: pixfmt.h:412
ptrdiff_t size
Definition: opengl_enc.c:100
#define AV_PIX_FMT_YUV422P12
Definition: pixfmt.h:404
#define AV_PIX_FMT_YUVA420P16
Definition: pixfmt.h:441
#define av_log(a,...)
A filter pad used for either input or output.
Definition: internal.h:54
#define OFFSET(x)
#define src
Definition: vp8dsp.c:255
planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples)
Definition: pixfmt.h:176
uint8_t rgba_color[4]
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
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:588
Various defines for YUV<->RGB conversion.
uint8_t log2_chroma_h
Amount to shift the luma height right to find the chroma height.
Definition: pixdesc.h:101
#define AV_PIX_FMT_FLAG_RGB
The pixel format contains RGB-like data (as opposed to YUV/grayscale).
Definition: pixdesc.h:148
static void reflect_borders8(FillBordersContext *s, AVFrame *frame)
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:115
int ff_filter_process_command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
Generic processing of user supplied commands that are set in the same way as the filter options...
Definition: avfilter.c:885
void * priv
private data for use by the filter
Definition: avfilter.h:356
unsigned int pos
Definition: spdifenc.c:410
#define RGB_TO_U_CCIR(r1, g1, b1, shift)
Definition: colorspace.h:102
#define AV_PIX_FMT_YUVA444P16
Definition: pixfmt.h:443
#define AV_PIX_FMT_GBRAP12
Definition: pixfmt.h:420
simple assert() macros that are a bit more flexible than ISO C assert().
#define AV_PIX_FMT_YUV444P10
Definition: pixfmt.h:402
#define AV_PIX_FMT_GBRAP16
Definition: pixfmt.h:421
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:70
uint64_t flags
Combination of AV_PIX_FMT_FLAG_...
Definition: pixdesc.h:106
#define AV_PIX_FMT_YUV422P9
Definition: pixfmt.h:397
uint8_t nb_components
The number of components each pixel has, (1-4)
Definition: pixdesc.h:83
#define AV_PIX_FMT_GBRP16
Definition: pixfmt.h:418
#define AV_PIX_FMT_GRAY16
Definition: pixfmt.h:383
planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting col...
Definition: pixfmt.h:78
static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
static void smear_borders8(FillBordersContext *s, AVFrame *frame)
#define AV_PIX_FMT_YUVA444P12
Definition: pixfmt.h:440
typedef void(APIENTRY *FF_PFNGLACTIVETEXTUREPROC)(GLenum texture)
static int config_input(AVFilterLink *inlink)
AVFormatContext * ctx
Definition: movenc.c:48
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 the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
#define s(width, name)
Definition: cbs_vp9.c:257
#define AV_PIX_FMT_YUVA444P10
Definition: pixfmt.h:438
#define AV_PIX_FMT_YUV444P9
Definition: pixfmt.h:398
#define AV_PIX_FMT_GBRP14
Definition: pixfmt.h:417
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
int ff_fill_rgba_map(uint8_t *rgba_map, enum AVPixelFormat pix_fmt)
Definition: drawutils.c:35
#define AV_PIX_FMT_YUV420P16
Definition: pixfmt.h:410
#define AV_PIX_FMT_YUV420P14
Definition: pixfmt.h:407
misc drawing utilities
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:345
uint8_t yuv_color[4]
planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
Definition: pixfmt.h:177
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:81
#define AV_PIX_FMT_GRAY14
Definition: pixfmt.h:382
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 AV_PIX_FMT_YUV420P10
Definition: pixfmt.h:399
planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
Definition: pixfmt.h:72
static int query_formats(AVFilterContext *ctx)
Describe the class of an AVClass context structure.
Definition: log.h:67
Filter definition.
Definition: avfilter.h:145
static const AVFilterPad fillborders_outputs[]
const char * name
Filter name.
Definition: avfilter.h:149
#define AV_PIX_FMT_YUV440P12
Definition: pixfmt.h:405
#define AV_PIX_FMT_YUV420P9
Definition: pixfmt.h:396
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:353
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:303
#define AV_PIX_FMT_YUV422P14
Definition: pixfmt.h:408
#define AV_PIX_FMT_GBRP12
Definition: pixfmt.h:416
#define flags(name, subs,...)
Definition: cbs_av1.c:561
#define AV_PIX_FMT_YUV422P10
Definition: pixfmt.h:400
#define AV_PIX_FMT_YUV444P12
Definition: pixfmt.h:406
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:328
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
static void reflect_borders16(FillBordersContext *s, AVFrame *frame)
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:66
Y , 8bpp.
Definition: pixfmt.h:74
common internal and external API header
planar GBRA 4:4:4:4 32bpp
Definition: pixfmt.h:215
#define AV_PIX_FMT_YUVA444P9
Definition: pixfmt.h:435
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
static void wrap_borders16(FillBordersContext *s, AVFrame *frame)
FillMode
AVFilter ff_vf_fillborders
A list of supported formats for one end of a filter link.
Definition: formats.h:65
#define RGB_TO_V_CCIR(r1, g1, b1, shift)
Definition: colorspace.h:106
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:341
static void wrap_borders8(FillBordersContext *s, AVFrame *frame)
planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
Definition: pixfmt.h:99
void(* fillborders)(struct FillBordersContext *s, AVFrame *frame)
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
static int lerp8(int fill, int src, int pos, int size)
int depth
Number of bits in the component.
Definition: pixdesc.h:58
#define RGB_TO_Y_CCIR(r, g, b)
Definition: colorspace.h:98
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
mode
Use these values in ebur128_init (or&#39;ed).
Definition: ebur128.h:83
#define AV_PIX_FMT_YUV422P16
Definition: pixfmt.h:411
for(j=16;j >0;--j)
int i
Definition: input.c:407
#define AV_PIX_FMT_YUVA422P12
Definition: pixfmt.h:439
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:58
static av_always_inline av_const unsigned av_clip_uintp2_c(int a, int p)
Clip a signed integer to an unsigned power of two range.
Definition: common.h:229