[vlc-devel] [PATCH 1/2] Anti-flicker filter initial version

dharani.prabhu.s dharani.prabhu.s at gmail.com
Sun Apr 3 07:38:34 CEST 2011


---
 modules/video_filter/Modules.am    |    4 +-
 modules/video_filter/antiflicker.c |  340 ++++++++++++++++++++++++++++++++++++
 2 files changed, 343 insertions(+), 1 deletions(-)
 create mode 100755 modules/video_filter/antiflicker.c

diff --git a/modules/video_filter/Modules.am b/modules/video_filter/Modules.am
index 2b3bbe5..84dc8ef 100644
--- a/modules/video_filter/Modules.am
+++ b/modules/video_filter/Modules.am
@@ -54,6 +54,7 @@ SOURCES_swscale_omap = swscale_omap.c \
 SOURCES_scene = scene.c
 SOURCES_sepia = sepia.c
 SOURCES_yuvp = yuvp.c
+SOURCES_antiflicker = antiflicker.c
 SOURCES_atmo = atmo/atmo.cpp \
 	atmo/AtmoDefs.h \
 	atmo/AtmoCalculations.cpp atmo/AtmoCalculations.h \
@@ -121,4 +122,5 @@ libvlc_LTLIBRARIES += \
 	libwall_plugin.la \
 	libwave_plugin.la \
 	libgradfun_plugin.la \
