Qt: fix build
[vlc.git] / modules / video_filter / gradfun.c
blob8ebb95d0aa0aa6210ba4a2a9a3a5de5ab6a3d8ec
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>
38 #include <vlc_picture.h>
40 /*****************************************************************************
41 * Module descriptor
42 *****************************************************************************/
43 static int Open (vlc_object_t *);
44 static void Close(vlc_object_t *);
46 #define CFG_PREFIX "gradfun-"
48 #define RADIUS_MIN (4)
49 #define RADIUS_MAX (32)
50 #define RADIUS_TEXT N_("Radius")
51 #define RADIUS_LONGTEXT N_("Radius in pixels")
53 #define STRENGTH_MIN (0.51f)
54 #define STRENGTH_MAX (255)
55 #define STRENGTH_TEXT N_("Strength")
56 #define STRENGTH_LONGTEXT N_("Strength used to modify the value of a pixel")
58 vlc_module_begin()
59 set_description(N_("Gradfun video filter"))
60 set_shortname(N_("Gradfun"))
61 set_help(N_("Debanding algorithm"))
62 set_capability("video filter", 0)
63 set_category(CAT_VIDEO)
64 set_subcategory(SUBCAT_VIDEO_VFILTER)
65 add_integer_with_range(CFG_PREFIX "radius", 16, RADIUS_MIN, RADIUS_MAX,
66 RADIUS_TEXT, RADIUS_LONGTEXT, false)
67 add_float_with_range(CFG_PREFIX "strength", 1.2, STRENGTH_MIN, STRENGTH_MAX,
68 STRENGTH_TEXT, STRENGTH_LONGTEXT, false)
70 set_callbacks(Open, Close)
71 vlc_module_end()
73 /*****************************************************************************
74 * Local prototypes
75 *****************************************************************************/
76 #define FFMAX(a,b) __MAX(a,b)
77 #ifdef CAN_COMPILE_MMXEXT
78 # define HAVE_MMX2 1
79 #else
80 # define HAVE_MMX2 0
81 #endif
82 #ifdef CAN_COMPILE_SSE2
83 # define HAVE_SSE2 1
84 #else
85 # define HAVE_SSE2 0
86 #endif
87 #ifdef CAN_COMPILE_SSSE3
88 # define HAVE_SSSE3 1
89 #else
90 # define HAVE_SSSE3 0
91 #endif
92 // FIXME too restrictive
93 #ifdef __x86_64__
94 # define HAVE_6REGS 1
95 #else
96 # define HAVE_6REGS 0
97 #endif
98 #define av_clip_uint8 clip_uint8_vlc
99 #include <stdalign.h>
100 #include "gradfun.h"
102 static picture_t *Filter(filter_t *, picture_t *);
103 static int Callback(vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void *);
105 struct filter_sys_t {
106 vlc_mutex_t lock;
107 float strength;
108 int radius;
109 const vlc_chroma_description_t *chroma;
110 struct vf_priv_s cfg;
113 static int Open(vlc_object_t *object)
115 filter_t *filter = (filter_t *)object;
116 const vlc_fourcc_t fourcc = filter->fmt_in.video.i_chroma;
118 const vlc_chroma_description_t *chroma = vlc_fourcc_GetChromaDescription(fourcc);
119 if (!chroma || chroma->plane_count < 3 || chroma->pixel_size != 1) {
120 msg_Err(filter, "Unsupported chroma (%4.4s)", (char*)&fourcc);
121 return VLC_EGENERIC;
124 filter_sys_t *sys = malloc(sizeof(*sys));
125 if (!sys)
126 return VLC_ENOMEM;
128 vlc_mutex_init(&sys->lock);
129 sys->chroma = chroma;
130 sys->strength = var_CreateGetFloatCommand(filter, CFG_PREFIX "strength");
131 sys->radius = var_CreateGetIntegerCommand(filter, CFG_PREFIX "radius");
132 var_AddCallback(filter, CFG_PREFIX "strength", Callback, NULL);
133 var_AddCallback(filter, CFG_PREFIX "radius", Callback, NULL);
134 sys->cfg.buf = NULL;
136 struct vf_priv_s *cfg = &sys->cfg;
137 cfg->thresh = 0.0;
138 cfg->radius = 0;
139 cfg->buf = NULL;
141 #if HAVE_SSE2 && HAVE_6REGS
142 if (vlc_CPU_SSE2())
143 cfg->blur_line = blur_line_sse2;
144 else
145 #endif
146 cfg->blur_line = blur_line_c;
147 #if HAVE_SSSE3
148 if (vlc_CPU_SSSE3())
149 cfg->filter_line = filter_line_ssse3;
150 else
151 #endif
152 #if HAVE_MMX2
153 if (vlc_CPU_MMXEXT())
154 cfg->filter_line = filter_line_mmx2;
155 else
156 #endif
157 cfg->filter_line = filter_line_c;
159 filter->p_sys = sys;
160 filter->pf_video_filter = Filter;
161 return VLC_SUCCESS;
164 static void Close(vlc_object_t *object)
166 filter_t *filter = (filter_t *)object;
167 filter_sys_t *sys = filter->p_sys;
169 var_DelCallback(filter, CFG_PREFIX "radius", Callback, NULL);
170 var_DelCallback(filter, CFG_PREFIX "strength", Callback, NULL);
171 aligned_free(sys->cfg.buf);
172 vlc_mutex_destroy(&sys->lock);
173 free(sys);
176 static picture_t *Filter(filter_t *filter, picture_t *src)
178 filter_sys_t *sys = filter->p_sys;
180 picture_t *dst = filter_NewPicture(filter);
181 if (!dst) {
182 picture_Release(src);
183 return NULL;
186 vlc_mutex_lock(&sys->lock);
187 float strength = VLC_CLIP(sys->strength, STRENGTH_MIN, STRENGTH_MAX);
188 int radius = VLC_CLIP((sys->radius + 1) & ~1, RADIUS_MIN, RADIUS_MAX);
189 vlc_mutex_unlock(&sys->lock);
191 const video_format_t *fmt = &filter->fmt_in.video;
192 struct vf_priv_s *cfg = &sys->cfg;
194 cfg->thresh = (1 << 15) / strength;
195 if (cfg->radius != radius) {
196 cfg->radius = radius;
197 cfg->buf = aligned_alloc(16,
198 (((fmt->i_width + 15) & ~15) * (cfg->radius + 1) / 2 + 32) * sizeof(*cfg->buf));
201 for (int i = 0; i < dst->i_planes; i++) {
202 const plane_t *srcp = &src->p[i];
203 plane_t *dstp = &dst->p[i];
205 const vlc_chroma_description_t *chroma = sys->chroma;
206 int w = fmt->i_width * chroma->p[i].w.num / chroma->p[i].w.den;
207 int h = fmt->i_height * chroma->p[i].h.num / chroma->p[i].h.den;
208 int r = (cfg->radius * chroma->p[i].w.num / chroma->p[i].w.den +
209 cfg->radius * chroma->p[i].h.num / chroma->p[i].h.den) / 2;
210 r = VLC_CLIP((r + 1) & ~1, RADIUS_MIN, RADIUS_MAX);
211 if (__MIN(w, h) > 2 * r && cfg->buf) {
212 filter_plane(cfg, dstp->p_pixels, srcp->p_pixels,
213 w, h, dstp->i_pitch, srcp->i_pitch, r);
214 } else {
215 plane_CopyPixels(dstp, srcp);
219 picture_CopyProperties(dst, src);
220 picture_Release(src);
221 return dst;
224 static int Callback(vlc_object_t *object, char const *cmd,
225 vlc_value_t oldval, vlc_value_t newval, void *data)
227 filter_t *filter = (filter_t *)object;
228 filter_sys_t *sys = filter->p_sys;
229 VLC_UNUSED(oldval); VLC_UNUSED(data);
231 vlc_mutex_lock(&sys->lock);
232 if (!strcmp(cmd, CFG_PREFIX "strength"))
233 sys->strength = newval.f_float;
234 else
235 sys->radius = newval.i_int;
236 vlc_mutex_unlock(&sys->lock);
238 return VLC_SUCCESS;