[vlc-devel] [PATCH] [3 commits merged] Added static detect filter. Added JPEG quality parameter to the sout-ffmpeg.

noxelia at gmail.com noxelia at gmail.com
Tue Aug 19 20:48:20 CEST 2008


From: basOS G <noxelia at gmail.com>

Static detect detects stationary images within a video and takes snapshots of them.
It fully parametrized to account for videos with different amount of irrelevant motion
(e.g. noise). Main parameters are motion threshold and stationary time. The module is
called static. Full parameter description with vlc -p static --advanced.
One more feuture that is to be combined with this plugin and the normal snapshot
functionality is the --sout-ffmpeg-qcompress value for tuning JPEG Quality factor. The
default was 0.5. I don't know if this parameter has side effects on video encoding but its
main usage is to combine with --snapshot-format jpg.

PS: I didn't intent to pollute the list. Please take this patch as the complete implementation of static detect
---
 configure.ac                         |    4 +-
 modules/codec/avcodec/avcodec.c      |    4 +-
 modules/codec/avcodec/avcodec.h      |    3 +
 modules/codec/avcodec/encoder.c      |    9 +-
 modules/video_filter/Modules.am      |    2 +
 modules/video_filter/beep.c          |  141 ++++++
 modules/video_filter/beep.h          |   15 +
 modules/video_filter/static_detect.c |  835 ++++++++++++++++++++++++++++++++++
 8 files changed, 1010 insertions(+), 3 deletions(-)
 create mode 100644 modules/video_filter/beep.c
 create mode 100644 modules/video_filter/beep.h
 create mode 100644 modules/video_filter/static_detect.c

diff --git a/configure.ac b/configure.ac
index 0e3e745..3cc9ca9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1135,6 +1135,8 @@ VLC_ADD_PLUGIN([ripple])
 VLC_ADD_PLUGIN([psychedelic])
 VLC_ADD_PLUGIN([gradient])
 VLC_ADD_PLUGIN([motionblur])
+VLC_ADD_PLUGIN([staticdetect])
 VLC_ADD_PLUGIN([rv32])
 VLC_ADD_PLUGIN([rotate])
 VLC_ADD_PLUGIN([noise])
diff --git a/modules/codec/avcodec/avcodec.c b/modules/codec/avcodec/avcodec.c
index 3fa80a5..30dde7e 100644
--- a/modules/codec/avcodec/avcodec.c
+++ b/modules/codec/avcodec/avcodec.c
@@ -185,7 +185,9 @@ vlc_module_begin();
                  ENC_LUMA_ELIM_TEXT, ENC_LUMA_ELIM_LONGTEXT, true );
     add_integer( ENC_CFG_PREFIX "chroma-elim-threshold", 0, NULL,
                  ENC_CHROMA_ELIM_TEXT, ENC_CHROMA_ELIM_LONGTEXT, true );
-
+//MODA JPEG Q
+   add_float_with_range( ENC_CFG_PREFIX "qcompress", 0.5, 0.0, 1.0, NULL,
+                 ENC_QCOMPRESS_TEXT, NULL, true );
 #if LIBAVCODEC_VERSION_INT >= ((51<<16)+(40<<8)+4)
     /* Audio AAC encoder profile */
     add_string( ENC_CFG_PREFIX "aac-profile", "main", NULL,
diff --git a/modules/codec/avcodec/avcodec.h b/modules/codec/avcodec/avcodec.h
index 591d125..0c57840 100644
--- a/modules/codec/avcodec/avcodec.h
+++ b/modules/codec/avcodec/avcodec.h
@@ -224,6 +224,9 @@ void EndAudioDec( decoder_t *p_dec );
   "the PSNR isn't much changed (default: 0.0). The H264 specification " \
   "recommends 7." )
 
+//MODA JPEG Q
+#define ENC_QCOMPRESS_TEXT N_("Q Compress Value")
+
 #if LIBAVCODEC_VERSION_INT >= ((51<<16)+(40<<8)+4)
 #define ENC_PROFILE_TEXT N_( "Specify AAC audio profile to use" )
 #define ENC_PROFILE_LONGTEXT N_( "Specify the AAC audio profile to use " \
diff --git a/modules/codec/avcodec/encoder.c b/modules/codec/avcodec/encoder.c
index acd092f..e80293c 100644
--- a/modules/codec/avcodec/encoder.c
+++ b/modules/codec/avcodec/encoder.c
@@ -143,6 +143,7 @@ struct encoder_sys_t
     int        i_quality; /* for VBR */
     float      f_lumi_masking, f_dark_masking, f_p_masking, f_border_masking;
     int        i_luma_elim, i_chroma_elim;
+    float      f_qcompress ; /* MODA for JPEG QAULITY */
 #if LIBAVCODEC_VERSION_INT >= ((51<<16)+(40<<8)+4)
     int        i_aac_profile; /* AAC profile to use.*/
 #endif
@@ -161,6 +162,7 @@ static const char *const ppsz_enc_options[] = {
 #if LIBAVCODEC_VERSION_INT >= ((51<<16)+(40<<8)+4)
      "aac-profile",
 #endif
+/*MODA JPEG Q*/  "qcompress",
      NULL
 };
 
@@ -423,7 +425,12 @@ int OpenEncoder( vlc_object_t *p_this )
 
         /* Defaults from ffmpeg.c */
         p_context->qblur = 0.5;
-        p_context->qcompress = 0.5;
+        //MODA JPEG Q was 0.5
+        var_Get( p_enc, ENC_CFG_PREFIX "qcompress", &val );
+        if( val.f_float < 0.01 || val.f_float > 1.00 ) val.f_float = 0.5;
+        p_context->qcompress = val.f_float ;
+        msg_Dbg( p_enc, "Q Compress Value= %.2f", p_context->qcompress );
+
         p_context->b_quant_offset = 1.25;
         p_context->b_quant_factor = 1.25;
         p_context->i_quant_offset = 0.0;
diff --git a/modules/video_filter/Modules.am b/modules/video_filter/Modules.am
index 2268d9a..fb52578 100644
--- a/modules/video_filter/Modules.am
+++ b/modules/video_filter/Modules.am
@@ -44,4 +44,6 @@ SOURCES_chain = chain.c
 SOURCES_postproc = postproc.c
 SOURCES_swscale = swscale.c ../codec/avcodec/chroma.h
 SOURCES_imgresample = imgresample.c ../codec/avcodec/chroma.h
+# MODA static detect
+SOURCES_staticdetect = static_detect.c beep.c
 noinst_HEADERS = filter_common.h filter_picture.h
