skins2: fix initial text state to reflect documentation
[vlc.git] / modules / video_filter / gradfun.c
blob4665fe976e1f6760cd2d1566750b777a10015a79
1 /*****************************************************************************
2 * gradfun.c: wrapper for the gradfun filter from libav
3 *****************************************************************************
4 * Copyright (C) 2010 Laurent Aimar
5 * $Id$
7 * Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
9 * Based on the work of: Nolan Lum and Loren Merritt
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation; either version 2.1 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public License
22 * along with this program; if not, write to the Free Software Foundation,
23 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24 *****************************************************************************/
26 /*****************************************************************************
27 * Preamble
28 *****************************************************************************/
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
34 #include <vlc_common.h>
35 #include <vlc_plugin.h>
36 #include <vlc_cpu.h>
37 #include <vlc_filter.h>
39 /*****************************************************************************
40 * Module descriptor
41 *****************************************************************************/
42 static int Open (vlc_object_t *);
43 static void Close(vlc_object_t *);
45 #define CFG_PREFIX "gradfun-"
47 #define RADIUS_MIN (4)
48 #define RADIUS_MAX (32)
49 #define RADIUS_TEXT N_("Radius")
50 #define RADIUS_LONGTEXT N_("Radius in pixels")
52 #define STRENGTH_MIN (0.51)
53 #define STRENGTH_MAX (255)
54 #define STRENGTH_TEXT N_("Strength")
55 #define STRENGTH_LONGTEXT N_("Strength used to modify the value of a pixel")
57 vlc_module_begin()
58 set_description(N_("Gradfun video filter"))
59 set_shortname(N_("Gradfun"))
60 set_help(N_("Debanding algorithm"))
61 set_capability("video filter2", 0)
62 set_category(CAT_VIDEO)
63 set_subcategory(SUBCAT_VIDEO_VFILTER)
64 add_integer_with_range(CFG_PREFIX "radius", 16, RADIUS_MIN, RADIUS_MAX,
65 RADIUS_TEXT, RADIUS_LONGTEXT, false)
66 add_float_with_range(CFG_PREFIX "strength", 1.2, STRENGTH_MIN, STRENGTH_MAX,
67 STRENGTH_TEXT, STRENGTH_LONGTEXT, false)
69 set_callbacks(Open, Close)
70 vlc_module_end()
72 /*****************************************************************************
73 * Local prototypes
74 *****************************************************************************/
75 #define FFMAX(a,b) __MAX(a,b)
76 #ifdef CAN_COMPILE_MMXEXT
77 # define HAVE_MMX2 1
78 #else
79 # define HAVE_MMX2 0
80 #endif
81 #ifdef CAN_COMPILE_SSE2
82 # define HAVE_SSE2 1
83 #else
84 # define HAVE_SSE2 0
85 #endif
86 #ifdef CAN_COMPILE_SSSE3
87 # define HAVE_SSSE3 1
88 #else
89 # define HAVE_SSSE3 0
90 #endif
91 // FIXME too restrictive
92 #ifdef __x86_64__
93 # define HAVE_6REGS 1
94 #else
95 # define HAVE_6REGS 0
96 #endif
97 #define av_clip_uint8 clip_uint8_vlc
98 #include "gradfun.h"
100 static picture_t *Filter(filter_t *, picture_t *);
101 static int Callback(vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void *);
103 struct filter_sys_t {
104 vlc_mutex_t lock;
105 float strength;
106 int radius;
107 const vlc_chroma_description_t *chroma;
108 struct vf_priv_s cfg;
111 static int Open(vlc_object_t *object)
113 filter_t *filter = (filter_t *)object;
114 const vlc_fourcc_t fourcc = filter->fmt_in.video.i_chroma;
116 const vlc_chroma_description_t *chroma = vlc_fourcc_GetChromaDescription(fourcc);
117 if (!chroma || chroma->plane_count < 3 || chroma->pixel_size != 1) {
118 msg_Err(filter, "Unsupported chroma (%4.4s)", (char*)&fourcc);
119 return VLC_EGENERIC;
122 filter_sys_t *sys = malloc(sizeof(*sys));
123 if (!sys)
124 return VLC_ENOMEM;
126 vlc_mutex_init(&sys->lock);
127 sys->chroma = chroma;
128 sys->strength = var_CreateGetFloatCommand(filter, CFG_PREFIX "strength");
129 sys->radius = var_CreateGetIntegerCommand(filter, CFG_PREFIX "radius");
130 var_AddCallback(filter, CFG_PREFIX "strength", Callback, NULL);
131 var_AddCallback(filter, CFG_PREFIX "radius", Callback, NULL);
132 sys->cfg.buf = NULL;
134 struct vf_priv_s *cfg = &sys->cfg;
135 cfg->thresh = 0.0;
136 cfg->radius = 0;
137 cfg->buf = NULL;
139 #if HAVE_SSE2 && HAVE_6REGS
140 if (vlc_CPU_SSE2())
141 cfg->blur_line = blur_line_sse2;
142 else
143 #endif
144 cfg->blur_line = blur_line_c;
145 #if HAVE_SSSE3
146 if (vlc_CPU_SSSE3())
147 cfg->filter_line = filter_line_ssse3;
148 else
149 #endif
150 #if HAVE_MMX2
151 if (vlc_CPU_MMXEXT())
152 cfg->filter_line = filter_line_mmx2;
153 else
154 #endif
155 cfg->filter_line = filter_line_c;
157 filter->p_sys = sys;
158 filter->pf_video_filter = Filter;
159 return VLC_SUCCESS;
162 static void Close(vlc_object_t *object)
164 filter_t *filter = (filter_t *)object;
165 filter_sys_t *sys = filter->p_sys;
167 var_DelCallback(filter, CFG_PREFIX "radius", Callback, NULL);
168 var_DelCallback(filter, CFG_PREFIX "strength", Callback, NULL);
169 vlc_free(sys->cfg.buf);
170 vlc_mutex_destroy(&sys->lock);
171 free(sys);
174 static picture_t *Filter(filter_t *filter, picture_t *src)
176 filter_sys_t *sys = filter->p_sys;
178 picture_t *dst = filter_NewPicture(filter);
179 if (!dst) {
180 picture_Release(src);
181 return NULL;
184 vlc_mutex_lock(&sys->lock);
185 float strength = VLC_CLIP(sys->strength, STRENGTH_MIN, STRENGTH_MAX);
186 int radius = VLC_CLIP((sys->radius + 1) & ~1, RADIUS_MIN, RADIUS_MAX);
187 vlc_mutex_unlock(&sys->lock);
189 const video_format_t *fmt = &filter->fmt_in.video;
190 struct vf_priv_s *cfg = &sys->cfg;
192 cfg->thresh = (1 << 15) / strength;
193 if (cfg->radius != radius) {
194 cfg->radius = radius;
195 cfg->buf = vlc_memalign(16,
196 (((fmt->i_width + 15) & ~15) * (cfg->radius + 1) / 2 + 32) * sizeof(*cfg->buf));
199 for (int i = 0; i < dst->i_planes; i++) {
200 const plane_t *srcp = &src->p[i];
201 plane_t *dstp = &dst->p[i];
203 const vlc_chroma_description_t *chroma = sys->chroma;
204 int w = fmt->i_width * chroma->p[i].w.num / chroma->p[i].w.den;
205 int h = fmt->i_height * chroma->p[i].h.num / chroma->p[i].h.den;
206 int r = (cfg->radius * chroma->p[i].w.num / chroma->p[i].w.den +
207 cfg->radius * chroma->p[i].h.num / chroma->p[i].h.den) / 2;
208 r = VLC_CLIP((r + 1) & ~1, RADIUS_MIN, RADIUS_MAX);
209 if (__MIN(w, h) > 2 * r && cfg->buf) {
210 filter_plane(cfg, dstp->p_pixels, srcp->p_pixels,
211 w, h, dstp->i_pitch, srcp->i_pitch, r);
212 } else {
213 plane_CopyPixels(dstp, srcp);
217 picture_CopyProperties(dst, src);
218 picture_Release(src);
219 return dst;
222 static int Callback(vlc_object_t *object, char const *cmd,
223 vlc_value_t oldval, vlc_value_t newval, void *data)
225 filter_t *filter = (filter_t *)object;
226 filter_sys_t *sys = filter->p_sys;
227 VLC_UNUSED(oldval); VLC_UNUSED(data);
229 vlc_mutex_lock(&sys->lock);
230 if (!strcmp(cmd, CFG_PREFIX "strength"))
231 sys->strength = newval.f_float;
232 else
233 sys->radius = newval.i_int;
234 vlc_mutex_unlock(&sys->lock);
236 return VLC_SUCCESS;