1 /*****************************************************************************
2 * motionblur.c : motion blur filter for vlc
3 *****************************************************************************
4 * Copyright (C) 2000, 2001, 2002, 2003 VLC authors and VideoLAN
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 it
11 * under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * 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 <vlc_atomic.h>
38 #include <vlc_picture.h>
39 #include "filter_picture.h"
41 /*****************************************************************************
43 *****************************************************************************/
44 static int Create ( vlc_object_t
* );
45 static void Destroy ( vlc_object_t
* );
46 static picture_t
*Filter ( filter_t
*, picture_t
* );
47 static void RenderBlur ( filter_sys_t
*, picture_t
*, picture_t
* );
48 static int MotionBlurCallback( vlc_object_t
*, char const *,
49 vlc_value_t
, vlc_value_t
, void * );
51 /*****************************************************************************
53 *****************************************************************************/
54 #define FACTOR_TEXT N_("Blur factor (1-127)")
55 #define FACTOR_LONGTEXT N_("The degree of blurring from 1 to 127.")
57 #define FILTER_PREFIX "blur-"
60 set_shortname( N_("Motion blur") )
61 set_description( N_("Motion blur filter") )
62 set_capability( "video filter", 0 )
63 set_category( CAT_VIDEO
)
64 set_subcategory( SUBCAT_VIDEO_VFILTER
)
66 add_integer_with_range( FILTER_PREFIX
"factor", 80, 1, 127,
67 FACTOR_TEXT
, FACTOR_LONGTEXT
, false )
69 add_shortcut( "blur" )
71 set_callbacks( Create
, Destroy
)
74 static const char *const ppsz_filter_options
[] = {
78 /*****************************************************************************
80 *****************************************************************************/
88 /*****************************************************************************
90 *****************************************************************************/
91 static int Create( vlc_object_t
*p_this
)
93 filter_t
*p_filter
= (filter_t
*)p_this
;
95 const vlc_chroma_description_t
*p_chroma
=
96 vlc_fourcc_GetChromaDescription( p_filter
->fmt_in
.video
.i_chroma
);
97 if( p_chroma
== NULL
|| p_chroma
->plane_count
== 0 )
100 /* Allocate structure */
101 p_filter
->p_sys
= malloc( sizeof( filter_sys_t
) );
102 if( p_filter
->p_sys
== NULL
)
105 p_filter
->p_sys
->p_tmp
= picture_NewFromFormat( &p_filter
->fmt_in
.video
);
106 if( !p_filter
->p_sys
->p_tmp
)
108 free( p_filter
->p_sys
);
111 p_filter
->p_sys
->b_first
= true;
113 p_filter
->pf_video_filter
= Filter
;
115 config_ChainParse( p_filter
, FILTER_PREFIX
, ppsz_filter_options
,
118 atomic_init( &p_filter
->p_sys
->i_factor
,
119 var_CreateGetIntegerCommand( p_filter
, FILTER_PREFIX
"factor" ) );
120 var_AddCallback( p_filter
, FILTER_PREFIX
"factor",
121 MotionBlurCallback
, p_filter
->p_sys
);
127 /*****************************************************************************
129 *****************************************************************************/
130 static void Destroy( vlc_object_t
*p_this
)
132 filter_t
*p_filter
= (filter_t
*)p_this
;
134 var_DelCallback( p_filter
, FILTER_PREFIX
"factor",
135 MotionBlurCallback
, p_filter
->p_sys
);
137 picture_Release( p_filter
->p_sys
->p_tmp
);
138 free( p_filter
->p_sys
);
141 /*****************************************************************************
143 *****************************************************************************/
144 static picture_t
*Filter( filter_t
*p_filter
, picture_t
*p_pic
)
146 picture_t
* p_outpic
;
147 filter_sys_t
*p_sys
= p_filter
->p_sys
;
149 if( !p_pic
) return NULL
;
151 p_outpic
= filter_NewPicture( p_filter
);
154 picture_Release( p_pic
);
160 picture_CopyPixels( p_sys
->p_tmp
, p_pic
);
161 p_sys
->b_first
= false;
164 /* Get a new picture */
165 RenderBlur( p_sys
, p_pic
, p_outpic
);
167 picture_CopyPixels( p_sys
->p_tmp
, p_outpic
);
169 return CopyInfoAndRelease( p_outpic
, p_pic
);
172 /*****************************************************************************
173 * RenderBlur: renders a blurred picture
174 *****************************************************************************/
175 static void RenderBlur( filter_sys_t
*p_sys
, picture_t
*p_newpic
,
176 picture_t
*p_outpic
)
178 const int i_oldfactor
= atomic_load( &p_sys
->i_factor
);
179 int i_newfactor
= 128 - i_oldfactor
;
181 for( int 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(psz_var
); VLC_UNUSED(oldval
);
213 filter_sys_t
*p_sys
= (filter_sys_t
*)p_data
;
215 atomic_store( &p_sys
->i_factor
, VLC_CLIP( newval
.i_int
, 1, 127 ) );