hi all,
all things I said for filter_facemask can be applied now too.

greetings, branko kokanovic
Index: filter/filter_xsharpen.c
===================================================================
RCS file: /cvstc/transcode/filter/filter_xsharpen.c,v
retrieving revision 1.25
diff -u -r1.25 filter_xsharpen.c
--- filter/filter_xsharpen.c	29 Sep 2006 17:34:44 -0000	1.25
+++ filter/filter_xsharpen.c	29 Jul 2007 18:20:47 -0000
@@ -1,9 +1,9 @@
 /*
-    filter_xsharpen.c
+    filter_xsharpen.c -- VirtualDub's XSharpen Filter
 
     Copyright (C) 1999-2000 Donald A. Graft
       modified 2002 by Tilmann Bitterberg for use with transcode
-
+      modified 2007 by Branko Kokanovic <branko.kokanovic at gmail dot com> to use NMS
     This file is part of transcode, a video stream processing tool
 
     Xsharpen Filter for VirtualDub -- sharpen by mapping pixels
@@ -29,17 +29,27 @@
 */
 
 #define MOD_NAME    "filter_xharpen.so"
-#define MOD_VERSION "(1.0b2) (2003-02-12)"
+#define MOD_VERSION "(1.0b3) (2007-07-29)"
 #define MOD_CAP     "VirtualDub's XSharpen Filter"
 #define MOD_AUTHOR  "Donald Graft, Tilmann Bitterberg"
+#define MOD_FEATURES \
+    TC_MODULE_FEATURE_FILTER|TC_MODULE_FEATURE_VIDEO
+#define MOD_FLAGS \
+    TC_MODULE_FLAG_RECONFIGURABLE
+
+/* -------------------------------------------------
+ *
+ * mandatory include files
+ *
+ *-------------------------------------------------*/
 
 #include "transcode.h"
 #include "filter.h"
 #include "libtc/libtc.h"
 #include "libtc/optstr.h"
+#include "libtc/tcmodule-plugin.h"
 #include "aclib/imgconvert.h"
 
-static vob_t *vob=NULL;
 
 /* vdub compat */
 typedef unsigned int	Pixel;
@@ -49,571 +59,698 @@
 typedef	int		PixDim;
 typedef	int		PixOffset;
 
-///////////////////////////////////////////////////////////////////////////
+static const char xsharpen_help[] = ""
+    "Overview\n"
+    "   This filter performs a subtle but useful sharpening effect. The\n"
+    "   result is a sharpening effect that not only avoids amplifying\n"
+    "   noise, but also tends to reduce it. A welcome side effect is that\n"
+    "   files processed with this filter tend to compress to smaller files.\n"
+    "\n"
+    "Options\n"
+    "   Strength 'strength' (0-255) [200]\n"
+    "   When this value is 255, mapped pixels are not blended with the\n"
+    "   original pixel values, so a full-strength effect is obtained. As\n"
+    "   the value is reduced, each mapped pixel is blended with more of the\n"
+    "   original pixel. At a value of 0, the original pixels are passed\n"
+    "   through and there is no sharpening effect.\n"
+    "\n"
+    "   Threshold 'threshold' (0-255) [255]\n"
+    "   This value determines how close a pixel must be to the brightest or\n"
+    "   dimmest pixel to be mapped. If a pixel is more than threshold away\n"
+    "   from the brightest or dimmest pixel, it is not mapped.  Thus, as\n"
+    "   the threshold is reduced, pixels in the mid range start to be\n"
+    "   spared.\n";
+
+/*************************************************************************/
 
 typedef struct MyFilterData {
-	Pixel32		*convertFrameIn;
-	Pixel32		*convertFrameOut;
-	int		strength;
-	int		strengthInv;
-	int		threshold;
-	int		srcPitch;
-	int		dstPitch;
-	TCVHandle	tcvhandle;
+    Pixel32		*convertFrameIn;
+    Pixel32		*convertFrameOut;
+    int		strength;
+    int		strengthInv;
+    int		threshold;
+    int		srcPitch;
+    int		dstPitch;
+    int codec;
+    TCVHandle	tcvhandle;
+    char conf_str[TC_BUF_MIN];
 } MyFilterData;
 
-static MyFilterData *mfd;
+/*************************************************************************/
+
+/* Module interface routines and data. */
+
+/*************************************************************************/
+
+/**
+ * xsharpen_init:  Initialize this instance of the module.  See
+ * tcmodule-data.h for function details.
+ */
 
