Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

191 lines (188 sloc) 6.927 kb
--- watermark-old.c 2009-09-12 10:53:42.000000000 +0100
+++ watermark.c 2009-09-06 22:51:51.000000000 +0100
@@ -3,7 +3,7 @@
* Copyright (c) 2005 Marcus Engene myfirstname(at)mylastname.se
*
* parameters for watermark:
- * -m nbr = nbr is 0..1. 0 is the default mode, see below.
+ * -m nbr = nbr is 0..2. 0 is the default mode, see below.
* -t nbr = nbr is six digit hex. Threshold.
* -f file = file is the watermark image filename. You must specify this!
*
@@ -29,13 +29,25 @@
* Per color do this:
* If mask color > threshold color then the watermark pixel is used.
*
+ * MODE 2:
+ * Paste the watermark image onto the video image respecting alpha channels.
+ *
+ * Alpha channels are regularly found in PNG images and affect the tranparency
+ * of the image. If the pixel has 0x00 alpha value it is entirely transparent
+ * and the original video pixel is unchanged. If the alpha value is 0xff
+ * (100%) the watermark pixel is used entirely. Otherwise, the following
+ * formula is used:
+ *
+ * video_pixel = (1 - alpha) * video_pixel + alpha * watermark_pixel
+ *
* Example usage:
* ffmpeg -i infile -vhook '/path/watermark.so -f wm.gif' -an out.mov
* ffmpeg -i infile -vhook '/path/watermark.so -f wm.gif -m 1 -t 222222' -an out.mov
+ * ffmpeg -i infile -vhook '/path/watermark.so -f wm.png -m 2' -an out.mov
*
* Note that the entire vhook argument is encapsulated in ''. This
* way, arguments to the vhook won't be mixed up with those for ffmpeg.
- *
+ *
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
@@ -309,6 +321,140 @@
av_free(buf);
}
+/****************************************************************************
+ * For mode 2 - alpha blending
+ ****************************************************************************/
+static void AlphaBlendingProcess(void *ctx,
+ AVPicture *picture,
+ enum PixelFormat pix_fmt,
+ int src_width,
+ int src_height,
+ int64_t pts)
+{
+ ContextInfo *ci = (ContextInfo *) ctx;
+ char *buf = 0;
+ AVPicture picture1;
+ AVPicture *pict = picture;
+
+ AVFrame *pFrameRGB;
+ int xm_size;
+ int ym_size;
+
+ int x;
+ int y;
+ int offs, offsm;
+ int mpoffs;
+ uint32_t *p_pixel = 0;
+ uint32_t pixel_meck;
+ uint32_t pixel;
+ uint32_t pixelm;
+ uint32_t tmp;
+ uint32_t alpha, src_colour, dest_colour, inverse_alpha;
+
+ if (pix_fmt != PIX_FMT_RGB32) {
+ int size;
+
+ size = avpicture_get_size(PIX_FMT_RGB32, src_width, src_height);
+ buf = av_malloc(size);
+
+ avpicture_fill(&picture1, buf, PIX_FMT_RGB32, src_width, src_height);
+
+ // if we already got a SWS context, let's realloc if is not re-useable
+ ci->toRGB_convert_ctx = sws_getCachedContext(ci->toRGB_convert_ctx,
+ src_width, src_height, pix_fmt,
+ src_width, src_height, PIX_FMT_RGB32,
+ sws_flags, NULL, NULL, NULL);
+ if (ci->toRGB_convert_ctx == NULL) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Cannot initialize the toRGB conversion context\n");
+ return;
+ }
+
+// img_convert parameters are 2 first destination, then 4 source
+// sws_scale parameters are context, 4 first source, then 2 destination
+ sws_scale(ci->toRGB_convert_ctx,
+ picture->data, picture->linesize, 0, src_height,
+ picture1.data, picture1.linesize);
+
+ pict = &picture1;
+ }
+
+ /* Insert filter code here */ /* ok */
+
+ // Get me next frame
+ if (0 > get_watermark_picture(ci, 0)) {
+ return;
+ }
+ // These are the three original static variables in the ffmpeg hack.
+ pFrameRGB = ci->pFrameRGB;
+ xm_size = ci->x_size;
+ ym_size = ci->y_size;
+
+ // I'll do the *4 => <<2 crap later. Most compilers understand that anyway.
+ // According to avcodec.h PIX_FMT_RGB32 is handled in endian specific manner.
+ for (y=0; y<src_height; y++) {
+ offs = y * (src_width * 4);
+ offsm = (((y * ym_size) / src_height) * 4) * xm_size; // offsm first in maskline. byteoffs!
+ for (x=0; x<src_width; x++) {
+ mpoffs = offsm + (((x * xm_size) / src_width) * 4);
+ p_pixel = (uint32_t *)&((pFrameRGB->data[0])[mpoffs]);
+ pixelm = *p_pixel;
+ p_pixel = (uint32_t *)&((pict->data[0])[offs]);
+ pixel = *p_pixel;
+ pixel_meck = pixel & 0xff000000;
+
+ alpha = (uint32_t)((pixelm >> 24) & 0xff);
+
+ if (alpha) {
+ alpha++;
+ inverse_alpha = 0x100 - alpha;
+
+ // R
+ dest_colour = (int)((pixel >> 16) & 0xff);
+ src_colour = (int)((pixelm >> 16) & 0xff);
+ tmp = ((dest_colour * inverse_alpha) >> 8) + ((src_colour * alpha) >> 8);
+ pixel_meck |= (tmp << 16) & 0xff0000;
+ // G
+ dest_colour = (int)((pixel >> 8) & 0xff);
+ src_colour = (int)((pixelm >> 8) & 0xff);
+ tmp = ((dest_colour * inverse_alpha) >> 8) + ((src_colour * alpha) >> 8);
+ pixel_meck |= (tmp << 8) & 0xff00;
+ // B
+ dest_colour = (int)(pixel & 0xff);
+ src_colour = (int)(pixelm & 0xff);
+ tmp = ((dest_colour * inverse_alpha) >> 8) + ((src_colour * alpha) >> 8);
+ pixel_meck |= (tmp << 0) & 0xff;
+
+ *p_pixel = pixel_meck;
+ }
+
+ offs += 4;
+ } // foreach X
+ } // foreach Y
+
+
+
+
+ if (pix_fmt != PIX_FMT_RGB32) {
+ ci->fromRGB_convert_ctx = sws_getCachedContext(ci->fromRGB_convert_ctx,
+ src_width, src_height, PIX_FMT_RGB32,
+ src_width, src_height, pix_fmt,
+ sws_flags, NULL, NULL, NULL);
+ if (ci->fromRGB_convert_ctx == NULL) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Cannot initialize the fromRGB conversion context\n");
+ return;
+ }
+// img_convert parameters are 2 first destination, then 4 source
+// sws_scale parameters are context, 4 first source, then 2 destination
+ sws_scale(ci->fromRGB_convert_ctx,
+ picture1.data, picture1.linesize, 0, src_height,
+ picture->data, picture->linesize);
+ }
+
+ av_free(buf);
+}
+
/****************************************************************************
* For mode 1 (the original one)
@@ -432,7 +578,9 @@
int64_t pts)
{
ContextInfo *ci = (ContextInfo *) ctx;
- if (1 == ci->mode) {
+ if (2 == ci->mode) {
+ AlphaBlendingProcess(ctx, picture, pix_fmt, src_width, src_height, pts);
+ } else if (1 == ci->mode) {
Process1(ctx, picture, pix_fmt, src_width, src_height, pts);
} else {
Process0(ctx, picture, pix_fmt, src_width, src_height, pts);
Jump to Line
Something went wrong with that request. Please try again.