FFmpeg
Loading...
Searching...
No Matches
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"
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 "filters.h"
29#include "video.h"
30
31enum { Y, U, V, A };
32enum { R, G, B };
33
35
36typedef struct Borders {
38} Borders;
39
40typedef struct FillBordersContext {
41 const AVClass *class;
43 int mode;
44
46 int depth;
48 int planewidth[4];
50 uint8_t fill[4];
51 uint8_t yuv_color[4];
52 uint8_t rgba_color[4];
53
56
78
80{
81 int p, y;
82
83 for (p = 0; p < s->nb_planes; p++) {
84 uint8_t *ptr = frame->data[p];
85 ptrdiff_t linesize = frame->linesize[p];
86
87 for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) {
88 memset(ptr + y * linesize,
89 *(ptr + y * linesize + s->borders[p].left),
90 s->borders[p].left);
91 memset(ptr + y * linesize + s->planewidth[p] - s->borders[p].right,
92 *(ptr + y * linesize + s->planewidth[p] - s->borders[p].right - 1),
93 s->borders[p].right);
94 }
95
96 for (y = 0; y < s->borders[p].top; y++) {
97 memcpy(ptr + y * linesize,
98 ptr + s->borders[p].top * linesize, s->planewidth[p]);
99 }
100
101 for (y = s->planeheight[p] - s->borders[p].bottom; y < s->planeheight[p]; y++) {
102 memcpy(ptr + y * linesize,
103 ptr + (s->planeheight[p] - s->borders[p].bottom - 1) * linesize,
104 s->planewidth[p]);
105 }
106 }
107}
108
110{
111 int p, y, x;
112
113 for (p = 0; p < s->nb_planes; p++) {
114 uint16_t *ptr = (uint16_t *)frame->data[p];
115 ptrdiff_t linesize = frame->linesize[p] / 2;
116
117 for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) {
118 for (x = 0; x < s->borders[p].left; x++) {
119 ptr[y * linesize + x] = *(ptr + y * linesize + s->borders[p].left);
120 }
121
122 for (x = 0; x < s->borders[p].right; x++) {
123 ptr[y * linesize + s->planewidth[p] - s->borders[p].right + x] =
124 *(ptr + y * linesize + s->planewidth[p] - s->borders[p].right - 1);
125 }
126 }
127
128 for (y = 0; y < s->borders[p].top; y++) {
129 memcpy(ptr + y * linesize,
130 ptr + s->borders[p].top * linesize, s->planewidth[p] * 2);
131 }
132
133 for (y = s->planeheight[p] - s->borders[p].bottom; y < s->planeheight[p]; y++) {
134 memcpy(ptr + y * linesize,
135 ptr + (s->planeheight[p] - s->borders[p].bottom - 1) * linesize,
136 s->planewidth[p] * 2);
137 }
138 }
139}
140
142{
143 int p, y, x;
144
145 for (p = 0; p < s->nb_planes; p++) {
146 uint8_t *ptr = frame->data[p];
147 ptrdiff_t linesize = frame->linesize[p];
148
149 for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) {
150 for (x = 0; x < s->borders[p].left; x++) {
151 ptr[y * linesize + x] = ptr[y * linesize + s->borders[p].left * 2 - 1 - x];
152 }
153
154 for (x = 0; x < s->borders[p].right; x++) {
155 ptr[y * linesize + s->planewidth[p] - s->borders[p].right + x] =
156 ptr[y * linesize + s->planewidth[p] - s->borders[p].right - 1 - x];
157 }
158 }
159
160 for (y = 0; y < s->borders[p].top; y++) {
161 memcpy(ptr + y * linesize,
162 ptr + (s->borders[p].top * 2 - 1 - y) * linesize,
163 s->planewidth[p]);
164 }
165
166 for (y = 0; y < s->borders[p].bottom; y++) {
167 memcpy(ptr + (s->planeheight[p] - s->borders[p].bottom + y) * linesize,
168 ptr + (s->planeheight[p] - s->borders[p].bottom - 1 - y) * linesize,
169 s->planewidth[p]);
170 }
171 }
172}
173
175{
176 int p, y, x;
177
178 for (p = 0; p < s->nb_planes; p++) {
179 uint16_t *ptr = (uint16_t *)frame->data[p];
180 ptrdiff_t linesize = frame->linesize[p] / 2;
181
182 for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) {
183 for (x = 0; x < s->borders[p].left; x++) {
184 ptr[y * linesize + x] = ptr[y * linesize + s->borders[p].left * 2 - 1 - x];
185 }
186
187 for (x = 0; x < s->borders[p].right; x++) {
188 ptr[y * linesize + s->planewidth[p] - s->borders[p].right + x] =
189 ptr[y * linesize + s->planewidth[p] - s->borders[p].right - 1 - x];
190 }
191 }
192
193 for (y = 0; y < s->borders[p].top; y++) {
194 memcpy(ptr + y * linesize,
195 ptr + (s->borders[p].top * 2 - 1 - y) * linesize,
196 s->planewidth[p] * 2);
197 }
198
199 for (y = 0; y < s->borders[p].bottom; y++) {
200 memcpy(ptr + (s->planeheight[p] - s->borders[p].bottom + y) * linesize,
201 ptr + (s->planeheight[p] - s->borders[p].bottom - 1 - y) * linesize,
202 s->planewidth[p] * 2);
203 }
204 }
205}
206
208{
209 int p, y;
210
211 for (p = 0; p < s->nb_planes; p++) {
212 uint8_t *ptr = frame->data[p];
213 uint8_t fill = s->fill[p];
214 ptrdiff_t linesize = frame->linesize[p];
215
216 for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) {
217 memset(ptr + y * linesize, fill, s->borders[p].left);
218 memset(ptr + y * linesize + s->planewidth[p] - s->borders[p].right, fill,
219 s->borders[p].right);
220 }
221
222 for (y = 0; y < s->borders[p].top; y++) {
223 memset(ptr + y * linesize, fill, s->planewidth[p]);
224 }
225
226 for (y = s->planeheight[p] - s->borders[p].bottom; y < s->planeheight[p]; y++) {
227 memset(ptr + y * linesize, fill, s->planewidth[p]);
228 }
229 }
230}
231
233{
234 int p, y, x;
235
236 for (p = 0; p < s->nb_planes; p++) {
237 uint16_t *ptr = (uint16_t *)frame->data[p];
238 uint16_t fill = s->fill[p] << (s->depth - 8);
239 ptrdiff_t linesize = frame->linesize[p] / 2;
240
241 for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) {
242 for (x = 0; x < s->borders[p].left; x++) {
243 ptr[y * linesize + x] = fill;
244 }
245
246 for (x = 0; x < s->borders[p].right; x++) {
247 ptr[y * linesize + s->planewidth[p] - s->borders[p].right + x] = fill;
248 }
249 }
250
251 for (y = 0; y < s->borders[p].top; y++) {
252 for (x = 0; x < s->planewidth[p]; x++) {
253 ptr[y * linesize + x] = fill;
254 }
255 }
256
257 for (y = s->planeheight[p] - s->borders[p].bottom; y < s->planeheight[p]; y++) {
258 for (x = 0; x < s->planewidth[p]; x++) {
259 ptr[y * linesize + x] = fill;
260 }
261 }
262 }
263}
264
266{
267 int p, y, x;
268
269 for (p = 0; p < s->nb_planes; p++) {
270 uint8_t *ptr = frame->data[p];
271 ptrdiff_t linesize = frame->linesize[p];
272
273 for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) {
274 for (x = 0; x < s->borders[p].left; x++) {
275 ptr[y * linesize + x] = ptr[y * linesize + s->borders[p].left * 2 - x];
276 }
277
278 for (x = 0; x < s->borders[p].right; x++) {
279 ptr[y * linesize + s->planewidth[p] - s->borders[p].right + x] =
280 ptr[y * linesize + s->planewidth[p] - s->borders[p].right - 2 - x];
281 }
282 }
283
284 for (y = 0; y < s->borders[p].top; y++) {
285 memcpy(ptr + y * linesize,
286 ptr + (s->borders[p].top * 2 - y) * linesize,
287 s->planewidth[p]);
288 }
289
290 for (y = 0; y < s->borders[p].bottom; y++) {
291 memcpy(ptr + (s->planeheight[p] - s->borders[p].bottom + y) * linesize,
292 ptr + (s->planeheight[p] - s->borders[p].bottom - 2 - y) * linesize,
293 s->planewidth[p]);
294 }
295 }
296}
297
299{
300 int p, y, x;
301
302 for (p = 0; p < s->nb_planes; p++) {
303 uint16_t *ptr = (uint16_t *)frame->data[p];
304 ptrdiff_t linesize = frame->linesize[p] / 2;
305
306 for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) {
307 for (x = 0; x < s->borders[p].left; x++) {
308 ptr[y * linesize + x] = ptr[y * linesize + s->borders[p].left * 2 - x];
309 }
310
311 for (x = 0; x < s->borders[p].right; x++) {
312 ptr[y * linesize + s->planewidth[p] - s->borders[p].right + x] =
313 ptr[y * linesize + s->planewidth[p] - s->borders[p].right - 2 - x];
314 }
315 }
316
317 for (y = 0; y < s->borders[p].top; y++) {
318 memcpy(ptr + y * linesize,
319 ptr + (s->borders[p].top * 2 - y) * linesize,
320 s->planewidth[p] * 2);
321 }
322
323 for (y = 0; y < s->borders[p].bottom; y++) {
324 memcpy(ptr + (s->planeheight[p] - s->borders[p].bottom + y) * linesize,
325 ptr + (s->planeheight[p] - s->borders[p].bottom - 2 - y) * linesize,
326 s->planewidth[p] * 2);
327 }
328 }
329}
330
332{
333 int p, y, x;
334
335 for (p = 0; p < s->nb_planes; p++) {
336 uint8_t *ptr = frame->data[p];
337 ptrdiff_t linesize = frame->linesize[p];
338
339 for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) {
340 for (x = 0; x < s->borders[p].left; x++) {
341 ptr[y * linesize + x] = ptr[y * linesize + s->planewidth[p] - s->borders[p].right - s->borders[p].left + x];
342 }
343
344 for (x = 0; x < s->borders[p].right; x++) {
345 ptr[y * linesize + s->planewidth[p] - s->borders[p].right + x] =
346 ptr[y * linesize + s->borders[p].left + x];
347 }
348 }
349
350 for (y = 0; y < s->borders[p].top; y++) {
351 memcpy(ptr + y * linesize,
352 ptr + (s->planeheight[p] - s->borders[p].bottom - s->borders[p].top + y) * linesize,
353 s->planewidth[p]);
354 }
355
356 for (y = 0; y < s->borders[p].bottom; y++) {
357 memcpy(ptr + (s->planeheight[p] - s->borders[p].bottom + y) * linesize,
358 ptr + (s->borders[p].top + y) * linesize,
359 s->planewidth[p]);
360 }
361 }
362}
363
365{
366 int p, y, x;
367
368 for (p = 0; p < s->nb_planes; p++) {
369 uint16_t *ptr = (uint16_t *)frame->data[p];
370 ptrdiff_t linesize = frame->linesize[p] / 2;
371
372 for (y = s->borders[p].top; y < s->planeheight[p] - s->borders[p].bottom; y++) {
373 for (x = 0; x < s->borders[p].left; x++) {
374 ptr[y * linesize + x] = ptr[y * linesize + s->planewidth[p] - s->borders[p].right - s->borders[p].left + x];
375 }
376
377 for (x = 0; x < s->borders[p].right; x++) {
378 ptr[y * linesize + s->planewidth[p] - s->borders[p].right + x] =
379 ptr[y * linesize + s->borders[p].left + x];
380 }
381 }
382
383 for (y = 0; y < s->borders[p].top; y++) {
384 memcpy(ptr + y * linesize,
385 ptr + (s->planeheight[p] - s->borders[p].bottom - s->borders[p].top + y) * linesize,
386 s->planewidth[p] * 2);
387 }
388
389 for (y = 0; y < s->borders[p].bottom; y++) {
390 memcpy(ptr + (s->planeheight[p] - s->borders[p].bottom + y) * linesize,
391 ptr + (s->borders[p].top + y) * linesize,
392 s->planewidth[p] * 2);
393 }
394 }
395}
396
397static int lerp8(int fill, int src, int pos, int size)
398{
399 return av_clip_uint8(((fill * 256 * pos / size) + (src * 256 * (size - pos) / size)) >> 8);
400}
401
402static int lerp16(int fill, int src, int pos, int size, int depth)
403{
404 return av_clip_uintp2_c(((fill * (1LL << depth) * pos / size) + (src * (1LL << depth) * (size - pos) / size)) >> depth, depth);
405}
406
408{
409 int p, y, x;
410
411 for (p = 0; p < s->nb_planes; p++) {
412 uint8_t *ptr = frame->data[p];
413 const uint8_t fill = s->fill[p];
414 const ptrdiff_t linesize = frame->linesize[p];
415 const int start_left = s->borders[p].left;
416 const int start_right = s->planewidth[p] - s->borders[p].right;
417 const int start_top = s->borders[p].top;
418 const int start_bottom = s->planeheight[p] - s->borders[p].bottom;
419
420 for (y = 0; y < start_top; y++) {
421 for (x = 0; x < s->planewidth[p]; x++) {
422 int src = ptr[y * linesize + x];
423 ptr[y * linesize + x] = lerp8(fill, src, start_top - y, start_top);
424 }
425 }
426
427 for (y = start_bottom; y < s->planeheight[p]; y++) {
428 for (x = 0; x < s->planewidth[p]; x++) {
429 int src = ptr[y * linesize + x];
430 ptr[y * linesize + x] = lerp8(fill, src, y - start_bottom, s->borders[p].bottom);
431 }
432 }
433
434 for (y = 0; y < s->planeheight[p]; y++) {
435 for (x = 0; x < start_left; x++) {
436 int src = ptr[y * linesize + x];
437 ptr[y * linesize + x] = lerp8(fill, src, start_left - x, start_left);
438 }
439
440 for (x = 0; x < s->borders[p].right; x++) {
441 int src = ptr[y * linesize + start_right + x];
442 ptr[y * linesize + start_right + x] = lerp8(fill, src, x, s->borders[p].right);
443 }
444 }
445 }
446}
447
449{
450 const int depth = s->depth;
451 int p, y, x;
452
453 for (p = 0; p < s->nb_planes; p++) {
454 uint16_t *ptr = (uint16_t *)frame->data[p];
455 const uint16_t fill = s->fill[p] << (depth - 8);
456 const ptrdiff_t linesize = frame->linesize[p] / 2;
457 const int start_left = s->borders[p].left;
458 const int start_right = s->planewidth[p] - s->borders[p].right;
459 const int start_top = s->borders[p].top;
460 const int start_bottom = s->planeheight[p] - s->borders[p].bottom;
461
462 for (y = 0; y < start_top; y++) {
463 for (x = 0; x < s->planewidth[p]; x++) {
464 int src = ptr[y * linesize + x];
465 ptr[y * linesize + x] = lerp16(fill, src, start_top - y, start_top, depth);
466 }
467 }
468
469 for (y = start_bottom; y < s->planeheight[p]; y++) {
470 for (x = 0; x < s->planewidth[p]; x++) {
471 int src = ptr[y * linesize + x];
472 ptr[y * linesize + x] = lerp16(fill, src, y - start_bottom, s->borders[p].bottom, depth);
473 }
474 }
475
476 for (y = 0; y < s->planeheight[p]; y++) {
477 for (x = 0; x < start_left; x++) {
478 int src = ptr[y * linesize + x];
479 ptr[y * linesize + x] = lerp16(fill, src, start_left - x, start_left, depth);
480 }
481
482 for (x = 0; x < s->borders[p].right; x++) {
483 int src = ptr[y * linesize + start_right + x];
484 ptr[y * linesize + start_right + x] = lerp16(fill, src, x, s->borders[p].right, depth);
485 }
486 }
487 }
488}
489
491{
492 for (int p = 0; p < s->nb_planes; p++) {
493 uint8_t *ptr = (uint8_t *)frame->data[p];
494 const ptrdiff_t linesize = frame->linesize[p];
495 const int left = s->borders[p].left;
496 const int right = s->borders[p].right;
497 const int top = s->borders[p].top;
498 const int bottom = s->borders[p].bottom;
499 const int width = s->planewidth[p];
500 const int height = s->planeheight[p];
501
502 for (int y = top; y < height - bottom; y++) {
503 memset(ptr + linesize * y, ptr[linesize * y + left], left);
504 memset(ptr + linesize * y + width - right, (ptr + linesize * y + width - right)[-1], right);
505 }
506
507 for (int y = top - 1; y >= 0; y--) {
508 ptr[linesize * y] = ptr[linesize * (y + 1)];
509 memcpy(ptr + linesize * y + width - 8, ptr + linesize * (y + 1) + width - 8, 8);
510
511 for (int x = 1; x < width - 8; x++) {
512 int prev = ptr[linesize * (y + 1) + x - 1];
513 int cur = ptr[linesize * (y + 1) + x];
514 int next = ptr[linesize * (y + 1) + x + 1];
515
516 ptr[linesize * y + x] = (3 * prev + 2 * cur + 3 * next + 4) >> 3;
517 }
518 }
519
520 for (int y = height - bottom; y < height; y++) {
521 ptr[linesize * y] = ptr[linesize * (y - 1)];
522 memcpy(ptr + linesize * y + width - 8, ptr + linesize * (y - 1) + width - 8, 8);
523
524 for (int x = 1; x < width - 8; x++) {
525 int prev = ptr[linesize * (y - 1) + x - 1];
526 int cur = ptr[linesize * (y - 1) + x];
527 int next = ptr[linesize * (y - 1) + x + 1];
528
529 ptr[linesize * y + x] = (3 * prev + 2 * cur + 3 * next + 4) >> 3;
530 }
531 }
532 }
533}
534
536{
537 for (int p = 0; p < s->nb_planes; p++) {
538 uint16_t *ptr = (uint16_t *)frame->data[p];
539 const ptrdiff_t linesize = frame->linesize[p] / 2;
540 const int left = s->borders[p].left;
541 const int right = s->borders[p].right;
542 const int top = s->borders[p].top;
543 const int bottom = s->borders[p].bottom;
544 const int width = s->planewidth[p];
545 const int height = s->planeheight[p];
546
547 for (int y = top; y < height - bottom; y++) {
548 for (int x = 0; x < left; x++)
549 ptr[linesize * y + x] = ptr[linesize * y + left];
550
551 for (int x = 0; x < right; x++)
552 ptr[linesize * y + width - right + x] = ptr[linesize * y + width - right - 1];
553 }
554
555 for (int y = top - 1; y >= 0; y--) {
556 ptr[linesize * y] = ptr[linesize * (y + 1)];
557 memcpy(ptr + linesize * y + width - 8, ptr + linesize * (y + 1) + width - 8, 16);
558
559 for (int x = 1; x < width - 8; x++) {
560 int prev = ptr[linesize * (y + 1) + x - 1];
561 int cur = ptr[linesize * (y + 1) + x];
562 int next = ptr[linesize * (y + 1) + x + 1];
563
564 ptr[linesize * y + x] = (3 * prev + 2 * cur + 3 * next + 4) >> 3;
565 }
566 }
567
568 for (int y = height - bottom; y < height; y++) {
569 ptr[linesize * y] = ptr[linesize * (y - 1)];
570 memcpy(ptr + linesize * y + width - 8, ptr + linesize * (y - 1) + width - 8, 16);
571
572 for (int x = 1; x < width - 8; x++) {
573 int prev = ptr[linesize * (y - 1) + x - 1];
574 int cur = ptr[linesize * (y - 1) + x];
575 int next = ptr[linesize * (y - 1) + x + 1];
576
577 ptr[linesize * y + x] = (3 * prev + 2 * cur + 3 * next + 4) >> 3;
578 }
579 }
580 }
581}
582
584{
585 FillBordersContext *s = inlink->dst->priv;
586
587 s->fillborders(s, frame);
588
589 return ff_filter_frame(inlink->dst->outputs[0], frame);
590}
591
592static int config_input(AVFilterLink *inlink)
593{
594 AVFilterContext *ctx = inlink->dst;
595 FillBordersContext *s = ctx->priv;
597
598 s->nb_planes = desc->nb_components;
599 s->depth = desc->comp[0].depth;
600
601 s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
602 s->planeheight[0] = s->planeheight[3] = inlink->h;
603 s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w);
604 s->planewidth[0] = s->planewidth[3] = inlink->w;
605
606 if (inlink->w < s->left + s->right ||
607 inlink->w <= s->left ||
608 inlink->w <= s->right ||
609 inlink->h < s->top + s->bottom ||
610 inlink->h <= s->top ||
611 inlink->h <= s->bottom ||
612 inlink->w < s->left * 2 ||
613 inlink->w < s->right * 2 ||
614 inlink->h < s->top * 2 ||
615 inlink->h < s->bottom * 2) {
616 av_log(ctx, AV_LOG_ERROR, "Borders are bigger than input frame size.\n");
617 return AVERROR(EINVAL);
618 }
619
620 s->borders[0].left = s->borders[3].left = s->left;
621 s->borders[0].right = s->borders[3].right = s->right;
622 s->borders[0].top = s->borders[3].top = s->top;
623 s->borders[0].bottom = s->borders[3].bottom = s->bottom;
624
625 s->borders[1].left = s->left >> desc->log2_chroma_w;
626 s->borders[1].right = s->right >> desc->log2_chroma_w;
627 s->borders[1].top = s->top >> desc->log2_chroma_h;
628 s->borders[1].bottom = s->bottom >> desc->log2_chroma_h;
629
630 s->borders[2].left = s->left >> desc->log2_chroma_w;
631 s->borders[2].right = s->right >> desc->log2_chroma_w;
632 s->borders[2].top = s->top >> desc->log2_chroma_h;
633 s->borders[2].bottom = s->bottom >> desc->log2_chroma_h;
634
635 switch (s->mode) {
636 case FM_SMEAR: s->fillborders = s->depth <= 8 ? smear_borders8 : smear_borders16; break;
637 case FM_MIRROR: s->fillborders = s->depth <= 8 ? mirror_borders8 : mirror_borders16; break;
638 case FM_FIXED: s->fillborders = s->depth <= 8 ? fixed_borders8 : fixed_borders16; break;
639 case FM_REFLECT:s->fillborders = s->depth <= 8 ? reflect_borders8: reflect_borders16;break;
640 case FM_WRAP: s->fillborders = s->depth <= 8 ? wrap_borders8 : wrap_borders16; break;
641 case FM_FADE: s->fillborders = s->depth <= 8 ? fade_borders8 : fade_borders16; break;
642 case FM_MARGINS:s->fillborders = s->depth <= 8 ? margins_borders8: margins_borders16;break;
643 default: av_assert0(0);
644 }
645
646 s->yuv_color[Y] = RGB_TO_Y_CCIR(s->rgba_color[R], s->rgba_color[G], s->rgba_color[B]);
647 s->yuv_color[U] = RGB_TO_U_CCIR(s->rgba_color[R], s->rgba_color[G], s->rgba_color[B], 0);
648 s->yuv_color[V] = RGB_TO_V_CCIR(s->rgba_color[R], s->rgba_color[G], s->rgba_color[B], 0);
649 s->yuv_color[A] = s->rgba_color[A];
650
651 if (desc->flags & AV_PIX_FMT_FLAG_RGB) {
652 uint8_t rgba_map[4];
653 int i;
654
655 ff_fill_rgba_map(rgba_map, inlink->format);
656 for (i = 0; i < 4; i++)
657 s->fill[rgba_map[i]] = s->rgba_color[i];
658 } else {
659 memcpy(s->fill, s->yuv_color, sizeof(s->yuv_color));
660 }
661
662 return 0;
663}
664
665static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
666 char *res, int res_len, int flags)
667{
668 int ret;
669
670 ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags);
671 if (ret < 0)
672 return ret;
673
674 return config_input(ctx->inputs[0]);
675}
676
677#define OFFSET(x) offsetof(FillBordersContext, x)
678#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
679
681 { "left", "set the left fill border", OFFSET(left), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS },
682 { "right", "set the right fill border", OFFSET(right), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS },
683 { "top", "set the top fill border", OFFSET(top), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS },
684 { "bottom", "set the bottom fill border", OFFSET(bottom), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS },
685 { "mode", "set the fill borders mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=FM_SMEAR}, 0, FM_NB_MODES-1, FLAGS, .unit = "mode" },
686 { "smear", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FM_SMEAR}, 0, 0, FLAGS, .unit = "mode" },
687 { "mirror", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FM_MIRROR}, 0, 0, FLAGS, .unit = "mode" },
688 { "fixed", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FM_FIXED}, 0, 0, FLAGS, .unit = "mode" },
689 { "reflect",NULL, 0, AV_OPT_TYPE_CONST, {.i64=FM_REFLECT},0, 0, FLAGS, .unit = "mode" },
690 { "wrap", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FM_WRAP}, 0, 0, FLAGS, .unit = "mode" },
691 { "fade", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FM_FADE}, 0, 0, FLAGS, .unit = "mode" },
692 { "margins",NULL, 0, AV_OPT_TYPE_CONST, {.i64=FM_MARGINS},0, 0, FLAGS, .unit = "mode" },
693 { "color", "set the color for the fixed/fade mode", OFFSET(rgba_color), AV_OPT_TYPE_COLOR, {.str = "black"}, .flags = FLAGS },
694 { NULL }
695};
696
698
700 {
701 .name = "default",
702 .type = AVMEDIA_TYPE_VIDEO,
704 .config_props = config_input,
705 .filter_frame = filter_frame,
706 },
707};
708
710 .p.name = "fillborders",
711 .p.description = NULL_IF_CONFIG_SMALL("Fill borders of the input video."),
712 .p.priv_class = &fillborders_class,
714 .priv_size = sizeof(FillBordersContext),
718 .process_command = process_command,
719};
static int config_input(AVFilterLink *inlink)
static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags)
const FFFilter ff_vf_fillborders
static AVFormatContext * ctx
#define U(x)
Definition vpx_arith.h:37
#define A(x)
Definition vpx_arith.h:28
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition avassert.h:42
#define V
Definition avdct.c:32
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition avfilter.c:1068
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:906
Main libavfilter public API header.
static int BS_FUNC left(const BSCTX *bc)
Return the number of the bits left in a buffer.
#define Y
Definition boxblur.h:37
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
#define FLAGS
Definition cmdutils.c:598
common internal and external API header
#define AV_CEIL_RSHIFT(a, b)
Definition common.h:60
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:280
#define av_clip_uint8
Definition common.h:106
#define NULL
Definition coverity.c:32
static AVFrame * frame
static int filter_frame(DBEDecodeContext *s, AVFrame *frame)
Definition dolby_e.c:1067
int ff_fill_rgba_map(uint8_t *rgba_map, enum AVPixelFormat pix_fmt)
Definition drawutils.c:80
misc drawing utilities
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition opt.h:298
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition opt.h:258
@ AV_OPT_TYPE_COLOR
Underlying C type is uint8_t[4].
Definition opt.h:322
#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:196
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
#define B
Definition huffyuv.h:42
#define R
Definition huffyuv.h:44
#define G
Definition huffyuv.h:43
#define FILTER_INPUTS(array)
Definition filters.h:264
#define FILTER_OUTPUTS(array)
Definition filters.h:265
#define AVFILTERPAD_FLAG_NEEDS_WRITABLE
The filter expects writable frames from its input link, duplicating data buffers if needed.
Definition filters.h:59
#define FILTER_PIXFMTS_ARRAY(array)
Definition filters.h:244
#define AVFILTER_DEFINE_CLASS(fname)
Definition filters.h:478
Various defines for YUV<->RGB conversion.
#define RGB_TO_U_CCIR(r1, g1, b1, shift)
Definition colorspace.h:102
#define RGB_TO_Y_CCIR(r, g, b)
Definition colorspace.h:98
#define RGB_TO_V_CCIR(r1, g1, b1, shift)
Definition colorspace.h:106
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition internal.h:88
static enum AVPixelFormat pix_fmts[]
Definition libkvazaar.c:296
const char * desc
Definition libsvtav1.c:83
AVOptions.
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3460
#define AV_PIX_FMT_FLAG_RGB
The pixel format contains RGB-like data (as opposed to YUV/grayscale).
Definition pixdesc.h:136
#define AV_PIX_FMT_GBRAP12
Definition pixfmt.h:569
#define AV_PIX_FMT_YUV420P16
Definition pixfmt.h:556
#define AV_PIX_FMT_YUV444P12
Definition pixfmt.h:552
#define AV_PIX_FMT_YUV444P9
Definition pixfmt.h:544
#define AV_PIX_FMT_YUV420P10
Definition pixfmt.h:545
#define AV_PIX_FMT_YUV440P12
Definition pixfmt.h:551
#define AV_PIX_FMT_GRAY9
Definition pixfmt.h:524
#define AV_PIX_FMT_GBRAP16
Definition pixfmt.h:571
#define AV_PIX_FMT_GBRP9
Definition pixfmt.h:563
#define AV_PIX_FMT_YUV422P9
Definition pixfmt.h:543
#define AV_PIX_FMT_YUVA444P10
Definition pixfmt.h:598
#define AV_PIX_FMT_YUVA420P16
Definition pixfmt.h:601
#define AV_PIX_FMT_YUV420P12
Definition pixfmt.h:549
#define AV_PIX_FMT_YUVA420P10
Definition pixfmt.h:596
#define AV_PIX_FMT_YUVA422P9
Definition pixfmt.h:594
#define AV_PIX_FMT_YUV422P12
Definition pixfmt.h:550
#define AV_PIX_FMT_GBRP10
Definition pixfmt.h:564
#define AV_PIX_FMT_YUV422P10
Definition pixfmt.h:546
#define AV_PIX_FMT_GRAY12
Definition pixfmt.h:526
#define AV_PIX_FMT_GBRP12
Definition pixfmt.h:565
#define AV_PIX_FMT_YUV420P9
Definition pixfmt.h:542
#define AV_PIX_FMT_YUVA420P9
Definition pixfmt.h:593
#define AV_PIX_FMT_YUVA422P10
Definition pixfmt.h:597
#define AV_PIX_FMT_YUV420P14
Definition pixfmt.h:553
AVPixelFormat
Pixel format.
Definition pixfmt.h:71
@ AV_PIX_FMT_NONE
Definition pixfmt.h:72
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition pixfmt.h:73
@ AV_PIX_FMT_YUV440P
planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
Definition pixfmt.h:106
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition pixfmt.h:77
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition pixfmt.h:81
@ AV_PIX_FMT_YUVA420P
planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
Definition pixfmt.h:108
@ 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:107
@ AV_PIX_FMT_YUV410P
planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
Definition pixfmt.h:79
@ AV_PIX_FMT_YUV411P
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
Definition pixfmt.h:80
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition pixfmt.h:78
@ AV_PIX_FMT_YUVA444P
planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
Definition pixfmt.h:174
@ 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:283
@ AV_PIX_FMT_GBRAP
planar GBRA 4:4:4:4 32bpp
Definition pixfmt.h:212
@ 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:86
@ AV_PIX_FMT_YUVA422P
planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples)
Definition pixfmt.h:173
@ AV_PIX_FMT_GBRP
planar GBR 4:4:4 24bpp
Definition pixfmt.h:165
@ 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:87
@ 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:85
#define AV_PIX_FMT_YUVA422P12
Definition pixfmt.h:599
#define AV_PIX_FMT_YUV422P14
Definition pixfmt.h:554
#define AV_PIX_FMT_GRAY10
Definition pixfmt.h:525
#define AV_PIX_FMT_GRAY14
Definition pixfmt.h:527
#define AV_PIX_FMT_YUV422P16
Definition pixfmt.h:557
#define AV_PIX_FMT_GRAY16
Definition pixfmt.h:528
#define AV_PIX_FMT_GBRAP10
Definition pixfmt.h:568
#define AV_PIX_FMT_YUVA444P16
Definition pixfmt.h:603
#define AV_PIX_FMT_YUVA422P16
Definition pixfmt.h:602
#define AV_PIX_FMT_GBRP16
Definition pixfmt.h:567
#define AV_PIX_FMT_YUV444P14
Definition pixfmt.h:555
#define AV_PIX_FMT_YUVA444P9
Definition pixfmt.h:595
#define AV_PIX_FMT_GBRP14
Definition pixfmt.h:566
#define AV_PIX_FMT_YUVA444P12
Definition pixfmt.h:600
#define AV_PIX_FMT_YUV444P16
Definition pixfmt.h:558
#define AV_PIX_FMT_YUV444P10
Definition pixfmt.h:548
unsigned int pos
Definition spdifenc.c:431
Describe the class of an AVClass context structure.
Definition log.h:76
An instance of a filter.
Definition avfilter.h:273
void * priv
private data for use by the filter
Definition avfilter.h:288
AVFilterLink ** outputs
array of pointers to output links
Definition avfilter.h:285
A filter pad used for either input or output.
Definition filters.h:40
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
AVOption.
Definition opt.h:428
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition pixdesc.h:69
void(* fillborders)(struct FillBordersContext *s, AVFrame *frame)
Definition swscale.c:71
#define av_log(a,...)
#define src
Definition vp8dsp.c:248
#define height
Definition dsp.h:89
#define width
Definition dsp.h:89
int size
static void mirror_borders8(FillBordersContext *s, AVFrame *frame)
static void reflect_borders16(FillBordersContext *s, AVFrame *frame)
static void mirror_borders16(FillBordersContext *s, AVFrame *frame)
static void smear_borders8(FillBordersContext *s, AVFrame *frame)
static void fixed_borders16(FillBordersContext *s, AVFrame *frame)
static void fixed_borders8(FillBordersContext *s, AVFrame *frame)
static const AVOption fillborders_options[]
static void margins_borders16(FillBordersContext *s, AVFrame *frame)
static const AVFilterPad fillborders_inputs[]
static void fade_borders16(FillBordersContext *s, AVFrame *frame)
static int config_input(AVFilterLink *inlink)
static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
FillMode
@ FM_NB_MODES
@ FM_MIRROR
@ FM_MARGINS
@ FM_SMEAR
@ FM_WRAP
@ FM_FADE
@ FM_FIXED
@ FM_REFLECT
static int lerp8(int fill, int src, int pos, int size)
static void wrap_borders8(FillBordersContext *s, AVFrame *frame)
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 margins_borders8(FillBordersContext *s, AVFrame *frame)
#define OFFSET(x)
static void reflect_borders8(FillBordersContext *s, AVFrame *frame)
static void wrap_borders16(FillBordersContext *s, AVFrame *frame)
static int lerp16(int fill, int src, int pos, int size, int depth)
static void fade_borders8(FillBordersContext *s, AVFrame *frame)
const AVFilterPad ff_video_default_filterpad[1]
An AVFilterPad array whose only entry has name "default" and is of type AVMEDIA_TYPE_VIDEO.
Definition video.c:37