-static void help_optstr(void)
+static int xsharpen_init(TCModuleInstance *self, uint32_t features)
 {
-   tc_log_info (MOD_NAME, "(%s) help\n"
-"* Overview\n"
-"    This filter performs a subtle but useful sharpening effect. The\n"
-"    result is a sharpening effect that not only avoids amplifying\n"
-"    noise, but also tends to reduce it. A welcome side effect is that\n"
-"    files processed with this filter tend to compress to smaller files.\n"
-"\n"
-"* Options\n"
-"  * Strength 'strength' (0-255) [200]\n"
-"    When this value is 255, mapped pixels are not blended with the\n"
-"    original pixel values, so a full-strength effect is obtained. As\n"
-"    the value is reduced, each mapped pixel is blended with more of the\n"
-"    original pixel. At a value of 0, the original pixels are passed\n"
-"    through and there is no sharpening effect.\n"
-"\n"
-"  * Threshold 'threshold' (0-255) [255]\n"
-"    This value determines how close a pixel must be to the brightest or\n"
-"    dimmest pixel to be mapped. If a pixel is more than threshold away\n"
-"    from the brightest or dimmest pixel, it is not mapped.  Thus, as\n"
-"    the threshold is reduced, pixels in the mid range start to be\n"
-"    spared.\n"
-		, MOD_CAP);
+    MyFilterData *mfd = NULL;
+
+    TC_MODULE_SELF_CHECK(self, "init");
+    TC_MODULE_INIT_CHECK(self, MOD_FEATURES, features);
+
+    mfd = tc_malloc(sizeof(MyFilterData));
+    if (!mfd) {
+        tc_log_error(MOD_NAME, "init: out of memory!");
+        return TC_ERROR;
+    }
+    self->userdata = mfd;
+
+    /* initialize data */
+    mfd->strength       = 200; /* 255 is too much */
+    mfd->strengthInv    = 255 - mfd->strength;
+    mfd->threshold      = 255;
+    mfd->srcPitch       = 0;
+    mfd->dstPitch       = 0;
+    mfd->convertFrameIn = NULL;
+    mfd->convertFrameOut= NULL;
+
+    return TC_OK;
 }
 
-int tc_filter(frame_list_t *ptr_, char *options)
+/*************************************************************************/
+
+/**
+ * xsharpen_fini:  Clean up after this instance of the module.  See
+ * tcmodule-data.h for function details.
+ */
+
+static int xsharpen_fini(TCModuleInstance *self)
 {
-  vframe_list_t *ptr = (vframe_list_t *)ptr_;
+    MyFilterData *mfd = NULL;
+
+    TC_MODULE_SELF_CHECK(self, "fini");
+
+    mfd = self->userdata;
+
+    if (mfd->convertFrameIn)
+        tc_free(mfd->convertFrameIn);
+    mfd->convertFrameIn = NULL;
+
+    if (mfd->convertFrameOut)
+        tc_free(mfd->convertFrameOut);
+    mfd->convertFrameOut = NULL;
+
+    if (mfd->tcvhandle){
+        tcv_free(mfd->tcvhandle);
+    }
+    mfd->tcvhandle = 0;
 
-  //----------------------------------
-  //
-  // filter init
-  //
-  //----------------------------------
+    tc_free(self->userdata);
+    self->userdata = NULL;
 
+    return TC_OK;
+}
+
+/*************************************************************************/
 