diff --git a/modules/video_filter/beep.c b/modules/video_filter/beep.c
new file mode 100644
index 0000000..6d2d5bc
--- /dev/null
+++ b/modules/video_filter/beep.c
@@ -0,0 +1,141 @@
+/* A Beep facility implemented on windows and linux */
+#include "beep.h"
+
+#ifdef __linux__
+/*  beep - just what it sounds like, makes the console beep - but with
+ * precision control.  See the man page for details.
+ *
+ *
+ * This code is copyright (C) Johnathan Nightingale, 2000.
+ *
+ * This code may distributed only under the terms of the GNU Public License
+ * which can be found at http://www.gnu.org/copyleft or in the file COPYING
+ * supplied with this code.
+ *
+ * This code is not distributed with warranties of any kind, including implied
+ * warranties of merchantability or fitness for a particular use or ability to
+ * breed pandas in captivity, it just can't be done.
+ *
+ * Bug me, I like it:  http://johnath.com/  or johnath at johnath.com
+ */
+
+#include <fcntl.h>
+#include <getopt.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <linux/kd.h>
+
+/* I don't know where this number comes from, I admit that freely.  A
+   wonderful human named Raine M. Ekman used it in a program that played
+   a tune at the console, and apparently, it's how the kernel likes its
+   sound requests to be phrased.  If you see Raine, thank him for me.
+
+   June 28, email from Peter Tirsek (peter at tirsek dot com):
+
+   This number represents the fixed frequency of the original PC XT's
+   timer chip (the 8254 AFAIR), which is approximately 1.193 MHz. This
+   number is divided with the desired frequency to obtain a counter value,
+   that is subsequently fed into the timer chip, tied to the PC speaker.
+   The chip decreases this counter at every tick (1.193 MHz) and when it
+   reaches zero, it toggles the state of the speaker (on/off, or in/out),
+   resets the counter to the original value, and starts over. The end
+   result of this is a tone at approximately the desired frequency. :)
+*/
+#ifndef CLOCK_TICK_RATE
+#define CLOCK_TICK_RATE 1193180
+#endif
+
+#define VERSION_STRING "beep-1.2.2"
+
+/* Meaningful Defaults */
+
+#define DEFAULT_REPS       1
+#define DEFAULT_DELAY      100   /* milliseconds */
+
+
+typedef struct beep_parms_t {
+  float freq;     /* tone frequency (Hz)      */
+  int length;     /* tone length    (ms)      */
+  int reps;       /* # of repetitions         */
+  int delay;      /* delay between reps  (ms) */
+} beep_parms_t;
+
+int play_beep(float freq, int length) {
+
+  int i; /* loop counter */
+  int console_fd; /* file descriptor */
+  beep_parms_t parms;
+
+  /* try to snag the console */
+  if((console_fd = open("/dev/console", O_WRONLY)) == -1) {
+    //fprintf(stderr, "Could not open /dev/console for writing.\n");
+    printf("\a");  /* Output the only beep we can, in an effort to fall back on usefulness */
+    return -1;
+  }
+
+  parms.freq       = ( freq ? freq : DEFAULT_FREQ );
+  parms.length     = ( length ? length : DEFAULT_LENGTH );
+  parms.reps       = DEFAULT_REPS;
+  parms.delay      = DEFAULT_DELAY;
+
+  /* Beep */
+  for (i = 0; i < parms.reps; i++) {                    /* start beep */
+    if(ioctl(console_fd, KIOCSOUND, (int)(CLOCK_TICK_RATE/parms.freq)) < 0) {
+      printf("\a");  /* Output the only beep we can, in an effort to fall back on usefulness */
+      return -2;
+    }
+    /* Look ma, I'm not ansi C compatible! */
+    usleep(1000*parms.length);                          /* wait...    */
+    ioctl(console_fd, KIOCSOUND, 0);                    /* stop beep  */
+    if(i+1 < parms.reps)
+       usleep(1000*parms.delay);                        /* wait...    */
+  }
+  close(console_fd);
+  return 0;
+}
+
+/* If we get interrupted, it would be nice to not leave the speaker beeping in
+   perpetuity. */
+/*void handle_signal(int signum) {
+  switch(signum) {
+  case SIGINT:
+    if(console_fd >= 0) {
+      // Kill the sound, quit gracefully
+      ioctl(console_fd, KIOCSOUND, 0);
+      close(console_fd);
+      exit(signum);
+    } else {
+      // Just quit gracefully
+      exit(signum);
+    }
+  }
+}*/
+
+
+#elif defined WIN32
+
+#include <windows.h>
+int play_beep( float freq, int length)
+{
+    int freqi = (int) freq;
+    if ( !freq ) freq = DEFAULT_FREQ;
+    if ( !length ) length = DEFAULT_LENGTH;
+    if ( freqi > 32767 || freqi < 37 )
+        return -10;
+    if ( Beep( freqi, length ) ) /* error occured */
+         return -11;
+    return 0;
+}
+
+#else
+/* Other Platforms should be quiet for now... */
+int play_beep( float freq, int length)
+{
+    return -40;
+}
+#endif
diff --git a/modules/video_filter/beep.h b/modules/video_filter/beep.h
new file mode 100644
index 0000000..e26cae5
--- /dev/null
+++ b/modules/video_filter/beep.h
@@ -0,0 +1,15 @@
+/* A Beep facility implemented on windows and linux */
+/* Prototype : we export a windows/linux beep function
+   arg1 frequency in Hz (notice that in windows the range is 37 to 32767 Hz)
+   arg2 beep duration in miliseconds
+   Return Value : 0 = success
+                  < 0 = error
+   Also note that in linux if we get interrupted by signal and the program exits
+      the console may still beeping
+
+   moded by basOS 2008
+*/
+int play_beep(float freq, int length);
+
+#define DEFAULT_FREQ       440.0 /* Middle A */
+#define DEFAULT_LENGTH     200   /* milliseconds */
diff --git a/modules/video_filter/static_detect.c b/modules/video_filter/static_detect.c
new file mode 100644
index 0000000..5815772
--- /dev/null
+++ b/modules/video_filter/static_detect.c
@@ -0,0 +1,835 @@
+/*****************************************************************************
+ * motion_blur.c : static detect filter for VLC
+ *****************************************************************************
+ * Copyright (C) 2008 the VideoLAN team
+ *
+ * Authors: basOS G <noxelia 4t gmai1 , c0m>
+ *  based on the work of Antoine Cellerier for motion detect VLC VFilter
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_vout.h>
+#include <vlc_filter.h>
+#include "filter_picture.h"
+#include "beep.h"
+#include <assert.h>
+/*#include <vlc/vlc.h>
+#include <vlc/libvlc_internal.h>
+*/
+
+/*****************************************************************************
+ * Help Data Types
+ *****************************************************************************/
+#undef NOIZ  /* Should we compile a noise reduction filter ? Leave it out for now w*/
+/*difference frame data type: 16 bit for now to account for overflow (8 bit per channel
+  x 3 channels: max diff is 256x3 = 768 : we need more than 8 bits */
+typedef uint16_t diff_t;
+typedef void ( *findDiffs_t )( diff_t*, picture_t*, picture_t*, filter_t *  );
+typedef void ( *motionMeter_t )( float , float , picture_t* , filter_t*  );
+/*typedef void ( *markPicture_t )( diff_t*, picture_t*, diff_t , filter_t * p_filter );*/
+
+/*****************************************************************************
+ * Local protypes
+ *****************************************************************************/
+static int  Create       ( vlc_object_t * );
+static void Destroy      ( vlc_object_t * );
+static picture_t *Filter ( filter_t *, picture_t * );
+
+/*****************************************************************************
+ ** Some Predefined Protos
+ *****************************************************************************/
+void findDiffs (diff_t* p_diff, picture_t* p_new_pic, picture_t* p_old_pic, filter_t * p_filter );
+void findDiffsPacked (diff_t* p_diff, picture_t* p_new_pic, picture_t* p_old_pic, filter_t * p_filter);
+#ifdef NOIZ
+static void GaussianConvolution( diff_t *p_inpix, picture_t* p_ref_pic );
+#endif
+float countMovedPixelsPercent( diff_t* p_diff, picture_t* p_ref_pic, diff_t i_motion_threshold );
+void motionMeter( float f_motion, float f_threshold, picture_t* p_out_pic, filter_t* p_filter );
+void motionMeterPacked( float f_motion, float f_threshold, picture_t* p_out_pic, filter_t* p_filter );
+
+/*void markPicture( diff_t* p_diff, picture_t* p_out_pic, diff_t , filter_t * p_filter );
+void markPicturePacked( diff_t* p_diff, picture_t* p_out_pic, diff_t , filter_t * p_filter ); */
+/*TODO :static int StaticDetectCallback( vlc_object_t *, char const *,
+                               vlc_value_t, vlc_value_t, void * );
+*/
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+#define MTHRESHOLD_TEXT N_("Motion Tolerance Percent")
+#define MTHRESHOLD_LONGTEXT N_("Percentage of image pixels that have to be changed for motion to be detected.")
+#define TTHRESHOLD_TEXT N_("Static Time needed for snapshot (mseconds)")
+#define TTHRESHOLD_LONGTEXT N_("Amount of time in mseconds that video should remain unchanged for a snapshot to occur.")
+#define DTHRESHOLD_TEXT N_("Motion Sensivity")
+#define DTHRESHOLD_LONGTEXT N_("Amount of chroma and luminance difference for two pixels to be considered changed. You should mess with Motion Tolerance first if you want to tune motion detection system sensivity.")
+#define FREEZE_TEXT N_("Snapshot Freeze Time (mseconds)")
+#define FREEZE_LONGTEXT N_("How long should the snapped image stay freezed on the video. Use 0 to disable")
+#define MOTIONM_TEXT N_("Display Motion meter")
+#define BEEP_TEXT N_("Beep When Static Detected")
+
+#define FILTER_PREFIX "staticdetect-"
+#define PAR_MTHRESHOLD "tolerance"
+#define PAR_TTHRESHOLD "snaptime"
+#define PAR_DTHRESHOLD "sensivity"
+#define PAR_FREEZETIME "freezetime"
+#define PAR_MMETER "motionmeter"
+#define PAR_BEEP "beep"
+
+/* default difference threshold */
+#define DEFAULT_DIFF_THRESHOLD 9
+/* default time threshold */
+#define DEFAULT_TIME_THRESHOLD 700
+/* default pix count percent threshold */
+#define DEFAULT_PIX_COUNT_THRESHOLD 1.1
+/*default motion meter stat */
+#define DEFAULT_MMETER true
+/* time the station mark should be presented (in msecs)*/
+#define DEFAULT_FREEZE_TIME 1200
+/* default beep status */
+#define DEFAULT_BEEP true
+
+vlc_module_begin();
+    set_shortname( N_("Static Image Detector") );
+    set_description( N_("Detects stationary images from a video and takes snapshots of them") );
+    set_capability( "video filter2", 0 );
+    set_category( CAT_VIDEO );
+    set_subcategory( SUBCAT_VIDEO_VFILTER );
+
+    add_float_with_range( FILTER_PREFIX PAR_MTHRESHOLD, DEFAULT_PIX_COUNT_THRESHOLD, 1, 100, NULL,
+                        MTHRESHOLD_TEXT, MTHRESHOLD_LONGTEXT, false );
+    add_integer ( FILTER_PREFIX PAR_TTHRESHOLD, DEFAULT_TIME_THRESHOLD, NULL,
+                        TTHRESHOLD_TEXT, TTHRESHOLD_LONGTEXT, false );
+    add_integer ( FILTER_PREFIX PAR_FREEZETIME, DEFAULT_FREEZE_TIME, NULL,
+                        FREEZE_TEXT, FREEZE_LONGTEXT, true );
+    add_integer_with_range ( FILTER_PREFIX PAR_DTHRESHOLD, DEFAULT_DIFF_THRESHOLD, 0, 768, NULL,
+			DTHRESHOLD_TEXT, DTHRESHOLD_LONGTEXT, false );
+    add_bool ( FILTER_PREFIX PAR_MMETER, DEFAULT_MMETER, NULL,
+                        MOTIONM_TEXT, NULL, false );
+    add_bool ( FILTER_PREFIX PAR_BEEP, DEFAULT_BEEP, NULL,
+			BEEP_TEXT, NULL, true );
+    add_shortcut( "static" );
+
+    set_callbacks( Create, Destroy );
+vlc_module_end();
+
+/*TOCHECK : WHAT is this for?? It parses command line args without it*/
+static const char *const psz_filter_options[] = {
+    PAR_MTHRESHOLD,
+    PAR_TTHRESHOLD,
+    PAR_DTHRESHOLD,
+    PAR_FREEZETIME,
+    PAR_MMETER,
+    PAR_BEEP,
+     NULL
+};
+
+
+/*****************************************************************************
+ * filter_sys_t
+ *****************************************************************************/
+struct filter_sys_t
+{
+    findDiffs_t pf_findDiffs ; /* findPixelDiffs: are we on a packed YCbCr data format? see www.fourcc.org */
+    /*markPicture_t pf_markPicture;*/ /* mark Pixel Diffs */
+    motionMeter_t pf_motionMeter; /* Draw a nice motion meter */
+
+    float f_pix_count_thres_percent ; /* motion threshold % pixels of an image */
+    int i_frame_thres ; /* time threshold of stationary image at msecs */
+    diff_t i_pix_diff_thres ;/* Difference of 2 pixels to mark it as changed */
+
+    bool b_is_snaped ; /* Is the picture snaped */
+    int i_static_frames ; /* # of static frames */
+    bool b_beep ; /* Should we beep ? */
+
+    picture_t* p_old_pic; /*previous frame */
+    bool b_has_old_pic;
+    diff_t* p_diff; /*difference frame */
+
+    picture_t* p_freeze_pic; /*difference frame for marking video output */
+    int i_freeze_frames; /* # of frames used for marking */
+    int i_freeze_counter; /* # of frames left to dispay the current differencies*/
+
+    /* various motion stats */
+    float f_motion_min;
+    float f_motion_max;
+    unsigned int i_motion_n;
+    float f_motion_avg;
+};
+
+/* Motion Statistics Handling */
+void resetStats( filter_t* p_filter )
+{
+    p_filter->p_sys->i_motion_n = 0;
+    p_filter->p_sys->f_motion_max = 0 ;
+    p_filter->p_sys->f_motion_min = 100 ;
+    p_filter->p_sys->f_motion_avg = 0 ;
+}
+void echoStats( filter_t* p_filter )
+{
+    msg_Dbg( p_filter, "Motion Stats:\n"
+             "[static]\tMinimum: %.4f\t Maximum: %.4f\tAverage: %.4f\tFrames:%d",
+             p_filter->p_sys->f_motion_min, p_filter->p_sys->f_motion_max,
+             p_filter->p_sys->f_motion_avg, p_filter->p_sys->i_motion_n );
+}
+
+/*****************************************************************************
+ ** Create
+ *****************************************************************************/
+static int Create( vlc_object_t *p_this )
+{
+    filter_t *p_filter = (filter_t *)p_this;
+    const video_format_t *p_fmt = &p_filter->fmt_in.video;
+    findDiffs_t pf_findDiffs;
+    //markPicture_t pf_markPicture;
+    motionMeter_t pf_motionMeter;
+    filter_sys_t *p_sys;
+
+    switch( p_fmt->i_chroma )
+    {
+        CASE_PLANAR_YUV
+            pf_findDiffs = findDiffs;
+            //pf_markPicture = markPicture;
+            pf_motionMeter = motionMeter;
+            msg_Dbg( p_filter, "Using YUV *Planar* Chroma") ;
+            break;
+
+        CASE_PACKED_YUV_422
+            pf_findDiffs = findDiffsPacked ;
+            //pf_markPicture = markPicturePacked ;
+            pf_motionMeter = motionMeterPacked ;
+            msg_Dbg( p_filter, "Using YUV *Packed* Chroma") ;
+            break;
+
+        default:
+            msg_Err( p_filter, "Unsupported input chroma (%4s)",
+                     (char*)&(p_fmt->i_chroma) );
+            return VLC_EGENERIC;
+    }
+
+    /* Allocate structure */
+    p_filter->p_sys = p_sys = malloc( sizeof( filter_sys_t ) );
+    if( p_sys == NULL )
+        return VLC_ENOMEM;
+
+
+
+    /* Parse config */
+    config_ChainParse( p_filter, FILTER_PREFIX, psz_filter_options,
+                       p_filter->p_cfg );
+    /* Initialize parameters */
+    p_sys->f_pix_count_thres_percent =
+        var_CreateGetFloatCommand( p_filter, FILTER_PREFIX PAR_MTHRESHOLD );
+    int i_time_threshold =
+        var_CreateGetIntegerCommand( p_filter, FILTER_PREFIX PAR_TTHRESHOLD );
+    float f_frame_rate ;
+    switch ( p_fmt->i_frame_rate_base )
+    { /* NASTY hack to deal with nasty frame rate values in various formats ... */
+        case 0 :
+            f_frame_rate = 25 ;
+        break;
+        case 1 :
+            f_frame_rate = ( (float) p_fmt->i_frame_rate / ( p_fmt->i_frame_rate > 1000 ? 1000 : 1 ) ) ;
+        break;
+        default :
+            f_frame_rate = ( (float) p_fmt->i_frame_rate / p_fmt->i_frame_rate_base ) ;
+    }
+    p_sys->i_frame_thres = ((float) i_time_threshold / 1000) * ( f_frame_rate ) ;
+    int i_freeze_time =
+        var_CreateGetIntegerCommand( p_filter, FILTER_PREFIX PAR_FREEZETIME );
+    msg_Dbg( p_filter, "frame rate=%d  base=%d:\n", p_fmt->i_frame_rate , p_fmt->i_frame_rate_base );
+    p_sys->i_freeze_frames =  ((float) i_freeze_time / 1000) * ( f_frame_rate ) ;
+    p_filter->p_sys->i_pix_diff_thres =
+        var_CreateGetIntegerCommand( p_filter, FILTER_PREFIX PAR_DTHRESHOLD );
+    bool b_meter = var_CreateGetBoolCommand( p_filter, FILTER_PREFIX PAR_MMETER );
+    if ( !b_meter)  pf_motionMeter = NULL;
+    p_sys->b_beep = var_CreateGetBoolCommand( p_filter, FILTER_PREFIX PAR_BEEP );
+
+    /*TODO : Check for callback meaning. Do we need it ?*/
+    /*var_AddCallback( p_filter, FILTER_PREFIX "factor",
+                     MotionBlurCallback, p_filter->p_sys );
+    */
+    msg_Dbg( p_filter, "Static Detect Parameters:\n"
+                       "\t[static] Pixel Count Threshold= %.2f\n"
+                       "\t[static] Frame Count Threshold= %d\n"
+                       "\t[static] Pixel Difference Threshold= %d\n"
+                       "\t[static] Motion Meter %s\n",
+                       p_filter->p_sys->f_pix_count_thres_percent,
+                       p_filter->p_sys->i_frame_thres, p_filter->p_sys->i_pix_diff_thres,
+                       ( b_meter ? "on" : "off" ) );
+
+    p_sys->p_old_pic = picture_New( p_fmt->i_chroma,
+                                p_fmt->i_width, p_fmt->i_height, 0 );
+    p_sys->p_freeze_pic = picture_New( p_fmt->i_chroma,
+                                p_fmt->i_width, p_fmt->i_height, 0 );
+
+    p_sys->p_diff  = calloc( p_fmt->i_width * p_fmt->i_height, sizeof(*p_sys->p_diff) );
+
+    if( !p_sys->p_old_pic || !p_sys->p_diff || !p_sys->p_freeze_pic )
+    {
+        free( p_sys->p_diff );
+        if( p_sys->p_old_pic )
+            picture_Release( p_sys->p_old_pic );
+        if( p_sys->p_freeze_pic )
+            picture_Release( p_sys->p_freeze_pic );
+        return VLC_ENOMEM;
+    }
+
+    p_sys->b_has_old_pic = false;
+    p_sys->i_freeze_counter = 0;
+
+    resetStats( p_filter );
+
+    /* libvlc event manager */
+    /*libvlc_exception_t e;
+    libvlc_exception_init( &e );
+    p_filter->p_event_manager = libvlc_event_manager_new( p_filter, p_filter->p_libvlc_instance, &e );
+    libvlc_event_manager_register_event_type( p_fitler->p_event_manager, libvlc_snapshotTaken, &e );'
+    */
+
+   /* Set Video Filter Proccessor */
+    p_filter->pf_video_filter = Filter;
+    p_sys->pf_findDiffs = pf_findDiffs ;
+    //p_sys->pf_markPicture = pf_markPicture ;
+    p_sys->pf_motionMeter = pf_motionMeter ;
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ ** Destroy
+ *****************************************************************************/
+static void Destroy( vlc_object_t *p_this )
+{
+    filter_t *p_filter = (filter_t *)p_this;
+
+    echoStats( p_filter );
+    free( p_filter->p_sys->p_diff );
+    picture_Release( p_filter->p_sys->p_freeze_pic );
+    picture_Release( p_filter->p_sys->p_old_pic );
+    free( p_filter->p_sys );
+}
+
+
+/*****************************************************************************
+ * Filter
+ *****************************************************************************/
+static picture_t *Filter( filter_t *p_filter, picture_t *p_in_pic )
+{
+    filter_sys_t *p_sys = p_filter->p_sys;
+    picture_t *p_out_pic;
+    diff_t *p_diff = p_sys->p_diff;
+
+    if( !p_in_pic ) /* we are called with empty pic */
+        return NULL;
+
+
+    if( !p_sys->b_has_old_pic )
+    {   /* It is the first time we are called */
+        picture_Copy( p_sys->p_old_pic, p_in_pic );
+        p_sys->i_static_frames = 0;
+        p_sys->b_is_snaped = false ;
+	p_sys->b_has_old_pic = true;
+        return p_in_pic;
+    }
+    p_out_pic = filter_NewPicture( p_filter );
+
+    if( !p_out_pic )
+    {
+        picture_Release( p_in_pic );
+        return NULL;
+    }
+
+#if 1
+    /* Find Differences */
+    (p_sys->pf_findDiffs) ( p_diff, p_in_pic, p_sys->p_old_pic, p_filter );
+
+#ifdef NOIZ
+    /* Clean Diff Image from noise */
+    GaussianConvolution( p_diff, p_in_pic );
+#endif
+
+    /* Count moved pixels */
+    float f_motion ;
+    if ( (f_motion = countMovedPixelsPercent (p_diff, p_in_pic, p_sys->i_pix_diff_thres) )
+            > p_sys->f_pix_count_thres_percent )
+    { /* we have motion: reset static state */
+        //msg_Dbg( p_filter, "Motion Detected. Reseting state" );
+        p_sys->i_static_frames = 0;
+        p_sys->b_is_snaped = false;
+        //(p_sys->pf_markPicture) ( p_sys->p_diff, p_out_pic, p_sys->i_pix_diff_thres, p_filter );
+    } else /* we have static */
+    {
+        p_sys->i_static_frames++;
+        if ( p_sys->i_static_frames >= p_sys->i_frame_thres )
+        { /* we are too long stationary : snap it if not alredy */
+             if ( !p_sys->b_is_snaped ) {
+                  int ec;
+                  msg_Dbg( p_filter, "Static Detected. Snapping NOW" );
+                  if ( ( p_sys->i_freeze_counter = p_sys->i_freeze_frames ) )
+                      picture_Copy( p_sys->p_freeze_pic, p_in_pic );
+                  vout_Snapshot( (vout_thread_t*) p_filter->p_owner, p_in_pic );
+                  /*vout_Control( (vout_thread_t*) p_filter->p_owner, VOUT_SNAPSHOT );*/
+                  if ( p_sys->b_beep )
+                       if ( (ec = play_beep ( 0, 0)) ) //play a default beep sound on the speaker
+                            msg_Warn( p_filter, "Error [%d] while Beeping",ec );
+                  p_sys->b_is_snaped = true;
+             }
+ #if 0
+             if ( p_sys->i_static_frames % 30 == 0 )
+                  msg_Dbg( p_filter, "Static Detected [%d]. %s", p_sys->i_static_frames,
+                 ( p_sys->b_is_snaped ? "Snapped" : "Not snapped" ) );
+#endif
+        }
+    }
+    if ( p_sys->i_motion_n % ( p_sys->i_frame_thres * 8 ) == 0 )
+    { /* echo stats every 8 times the static framecount */
+         echoStats( p_filter );
+         resetStats( p_filter );
+    }
+    /*update motion stats */
+    p_sys->f_motion_max = __MAX( p_sys->f_motion_max, f_motion );
+    p_sys->f_motion_min = __MIN( p_sys->f_motion_min, f_motion );
+    p_sys->f_motion_avg = ( p_sys->f_motion_avg * p_sys->i_motion_n + f_motion ) / ( ++p_sys->i_motion_n );
+
+    if ( p_sys->i_freeze_counter > 0 )
+    {
+        picture_Copy( p_out_pic, p_sys->p_freeze_pic );  /* Display the snapshot image for a while */
+        p_sys->i_freeze_counter-- ;
+    }
+    else
+        picture_Copy( p_out_pic, p_in_pic ); /* Just Copy the image data for display */
+
+    if (p_sys->pf_motionMeter)
+         ( p_sys->pf_motionMeter)( f_motion, p_sys->f_pix_count_thres_percent, p_out_pic, p_filter );
+#endif
+    /*
+     * We're done. Lets keep a copy of the picture
+     * TODO we may just picture_Release with a latency of 1 if the filters/vout
+     * handle it correctly */
+    picture_Copy( p_sys->p_old_pic, p_in_pic );
+
+    picture_Release( p_in_pic );
+    return p_out_pic;
+}
+
+void motionMeter( float f_motion, float f_threshold, picture_t* p_out_pic, filter_t* p_filter )
+{
+    /* Create a horizontial bar at the bottom of the picture showing the motion level */
+    const video_frame_format_t *p_fmt = &p_out_pic->format;
+    /* NOTE:  We take format type from picture (not from filter ) */
+    const unsigned int i_height = p_fmt->i_height;
+    const unsigned int i_width = p_fmt->i_width;
+
+    uint8_t* p_y_pix = p_out_pic->p[Y_PLANE].p_pixels;
+    const int i_y_pitch = p_out_pic->p[Y_PLANE].i_pitch;
+
+    unsigned int x,y;
+
+    #define HMARGIN  0.020  /* bar margin from left/right */
+    #define VMARGIN  0.010  /* bar margin from bottom */
+    #define BHEIGHT 0.025  /* bar height */
+    unsigned int i_bar_x1 = (float) i_width * HMARGIN ;
+    unsigned int i_bar_width = (float) i_width * ( 1 - 2 * HMARGIN ) ;
+    unsigned int i_bar_x2 = i_bar_x1 + i_bar_width ;
+    unsigned int i_bar_height = (float) i_height * ( BHEIGHT );
+    unsigned int i_bar_y1 = i_height - ( (float) i_height * VMARGIN + i_bar_height ) ;
+    unsigned int i_bar_y2 = i_height - ( (float) i_height * VMARGIN ) ;
+    unsigned int i_bar_value = ( f_motion / 100 ) * i_bar_width + i_bar_x1 ;
+    unsigned int i_bar_threshold = ( f_threshold / 100 ) * i_bar_width + i_bar_x1 ;
+    unsigned int i_bar_threshold_x1 = (float) i_bar_threshold * 0.98 ; /*thicken the threshold a little */
+    unsigned int i_bar_threshold_x2 = (float) i_bar_threshold * 1.02 ;
+    #undef HMARGIN
+    #undef VMARGIN
+    #undef BHEIGHT
+    /*fprintf( stderr, "static motionMeter value:%d thres:%d [%d-%d]\n", i_bar_value, i_bar_threshold,
+          i_bar_threshold_x1, i_bar_threshold_x2);
+    */
+    if ( !p_out_pic) return;
+
+    for (x = i_bar_x1; x <= i_bar_x2 ; x++)
+        for (y = i_bar_y1; y <= i_bar_y2; y++ )
+        {
+             if ( x <= i_bar_value ) // Draw Value
+                    p_y_pix[y*i_y_pitch+x] = 0xaf;
+             else if ( y == i_bar_y1 || y == i_bar_y2 || x == i_bar_x1 || x == i_bar_x2 ) // Draw surrounting rectangle
+                    p_y_pix[y*i_y_pitch+x] = 0xef;
+             if ( x >= i_bar_threshold_x1 && x <= i_bar_threshold_x2 ) // Draw Limit
+                    p_y_pix[y*i_y_pitch+x] = 0xff;
+        }
+}
+
+void motionMeterPacked( float f_motion, float f_threshold, picture_t* p_out_pic, filter_t* p_filter )
+{
+    /* Create a horizontial bar at the bottom of the picture showing the motion level */
+    const video_frame_format_t *p_fmt = &p_out_pic->format;
+    /* NOTE:  We take format type from picture (not from filter ) */
+    const unsigned int i_height = p_fmt->i_height;
+    const unsigned int i_width = p_fmt->i_width;
+
+    uint8_t* p_y_pix = p_out_pic->p[Y_PLANE].p_pixels;
+    const int i_y_pitch = p_out_pic->p[Y_PLANE].i_pitch;
+
+    unsigned int x,y;
+
+    if ( !p_out_pic) return;
+
+    #define HMARGIN  0.020  /* bar margin from left/right */
+    #define VMARGIN  0.010  /* bar margin from bottom */
+    #define BHEIGHT 0.025  /* bar height */
+    unsigned int i_bar_x1 = (float) i_width * HMARGIN ;
+    unsigned int i_bar_width = (float) i_width * ( 1 - 2 * HMARGIN ) ;
+    unsigned int i_bar_x2 = i_bar_x1 + i_bar_width ;
+    unsigned int i_bar_height = (float) i_height * ( BHEIGHT );
+    unsigned int i_bar_y1 = i_height - ( (float) i_height * VMARGIN + i_bar_height ) ;
+    unsigned int i_bar_y2 = i_height - ( (float) i_height * VMARGIN ) ;
+    unsigned int i_bar_value = ( f_motion / 100 ) * i_bar_width + i_bar_x1 ;
+    unsigned int i_bar_threshold = ( f_threshold / 100 ) * i_bar_width + i_bar_x1 ;
+    unsigned int i_bar_threshold_x1 = (float) i_bar_threshold * 0.98 ; /*thicken the threshold a little */
+    unsigned int i_bar_threshold_x2 = (float) i_bar_threshold * 1.02 ;
+    #undef HMARGIN
+    #undef VMARGIN
+    #undef BHEIGHT
+    /*fprintf( stderr, "static motionMeter value:%d thres:%d [%d-%d]\n", i_bar_value, i_bar_threshold,
+          i_bar_threshold_x1, i_bar_threshold_x2);
+    */
+    int i_y_offset, i_u_offset, i_v_offset;
+    if( GetPackedYuvOffsets( p_fmt->i_chroma,
+                             &i_y_offset, &i_u_offset, &i_v_offset ) != VLC_SUCCESS )
+    {
+        msg_Warn( p_filter, "Unsupported input chroma (%4s)",
+                  (char*)&p_fmt->i_chroma );
+        return ;
+    }
+
+    for( x = i_bar_x1; x <= i_bar_x2; x+=2 )
+    {
+        for( y = i_bar_y1; y < i_bar_y2; y++ )
+        /* 1 macropixel = 4 bytes = 2 image pixels. For we proccess 2 image pixels per itteration*/
+        {
+            int i;
+            for ( i = 0; i < 2; i++)
+            {
+               if ( x <= i_bar_value ) // Draw Value
+                    p_y_pix[y*i_y_pitch+2*(x+i)+i_y_offset] = 0xaf;
+               else if ( y == i_bar_y1 || y == i_bar_y2 || x == i_bar_x1 || x == i_bar_x2 )
+                    p_y_pix[y*i_y_pitch+2*(x+i)+i_y_offset] = 0xef; // Draw surrounting rectangle
+               if ( x >= i_bar_threshold_x1 && x <= i_bar_threshold_x2 )
+                    p_y_pix[y*i_y_pitch+2*(x+i)+i_y_offset] = 0xff; // Draw Limit
+            }
+        }
+    }
+}
+
+#if 0
+void markPicture( diff_t* p_diff, picture_t* p_out_pic, diff_t i_motion_thres, filter_t * p_filter )
+{
+    const video_frame_format_t *p_fmt = &p_out_pic->format;
+    // NOTE:  We take format type from picture (not from filter )
+    const unsigned int i_height = p_fmt->i_height;
+    const unsigned int i_width = p_fmt->i_width;
+
+    uint8_t* p_y_pix = p_out_pic->p[Y_PLANE].p_pixels;
+    const int i_y_pitch = p_out_pic->p[Y_PLANE].i_pitch;
+
+    unsigned int x,y;
+    //msg_Dbg( p_filter, "In markPicture" );
+    if ( !p_out_pic) return;
+
+    for (y = 0; y < i_height; y++ )
+        for (x = 0; x < i_width ; x++)
+        {
+               if ( p_diff[y*i_width+x] > i_motion_thres )
+                    p_y_pix[y*i_y_pitch+x] = 0xff;
+        }
+}
+
+void markPicturePacked( diff_t* p_diff, picture_t* p_out_pic,diff_t i_motion_thres, filter_t * p_filter )
+{
+    const video_frame_format_t *p_fmt = &p_out_pic->format;
+    // NOTE:  We take format type from picture (not from filter )
+    const unsigned int i_height = p_fmt->i_height;
+    const unsigned int i_width = p_fmt->i_width;
+
+    uint8_t* p_y_pix = p_out_pic->p[Y_PLANE].p_pixels;
+    const int i_y_pitch = p_out_pic->p[Y_PLANE].i_pitch;
+
+    unsigned int x,y;
+    int i_y_offset, i_u_offset, i_v_offset;
+    //msg_Dbg( p_filter, "In markPicturePacked" );
+
+   if( GetPackedYuvOffsets( p_fmt->i_chroma,
+                             &i_y_offset, &i_u_offset, &i_v_offset ) != VLC_SUCCESS )
+    {
+        msg_Warn( p_filter, "Unsupported input chroma (%4s)",
+                  (char*)&p_fmt->i_chroma );
+
+         return ;
+    }
+
+    for( y = 0; y < i_height; y++ )
+    {
+        for( x = 0; x < i_width; x+=2 )
+        // 1 macropixel = 4 bytes = 2 image pixels. For we proccess 2 image pixels per itteration
+        {
+            int i;
+            for ( i = 0; i < 2; i++)
+                if ( p_diff[y*i_width+x] > i_motion_thres )
+                     p_y_pix[y*i_y_pitch+2*(x+i)+i_y_offset] = 0xff ;
+        }
+    }
+
+}
+#endif
+
+float countMovedPixelsPercent( diff_t* p_diff, picture_t* p_ref_pic, diff_t i_motion_threshold )
+{
+    const video_frame_format_t *p_fmt = &p_ref_pic->format;
+    /* NOTE:  We take format type from picture (not from filter ) */
+    const unsigned int i_height = p_fmt->i_height;
+    const unsigned int i_width = p_fmt->i_width;
+
+
+    unsigned int x,y,i_pix_count = 0;
+
+    for (y = 0; y < i_height; y++ )
+        for (x = 0; x < i_width ; x++)
+             if ( p_diff[y*i_width+x] > i_motion_threshold )
+                  i_pix_count++;
+    /*fprintf( stderr, "static detect: countMovedPixels: %d / %d [%f%%]\n", i_pix_count,
+                 ( i_height * i_width ), (float) i_pix_count / ( i_height * i_width ) * 100 );
+    */
+    /* Compute percentage of total pixel count */
+    return (float) ( i_pix_count ) / (float) ( i_height * i_width ) * 100 ;
+}
+
+void findDiffs (diff_t* p_diff, picture_t* p_new_pic, picture_t* p_old_pic, filter_t * p_filter )
+{
+    const video_frame_format_t *p_fmt = &p_new_pic->format;
+    /* NOTE:  We take format type from picture (not from filter ) */
+    const unsigned int i_height = p_fmt->i_height;
+    const unsigned int i_width = p_fmt->i_width;
+
+    const uint8_t* p_new_pix = p_new_pic->p[Y_PLANE].p_pixels;
+    const int i_new_pitch = p_new_pic->p[Y_PLANE].i_pitch;
+
+    const uint8_t *p_old_pix = p_old_pic->p[Y_PLANE].p_pixels;
+    const int i_old_pitch = p_old_pic->p[Y_PLANE].i_pitch;
+
+    /**
+     * Substract Y planes
+     */
+    unsigned x, y;
+    for( y = 0; y < i_height; y++ )
+    {
+        for( x = 0; x < i_width; x++ )
+            p_diff[y*i_width+x] = abs( p_new_pix[y*i_new_pitch+x] - p_old_pix[y*i_old_pitch+x] );
+    }
+
+    int i_chroma_dx;
+    int i_chroma_dy;
+    switch( p_new_pic->format.i_chroma )
+    /* NOTE: We check here with picture->format.i_chrome and we initialized with p_filter->fmt_in.video.i_chroma */
+    {
+        case VLC_FOURCC('I','4','2','0'):
+        case VLC_FOURCC('I','Y','U','V'):
+        case VLC_FOURCC('J','4','2','0'):
+        case VLC_FOURCC('Y','V','1','2'):
+            i_chroma_dx = 2;
+            i_chroma_dy = 2;
+            break;
+
+        case VLC_FOURCC('I','4','2','2'):
+        case VLC_FOURCC('J','4','2','2'):
+            i_chroma_dx = 2;
+            i_chroma_dy = 1;
+            break;
+
+        default:
+            //FIX: Is it ok to hang to the p_new_pic ??
+            msg_Warn( p_filter, "Not taking chroma into account" );
+            i_chroma_dx = 0;
+            i_chroma_dy = 0;
+            break;
+    }
+    /* Subtrack Cb (U) and Cr (V) planes */
+
+
+    if( i_chroma_dx != 0 && i_chroma_dy != 0 )
+    {
+        const uint8_t *p_new_pix_u = p_new_pic->p[U_PLANE].p_pixels;
+        const uint8_t *p_new_pix_v = p_new_pic->p[V_PLANE].p_pixels;
+        const int i_new_pitch_u = p_new_pic->p[U_PLANE].i_pitch;
+        const int i_new_pitch_v = p_new_pic->p[V_PLANE].i_pitch;
+
+        const uint8_t *p_old_pix_u = p_old_pic->p[U_PLANE].p_pixels;
+        const uint8_t *p_old_pix_v = p_old_pic->p[V_PLANE].p_pixels;
+        const int i_old_pitch_u = p_old_pic->p[U_PLANE].i_pitch;
+        const int i_old_pitch_v = p_old_pic->p[V_PLANE].i_pitch;
+
+        for( y = 0; y < i_height/i_chroma_dy; y++ )
+        {
+            for( x = 0; x < i_width/i_chroma_dx; x ++ )
+            {
+                const diff_t d = abs( p_new_pix_u[y*i_new_pitch_u+x] - p_old_pix_u[y*i_old_pitch_u+x] ) +
+                                 abs( p_new_pix_v[y*i_new_pitch_v+x] - p_old_pix_v[y*i_old_pitch_v+x] );
+                int i, j;
+
+                for( j = 0; j < i_chroma_dy; j++ )
+                {
+                    for( i = 0; i < i_chroma_dx; i++ )
+                        p_diff[i_chroma_dy*i_width*j + i_chroma_dx*i] += d;
+                }
+            }
+        }
+    }
+}
+
+void findDiffsPacked (diff_t* p_diff, picture_t* p_new_pic, picture_t* p_old_pic, filter_t * p_filter )
+{
+    const video_frame_format_t *p_fmt = &p_new_pic->format;
+    /* NOTE:  We take format type from picture (not from filter ) */
+    const unsigned int i_height = p_fmt->i_height;
+    const unsigned int i_width = p_fmt->i_width;
+
+    const uint8_t* p_new_pix = p_new_pic->p[Y_PLANE].p_pixels;
+    const int i_new_pitch = p_new_pic->p[Y_PLANE].i_pitch;
+
+    const uint8_t *p_old_pix = p_old_pic->p[Y_PLANE].p_pixels;
+    const int i_old_pitch = p_old_pic->p[Y_PLANE].i_pitch;
+
+    int i_y_offset, i_u_offset, i_v_offset;
+    unsigned x, y;
+
+    if( GetPackedYuvOffsets( p_fmt->i_chroma,
+                             &i_y_offset, &i_u_offset, &i_v_offset ) != VLC_SUCCESS )
+    {
+        msg_Warn( p_filter, "Unsupported input chroma (%4s)",
+                  (char*)&p_fmt->i_chroma );
+        return ;
+    }
+
+    /* Subtract all planes at once */
+
+    for( y = 0; y < i_height; y++ )
+    {
+        for( x = 0; x < i_width; x+=2 )
+        /* 1 macropixel = 4 bytes = 2 image pixels. For we proccess 2 image pixels per itteration */
+        {
+            int i;
+            diff_t d;
+
+            d = abs( p_new_pix[y*i_new_pitch+2*x+i_u_offset] - p_old_pix[y*i_old_pitch+2*x+i_u_offset] ) + /* U */
+                abs( p_new_pix[y*i_new_pitch+2*x+i_v_offset] - p_old_pix[y*i_old_pitch+2*x+i_v_offset] );  /* V */
+
+            for( i = 0; i < 2; i++ )
+                p_diff[y*i_width+x+i] =
+                   abs( p_new_pix[y*i_new_pitch+2*(x+i)+i_y_offset] - p_old_pix[y*i_old_pitch+2*(x+i)+i_y_offset] ) + d;
+        }
+    }
+
+}
+
+#ifdef NOIZ
+/*****************************************************************************
+ * Gaussian Convolution
+ *****************************************************************************
+ *    Gaussian convolution ( sigma == 1.4 )
+ *
+ *    |  2  4  5  4  2  |   |  2  4  4  4  2 |
+ *    |  4  9 12  9  4  |   |  4  8 12  8  4 |
+ *    |  5 12 15 12  5  | ~ |  4 12 16 12  4 |
+ *    |  4  9 12  9  4  |   |  4  8 12  8  4 |
+ *    |  2  4  5  4  2  |   |  2  4  4  4  2 |
+ *****************************************************************************/
+static void GaussianConvolution( diff_t *p_inpix,
+                                 picture_t* p_ref_pic )
+{
+    const video_frame_format_t *p_fmt = &p_ref_pic->format;
+    /* NOTE:  We take format type from picture (not from filter ) */
+    const int i_num_lines = p_fmt->i_height;
+    const int i_src_pitch = p_fmt->i_width;
+    const int i_src_visible = p_fmt->i_visible_width ;
+
+    int x,y;
+    diff_t* p_smooth = calloc( i_src_pitch * i_num_lines, sizeof( *p_smooth ) );
+    if ( !p_smooth )
+            return;
+
+    for( y = 2; y < i_num_lines - 2; y++ )
+    {
+        for( x = 2; x < i_src_visible - 2; x++ )
+        {
+            p_smooth[y*i_src_visible+x] = (uint32_t)(
+              /* 2 rows up */
+                ( p_inpix[(y-2)*i_src_pitch+x-2] )
+              + ((p_inpix[(y-2)*i_src_pitch+x-1]
+              +   p_inpix[(y-2)*i_src_pitch+x]
+              +   p_inpix[(y-2)*i_src_pitch+x+1])<<1 )
+              + ( p_inpix[(y-2)*i_src_pitch+x+2] )
+              /* 1 row up */
+              + ((p_inpix[(y-1)*i_src_pitch+x-2]
+              + ( p_inpix[(y-1)*i_src_pitch+x-1]<<1 )
+              + ( p_inpix[(y-1)*i_src_pitch+x]*3 )
+              + ( p_inpix[(y-1)*i_src_pitch+x+1]<<1 )
+              +   p_inpix[(y-1)*i_src_pitch+x+2]
+              /* */
+              +   p_inpix[y*i_src_pitch+x-2]
+              + ( p_inpix[y*i_src_pitch+x-1]*3 )
+              + ( p_inpix[y*i_src_pitch+x]<<2 )
+              + ( p_inpix[y*i_src_pitch+x+1]*3 )
+              +   p_inpix[y*i_src_pitch+x+2]
+              /* 1 row down */
+              +   p_inpix[(y+1)*i_src_pitch+x-2]
+              + ( p_inpix[(y+1)*i_src_pitch+x-1]<<1 )
+              + ( p_inpix[(y+1)*i_src_pitch+x]*3 )
+              + ( p_inpix[(y+1)*i_src_pitch+x+1]<<1 )
+              +   p_inpix[(y+1)*i_src_pitch+x+2] )<<1 )
+              /* 2 rows down */
+              + ( p_inpix[(y+2)*i_src_pitch+x-2] )
+              + ((p_inpix[(y+2)*i_src_pitch+x-1]
+              +   p_inpix[(y+2)*i_src_pitch+x]
+              +   p_inpix[(y+2)*i_src_pitch+x+1])<<1 )
+              + ( p_inpix[(y+2)*i_src_pitch+x+2] )
+              ) >> 6 /* 115 */;
+        }
+    }
+    memcpy( p_inpix, p_smooth, i_src_pitch * i_num_lines * sizeof( *p_inpix ) );
+    free( p_smooth );
+
+}
+#endif
+
+//TODO: On The fly parameter Change
+/*static int MotionBlurCallback( vlc_object_t *p_this, char const *psz_var,
+                               vlc_value_t oldval, vlc_value_t newval,
+                               void *p_data )
+{
+    VLC_UNUSED(p_this); VLC_UNUSED(oldval);
+    filter_sys_t *p_sys = (filter_sys_t *)p_data;
+    if( !strcmp( psz_var, FILTER_PREFIX "factor" ) )
+        p_sys->i_factor = __MIN( 127, __MAX( 1, newval.i_int ) );
+    return VLC_SUCCESS;
+}*/
-- 
1.5.4.3




More information about the vlc-devel mailing list