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