-  if(ptr->tag & TC_FILTER_INIT) {
+/**
+ * xsharpen_configure:  Configure this instance of the module.  See
+ * tcmodule-data.h for function details.
+ */
 
+static int xsharpen_configure(TCModuleInstance *self,
+                          const char *options, vob_t *vob)
+{
+    MyFilterData *mfd = NULL;
 	int width, height;
 
-	if((vob = tc_get_vob())==NULL) return(-1);
+    TC_MODULE_SELF_CHECK(self, "configure");
 
-	mfd = tc_malloc(sizeof(MyFilterData));
+    mfd = self->userdata;
 
-	if (!mfd) {
-		tc_log_error(MOD_NAME, "No memory at %d!", __LINE__);
-		return (-1);
-	}
+	if(vob == NULL){
+        return TC_ERROR;
+    }
 
 	height = vob->ex_v_height;
 	width  = vob->ex_v_width;
 
-	/* default values */
-	mfd->strength       = 200; /* 255 is too much */
-	mfd->strengthInv    = 255 - mfd->strength;
-	mfd->threshold      = 255;
-	mfd->srcPitch       = 0;
-	mfd->dstPitch       = 0;
+    /* setup defaults */
+    mfd->codec          = vob->im_v_codec;
+    mfd->strength       = 200; /* 255 is too much */
+    mfd->strengthInv    = 255 - mfd->strength;
+    mfd->threshold      = 255;
+    mfd->srcPitch       = 0;
+    mfd->dstPitch       = 0;
 
-	if (options != NULL) {
+    if (options) {
+        if (verbose >= TC_STATS) {
+            tc_log_info(MOD_NAME, "options=%s", options);
+        }
+        optstr_get (options, "strength",  "%d", &mfd->strength);
+        optstr_get (options, "threshold", "%d", &mfd->threshold);
+    }
+    mfd->strengthInv    = 255 - mfd->strength;
 
-	  if(verbose) tc_log_info(MOD_NAME, "options=%s", options);
+    if (verbose > TC_INFO) {
+        tc_log_info (MOD_NAME, " XSharpen Filter Settings (%dx%d):", width,height);
+        tc_log_info (MOD_NAME, "          strength = %d", mfd->strength);
+        tc_log_info (MOD_NAME, "         threshold = %d", mfd->threshold);
+    }
 
-	  optstr_get (options, "strength",  "%d", &mfd->strength);
-	  optstr_get (options, "threshold", "%d", &mfd->threshold);
+    /* fetch memory */
+    mfd->convertFrameIn = tc_malloc (width*height*sizeof(Pixel32));
+    if (!mfd->convertFrameIn) {
+        tc_log_error(MOD_NAME, "No memory at %d!", __LINE__);
+        return TC_ERROR;
+    }
+    memset(mfd->convertFrameIn, 0, width*height*sizeof(Pixel32));
 
-	}
+    mfd->convertFrameOut = tc_malloc (width*height*sizeof(Pixel32));
+    if (!mfd->convertFrameOut) {
+        tc_log_error(MOD_NAME, "No memory at %d!", __LINE__);
+        return TC_ERROR;
+    }
+    memset(mfd->convertFrameOut, 0, width*height*sizeof(Pixel32));
 
-	mfd->strengthInv    = 255 - mfd->strength;
+    mfd->tcvhandle = tcv_init();
 
-	if (verbose > 1) {
+    /* filter init ok */
+    if (verbose) {
+        tc_log_info(MOD_NAME, "%s %s", MOD_VERSION, MOD_CAP);
+    }
 
-	  tc_log_info (MOD_NAME, " XSharpen Filter Settings (%dx%d):", width,height);
-	  tc_log_info (MOD_NAME, "          strength = %d", mfd->strength);
-	  tc_log_info (MOD_NAME, "         threshold = %d", mfd->threshold);
-	}
+    return TC_OK;
+}
 
-	if (options)
-		if ( optstr_lookup(options, "help") != NULL) {
-			help_optstr();
-		}
+/*************************************************************************/
 
-	/* fetch memory */
+/**
+ * xsharpen_stop:  Reset this instance of the module.  See tcmodule-data.h
+ * for function details.
+ */
 
-	mfd->convertFrameIn = tc_malloc (width*height*sizeof(Pixel32));
-	if (!mfd->convertFrameIn) {
-		tc_log_error(MOD_NAME, "No memory at %d!", __LINE__);
-		return (-1);
-	}
-	memset(mfd->convertFrameIn, 0, width*height*sizeof(Pixel32));
+static int xsharpen_stop(TCModuleInstance *self)
+{
+    TC_MODULE_SELF_CHECK(self, "stop");
+    return TC_OK;
+}
 
-	mfd->convertFrameOut = tc_malloc (width*height*sizeof(Pixel32));
-	if (!mfd->convertFrameOut) {
-		tc_log_error(MOD_NAME, "No memory at %d!", __LINE__);
-		return (-1);
-	}
-	memset(mfd->convertFrameOut, 0, width*height*sizeof(Pixel32));
+/*************************************************************************/
 
-	mfd->tcvhandle = tcv_init();
+/**
+ * xsharpen_inspect:  Return the value of an option in this instance of
+ * the module.  See tcmodule-data.h for function details.
+ */
 
-	// filter init ok.
-	if(verbose) tc_log_info(MOD_NAME, "%s %s", MOD_VERSION, MOD_CAP);
+static int xsharpen_inspect(TCModuleInstance *self,
+                        const char *param, const char **value)
+{
+    MyFilterData *mfd = NULL;
 
-	return 0;
+    TC_MODULE_SELF_CHECK(self, "inspect");
+    TC_MODULE_SELF_CHECK(param, "inspect");
+    TC_MODULE_SELF_CHECK(value, "inspect");
 
-  } /* TC_FILTER_INIT */
+    mfd = self->userdata;
 
+    if (optstr_lookup(param, "help")) {
+        *value = xsharpen_help;
+    }
+    if (optstr_lookup(param, "strength")) {
+        tc_snprintf(mfd->conf_str, sizeof(mfd->conf_str),"ypos=%d",mfd->strength);
+        *value = mfd->conf_str;
+    }
+    if (optstr_lookup(param, "threshold")) {
+        tc_snprintf(mfd->conf_str, sizeof(mfd->conf_str),"ypos=%d",mfd->threshold);
+        *value = mfd->conf_str;
+    }
 
-  if(ptr->tag & TC_FILTER_GET_CONFIG) {
-    if (options) {
-	    char buf[256];
-	    optstr_filter_desc (options, MOD_NAME, MOD_CAP, MOD_VERSION, MOD_AUTHOR, "VRYO", "1");
-	    tc_snprintf (buf, sizeof(buf), "%d", mfd->strength);
-	    optstr_param (options, "strength", "How much  of the effect", "%d", buf, "0", "255");
-
-	    tc_snprintf (buf, sizeof(buf), "%d", mfd->threshold);
-	    optstr_param (options, "threshold",
-			  "How close a pixel must be to the brightest or dimmest pixel to be mapped",
-			  "%d", buf, "0", "255");
-    }
-  }
-
-
-  if(ptr->tag & TC_FILTER_CLOSE) {
-
-	if (mfd->convertFrameIn)
-		free (mfd->convertFrameIn);
-	mfd->convertFrameIn = NULL;
-
-	if (mfd->convertFrameOut)
-		free (mfd->convertFrameOut);
-	mfd->convertFrameOut = NULL;
-
-	tcv_free(mfd->tcvhandle);
-	mfd->tcvhandle = 0;
-
-	if (mfd)
-		free(mfd);
-	mfd = NULL;
-
-	return 0;
-
-  } /* TC_FILTER_CLOSE */
-
-///////////////////////////////////////////////////////////////////////////
-
-  if(ptr->tag & TC_POST_M_PROCESS && ptr->tag & TC_VIDEO && !(ptr->attributes & TC_FRAME_IS_SKIPPED)) {
-
-     if (vob->im_v_codec == CODEC_RGB) {
-	const PixDim	width  = ptr->v_width;
-	const PixDim	height = ptr->v_height;
-	Pixel32         *src, *dst;
-	int             x, y;
-	int             r, g, b, R, G, B;
-	Pixel32         p, min=1000, max=-1;
-	int             luma, lumac, lumamax, lumamin, mindiff, maxdiff;
-	const int	srcpitch = ptr->v_width*sizeof(Pixel32);
-	const int	dstpitch = ptr->v_width*sizeof(Pixel32);
-
-	Pixel32 * dst_buf;
-	Pixel32 * src_buf;
-
-	tcv_convert(mfd->tcvhandle, ptr->video_buf,
-		    (uint8_t *)mfd->convertFrameIn,
-		    ptr->v_width, ptr->v_height, IMG_RGB24, IMG_BGRA32);
-
-	src_buf = mfd->convertFrameIn;
-	dst_buf = mfd->convertFrameOut;
-
-	/* First copy through the four border lines. */
-	src	= src_buf;
-	dst	= dst_buf;
-	for (x = 0; x < width; x++)
-	{
-		dst[x] = src[x];
-	}
-	src	= (Pixel *)((char *)src_buf + (height - 1) * srcpitch);
-	dst	= (Pixel *)((char *)dst_buf + (height - 1) * dstpitch);
-	for (x = 0; x < width; x++)
-	{
-		dst[x] = src[x];
-	}
-	src	= src_buf;
-	dst	= dst_buf;
-	for (y = 0; y < height; y++)
-	{
-		dst[0] = src[0];
-		dst[width-1] = src[width-1];
-		src	= (Pixel *)((char *)src + srcpitch);
-		dst	= (Pixel *)((char *)dst + dstpitch);
-	}
-
-	/* Now calculate and store the pixel luminances for the remaining pixels. */
-	src	= src_buf;
-	for (y = 0; y < height; y++)
-	{
-		for (x = 0; x < width; x++)
-		{
-			r = (src[x] >> 16) & 0xff;
-			g = (src[x] >> 8) & 0xff;
-			b = src[x] & 0xff;
-			luma = (55 * r + 182 * g + 19 * b) >> 8;
-			src[x] &= 0x00ffffff;
-			src[x] |= (luma << 24);
-		}
-		src	= (Pixel *)((char *)src + srcpitch);
-	}
-
-	/* Finally run the 3x3 rank-order sharpening kernel over the pixels. */
-	src	= (Pixel *)((char *)src_buf + srcpitch);
-	dst	= (Pixel *)((char *)dst_buf + dstpitch);
-	for (y = 1; y < height - 1; y++)
-	{
-		for (x = 1; x < width - 1; x++)
-		{
-			/* Find the brightest and dimmest pixels in the 3x3 window
-			   surrounding the current pixel. */
-			lumamax = -1;
-			lumamin = 1000;
-
-			p = ((Pixel32 *)((char *)src - srcpitch))[x-1];
-			luma = p >> 24;
-			if (luma > lumamax)
-			{
-				lumamax = luma;
-				max = p;
-			}
-			if (luma < lumamin)
-			{
-				lumamin = luma;
-				min = p;
-			}
-
-			p = ((Pixel32 *)((char *)src - srcpitch))[x];
-			luma = p >> 24;
-			if (luma > lumamax)
-			{
-				lumamax = luma;
-				max = p;
-			}
-			if (luma < lumamin)
-			{
-				lumamin = luma;
-				min = p;
-			}
-
-			p = ((Pixel32 *)((char *)src - srcpitch))[x+1];
-			luma = p >> 24;
-			if (luma > lumamax)
-			{
-				lumamax = luma;
-				max = p;
-			}
-			if (luma < lumamin)
-			{
-				lumamin = luma;
-				min = p;
-			}
-
-			p = src[x-1];
-			luma = p >> 24;
-			if (luma > lumamax)
-			{
-				lumamax = luma;
-				max = p;
-			}
-			if (luma < lumamin)
-			{
-				lumamin = luma;
-				min = p;
-			}
-
-			p = src[x];
-			lumac = luma = p >> 24;
-			if (luma > lumamax)
-			{
-				lumamax = luma;
-				max = p;
-			}
-			if (luma < lumamin)
-			{
-				lumamin = luma;
-				min = p;
-			}
-
-			p = src[x+1];
-			luma = p >> 24;
-			if (luma > lumamax)
-			{
-				lumamax = luma;
-				max = p;
-			}
-			if (luma < lumamin)
-			{
-				lumamin = luma;
-				min = p;
-			}
-
-			p = ((Pixel32 *)((char *)src + srcpitch))[x-1];
-			luma = p >> 24;
-			if (luma > lumamax)
-			{
-				lumamax = luma;
-				max = p;
-			}
-			if (luma < lumamin)
-			{
-				lumamin = luma;
-				min = p;
-			}
-
-			p = ((Pixel32 *)((char *)src + srcpitch))[x];
-			luma = p >> 24;
-			if (luma > lumamax)
-			{
-				lumamax = luma;
-				max = p;
-			}
-			if (luma < lumamin)
-			{
-				lumamin = luma;
-				min = p;
-			}
-
-			p = ((Pixel32 *)((char *)src + srcpitch))[x+1];
-			luma = p >> 24;
-			if (luma > lumamax)
-			{
-				lumamax = luma;
-				max = p;
-			}
-			if (luma < lumamin)
-			{
-				lumamin = luma;
-				min = p;
-			}
-
-			/* Determine whether the current pixel is closer to the
-			   brightest or the dimmest pixel. Then compare the current
-			   pixel to that closest pixel. If the difference is within
-			   threshold, map the current pixel to the closest pixel;
-			   otherwise pass it through. */
-			p = -1;
-			if (mfd->strength != 0)
-			{
-				mindiff = lumac - lumamin;
-				maxdiff = lumamax - lumac;
-				if (mindiff > maxdiff)
-				{
-					if (maxdiff < mfd->threshold)
-					{
-						p = max;
-					}
-				}
-				else
-				{
-					if (mindiff < mfd->threshold)
-					{
-						p = min;
-					}
-				}
-			}
-			if (p == -1)
-			{
-				dst[x] = src[x];
-			}
-			else
-			{
-
-				R = (src[x] >> 16) & 0xff;
-				G = (src[x] >> 8) & 0xff;
-				B = src[x] & 0xff;
-				r = (p >> 16) & 0xff;
-				g = (p >> 8) & 0xff;
-				b = p & 0xff;
-				r = (mfd->strength * r + mfd->strengthInv * R) / 255;
-				g = (mfd->strength * g + mfd->strengthInv * G) / 255;
-				b = (mfd->strength * b + mfd->strengthInv * B) / 255;
-				dst[x] = (r << 16) | (g << 8) | b;
-			}
-		}
-		src	= (Pixel *)((char *)src + srcpitch);
-		dst	= (Pixel *)((char *)dst + dstpitch);
-	}
-
-	tcv_convert(mfd->tcvhandle, (uint8_t *)mfd->convertFrameOut,
-		    ptr->video_buf, ptr->v_width, ptr->v_height,
-		    IMG_BGRA32, IMG_RGB24);
-
-	return 0;
-     }
-
-
-     if (vob->im_v_codec == CODEC_YUV) {
-
-	const PixDim       width = ptr->v_width;
-	const PixDim       height = ptr->v_height;
-	char               *src, *dst;
-	int                x, y;
-	int        	   luma, lumac, lumamax, lumamin;
-	int 		   p, mindiff, maxdiff;
-	const int	   srcpitch = ptr->v_width;
-	const int	   dstpitch = ptr->v_width;
-
-	char * src_buf = ptr->video_buf;
-	static char * dst_buf = NULL;
-
-	if (!dst_buf)
-		dst_buf =  tc_malloc (width*height*3/2);
-
-	/* First copy through the four border lines. */
-	/* first */
-	src	= src_buf;
-	dst	= dst_buf;
-	ac_memcpy (dst, src, width);
-
-	/* last */
-	src     = src_buf+srcpitch*(height-1);
-	dst     = dst_buf+dstpitch*(height-1);
-	ac_memcpy (dst, src, width);
-
-	/* copy Cb and Cr */
-	ac_memcpy (dst_buf+dstpitch*height, src_buf+srcpitch*height, width*height>>1);
-
-	src	= src_buf;
-	dst	= dst_buf;
-	for (y = 0; y < height; y++)
-	{
-		*dst = *src;
-		*(dst+width-1) = *(src+width-1);
-		dst += dstpitch;
-		src += srcpitch;
-	}
-
-	src = src_buf+srcpitch;
-	dst = dst_buf+dstpitch;
-
-	/* Finally run the 3x3 rank-order sharpening kernel over the pixels. */
-	for (y = 1; y < height - 1; y++)
-	{
-		for (x = 1; x < width - 1; x++)
-		{
-			/* Find the brightest and dimmest pixels in the 3x3 window
-			   surrounding the current pixel. */
-			lumamax = -1000;
-			lumamin = 1000;
-
-			luma = (src - srcpitch)[x-1] &0xff;
-			if (luma > lumamax)
-				lumamax = luma;
-			if (luma < lumamin)
-				lumamin = luma;
-
-			luma = (src - srcpitch)[x] &0xff;
-			if (luma > lumamax)
-				lumamax = luma;
-			if (luma < lumamin)
-				lumamin = luma;
-
-			luma = (src - srcpitch)[x+1] &0xff;
-			if (luma > lumamax)
-				lumamax = luma;
-			if (luma < lumamin)
-				lumamin = luma;
-
-			luma = src[x-1] &0xff;
-			if (luma > lumamax)
-				lumamax = luma;
-			if (luma < lumamin)
-				lumamin = luma;
-
-			luma = src[x] &0xff;
-			lumac = luma;
-			if (luma > lumamax)
-				lumamax = luma;
-			if (luma < lumamin)
-				lumamin = luma;
-
-			luma = src[x+1] &0xff;
-			if (luma > lumamax)
-				lumamax = luma;
-			if (luma < lumamin)
-				lumamin = luma;
-
-			luma = (src + srcpitch)[x-1] &0xff;
-			if (luma > lumamax)
-				lumamax = luma;
-			if (luma < lumamin)
-				lumamin = luma;
-
-			luma = (src + srcpitch)[x] &0xff;
-			if (luma > lumamax)
-				lumamax = luma;
-			if (luma < lumamin)
-				lumamin = luma;
-
-			luma = (src + srcpitch)[x+1] &0xff;
-			if (luma > lumamax)
-				lumamax = luma;
-			if (luma < lumamin)
-				lumamin = luma;
-
-			/* Determine whether the current pixel is closer to the
-			   brightest or the dimmest pixel. Then compare the current
-			   pixel to that closest pixel. If the difference is within
-			   threshold, map the current pixel to the closest pixel;
-			   otherwise pass it through. */
-
-			p = -1;
-			if (mfd->strength != 0)
-			{
-				mindiff = lumac   - lumamin;
-				maxdiff = lumamax - lumac;
-				if (mindiff > maxdiff)
-				{
-					if (maxdiff < mfd->threshold)
-						p = lumamax&0xff;
-				}
-				else
-				{
-					if (mindiff < mfd->threshold)
-						p = lumamin&0xff;
-				}
-			}
-			if (p == -1)
-			{
-				dst[x] = src[x];
-			}
-			else
-			{
-			        int t;
-				lumac = src[x] &0xff;
-				t = ((mfd->strength*p + mfd->strengthInv*lumac)/255) & 0xff;
-				if (t>240) t = 240;
-				if (t<16)  t = 16;
-				dst[x] = t&0xff;
-
-			}
-		}
-		src += srcpitch;
-		dst += dstpitch;
-	}
-
-	ac_memcpy (ptr->video_buf, dst_buf, width*height*3/2);
-
-	return 0;
-
-     }
-  }
-  return 0;
+    return TC_OK;
 }
 
