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
41
43 "main_w", "W", ///< width of the main video
44 "main_h", "H", ///< height of the main video
45 "overlay_w", "w", ///< width of the overlay video
46 "overlay_h", "h", ///< height of the overlay video
47 "hsub",
48 "vsub",
49 "x",
50 "y",
51 "n", ///< number of frame
52 "pos", ///< position in the file
53 "t", ///< timestamp expressed in seconds
54 NULL
55 };
56
70 };
71
74
79
83
86 int x,
y;
///< position of overlayed picture
87
95 enum OverlayFormat { OVERLAY_FORMAT_YUV420, OVERLAY_FORMAT_YUV444, OVERLAY_FORMAT_RGB, OVERLAY_FORMAT_NB} format;
96 enum EvalMode { EVAL_MODE_INIT, EVAL_MODE_FRAME, EVAL_MODE_NB } eval_mode;
97
99
100 int main_pix_step[4];
///< steps per pixel for each plane of the main output
101 int overlay_pix_step[4];
///< steps per pixel for each plane of the overlay
102 int hsub,
vsub;
///< chroma subsampling values
103
108
110 {
112
116 }
117
119 {
121 return INT_MAX;
122 return (int)d & ~((1 << chroma_sub) - 1);
123 }
124
126 {
128
134 }
135
137 {
140
141 if (*pexpr)
142 old = *pexpr;
144 NULL, NULL, NULL, NULL, 0, log_ctx);
145 if (ret < 0) {
147 "Error when evaluating the expression '%s' for %s\n",
148 expr, option);
149 *pexpr = old;
151 }
152
154 return 0;
155 }
156
159 {
162
163 if (!strcmp(cmd, "x"))
165 else if (!strcmp(cmd, "y"))
167 else
169
170 if (ret < 0)
172
178 }
180 }
181
183 {
185
186 /* overlay formats contains alpha, for avoiding conversion with alpha information loss */
189 };
190 static const enum AVPixelFormat overlay_pix_fmts_yuv420[] = {
192 };
193
196 };
197 static const enum AVPixelFormat overlay_pix_fmts_yuv444[] = {
199 };
200
206 };
211 };
212
215
217 case OVERLAY_FORMAT_YUV420:
220 break;
221 case OVERLAY_FORMAT_YUV444:
224 break;
225 case OVERLAY_FORMAT_RGB:
228 break;
229 default:
231 }
232
236
237 return 0;
238 }
239
244 };
245
247 {
250
252
255
259 return 0;
260 }
261
263 {
268
270
271 /* Finish the configuration by evaluating the expressions
272 now when both inputs are configured. */
284
288
292
298 }
299
301 "main w:%d h:%d fmt:%s overlay w:%d h:%d fmt:%s\n",
306 return 0;
307 }
308
310 {
314
317
321
322 return 0;
323 }
324
325 // divide by 255 and round to nearest
326 // apply a fast variant: (X+127)/255 = ((X+127)*257+257)>>16 = ((X+128)*257)>>16
327 #define FAST_DIV255(x) ((((x) + 128) * 257) >> 16)
328
329 // calculate the unpremultiplied alpha, applying the general equation:
330 // alpha = alpha_overlay / ( (alpha_main + alpha_overlay) - (alpha_main * alpha_overlay) )
331 // (((x) << 16) - ((x) << 9) + (x)) is a faster version of: 255 * 255 * x
332 // ((((x) + (y)) << 8) - ((x) + (y)) - (y) * (x)) is a faster version of: 255 * (x + y)
333 #define UNPREMULTIPLY_ALPHA(x, y) ((((x) << 16) - ((x) << 9) + (x)) / ((((x) + (y)) << 8) - ((x) + (y)) - (y) * (x)))
334
335 /**
336 * Blend image in src to destination buffer dst at position (x, y).
337 */
341 {
343 int i, imax, j, jmax, k, kmax;
344 const int src_w = src->
width;
345 const int src_h = src->
height;
346 const int dst_w = dst->
width;
347 const int dst_h = dst->
height;
348
349 if (x >= dst_w || x+src_w < 0 ||
350 y >= dst_h || y+src_h < 0)
351 return; /* no intersection */
352
354 uint8_t alpha;
///< the amount of overlay to blend on to main
367
371
372 for (imax =
FFMIN(-y + dst_h, src_h); i < imax; i++) {
374 s = sp + j * sstep;
375 d = dp + (x+j) * dstep;
376
377 for (jmax =
FFMIN(-x + dst_w, src_w); j < jmax; j++) {
378 alpha = s[sa];
379
380 // if the main channel has an alpha channel, alpha has to be calculated
381 // to create an un-premultiplied (straight) alpha value
382 if (main_has_alpha && alpha != 0 && alpha != 255) {
385 }
386
387 switch (alpha) {
388 case 0:
389 break;
390 case 255:
391 d[dr] = s[sr];
392 d[dg] = s[sg];
393 d[db] = s[sb];
394 break;
395 default:
396 // main_value = main_value * (1 - alpha) + overlay_value * alpha
397 // since alpha is in the range 0-255, the result must divided by 255
398 d[dr] =
FAST_DIV255(d[dr] * (255 - alpha) + s[sr] * alpha);
399 d[dg] =
FAST_DIV255(d[dg] * (255 - alpha) + s[sg] * alpha);
400 d[db] =
FAST_DIV255(d[db] * (255 - alpha) + s[sb] * alpha);
401 }
402 if (main_has_alpha) {
403 switch (alpha) {
404 case 0:
405 break;
406 case 255:
407 d[da] = s[sa];
408 break;
409 default:
410 // apply alpha compositing: main_alpha += (1-main_alpha) * overlay_alpha
412 }
413 }
414 d += dstep;
415 s += sstep;
416 }
419 }
420 } else {
422 if (main_has_alpha) {
423 uint8_t alpha;
///< the amount of overlay to blend on to main
425
429
430 for (imax =
FFMIN(-y + dst_h, src_h); i < imax; i++) {
432 s = sa + j;
433 d = da + x+j;
434
435 for (jmax =
FFMIN(-x + dst_w, src_w); j < jmax; j++) {
437 if (alpha != 0 && alpha != 255) {
440 }
441 switch (alpha) {
442 case 0:
443 break;
444 case 255:
446 break;
447 default:
448 // apply alpha compositing: main_alpha += (1-main_alpha) * overlay_alpha
450 }
451 d += 1;
452 s += 1;
453 }
456 }
457 }
458 for (i = 0; i < 3; i++) {
459 int hsub = i ? s->
hsub : 0;
460 int vsub = i ? s->
vsub : 0;
465 int yp = y>>vsub;
466 int xp = x>>hsub;
468
473
474 for (jmax =
FFMIN(-yp + dst_hp, src_hp); j < jmax; j++) {
476 d = dp + xp+k;
477 s = sp + k;
478 a = ap + (k<<hsub);
479
480 for (kmax =
FFMIN(-xp + dst_wp, src_wp); k < kmax; k++) {
481 int alpha_v, alpha_h,
alpha;
482
483 // average alpha for color components, improve quality
484 if (hsub && vsub && j+1 < src_hp && k+1 < src_wp) {
485 alpha = (a[0] + a[src->
linesize[3]] +
487 } else if (hsub || vsub) {
488 alpha_h = hsub && k+1 < src_wp ?
489 (a[0] + a[1]) >> 1 : a[0];
490 alpha_v = vsub && j+1 < src_hp ?
491 (a[0] + a[src->
linesize[3]]) >> 1 : a[0];
492 alpha = (alpha_v + alpha_h) >> 1;
493 } else
494 alpha = a[0];
495 // if the main channel has an alpha channel, alpha has to be calculated
496 // to create an un-premultiplied (straight) alpha value
497 if (main_has_alpha && alpha != 0 && alpha != 255) {
498 // average alpha for color components, improve quality
500 if (hsub && vsub && j+1 < src_hp && k+1 < src_wp) {
501 alpha_d = (d[0] + d[src->
linesize[3]] +
503 } else if (hsub || vsub) {
504 alpha_h = hsub && k+1 < src_wp ?
505 (d[0] + d[1]) >> 1 : d[0];
506 alpha_v = vsub && j+1 < src_hp ?
507 (d[0] + d[src->
linesize[3]]) >> 1 : d[0];
508 alpha_d = (alpha_v + alpha_h) >> 1;
509 } else
510 alpha_d = d[0];
512 }
514 s++;
515 d++;
516 a += 1 << hsub;
517 }
520 ap += (1 << vsub) * src->
linesize[3];
521 }
522 }
523 }
524 }
525
528 {
531
532 /* TODO: reindent */
535
540
546 }
547
549 return mainpic;
550 }
551
553 {
556 }
557
559 {
562 }
563
565 {
567
570 "The rgb option is deprecated and is overriding the format option, use format instead\n");
571 s->
format = OVERLAY_FORMAT_RGB;
572 }
574 return 0;
575 }
576
577 #define OFFSET(x) offsetof(OverlayContext, x)
578 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
579
583 {
"eval",
"specify when to evaluate expressions",
OFFSET(eval_mode),
AV_OPT_TYPE_INT, {.i64 = EVAL_MODE_FRAME}, 0, EVAL_MODE_NB-1,
FLAGS,
"eval" },
584 {
"init",
"eval expressions once during initialization", 0,
AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_INIT}, .flags =
FLAGS, .unit =
"eval" },
585 {
"frame",
"eval expressions per-frame", 0,
AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_FRAME}, .flags =
FLAGS, .unit =
"eval" },
586 {
"rgb",
"force packed RGB in input and output (deprecated)",
OFFSET(allow_packed_rgb),
AV_OPT_TYPE_INT, {.i64=0}, 0, 1,
FLAGS },
587 {
"shortest",
"force termination when the shortest input terminates",
OFFSET(dinput.shortest),
AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1,
FLAGS },
588 {
"format",
"set output format",
OFFSET(format),
AV_OPT_TYPE_INT, {.i64=OVERLAY_FORMAT_YUV420}, 0, OVERLAY_FORMAT_NB-1,
FLAGS,
"format" },
592 {
"repeatlast",
"repeat overlay of the last overlay frame",
OFFSET(dinput.repeatlast),
AV_OPT_TYPE_INT, {.i64=1}, 0, 1,
FLAGS },
593 { NULL }
594 };
595
597
599 {
604 .needs_writable = 1,
605 },
606 {
607 .name = "overlay",
611 },
612 { NULL }
613 };
614
616 {
621 },
622 { NULL }
623 };
624
631 .priv_class = &overlay_class,
634 .
inputs = avfilter_vf_overlay_inputs,
635 .
outputs = avfilter_vf_overlay_outputs,
637 };