1 /*****************************************************************************
2 * motion_blur.c : motion blur filter for vlc
3 *****************************************************************************
4 * Copyright (C) 2000, 2001, 2002, 2003 the VideoLAN team
7 * Authors: Sigmund Augdal Helberg <dnumgis@videolan.org>
8 * Antoine Cellerier <dionoea &t videolan d.t org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
36 #include <vlc_filter.h>
37 #include "filter_picture.h"
39 /*****************************************************************************
41 *****************************************************************************/
42 static int Create ( vlc_object_t
* );
43 static void Destroy ( vlc_object_t
* );
44 static picture_t
*Filter ( filter_t
*, picture_t
* );
45 static void RenderBlur ( filter_sys_t
*, picture_t
*, picture_t
* );
46 static int MotionBlurCallback( vlc_object_t
*, char const *,
47 vlc_value_t
, vlc_value_t
, void * );
49 /*****************************************************************************
51 *****************************************************************************/
52 #define FACTOR_TEXT N_("Blur factor (1-127)")
53 #define FACTOR_LONGTEXT N_("The degree of blurring from 1 to 127.")
55 #define FILTER_PREFIX "blur-"
58 set_shortname( N_("Motion blur") )
59 set_description( N_("Motion blur filter") )
60 set_capability( "video filter2", 0 )
61 set_category( CAT_VIDEO
)
62 set_subcategory( SUBCAT_VIDEO_VFILTER
)
64 add_integer_with_range( FILTER_PREFIX
"factor", 80, 1, 127, NULL
,
65 FACTOR_TEXT
, FACTOR_LONGTEXT
, false )
67 add_shortcut( "blur" )
69 set_callbacks( Create
, Destroy
)
72 static const char *const ppsz_filter_options
[] = {
76 /*****************************************************************************
78 *****************************************************************************/
88 /*****************************************************************************
90 *****************************************************************************/
91 static int Create( vlc_object_t
*p_this
)
93 filter_t
*p_filter
= (filter_t
*)p_this
;
95 /* Allocate structure */
96 p_filter
->p_sys
= malloc( sizeof( filter_sys_t
) );
97 if( p_filter
->p_sys
== NULL
)
100 p_filter
->p_sys
->p_tmp
= picture_NewFromFormat( &p_filter
->fmt_in
.video
);
101 if( !p_filter
->p_sys
->p_tmp
)
103 free( p_filter
->p_sys
);
106 p_filter
->p_sys
->b_first
= true;
108 p_filter
->pf_video_filter
= Filter
;
110 config_ChainParse( p_filter
, FILTER_PREFIX
, ppsz_filter_options
,
113 p_filter
->p_sys
->i_factor
=
114 var_CreateGetIntegerCommand( p_filter
, FILTER_PREFIX
"factor" );
115 vlc_spin_init( &p_filter
->p_sys
->lock
);
116 var_AddCallback( p_filter
, FILTER_PREFIX
"factor",
117 MotionBlurCallback
, p_filter
->p_sys
);
123 /*****************************************************************************
125 *****************************************************************************/
126 static void Destroy( vlc_object_t
*p_this
)
128 filter_t
*p_filter
= (filter_t
*)p_this
;
130 var_DelCallback( p_filter
, FILTER_PREFIX
"factor",
131 MotionBlurCallback
, p_filter
->p_sys
);
132 vlc_spin_destroy( &p_filter
->p_sys
->lock
);
134 picture_Release( p_filter
->p_sys
->p_tmp
);
135 free( p_filter
->p_sys
);
138 /*****************************************************************************
140 *****************************************************************************/
141 static picture_t
*Filter( filter_t
*p_filter
, picture_t
*p_pic
)
143 picture_t
* p_outpic
;
144 filter_sys_t
*p_sys
= p_filter
->p_sys
;
146 if( !p_pic
) return NULL
;
148 p_outpic
= filter_NewPicture( p_filter
);
151 picture_Release( p_pic
);
157 picture_CopyPixels( p_sys
->p_tmp
, p_pic
);
158 p_sys
->b_first
= false;
161 /* Get a new picture */
162 RenderBlur( p_sys
, p_pic
, p_outpic
);
164 picture_CopyPixels( p_sys
->p_tmp
, p_outpic
);
166 return CopyInfoAndRelease( p_outpic
, p_pic
);
169 /*****************************************************************************
170 * RenderBlur: renders a blurred picture
171 *****************************************************************************/
172 static void RenderBlur( filter_sys_t
*p_sys
, picture_t
*p_newpic
,
173 picture_t
*p_outpic
)
176 vlc_spin_lock( &p_sys
->lock
);
177 const int i_oldfactor
= p_sys
->i_factor
;
178 vlc_spin_unlock( &p_sys
->lock
);
179 int i_newfactor
= 128 - i_oldfactor
;
181 for( i_plane
= 0; i_plane
< p_outpic
->i_planes
; i_plane
++ )
183 uint8_t *p_old
, *p_new
, *p_out
, *p_out_end
, *p_out_line_end
;
184 const int i_visible_pitch
= p_outpic
->p
[i_plane
].i_visible_pitch
;
185 const int i_visible_lines
= p_outpic
->p
[i_plane
].i_visible_lines
;
187 p_out
= p_outpic
->p
[i_plane
].p_pixels
;
188 p_new
= p_newpic
->p
[i_plane
].p_pixels
;
189 p_old
= p_sys
->p_tmp
->p
[i_plane
].p_pixels
;
190 p_out_end
= p_out
+ p_outpic
->p
[i_plane
].i_pitch
* i_visible_lines
;
191 while ( p_out
< p_out_end
)
193 p_out_line_end
= p_out
+ i_visible_pitch
;
195 while ( p_out
< p_out_line_end
)
197 *p_out
++ = (((*p_old
++) * i_oldfactor
) +
198 ((*p_new
++) * i_newfactor
)) >> 7;
201 p_old
+= p_sys
->p_tmp
->p
[i_plane
].i_pitch
- i_visible_pitch
;
202 p_new
+= p_newpic
->p
[i_plane
].i_pitch
- i_visible_pitch
;
203 p_out
+= p_outpic
->p
[i_plane
].i_pitch
- i_visible_pitch
;
208 static int MotionBlurCallback( vlc_object_t
*p_this
, char const *psz_var
,
209 vlc_value_t oldval
, vlc_value_t newval
,
212 VLC_UNUSED(p_this
); VLC_UNUSED(oldval
);
213 filter_sys_t
*p_sys
= (filter_sys_t
*)p_data
;
215 if( !strcmp( psz_var
, FILTER_PREFIX
"factor" ) )
217 vlc_spin_lock( &p_sys
->lock
);
218 p_sys
->i_factor
= __MIN( 127, __MAX( 1, newval
.i_int
) );
219 vlc_spin_unlock( &p_sys
->lock
);