[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