1 /*
2 * Copyright (c) 2010 Stefano Sabatini
3 * Copyright (c) 2010 Baptiste Coudurier
4 * Copyright (c) 2007 Bobby Bingham
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 /**
24 * @file
25 * overlay one video on top of another
26 */
27
42
44 "main_w", "W", ///< width of the main video
45 "main_h", "H", ///< height of the main video
46 "overlay_w", "w", ///< width of the overlay video
47 "overlay_h", "h", ///< height of the overlay video
48 "hsub",
49 "vsub",
50 "x",
51 "y",
52 "n", ///< number of frame
53 "pos", ///< position in the file
54 "t", ///< timestamp expressed in seconds
56 };
57
71 };
72
77 };
78
80 "repeat", "endall", "pass"
81 };
82
85
90
94
97 int x,
y;
///< position of overlayed picture
98
108
110
111 int main_pix_step[4];
///< steps per pixel for each plane of the main output
114
117
119
122
124 {
126
130 }
131
133 {
135 return INT_MAX;
136 return (int)d & ~((1 << chroma_sub) - 1);
137 }
138
140 {
142
148 }
149
151 {
154
155 if (*pexpr)
156 old = *pexpr;
159 if (ret < 0) {
161 "Error when evaluating the expression '%s' for %s\n",
162 expr, option);
163 *pexpr = old;
165 }
166
168 return 0;
169 }
170
172 char *res,
int res_len,
int flags)
173 {
176
177 if (!strcmp(cmd, "x"))
179 else if (!strcmp(cmd, "y"))
181 else
183
184 if (ret < 0)
186
192 }
194 }
195
197 {
199
200 /* overlay formats contains alpha, for avoiding conversion with alpha information loss */
203 };
204 static const enum AVPixelFormat overlay_pix_fmts_yuv420[] = {
206 };
207
210 };
211 static const enum AVPixelFormat overlay_pix_fmts_yuv422[] = {
213 };
214
217 };
218 static const enum AVPixelFormat overlay_pix_fmts_yuv444[] = {
220 };
221
227 };
232 };
233
236
238 case OVERLAY_FORMAT_YUV420:
241 break;
242 case OVERLAY_FORMAT_YUV422:
245 break;
246 case OVERLAY_FORMAT_YUV444:
249 break;
250 case OVERLAY_FORMAT_RGB:
253 break;
254 default:
256 }
257
261
262 return 0;
263 }
264
269 };
270
272 {
275
277
280
284 return 0;
285 }
286
288 {
293
295
296 /* Finish the configuration by evaluating the expressions
297 now when both inputs are configured. */
309
313
317
323 }
324
326 "main w:%d h:%d fmt:%s overlay w:%d h:%d fmt:%s eof_action:%s\n",
332 return 0;
333 }
334
336 {
340
343
347
348 return 0;
349 }
350
351 // divide by 255 and round to nearest
352 // apply a fast variant: (X+127)/255 = ((X+127)*257+257)>>16 = ((X+128)*257)>>16
353 #define FAST_DIV255(x) ((((x) + 128) * 257) >> 16)
354
355 // calculate the unpremultiplied alpha, applying the general equation:
356 // alpha = alpha_overlay / ( (alpha_main + alpha_overlay) - (alpha_main * alpha_overlay) )
357 // (((x) << 16) - ((x) << 9) + (x)) is a faster version of: 255 * 255 * x
358 // ((((x) + (y)) << 8) - ((x) + (y)) - (y) * (x)) is a faster version of: 255 * (x + y)
359 #define UNPREMULTIPLY_ALPHA(x, y) ((((x) << 16) - ((x) << 9) + (x)) / ((((x) + (y)) << 8) - ((x) + (y)) - (y) * (x)))
360
361 /**
362 * Blend image in src to destination buffer dst at position (x, y).
363 */
367 {
369 int i, imax, j, jmax, k, kmax;
370 const int src_w = src->
width;
371 const int src_h = src->
height;
372 const int dst_w = dst->
width;
373 const int dst_h = dst->
height;
374
375 if (x >= dst_w || x+src_w < 0 ||
376 y >= dst_h || y+src_h < 0)
377 return; /* no intersection */
378
380 uint8_t alpha;
///< the amount of overlay to blend on to main
393
397
398 for (imax =
FFMIN(-y + dst_h, src_h); i < imax; i++) {
400 s = sp + j * sstep;
401 d = dp + (x+j) * dstep;
402
403 for (jmax =
FFMIN(-x + dst_w, src_w); j < jmax; j++) {
404 alpha = s[sa];
405
406 // if the main channel has an alpha channel, alpha has to be calculated
407 // to create an un-premultiplied (straight) alpha value
408 if (main_has_alpha && alpha != 0 && alpha != 255) {
411 }
412
413 switch (alpha) {
414 case 0:
415 break;
416 case 255:
417 d[dr] = s[sr];
418 d[dg] = s[sg];
419 d[db] = s[sb];
420 break;
421 default:
422 // main_value = main_value * (1 - alpha) + overlay_value * alpha
423 // since alpha is in the range 0-255, the result must divided by 255
424 d[dr] =
FAST_DIV255(d[dr] * (255 - alpha) + s[sr] * alpha);
425 d[dg] =
FAST_DIV255(d[dg] * (255 - alpha) + s[sg] * alpha);
426 d[db] =
FAST_DIV255(d[db] * (255 - alpha) + s[sb] * alpha);
427 }
428 if (main_has_alpha) {
429 switch (alpha) {
430 case 0:
431 break;
432 case 255:
433 d[da] = s[sa];
434 break;
435 default:
436 // apply alpha compositing: main_alpha += (1-main_alpha) * overlay_alpha
438 }
439 }
440 d += dstep;
441 s += sstep;
442 }
445 }
446 } else {
448 if (main_has_alpha) {
449 uint8_t alpha;
///< the amount of overlay to blend on to main
451
455
456 for (imax =
FFMIN(-y + dst_h, src_h); i < imax; i++) {
458 s = sa + j;
459 d = da + x+j;
460
461 for (jmax =
FFMIN(-x + dst_w, src_w); j < jmax; j++) {
463 if (alpha != 0 && alpha != 255) {
466 }
467 switch (alpha) {
468 case 0:
469 break;
470 case 255:
472 break;
473 default:
474 // apply alpha compositing: main_alpha += (1-main_alpha) * overlay_alpha
476 }
477 d += 1;
478 s += 1;
479 }
482 }
483 }
484 for (i = 0; i < 3; i++) {
485 int hsub = i ? s->
hsub : 0;
486 int vsub = i ? s->
vsub : 0;
491 int yp = y>>vsub;
492 int xp = x>>hsub;
494
499
500 for (jmax =
FFMIN(-yp + dst_hp, src_hp); j < jmax; j++) {
502 d = dp + xp+k;
503 s = sp + k;
504 a = ap + (k<<hsub);
505
506 for (kmax =
FFMIN(-xp + dst_wp, src_wp); k < kmax; k++) {
507 int alpha_v, alpha_h,
alpha;
508
509 // average alpha for color components, improve quality
510 if (hsub && vsub && j+1 < src_hp && k+1 < src_wp) {
511 alpha = (a[0] + a[src->
linesize[3]] +
513 } else if (hsub || vsub) {
514 alpha_h = hsub && k+1 < src_wp ?
515 (a[0] + a[1]) >> 1 : a[0];
516 alpha_v = vsub && j+1 < src_hp ?
517 (a[0] + a[src->
linesize[3]]) >> 1 : a[0];
518 alpha = (alpha_v + alpha_h) >> 1;
519 } else
520 alpha = a[0];
521 // if the main channel has an alpha channel, alpha has to be calculated
522 // to create an un-premultiplied (straight) alpha value
523 if (main_has_alpha && alpha != 0 && alpha != 255) {
524 // average alpha for color components, improve quality
526 if (hsub && vsub && j+1 < src_hp && k+1 < src_wp) {
527 alpha_d = (d[0] + d[src->
linesize[3]] +
529 } else if (hsub || vsub) {
530 alpha_h = hsub && k+1 < src_wp ?
531 (d[0] + d[1]) >> 1 : d[0];
532 alpha_v = vsub && j+1 < src_hp ?
533 (d[0] + d[src->
linesize[3]]) >> 1 : d[0];
534 alpha_d = (alpha_v + alpha_h) >> 1;
535 } else
536 alpha_d = d[0];
538 }
540 s++;
541 d++;
542 a += 1 << hsub;
543 }
546 ap += (1 << vsub) * src->
linesize[3];
547 }
548 }
549 }
550 }
551
554 {
557
560
565
571 }
572
574 return mainpic;
575 }
576
578 {
582 }
583
585 {
588 }
589
591 {
593
596 "The rgb option is deprecated and is overriding the format option, use format instead\n");
597 s->
format = OVERLAY_FORMAT_RGB;
598 }
602 }
606 }
607
609 return 0;
610 }
611
612 #define OFFSET(x) offsetof(OverlayContext, x)
613 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
614
618 { "eof_action", "Action to take when encountering EOF from secondary input ",
625 {
"init",
"eval expressions once during initialization", 0,
AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_INIT}, .flags =
FLAGS, .unit =
"eval" },
627 {
"rgb",
"force packed RGB in input and output (deprecated)",
OFFSET(allow_packed_rgb),
AV_OPT_TYPE_INT, {.i64=0}, 0, 1,
FLAGS },
628 {
"shortest",
"force termination when the shortest input terminates",
OFFSET(dinput.shortest),
AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1,
FLAGS },
629 {
"format",
"set output format",
OFFSET(format),
AV_OPT_TYPE_INT, {.i64=OVERLAY_FORMAT_YUV420}, 0, OVERLAY_FORMAT_NB-1,
FLAGS,
"format" },
634 {
"repeatlast",
"repeat overlay of the last overlay frame",
OFFSET(dinput.repeatlast),
AV_OPT_TYPE_INT, {.i64=1}, 0, 1,
FLAGS },
636 };
637
639
641 {
646 .needs_writable = 1,
647 },
648 {
649 .name = "overlay",
653 },
655 };
656
658 {
663 },
665 };
666
673 .priv_class = &overlay_class,
676 .
inputs = avfilter_vf_overlay_inputs,
677 .
outputs = avfilter_vf_overlay_outputs,
679 };