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

greetings, branko kokanovic
Index: filter/filter_facemask.c
===================================================================
RCS file: /cvstc/transcode/filter/filter_facemask.c,v
retrieving revision 1.18
diff -u -r1.18 filter_facemask.c
--- filter/filter_facemask.c	29 Sep 2006 05:03:09 -0000	1.18
+++ filter/filter_facemask.c	29 Jul 2007 18:20:46 -0000
@@ -1,9 +1,9 @@
 /*
- *  filter_facemask.c
+ *  filter_facemask.c -- mask people faces in video interviews
  *
  *  Copyright (C) Julien Tierny <[EMAIL PROTECTED]> - October 2004
  *  Copyright (C) Thomas Oestreich - June 2001
- *
+ *      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
  *
  *  transcode is free software; you can redistribute it and/or modify
@@ -23,27 +23,47 @@
  */
 
 #define MOD_NAME    "filter_facemask.so"
-#define MOD_VERSION "v0.2 (2004-11-01)"
+#define MOD_VERSION "v0.2.1 (2007-07-29)"
 #define MOD_CAP     "Mask people faces in video interviews."
 #define MOD_AUTHOR  "Julien Tierny"
+#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"
 /* For RGB->YUV conversion */
 #include "libtcvideo/tcvideo.h"
 
+static const char facemask_help[]=""
+    "Overview:\n"
+    "   This filter can mask people faces in video interviews.\n"
+    "   Both YUV and RGB formats are supported, in multithreaded mode.\n"
+    "\n"
+    "   Warning:\n"
+    "   You have to calibrate by your own the mask dimensions and positions so as it fits to your video sample.\n"
+    "   You also have to choose a resolution that is multiple of the mask dimensions.\n"
+    "\n"
+    "Options:\n"
+    "   'xpos':        Position of the upper left corner of the mask (x)\n"
+    "   'ypos':        Position of the upper left corner of the mask (y)\n"
+    "   'xresolution': Resolution of the mask (width)\n"
+    "   'yresolution': Resolution of the mask (height)\n"
+    "   'xdim':        Width of the mask (= n*xresolution)\n"
+    "   'ydim':        Height of the mask (= m*yresolution)\n";
 
-/*-------------------------------------------------
- *
- * single function interface
- *
- *-------------------------------------------------*/
-
-
-typedef struct parameter_struct {
+/*************************************************************************/
+typedef struct {
 	int 	xpos;
 	int	ypos;
 	int	xresolution;
@@ -51,30 +71,9 @@
 	int	xdim;
 	int	ydim;
 	TCVHandle tcvhandle;
-} parameter_struct;
-
-static parameter_struct *parameters = NULL;
-
-static void help_optstr(void)
-{
-    tc_log_info(MOD_NAME, "(%s) help"
-"\n* Overview:\n"
-"  This filter can mask people faces in video interviews.\n"
-"  Both YUV and RGB formats are supported, in multithreaded mode.\n"
-"\n"
-"* Warning:\n"
-"  You have to calibrate by your own the mask dimensions and positions so as it fits to your video sample.\n"
-"  You also have to choose a resolution that is multiple of the mask dimensions.\n"
-"\n"
-"* Options:\n"
-"  'xpos':        Position of the upper left corner of the mask (x)\n"
-"  'ypos':        Position of the upper left corner of the mask (y)\n"
-"  'xresolution': Resolution of the mask (width)\n"
-"  'yresolution': Resolution of the mask (height)\n"
-"  'xdim':        Width of the mask (= n*xresolution)\n"
-"  'ydim':        Height of the mask (= m*yresolution)\n"
-		, MOD_CAP);
-}
+    int codec;
+    char conf_str[TC_BUF_MIN];
+} FacemaskPrivateData;
 
 static int check_parameters(int x, int y, int w, int h, int W, int H, vob_t *vob){
 
@@ -134,131 +133,331 @@
 	return 0;
 }
 