+/*************************************************************************/
+
+/**
+ * xsharpen_filter_video:  show something on given frame of the video
+ * stream.  See tcmodule-data.h for function details.
+ */
+
+static int xsharpen_filter_video(TCModuleInstance *self, vframe_list_t *frame)
+{
+    MyFilterData *mfd = NULL;
+    int post = 0;
+
+    TC_MODULE_SELF_CHECK(self, "filer_video");
+    TC_MODULE_SELF_CHECK(frame, "filer_video");
+
+    mfd = self->userdata;
+    post = (frame->tag & TC_POST_M_PROCESS);
+
+    if(post && !(frame->attributes & TC_FRAME_IS_SKIPPED)) {
+        if (mfd->codec == CODEC_RGB) {
+            const PixDim    width  = frame->v_width;
+            const PixDim    height = frame->v_height;
+            Pixel32         *src, *dst;
+            int             x, y;
+            int             r, g, b, R, G, B;
+            Pixel32         p, min=1000, max=-1;
+            int             luma, lumac, lumamax, lumamin, mindiff, maxdiff;
+            const int       srcpitch = frame->v_width*sizeof(Pixel32);
+            const int       dstpitch = frame->v_width*sizeof(Pixel32);
+
+            Pixel32 * dst_buf;
+            Pixel32 * src_buf;
+
+            tcv_convert(mfd->tcvhandle, frame->video_buf,
+                (uint8_t *)mfd->convertFrameIn, frame->v_width, frame->v_height,
+                IMG_RGB24, IMG_BGRA32);
+
+            src_buf = mfd->convertFrameIn;
+            dst_buf = mfd->convertFrameOut;
+
+            /* First copy through the four border lines. */
+            src	= src_buf;
+            dst	= dst_buf;
+            for (x = 0; x < width; x++){
+                dst[x] = src[x];
+            }
+            src	= (Pixel *)((char *)src_buf + (height - 1) * srcpitch);
+            dst	= (Pixel *)((char *)dst_buf + (height - 1) * dstpitch);
+            for (x = 0; x < width; x++){
+                dst[x] = src[x];
+            }
+            src	= src_buf;
+            dst	= dst_buf;
+            for (y = 0; y < height; y++){
+                dst[0] = src[0];
+                dst[width-1] = src[width-1];
+                src	= (Pixel *)((char *)src + srcpitch);
+                dst	= (Pixel *)((char *)dst + dstpitch);
+            }
+
+            /* Now calculate and store the pixel luminances for the remaining pixels. */
+            src	= src_buf;
+            for (y = 0; y < height; y++){
+                for (x = 0; x < width; x++){
+                    r = (src[x] >> 16) & 0xff;
+                    g = (src[x] >> 8) & 0xff;
+                    b = src[x] & 0xff;
+                    luma = (55 * r + 182 * g + 19 * b) >> 8;
+                    src[x] &= 0x00ffffff;
+                    src[x] |= (luma << 24);
+                }
+                src	= (Pixel *)((char *)src + srcpitch);
+            }
+
+            /* Finally run the 3x3 rank-order sharpening kernel over the pixels. */
+            src = (Pixel *)((char *)src_buf + srcpitch);
+            dst = (Pixel *)((char *)dst_buf + dstpitch);
+            for (y = 1; y < height - 1; y++){
+                for (x = 1; x < width - 1; x++){
+                    /* Find the brightest and dimmest pixels in the 3x3 window
+                    surrounding the current pixel. */
+                    lumamax = -1;
+                    lumamin = 1000;
+
+                    p = ((Pixel32 *)((char *)src - srcpitch))[x-1];
+                    luma = p >> 24;
+                    if (luma > lumamax){
+                        lumamax = luma;
+                        max = p;
+                    }
+                    if (luma < lumamin){
+                        lumamin = luma;
+                        min = p;
+                    }
+
+                    p = ((Pixel32 *)((char *)src - srcpitch))[x];
+                    luma = p >> 24;
+                    if (luma > lumamax){
+                        lumamax = luma;
+                        max = p;
+                    }
+                    if (luma < lumamin){
+                        lumamin = luma;
+                        min = p;
+                    }
+
+                    p = ((Pixel32 *)((char *)src - srcpitch))[x+1];
+                    luma = p >> 24;
+                    if (luma > lumamax){
+                        lumamax = luma;
+                        max = p;
+                    }
+                    if (luma < lumamin){
+                        lumamin = luma;
+                        min = p;
+                    }
+
+                    p = src[x-1];
+                    luma = p >> 24;
+                    if (luma > lumamax){
+                        lumamax = luma;
+                        max = p;
+                    }
+                    if (luma < lumamin){
+                        lumamin = luma;
+                        min = p;
+                    }
+
+                    p = src[x];
+                    lumac = luma = p >> 24;
+                    if (luma > lumamax){
+                        lumamax = luma;
+                        max = p;
+                    }
+                    if (luma < lumamin){
+                        lumamin = luma;
+                        min = p;
+                    }
+
+                    p = src[x+1];
+                    luma = p >> 24;
+                    if (luma > lumamax){
+                        lumamax = luma;
+                        max = p;
+                    }
+                    if (luma < lumamin){
+                        lumamin = luma;
+                        min = p;
+                    }
+
+                    p = ((Pixel32 *)((char *)src + srcpitch))[x-1];
+                    luma = p >> 24;
+                    if (luma > lumamax){
+                        lumamax = luma;
+                        max = p;
+                    }
+                    if (luma < lumamin){
+                        lumamin = luma;
+                        min = p;
+                    }
+
+                    p = ((Pixel32 *)((char *)src + srcpitch))[x];
+                    luma = p >> 24;
+                    if (luma > lumamax){
+                        lumamax = luma;
+                        max = p;
+                    }
+                    if (luma < lumamin){
+                        lumamin = luma;
+                        min = p;
+                    }
+
+                    p = ((Pixel32 *)((char *)src + srcpitch))[x+1];
+                    luma = p >> 24;
+                    if (luma > lumamax){
+                        lumamax = luma;
+                        max = p;
+                    }
+                    if (luma < lumamin){
+                        lumamin = luma;
+                        min = p;
+                    }
+
+                    /* Determine whether the current pixel is closer to the
+                       brightest or the dimmest pixel. Then compare the current
+                       pixel to that closest pixel. If the difference is within
+                       threshold, map the current pixel to the closest pixel;
+                       otherwise pass it through. */
+                    p = -1;
+                    if (mfd->strength != 0){
+                        mindiff = lumac - lumamin;
+                        maxdiff = lumamax - lumac;
+                        if (mindiff > maxdiff){
+                            if (maxdiff < mfd->threshold){
+                                p = max;
+                            }
+                        }else{
+                            if (mindiff < mfd->threshold){
+                                p = min;
+                            }
+                        }
+                    }
+                    if (p == -1){
+                        dst[x] = src[x];
+                    }else{
+                        R = (src[x] >> 16) & 0xff;
+                        G = (src[x] >> 8) & 0xff;
+                        B = src[x] & 0xff;
+                        r = (p >> 16) & 0xff;
+                        g = (p >> 8) & 0xff;
+                        b = p & 0xff;
+                        r = (mfd->strength * r + mfd->strengthInv * R) / 255;
+                        g = (mfd->strength * g + mfd->strengthInv * G) / 255;
+                        b = (mfd->strength * b + mfd->strengthInv * B) / 255;
+                        dst[x] = (r << 16) | (g << 8) | b;
+                    }
+                }
+                src	= (Pixel *)((char *)src + srcpitch);
+                dst	= (Pixel *)((char *)dst + dstpitch);
+            }
+
+            tcv_convert(mfd->tcvhandle, (uint8_t *)mfd->convertFrameOut,
+                frame->video_buf, frame->v_width, frame->v_height,
+                IMG_BGRA32, IMG_RGB24);
+
+            return TC_OK;
+        }
+        if (mfd->codec == CODEC_YUV) {
+            const PixDim       width = frame->v_width;
+            const PixDim       height = frame->v_height;
+            char               *src, *dst;
+            int                x, y;
+            int        	   luma, lumac, lumamax, lumamin;
+            int 		   p, mindiff, maxdiff;
+            const int	   srcpitch = frame->v_width;
+            const int	   dstpitch = frame->v_width;
+
+            char * src_buf = frame->video_buf;
+            static char * dst_buf = NULL;
+
+            if (!dst_buf){
+                dst_buf =  tc_malloc (width*height*3/2);
+            }
+
+            /* First copy through the four border lines. */
+            /* first */
+            src	= src_buf;
+            dst	= dst_buf;
+            ac_memcpy (dst, src, width);
+
+            /* last */
+            src     = src_buf+srcpitch*(height-1);
+            dst     = dst_buf+dstpitch*(height-1);
+            ac_memcpy (dst, src, width);
+
+            /* copy Cb and Cr */
+            ac_memcpy (dst_buf+dstpitch*height, src_buf+srcpitch*height, width*height>>1);
+
+            src	= src_buf;
+            dst	= dst_buf;
+            for (y = 0; y < height; y++){
+                *dst = *src;
+                *(dst+width-1) = *(src+width-1);
+                dst += dstpitch;
+                src += srcpitch;
+            }
+
+            src = src_buf+srcpitch;
+            dst = dst_buf+dstpitch;
+
+            /* Finally run the 3x3 rank-order sharpening kernel over the pixels. */
+            for (y = 1; y < height - 1; y++){
+                for (x = 1; x < width - 1; x++){
+                    /* Find the brightest and dimmest pixels in the 3x3 window
+                       surrounding the current pixel. */
+                    lumamax = -1000;
+                    lumamin = 1000;
+
+                    luma = (src - srcpitch)[x-1] &0xff;
+                    if (luma > lumamax)
+                        lumamax = luma;
+                    if (luma < lumamin)
+                        lumamin = luma;
+
+                    luma = (src - srcpitch)[x] &0xff;
+                    if (luma > lumamax)
+                        lumamax = luma;
+                    if (luma < lumamin)
+                        lumamin = luma;
+                    luma = (src - srcpitch)[x+1] &0xff;
+                    if (luma > lumamax)
+                        lumamax = luma;
+                    if (luma < lumamin)
+                        lumamin = luma;
+
+                    luma = src[x-1] &0xff;
+                    if (luma > lumamax)
+                        lumamax = luma;
+                    if (luma < lumamin)
+                        lumamin = luma;
+                    luma = src[x] &0xff;
+                    lumac = luma;
+                    if (luma > lumamax)
+                        lumamax = luma;
+                    if (luma < lumamin)
+                        lumamin = luma;
+
+                    luma = src[x+1] &0xff;
+                    if (luma > lumamax)
+                        lumamax = luma;
+                    if (luma < lumamin)
+                        lumamin = luma;
+
+                    luma = (src + srcpitch)[x-1] &0xff;
+                    if (luma > lumamax)
+                        lumamax = luma;
+                    if (luma < lumamin)
+                        lumamin = luma;
+
+                    luma = (src + srcpitch)[x] &0xff;
+                    if (luma > lumamax)
+                        lumamax = luma;
+                    if (luma < lumamin)
+                        lumamin = luma;
+
+                    luma = (src + srcpitch)[x+1] &0xff;
+                    if (luma > lumamax)
+                        lumamax = luma;
+                    if (luma < lumamin)
+                        lumamin = luma;
+
+                    /* Determine whether the current pixel is closer to the
+                       brightest or the dimmest pixel. Then compare the current
+                       pixel to that closest pixel. If the difference is within
+                       threshold, map the current pixel to the closest pixel;
+                       otherwise pass it through. */
+
+                    p = -1;
+                    if (mfd->strength != 0){
+                        mindiff = lumac   - lumamin;
+                        maxdiff = lumamax - lumac;
+                        if (mindiff > maxdiff){
+                            if (maxdiff < mfd->threshold)
+                            p = lumamax&0xff;
+                        }else{
+                            if (mindiff < mfd->threshold)
+                            p = lumamin&0xff;
+                        }
+                    }
+                    if (p == -1){
+                        dst[x] = src[x];
+                    }else{
+                        int t;
+                        lumac = src[x] &0xff;
+                        t = ((mfd->strength*p + mfd->strengthInv*lumac)/255) & 0xff;
+                        if (t>240) t = 240;
+                        if (t<16)  t = 16;
+                        dst[x] = t&0xff;
+                    }
+                }
+                src += srcpitch;
+                dst += dstpitch;
+            }
+
+            ac_memcpy (frame->video_buf, dst_buf, width*height*3/2);
+            return TC_OK;
+        }
+    }
+    return TC_OK;
+}
+
+/*************************************************************************/
+
+static const TCCodecID xsharpen_codecs_in[] = { 
+    TC_CODEC_RGB, TC_CODEC_YUV420P, TC_CODEC_ERROR
+};
+static const TCCodecID xsharpen_codecs_out[] = {
+    TC_CODEC_RGB, TC_CODEC_YUV420P, TC_CODEC_ERROR
+};
+static const TCFormatID xsharpen_formats[] = {
+    TC_FORMAT_ERROR
+};
+
+static const TCModuleInfo xsharpen_info = {
+    .features    = MOD_FEATURES,
+    .flags       = MOD_FLAGS,
+    .name        = MOD_NAME,
+    .version     = MOD_VERSION,
+    .description = MOD_CAP,
+    .codecs_in   = xsharpen_codecs_in,
+    .codecs_out  = xsharpen_codecs_out,
+    .formats_in  = xsharpen_formats,
+    .formats_out = xsharpen_formats
+};
+
+static const TCModuleClass xsharpen_class = {
+    .info         = &xsharpen_info,
+
+    .init         = xsharpen_init,
+    .fini         = xsharpen_fini,
+    .configure    = xsharpen_configure,
+    .stop         = xsharpen_stop,
+    .inspect      = xsharpen_inspect,
+
+    .filter_video = xsharpen_filter_video
+};
+
+extern const TCModuleClass *tc_plugin_setup(void)
+{
+    return &xsharpen_class;
+}
+
+/*************************************************************************/
+
+static int xsharpen_get_config(TCModuleInstance *self, char *options)
+{
+    MyFilterData *mfd = NULL;
+    char buf[TC_BUF_MIN];
+
+    TC_MODULE_SELF_CHECK(self, "get_config");
+
+    mfd = self->userdata;
+
+    optstr_filter_desc(options, MOD_NAME, MOD_CAP, MOD_VERSION,
+                       MOD_AUTHOR, "VRYO", "1");
+
+    /* can be omitted */
+    optstr_param (options, "help", "VirtualDub's XSharpen Filter", "", "0");
+
+    tc_snprintf (buf, sizeof(buf), "%d", mfd->strength);
+    optstr_param (options, "strength", "How much  of the effect", "%d", buf, "0", "255");
+
+    tc_snprintf (buf, sizeof(buf), "%d", mfd->threshold);
+    optstr_param (options, "threshold",
+        "How close a pixel must be to the brightest or dimmest pixel to be mapped",
+        "%d", buf, "0", "255");
+
+    return TC_OK;
+}
+
+
+static int xsharpen_process(TCModuleInstance *self, 
+                            frame_list_t *frame)
+{
+    TC_MODULE_SELF_CHECK(self, "process");
+
+    if (frame->tag & TC_VIDEO) {
+        return xsharpen_filter_video(self, (vframe_list_t*)frame);
+    }
+    return TC_OK;
+}
+
+/*************************************************************************/
+
+/* Old-fashioned module interface. */
+
+TC_FILTER_OLDINTERFACE(xsharpen)
+
+/*************************************************************************/
+
+/*
+ * Local variables:
+ *   c-file-style: "stroustrup"
+ *   c-file-offsets: ((case-label . *) (statement-case-intro . *))
+ *   indent-tabs-mode: nil
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+ */

Reply via email to