1 /*****************************************************************************
2 * gradfun.c: wrapper for the gradfun filter from libav
3 *****************************************************************************
4 * Copyright (C) 2010 Laurent Aimar
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 /*****************************************************************************
28 *****************************************************************************/
34 #include <vlc_common.h>
35 #include <vlc_plugin.h>
37 #include <vlc_filter.h>
39 /*****************************************************************************
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")
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
)
72 /*****************************************************************************
74 *****************************************************************************/
75 #define FFMAX(a,b) __MAX(a,b)
76 #ifdef CAN_COMPILE_MMXEXT
81 #ifdef CAN_COMPILE_SSE2
86 #ifdef CAN_COMPILE_SSSE3
91 // FIXME too restrictive
97 #define av_clip_uint8 clip_uint8_vlc
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
{
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
);
122 filter_sys_t
*sys
= malloc(sizeof(*sys
));
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
);
134 struct vf_priv_s
*cfg
= &sys
->cfg
;
139 #if HAVE_SSE2 && HAVE_6REGS
141 cfg
->blur_line
= blur_line_sse2
;
144 cfg
->blur_line
= blur_line_c
;
147 cfg
->filter_line
= filter_line_ssse3
;
151 if (vlc_CPU_MMXEXT())
152 cfg
->filter_line
= filter_line_mmx2
;
155 cfg
->filter_line
= filter_line_c
;
158 filter
->pf_video_filter
= Filter
;
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
);
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
);
180 picture_Release(src
);
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
);
213 plane_CopyPixels(dstp
, srcp
);
217 picture_CopyProperties(dst
, src
);
218 picture_Release(src
);
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
;
233 sys
->radius
= newval
.i_int
;
234 vlc_mutex_unlock(&sys
->lock
);