-int tc_filter(frame_list_t *ptr_, char *options){
-	vframe_list_t *ptr = (vframe_list_t *)ptr_;
-	static 			vob_t *vob=NULL;
+/*************************************************************************/
 
+/* Module interface routines and data. */
 
-  if(ptr->tag & TC_FILTER_GET_CONFIG) {
-
-	optstr_filter_desc (options, MOD_NAME, MOD_CAP, MOD_VERSION, "Julien Tierny", "VRYMEO", "1");
-	optstr_param(options, "xpos", "Position of the upper left corner of the mask (x)", "%d", "0", "0", "oo");
-	optstr_param(options, "ypos", "Position of the upper left corner of the mask (y)", "%d", "0", "0", "oo");
-	optstr_param(options, "xresolution", "Resolution of the mask (width)", "%d", "0", "1", "oo");
-	optstr_param(options, "yresolution", "Resolution of the mask (height)", "%d", "0", "1", "oo");
-	optstr_param(options, "xdim", "Width of the mask (= n*xresolution)", "%d", "0", "1", "oo");
-	optstr_param(options, "ydim", "Height of the mask (= m*yresolution)", "%d", "0", "1", "oo");
-	return 0;
-  }
+/*************************************************************************/
 
-  //----------------------------------
-  //
-  // filter init
-  //
-  //----------------------------------
+/**
+ * facemask_init:  Initialize this instance of the module.  See
+ * tcmodule-data.h for function details.
+ */
 
+static int facemask_init(TCModuleInstance *self, uint32_t features)
+{
+    FacemaskPrivateData *fpd = NULL;
 
-  if(ptr->tag & TC_FILTER_INIT) {
+    TC_MODULE_SELF_CHECK(self, "init");
+    TC_MODULE_INIT_CHECK(self, MOD_FEATURES, features);
 
-    if((vob = tc_get_vob())==NULL)
-		return(-1);
+    fpd = tc_malloc(sizeof(FacemaskPrivateData));
+    if (!fpd) {
+        tc_log_error(MOD_NAME, "init: out of memory!");
+        return TC_ERROR;
+    }
+    self->userdata = fpd;
+
+    /* initialize data */
+    fpd->xpos           = 0;
+    fpd->ypos           = 0;
+    fpd->xresolution    = 1;
+    fpd->yresolution    = 1;
+    fpd->xdim           = 1;
+    fpd->ydim           = 1;
+    fpd->tcvhandle      = 0;
+
+    if(verbose) {
+        tc_log_info(MOD_NAME, "%s %s", MOD_VERSION, MOD_CAP);
+    }
+    return TC_OK;
+}
 
+/*************************************************************************/
 
-	/* Now, let's handle the options ... */
-	parameters = tc_malloc (sizeof(parameter_struct));
-	if(parameters == NULL)
-		return -1;
+/**
+ * facemask_fini:  Clean up after this instance of the module.  See
+ * tcmodule-data.h for function details.
+ */
+
+static int facemask_fini(TCModuleInstance *self)
+{
+    FacemaskPrivateData *fpd = NULL;
+
+    TC_MODULE_SELF_CHECK(self, "fini");
+
+    fpd = self->userdata;
+
+    if (fpd->tcvhandle){
+        tcv_free(fpd->tcvhandle);
+    }
+
+    tc_free(self->userdata);
+    self->userdata = NULL;
+
+    return TC_OK;
+}
+
+/*************************************************************************/
+
+/**
+ * facemask_configure:  Configure this instance of the module.  See
+ * tcmodule-data.h for function details.
+ */
+
+static int facemask_configure(TCModuleInstance *self,
+                          const char *options, vob_t *vob)
+{
+    FacemaskPrivateData *fpd = NULL;
+
+    TC_MODULE_SELF_CHECK(self, "configure");
+
+    fpd = self->userdata;
+
+    if(vob == NULL){
+        return TC_ERROR;
+    }
 
 	/* Filter default options */
-	if (verbose & TC_DEBUG)
-		tc_log_info(MOD_NAME, "Preparing default options.");
-	parameters->xpos 		= 0;
-	parameters->ypos 		= 0;
-	parameters->xresolution	= 1;
-	parameters->yresolution	= 1;
-	parameters->xdim		= 1;
-	parameters->ydim		= 1;
-	parameters->tcvhandle	= 0;
-
-	if (options){
-		/* Get filter options via transcode core */
-		if (verbose & TC_DEBUG)
-			tc_log_info(MOD_NAME, "Merging options from transcode.");
-		optstr_get(options, "xpos",  		 	"%d",		&parameters->xpos);
-		optstr_get(options, "ypos",   			"%d",		&parameters->ypos);
-		optstr_get(options, "xresolution",   	"%d",		&parameters->xresolution);
-		optstr_get(options, "yresolution",   	"%d",		&parameters->yresolution);
-		optstr_get(options, "xdim",			   	"%d",		&parameters->xdim);
-		optstr_get(options, "ydim",			   	"%d",		&parameters->ydim);
-		if (optstr_lookup(options, "help") !=NULL) help_optstr();
+    if (verbose & TC_DEBUG)
+        tc_log_info(MOD_NAME, "Preparing default options.");
+    fpd->codec          = vob->im_v_codec;
+    fpd->xpos           = 0;
+    fpd->ypos           = 0;
+    fpd->xresolution    = 1;
+    fpd->yresolution    = 1;
+    fpd->xdim           = 1;
+    fpd->ydim           = 1;
+    fpd->tcvhandle      = 0;
+
+	if (options) {
+        if (verbose >= TC_STATS) {
+            tc_log_info(MOD_NAME, "options=%s", options);
+        }
+        optstr_get(options, "xpos",  		 	"%d",		&fpd->xpos);
+        optstr_get(options, "ypos",   			"%d",		&fpd->ypos);
+        optstr_get(options, "xresolution",   	"%d",		&fpd->xresolution);
+        optstr_get(options, "yresolution",   	"%d",		&fpd->yresolution);
+        optstr_get(options, "xdim",			   	"%d",		&fpd->xdim);
+        optstr_get(options, "ydim",			   	"%d",		&fpd->ydim);
 	}
 
-	if (vob->im_v_codec == CODEC_YUV){
-		if (!(parameters->tcvhandle = tcv_init())) {
-			tc_log_error(MOD_NAME, "Error at image conversion initialization.");
-			return(-1);
-		}
-	}
+    if (vob->im_v_codec == CODEC_YUV){
+        fpd->tcvhandle = tcv_init();
+        if (!fpd->tcvhandle) {
+            tc_log_error(MOD_NAME, "Error at image conversion initialization.");
+            return TC_ERROR;
+        }
+    }
+
+    if (check_parameters(fpd->xpos, fpd->ypos, fpd->xresolution, fpd->yresolution, fpd->xdim, fpd->ydim, vob) < 0){
+        return TC_ERROR;
+    }
 
-	if (check_parameters(parameters->xpos, parameters->ypos, parameters->xresolution, parameters->yresolution, parameters->xdim, parameters->ydim, vob) < 0)
-		return -1;
+    return TC_OK;
+}
 
-	if(verbose)
-		tc_log_info(MOD_NAME, "%s %s", MOD_VERSION, MOD_CAP);
+/*************************************************************************/
 
-    return(0);
-  }
+/**
+ * facemask_stop:  Reset this instance of the module.  See tcmodule-data.h
+ * for function details.
+ */
 
-  //----------------------------------
-  //
-  // filter close
-  //
-  //----------------------------------
+static int facemask_stop(TCModuleInstance *self)
+{
+    TC_MODULE_SELF_CHECK(self, "stop");
+    return TC_OK;
+}
 
+/*************************************************************************/
 
-  if(ptr->tag & TC_FILTER_CLOSE) {
+/**
+ * facemask_inspect:  Return the value of an option in this instance of
+ * the module.  See tcmodule-data.h for function details.
+ */
 
-	tcv_free(parameters->tcvhandle);
+static int facemask_inspect(TCModuleInstance *self,
+                        const char *param, const char **value)
+{
+    FacemaskPrivateData *fpd = NULL;
 
-	/* Let's free the parameter structure */
-	free(parameters);
-	parameters = NULL;
+    TC_MODULE_SELF_CHECK(self, "inspect");
+    TC_MODULE_SELF_CHECK(param, "inspect");
+    TC_MODULE_SELF_CHECK(value, "inspect");
+
+    fpd = self->userdata;
+
+    if (optstr_lookup(param, "help")) {
+        *value = facemask_help; 
+    }
+    if (optstr_lookup(param, "xpos")) {
+        tc_snprintf(fpd->conf_str, sizeof(fpd->conf_str),"xpos=%d",fpd->xpos);
+        *value = fpd->conf_str;
+    }
+    if (optstr_lookup(param, "ypos")) {
+        tc_snprintf(fpd->conf_str, sizeof(fpd->conf_str),"ypos=%d",fpd->xpos);
+        *value = fpd->conf_str;
+    }
+    if (optstr_lookup(param, "xresolution")) {
+        tc_snprintf(fpd->conf_str, sizeof(fpd->conf_str),"xresolution=%d",fpd->xpos);
+        *value = fpd->conf_str;
+    }
+    if (optstr_lookup(param, "yresolution")) {
+        tc_snprintf(fpd->conf_str, sizeof(fpd->conf_str),"yresolution=%d",fpd->xpos);
+        *value = fpd->conf_str;
+    }
+    if (optstr_lookup(param, "xdim")) {
+        tc_snprintf(fpd->conf_str, sizeof(fpd->conf_str),"xdim=%d",fpd->xpos);
+        *value = fpd->conf_str;
+    }
+    if (optstr_lookup(param, "ydim")) {
+        tc_snprintf(fpd->conf_str, sizeof(fpd->conf_str),"ydim=%d",fpd->xpos);
+        *value = fpd->conf_str;
+    }
 
-    return(0);
-  }
+    return TC_OK;
+}
 
-  //----------------------------------
-  //
-  // filter frame routine
-  //
-  //----------------------------------
+/*************************************************************************/
 
-	if(ptr->tag & TC_POST_M_PROCESS && ptr->tag & TC_VIDEO && !(ptr->attributes & TC_FRAME_IS_SKIPPED)) {
+/**
+ * facemask_filter_video:  show something on given frame of the video
+ * stream.  See tcmodule-data.h for function details.
+ */
 
+static int facemask_filter_video(TCModuleInstance *self, vframe_list_t *frame)
+{
+    FacemaskPrivateData *fpd = NULL;
+    int post = 0;
 
-		switch(vob->im_v_codec){
-			case CODEC_RGB:
-				return print_mask(parameters->xpos, parameters->ypos, parameters->xresolution, parameters->yresolution, parameters->xdim, parameters->ydim, ptr);
-				break;
+    TC_MODULE_SELF_CHECK(self, "filer_video");
+    TC_MODULE_SELF_CHECK(frame, "filer_video");
 
-			case CODEC_YUV:
+    fpd = self->userdata;
+    post = (frame->tag & TC_POST_M_PROCESS);
 
-				if (!tcv_convert(parameters->tcvhandle, ptr->video_buf, ptr->video_buf, ptr->v_width, ptr->v_height, IMG_YUV_DEFAULT, IMG_RGB24)){
-					tc_log_error(MOD_NAME, "cannot convert YUV stream to RGB format !");
-					return -1;
+    if(post && !(frame->attributes & TC_FRAME_IS_SKIPPED)) {
+        switch(fpd->codec){
+            case CODEC_RGB:
+                return print_mask(fpd->xpos, fpd->ypos, fpd->xresolution, fpd->yresolution, fpd->xdim, fpd->ydim, frame);
+                break;
+            case CODEC_YUV:
+                if (!tcv_convert(fpd->tcvhandle, frame->video_buf, frame->video_buf, frame->v_width, frame->v_height,
+                        IMG_YUV_DEFAULT, IMG_RGB24)){
+                    tc_log_error(MOD_NAME, "cannot convert YUV stream to RGB format !");
+                    return TC_ERROR;
 				}
 
-				if ((print_mask(parameters->xpos, parameters->ypos, parameters->xresolution, parameters->yresolution, parameters->xdim, parameters->ydim, ptr))<0) return -1;
-				if (!tcv_convert(parameters->tcvhandle, ptr->video_buf, ptr->video_buf, ptr->v_width, ptr->v_height, IMG_RGB24, IMG_YUV_DEFAULT)){
-					tc_log_error(MOD_NAME, "cannot convert RGB stream to YUV format !");
-					return -1;
-				}
-				break;
+                if ((print_mask(fpd->xpos, fpd->ypos, fpd->xresolution, fpd->yresolution, fpd->xdim, fpd->ydim, frame))<0) {
+                    return TC_ERROR;
+                }
+
+                if (!tcv_convert(fpd->tcvhandle, frame->video_buf, frame->video_buf, frame->v_width, frame->v_height,
+                        IMG_RGB24, IMG_YUV_DEFAULT)){
+                    tc_log_error(MOD_NAME, "cannot convert RGB stream to YUV format !");
+                    return TC_ERROR;
+                }
+                break;
+            default:
+                tc_log_error(MOD_NAME, "Internal video codec is not supported.");
+                return TC_ERROR;
+        }
+    }
+    return TC_OK;
+}
 
-			default:
-				tc_log_error(MOD_NAME, "Internal video codec is not supported.");
-				return -1;
-		}
-	}
-	return(0);
+
+/*************************************************************************/
+
+static const TCCodecID facemask_codecs_in[] = { 
+    TC_CODEC_RGB, TC_CODEC_YUV420P, TC_CODEC_ERROR
+};
+static const TCCodecID facemask_codecs_out[] = {
+    TC_CODEC_RGB, TC_CODEC_YUV420P, TC_CODEC_ERROR
+};
+static const TCFormatID facemask_formats[] = {
+    TC_FORMAT_ERROR
+};
+
+static const TCModuleInfo facemask_info = {
+    .features    = MOD_FEATURES,
+    .flags       = MOD_FLAGS,
+    .name        = MOD_NAME,
+    .version     = MOD_VERSION,
+    .description = MOD_CAP,
+    .codecs_in   = facemask_codecs_in,
+    .codecs_out  = facemask_codecs_out,
+    .formats_in  = facemask_formats,
+    .formats_out = facemask_formats
+};
+
+static const TCModuleClass facemask_class = {
+    .info         = &facemask_info,
+
+    .init         = facemask_init,
+    .fini         = facemask_fini,
+    .configure    = facemask_configure,
+    .stop         = facemask_stop,
+    .inspect      = facemask_inspect,
+
+    .filter_video = facemask_filter_video
+};
+
+extern const TCModuleClass *tc_plugin_setup(void)
+{
+    return &facemask_class;
 }
+
+/*************************************************************************/
+
+static int facemask_get_config(TCModuleInstance *self, char *options)
+{
+    FacemaskPrivateData *fpd = NULL;
+
+    TC_MODULE_SELF_CHECK(self, "get_config");
+
+    fpd = self->userdata;
+
+    optstr_filter_desc(options, MOD_NAME, MOD_CAP, MOD_VERSION,
+                       MOD_AUTHOR, "VRYMEO", "1");
+
+    optstr_param (options, "help", "Mask people faces in video interviews", "", "0");
+    optstr_param(options, "xpos", "Position of the upper left corner of the mask (x)", "%d", "0", "0", "oo");
+    optstr_param(options, "ypos", "Position of the upper left corner of the mask (y)", "%d", "0", "0", "oo");
+    optstr_param(options, "xresolution", "Resolution of the mask (width)", "%d", "0", "1", "oo");
+    optstr_param(options, "yresolution", "Resolution of the mask (height)", "%d", "0", "1", "oo");
+    optstr_param(options, "xdim", "Width of the mask (= n*xresolution)", "%d", "0", "1", "oo");
+    optstr_param(options, "ydim", "Height of the mask (= m*yresolution)", "%d", "0", "1", "oo");
+
+    return TC_OK;
+}
+
+static int facemask_process(TCModuleInstance *self, 
+                            frame_list_t *frame)
+{
+    TC_MODULE_SELF_CHECK(self, "process");
+
+    if (frame->tag & TC_VIDEO) {
+        return facemask_filter_video(self, (vframe_list_t*)frame);
+    }
+    return TC_OK;
+}
+
+/*************************************************************************/
+
+/* Old-fashioned module interface. */
+
+TC_FILTER_OLDINTERFACE(facemask)
+
+/*************************************************************************/
+
+/*
+ * 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