[FFmpeg-soc] [soc]: r5617 - in libavfilter: diffs/03_libavfilter_doc.diff vf_overlay.c
stefano
subversion at mplayerhq.hu
Thu Feb 4 01:55:07 CET 2010
Author: stefano
Date: Thu Feb 4 01:55:07 2010
New Revision: 5617
Log:
Implement option for supporting alpha-blending in the overlay filter.
Based on a patch by Martin Storsjö $foo=martin <$foo@$foo.st>, and
adapted by Artur Bodera <a$surname at gmail.com> and me.
Modified:
libavfilter/diffs/03_libavfilter_doc.diff
libavfilter/vf_overlay.c
Modified: libavfilter/diffs/03_libavfilter_doc.diff
==============================================================================
--- libavfilter/diffs/03_libavfilter_doc.diff Mon Feb 1 23:45:01 2010 (r5616)
+++ libavfilter/diffs/03_libavfilter_doc.diff Thu Feb 4 01:55:07 2010 (r5617)
@@ -54,7 +54,7 @@ Index: doc/libavfilter.texi
@section noformat
Force libavfilter not to use any of the specified pixel formats for the
-@@ -149,6 +187,37 @@
+@@ -149,6 +187,64 @@
Pass the source unchanged to the output.
@@ -81,6 +81,33 @@ Index: doc/libavfilter.texi
+can be used to draw the overlay at 10 pixels from the bottom right
+corner of the main video.
+
++The filter accepts a third optional parameter, if set to a value
++different than 0, it will alpha-blend the overlayed video on top of
++the first one.
++
++This can be used in particular for performing watermarking effects, or
++for adding a logo on top of the input video.
++
++For example, the following command will insert a transparent PNG
++logo in the bottom left corner of the input video:
++ at example
++movie=0:png:logo.png [logo]; [in][logo] overlay=10:mainH-overlayH-10:1 [out]
++ at end example
++
++Notice the last parameter to overlay ":1" - this enables alpha blending.
++
++The following example will insert 2 different transparent PNG
++logos (second logo on bottom right corner):
++ at example
++movie=0:png:logo1.png [logo1];
++movie=0:png:logo2.png [logo2];
++[in][logo1] overlay=10:mainH-overlayH-10:1 [in+logo1];
++[in+logo1][logo2] overlay=mainW-overlayW-10:mainH-overlayH-10:1 [out]
++ at end example
++
++You could chain and add more overlays this way but the efficiency of
++such approach is yet to be tested.
++
+ at section rotate
+
+ at example
@@ -92,7 +119,7 @@ Index: doc/libavfilter.texi
@section scale
Scale the input video to width:height and/or convert the image format.
-@@ -174,6 +243,24 @@
+@@ -174,6 +270,24 @@
The default value of ``width'' and ``height'' is 0.
@@ -117,7 +144,7 @@ Index: doc/libavfilter.texi
@section slicify
Pass the images of input video on to next video filter as multiple
-@@ -189,6 +276,19 @@
+@@ -189,6 +303,19 @@
Adding this in the beginning of filter chains should make filtering
faster due to better use of the memory cache.
@@ -137,7 +164,7 @@ Index: doc/libavfilter.texi
@section vflip
Flip the input video vertically.
-@@ -201,6 +301,32 @@
+@@ -201,6 +328,32 @@
Below is a description of the currently available video sources.
Modified: libavfilter/vf_overlay.c
==============================================================================
--- libavfilter/vf_overlay.c Mon Feb 1 23:45:01 2010 (r5616)
+++ libavfilter/vf_overlay.c Thu Feb 4 01:55:07 2010 (r5617)
@@ -54,6 +54,8 @@ typedef struct {
int hsub, vsub; //< chroma subsampling
char x_expr[256], y_expr[256];
+
+ int blend;
} OverlayContext;
static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
@@ -64,7 +66,7 @@ static av_cold int init(AVFilterContext
av_strlcpy(over->y_expr, "0", sizeof(over->y_expr));
if (args)
- sscanf(args, "%255[^:]:%255[^:]", over->x_expr, over->y_expr);
+ sscanf(args, "%255[^:]:%255[^:]:%d", over->x_expr, over->y_expr, &over->blend);
return 0;
}
@@ -80,6 +82,24 @@ static av_cold void uninit(AVFilterConte
avfilter_unref_pic(over->pics[i][j]);
}
+static int query_formats(AVFilterContext *ctx)
+{
+ OverlayContext *over = ctx->priv;
+ if (over->blend) {
+ enum PixelFormat inout_pix_fmts[] = { PIX_FMT_YUV420P, PIX_FMT_NONE };
+ enum PixelFormat blend_pix_fmts[] = { PIX_FMT_YUVA420P, PIX_FMT_NONE };
+ AVFilterFormats *inout_formats = avfilter_make_format_list(inout_pix_fmts);
+ AVFilterFormats *blend_formats = avfilter_make_format_list(blend_pix_fmts);
+
+ avfilter_formats_ref(inout_formats, &ctx->inputs [0]->out_formats);
+ avfilter_formats_ref(blend_formats, &ctx->inputs [1]->out_formats);
+ avfilter_formats_ref(inout_formats, &ctx->outputs[0]->in_formats );
+ } else {
+ avfilter_default_query_formats(ctx);
+ }
+ return 0;
+}
+
static int config_input_main(AVFilterLink *link)
{
OverlayContext *over = link->dst->priv;
@@ -179,9 +199,30 @@ static int lower_timestamp(OverlayContex
return (over->pics[0][1]->pts > over->pics[1][1]->pts);
}
+static void copy_blended(uint8_t* out, int out_linesize,
+ const uint8_t* in, int in_linesize,
+ const uint8_t* alpha, int alpha_linesize,
+ int w, int h, int hsub, int vsub)
+{
+ int y;
+ for (y = 0; y < h; y++) {
+ int x;
+ uint8_t *optr = out + y * out_linesize;
+ const uint8_t *iptr = in + y * in_linesize;
+ const uint8_t *aptr = alpha + (y<<vsub) * alpha_linesize;
+ for (x = 0; x < w; x++) {
+ uint8_t a = *aptr;
+ *optr = (*optr * (0xff - a) + *iptr * a) >> 8;
+ optr++;
+ iptr++;
+ aptr += 1 << hsub;
+ }
+ }
+}
+
static void copy_image(AVFilterPicRef *dst, int x, int y,
AVFilterPicRef *src, int w, int h,
- int bpp, int hsub, int vsub)
+ int bpp, int hsub, int vsub, int blend)
{
AVPicture pic;
int i;
@@ -200,7 +241,17 @@ static void copy_image(AVFilterPicRef *d
}
}
+ if (blend) {
+ int chroma_w = w>>hsub;
+ int chroma_h = h>>vsub;
+ assert(dst->pic->format == PIX_FMT_YUV420P);
+ assert(src->pic->format == PIX_FMT_YUVA420P);
+ copy_blended(pic.data[0], pic.linesize[0], src->data[0], src->linesize[0], src->data[3], src->linesize[3], w, h, 0, 0);
+ copy_blended(pic.data[1], pic.linesize[1], src->data[1], src->linesize[1], src->data[3], src->linesize[3], chroma_w, chroma_h, hsub, vsub);
+ copy_blended(pic.data[2], pic.linesize[2], src->data[2], src->linesize[2], src->data[3], src->linesize[3], chroma_w, chroma_h, hsub, vsub);
+ } else {
av_picture_copy(&pic, (AVPicture *)src->data, dst->pic->format, w, h);
+ }
}
static int request_frame(AVFilterLink *link)
@@ -253,7 +304,7 @@ static int request_frame(AVFilterLink *l
if(over->pics[0][0]) {
pic->pixel_aspect = over->pics[0][0]->pixel_aspect;
copy_image(pic, 0, 0, over->pics[0][0], link->w, link->h,
- over->bpp, over->hsub, over->vsub);
+ over->bpp, over->hsub, over->vsub, 0);
}
x = FFMIN(over->x, link->w-1);
y = FFMIN(over->y, link->h-1);
@@ -261,7 +312,7 @@ static int request_frame(AVFilterLink *l
h = FFMIN(link->h-y, over->pics[1][0]->h);
if(over->pics[1][0])
copy_image(pic, x, y, over->pics[1][0], w, h,
- over->bpp, over->hsub, over->vsub);
+ over->bpp, over->hsub, over->vsub, over->blend);
/* we give the output frame the higher of the two current pts values */
pic->pts = FFMAX(over->pics[0][0]->pts, over->pics[1][0]->pts);
@@ -284,6 +335,8 @@ AVFilter avfilter_vf_overlay =
.priv_size = sizeof(OverlayContext),
+ .query_formats = query_formats,
+
.inputs = (AVFilterPad[]) {{ .name = "default",
.type = CODEC_TYPE_VIDEO,
.start_frame = start_frame,
More information about the FFmpeg-soc
mailing list