-	libyuvp_plugin.la
+	libyuvp_plugin.la \
+	libantiflicker_plugin.la
diff --git a/modules/video_filter/antiflicker.c b/modules/video_filter/antiflicker.c
new file mode 100755
index 0000000..c981875
--- /dev/null
+++ b/modules/video_filter/antiflicker.c
@@ -0,0 +1,340 @@
+/*****************************************************************************
+ * antiflicker.c : antiflicker video effect plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2000-2008 the VideoLAN team
+ * $Id: 
+ *
+ * Authors: S Dharani Prabhu
+ * Email:   dharani.prabhu.s at gmail.com
+ *
+ * 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_rand.h>
+
+#include <vlc_filter.h>
+#include "filter_picture.h"
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int GetLuminanceAvg( picture_t * p_pic );
+static picture_t *Filter( filter_t *, picture_t * );
+static int AntiFlickerCallback( vlc_object_t *p_this, char const *psz_var,
+                           vlc_value_t oldval, vlc_value_t newval,
+                           void *p_data );
+
+static int  Create    ( vlc_object_t * );
+static void Destroy   ( vlc_object_t * );
+
+#define WINDOW_TEXT N_("Window size")
+#define WINDOW_LONGTEXT N_("Number of frames (0 to 100)")
+
+#define SFTN_TEXT N_("Softening value")
+#define SFTN_LONGTEXT N_("Number of frames consider for smoothening (0 to 30)")
+
+#define FILTER_PREFIX "antiflicker-"
+
+#define MAX_WINDOW_SZ 100 
+#define MAX_SOFTENING_SZ 31
+#define SCENE_CHANGE_THRESHOLD 100 
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin ()
+    set_description( N_("antiflicker video filter") )
+    set_shortname( N_( "antiflicker" ))
+    set_capability( "video filter2", 0 )
+    set_category( CAT_VIDEO )
+    set_subcategory( SUBCAT_VIDEO_VFILTER )
+
+    add_integer_with_range( FILTER_PREFIX "winsz", 10, 0, MAX_WINDOW_SZ, NULL,
+        WINDOW_TEXT, WINDOW_LONGTEXT, false )
+
+    add_integer_with_range( FILTER_PREFIX "sftn", 10, 0, MAX_SOFTENING_SZ, NULL,
+        SFTN_TEXT, SFTN_LONGTEXT, false )
+
+    add_shortcut( "antiflicker" )
+    set_callbacks( Create, Destroy )
+vlc_module_end ()
+
+/*****************************************************************************
+ * filter_sys_t: Distort video output method descriptor
+ *****************************************************************************
+ * This structure is part of the video output thread descriptor.
+ * It describes the Distort specific properties of an output thread.
+ *****************************************************************************/
+struct filter_sys_t
+{
+    vlc_mutex_t lock;
+    uint8_t i_window_size;
+    uint8_t i_softening;
+    uint8_t* p_old_data;
+    uint32_t ia_luminance_data[MAX_WINDOW_SZ];
+};
+
+/*****************************************************************************
+ * Create: allocates Distort video thread output method
+ *****************************************************************************
+ * This function allocates and initializes a Distort vout method.
+ *****************************************************************************/
+static int Create( vlc_object_t *p_this )
+{
+    filter_t *p_filter = (filter_t *)p_this;
+
+    /* Allocate structure */
+    p_filter->p_sys = malloc( sizeof( filter_sys_t ) );
+    if( p_filter->p_sys == NULL )
+        return VLC_ENOMEM;
+
+    p_filter->pf_video_filter = Filter;
+
+    /* Initialize the arguments */
+    p_filter->p_sys->i_window_size = var_CreateGetIntegerCommand( p_filter,
+                                               FILTER_PREFIX "winsz" );
+    p_filter->p_sys->i_softening = var_CreateGetIntegerCommand( p_filter,
+                                               FILTER_PREFIX "sftn" );
+
+    memset( p_filter->p_sys->ia_luminance_data, 0, 
+                    sizeof(p_filter->p_sys->ia_luminance_data) );
+    p_filter->p_sys->p_old_data = NULL;
+    p_filter->p_sys->ia_luminance_data[0] = 256;
+  
+    vlc_mutex_init( &p_filter->p_sys->lock ); 
+    var_AddCallback(p_filter,FILTER_PREFIX "winsz",
+        AntiFlickerCallback, p_filter->p_sys);
+    var_AddCallback(p_filter,FILTER_PREFIX "sftn",
+        AntiFlickerCallback, p_filter->p_sys);
+ 
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Destroy: destroy Distort video thread output method
+ *****************************************************************************
+ * Terminate an output method created by DistortCreateOutputMethod
+ *****************************************************************************/
+static void Destroy( vlc_object_t *p_this )
+{
+    filter_t *p_filter = (filter_t *)p_this;
+
+    var_DelCallback(p_filter,FILTER_PREFIX "winsz",
+        AntiFlickerCallback, p_filter->p_sys);
+    var_DelCallback(p_filter,FILTER_PREFIX "sftn",
+        AntiFlickerCallback, p_filter->p_sys);
+    vlc_mutex_destroy( &p_filter->p_sys->lock );
+    free( p_filter->p_sys );
+}
+
+/*****************************************************************************
+ * GetLuminanceAvg : The funtion returns the luminance average for a picture
+ *****************************************************************************/
+static int GetLuminanceAvg( picture_t * p_pic )
+{
+    uint8_t *p_yplane_out = p_pic->p[Y_PLANE].p_pixels;
+
+    int i_num_lines = p_pic->p[Y_PLANE].i_visible_lines;
+    int i_num_cols = p_pic->p[Y_PLANE].i_visible_pitch;
+    int i_in_pitch = p_pic->p[Y_PLANE].i_pitch;
+    
+    uint32_t lum_sum = 0;
+    uint8_t lum_avg = 0;
+    for( int i_line = 0 ; i_line < i_num_lines ; i_line++ )
+    {
+        for( int i_col = 0 ; i_col < i_num_cols; ++i_col )
+        {
+            lum_sum += p_yplane_out[i_line*i_in_pitch+i_col];
+        }   
+    }
+    lum_avg = lum_sum / ( i_num_lines * i_num_cols );
+    return lum_avg;
+}
+
+/*****************************************************************************
+ * Filter: adjust the luminance value and renders
+ *****************************************************************************
+ * The function uses moving average of past frames to adjust the luminance 
+ * of current frame also applies temporaral smoothening if enabled.
+ *****************************************************************************/
+static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
+{
+    if( !p_pic ) return NULL;
+
+    picture_t *p_outpic = filter_NewPicture( p_filter );
+    if( !p_outpic )
+    {
+        msg_Warn( p_filter, "can't get output picture" );
+        picture_Release( p_pic );
+        return NULL;
+    }
+
+    /****************** Get variables *************************/
+
+    uint8_t i_window_size = 10;
+    uint8_t i_softening = 0;
+
+    vlc_mutex_lock( &p_filter->p_sys->lock );
+    i_window_size = p_filter->p_sys->i_window_size;
+    i_softening = p_filter->p_sys->i_softening;
+    vlc_mutex_unlock( &p_filter->p_sys->lock );
+
+    uint8_t *p_yplane_in = p_pic->p[Y_PLANE].p_pixels;
+    uint8_t *p_yplane_out = p_outpic->p[Y_PLANE].p_pixels;
+    bool scene_changed = false;
+
+    int16_t i_num_lines = p_pic->p[Y_PLANE].i_visible_lines;
+    int16_t i_num_cols = p_pic->p[Y_PLANE].i_visible_pitch;
+    int16_t i_in_pitch = p_pic->p[Y_PLANE].i_pitch;
+    int16_t i_out_pitch = p_outpic->p[Y_PLANE].i_pitch;
+
+    /******** Get the luminance average for the current picture ********/
+    uint8_t lum_avg = GetLuminanceAvg( p_pic );
+
+    /******** Identify scene changes ************/
+    if( abs((int)lum_avg - (int)p_filter->p_sys->
+        ia_luminance_data[i_window_size - 1]) 
+            > SCENE_CHANGE_THRESHOLD )
+    {
+        scene_changed = true;
+    }
+
+    /******* Compute the adjustment factor using moving average ********/
+    double scale = 1.0;
+
+    if ( scene_changed )
+    {
+        //reset the luminance data
+        for (int i = 0; i < i_window_size; ++i) 
+            p_filter->p_sys->ia_luminance_data[i] = lum_avg;
+    }
+    else
+    {
+        for (int i = 0; i < i_window_size-1 ; ++i) 
+            p_filter->p_sys->ia_luminance_data[i] = 
+                           p_filter->p_sys->ia_luminance_data[i+1];
+
+        p_filter->p_sys->ia_luminance_data[i_window_size - 1] = lum_avg;
+        
+        if (lum_avg > 0)
+        {
+             scale = 1.0f/lum_avg;
+             double filt = 0;
+             for (int i = 0; i < i_window_size; i++) 
+                  filt += (float) p_filter->p_sys->ia_luminance_data[i] /
+                              i_window_size;
+             scale *= filt;
+        }
+    }
+
+    /********* Apply the adjustment factor to each pixel on Y_PLANE *********/
+    for( int16_t i_line = 0 ; i_line < i_num_lines ; i_line++ )
+    {
+        for( int16_t i_col = 0; i_col < i_num_cols  ; i_col++ )
+        {
+            if( scene_changed )
+                p_yplane_out[i_line*i_out_pitch+i_col] = lum_avg;
+            else
+            {
+                uint8_t pixel_data = p_yplane_in[i_line*i_in_pitch+i_col];
+                float s = scale;
+                if ( scale * pixel_data > 255) 
+                    s = 255.0 / (float)pixel_data;
+                p_yplane_out[i_line*i_out_pitch+i_col] = s * (float)pixel_data;
+            }
+        }
+    }
+    
+    /***************** Copy the UV plane as such *****************************/
+    plane_CopyPixels( &p_outpic->p[U_PLANE], &p_pic->p[U_PLANE] );
+    plane_CopyPixels( &p_outpic->p[V_PLANE], &p_pic->p[V_PLANE] );
+
+    if (scene_changed || i_softening == 0)
+    {
+       return CopyInfoAndRelease( p_outpic, p_pic );
+    }
+
+    /******* Temporal softening phase. Adapted from code by Steven Don ******/ 
+    uint8_t *src1, *src2;
+    long diff, ofs, sum;
+
+    if( !p_filter->p_sys->p_old_data )
+    {
+        p_filter->p_sys->p_old_data = 
+          malloc( (i_num_lines * i_out_pitch + i_num_cols) * sizeof(uint8_t) );
+        memset( p_filter->p_sys->p_old_data, 0, 
+                  (i_num_lines * i_out_pitch + i_num_cols) * sizeof(uint8_t) );
+        
+        msg_Warn( p_filter, "can't get output picture" );
+        return NULL;
+    }
+
+    ofs = (i_num_lines * i_out_pitch + i_num_cols);
+    src1 = p_outpic->p[Y_PLANE].p_pixels;
+    src2 = p_filter->p_sys->p_old_data;
+
+    do
+    {
+        diff = abs(*src1 - *src2);
+        if (diff < i_softening)
+        {
+            if (diff > (i_softening >> 1))
+            {
+                sum = *src1 + *src1 + *src2;
+                *src2 = sum / 3;
+            }
+        }
+        else
+        {
+            *src2 = *src1;
+        }
+        *src1 = *src2;
+        src1++; src2++;
+    } while (--ofs);
+
+    return CopyInfoAndRelease( p_outpic, p_pic );
+}
+
+/*****************************************************************************
+ * Callback function to set the parameters 
+ *****************************************************************************
+ * This function sets the parameters necesscary for the filter
+ *****************************************************************************/
+static int AntiFlickerCallback( 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;
+
+    vlc_mutex_lock( &p_sys->lock );
+    if( !strcmp( psz_var, FILTER_PREFIX "winsz" ) )
+        p_sys->i_window_size = newval.i_int;
+    else if( !strcmp( psz_var, FILTER_PREFIX "sftn" ) )
+        p_sys->i_softening = newval.i_int;
+    vlc_mutex_unlock( &p_sys->lock );
+
+    return VLC_SUCCESS;
+}
-- 
1.6.3.3




More information about the vlc-devel mailing list