1 /*****************************************************************************
2 * gradfun.c: wrapper for the gradfun filter from libav
3 *****************************************************************************
4 * Copyright (C) 2010 Laurent Aimar
6 * Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
8 * Based on the work of: Nolan Lum and Loren Merritt
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_picture.h>
39 /*****************************************************************************
41 *****************************************************************************/
42 static int Open (filter_t
*);
44 #define CFG_PREFIX "gradfun-"
46 #define RADIUS_MIN (4)
47 #define RADIUS_MAX (32)
48 #define RADIUS_TEXT N_("Radius")
49 #define RADIUS_LONGTEXT N_("Radius in pixels")
51 #define STRENGTH_MIN (0.51f)
52 #define STRENGTH_MAX (255)
53 #define STRENGTH_TEXT N_("Strength")
54 #define STRENGTH_LONGTEXT N_("Strength used to modify the value of a pixel")
57 set_description(N_("Gradfun video filter"))
58 set_shortname(N_("Gradfun"))
59 set_help(N_("Debanding algorithm"))
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)
67 set_callback_video_filter(Open
)
70 /*****************************************************************************
72 *****************************************************************************/
73 #define FFMAX(a,b) __MAX(a,b)
74 #ifdef CAN_COMPILE_MMXEXT
79 #ifdef CAN_COMPILE_SSE2
84 #ifdef CAN_COMPILE_SSSE3
89 // FIXME too restrictive
95 #define av_clip_uint8 clip_uint8_vlc
99 static int Callback(vlc_object_t
*, char const *, vlc_value_t
, vlc_value_t
, void *);
100 VIDEO_FILTER_WRAPPER_CLOSE(Filter
, Close
)
107 const vlc_chroma_description_t
*chroma
;
108 struct vf_priv_s cfg
;
111 static int Open(filter_t
*filter
)
113 const vlc_fourcc_t fourcc
= filter
->fmt_in
.video
.i_chroma
;
115 const vlc_chroma_description_t
*chroma
= vlc_fourcc_GetChromaDescription(fourcc
);
116 if (!chroma
|| chroma
->plane_count
< 3 || chroma
->pixel_size
!= 1) {
117 msg_Err(filter
, "Unsupported chroma (%4.4s)", (char*)&fourcc
);
121 filter_sys_t
*sys
= malloc(sizeof(*sys
));
125 vlc_mutex_init(&sys
->lock
);
126 sys
->chroma
= chroma
;
127 sys
->strength
= var_CreateGetFloatCommand(filter
, CFG_PREFIX
"strength");
128 sys
->radius
= var_CreateGetIntegerCommand(filter
, CFG_PREFIX
"radius");
129 var_AddCallback(filter
, CFG_PREFIX
"strength", Callback
, NULL
);
130 var_AddCallback(filter
, CFG_PREFIX
"radius", Callback
, NULL
);
133 struct vf_priv_s
*cfg
= &sys
->cfg
;
138 #if HAVE_SSE2 && HAVE_6REGS
140 cfg
->blur_line
= blur_line_sse2
;
143 cfg
->blur_line
= blur_line_c
;
146 cfg
->filter_line
= filter_line_ssse3
;
150 if (vlc_CPU_MMXEXT())
151 cfg
->filter_line
= filter_line_mmx2
;
154 cfg
->filter_line
= filter_line_c
;
157 filter
->ops
= &Filter_ops
;
161 static void Close(filter_t
*filter
)
163 filter_sys_t
*sys
= filter
->p_sys
;
165 var_DelCallback(filter
, CFG_PREFIX
"radius", Callback
, NULL
);
166 var_DelCallback(filter
, CFG_PREFIX
"strength", Callback
, NULL
);
167 aligned_free(sys
->cfg
.buf
);
171 static void Filter(filter_t
*filter
, picture_t
*src
, picture_t
*dst
)
173 filter_sys_t
*sys
= filter
->p_sys
;
175 vlc_mutex_lock(&sys
->lock
);
176 float strength
= VLC_CLIP(sys
->strength
, STRENGTH_MIN
, STRENGTH_MAX
);
177 int radius
= VLC_CLIP((sys
->radius
+ 1) & ~1, RADIUS_MIN
, RADIUS_MAX
);
178 vlc_mutex_unlock(&sys
->lock
);
180 const video_format_t
*fmt
= &filter
->fmt_in
.video
;
181 struct vf_priv_s
*cfg
= &sys
->cfg
;
183 cfg
->thresh
= (1 << 15) / strength
;
184 if (cfg
->radius
!= radius
) {
185 cfg
->radius
= radius
;
186 cfg
->buf
= aligned_alloc(16,
187 (((fmt
->i_width
+ 15) & ~15) * (cfg
->radius
+ 1) / 2 + 32) * sizeof(*cfg
->buf
));
190 for (int i
= 0; i
< dst
->i_planes
; i
++) {
191 const plane_t
*srcp
= &src
->p
[i
];
192 plane_t
*dstp
= &dst
->p
[i
];
194 const vlc_chroma_description_t
*chroma
= sys
->chroma
;
195 int w
= fmt
->i_width
* chroma
->p
[i
].w
.num
/ chroma
->p
[i
].w
.den
;
196 int h
= fmt
->i_height
* chroma
->p
[i
].h
.num
/ chroma
->p
[i
].h
.den
;
197 int r
= (cfg
->radius
* chroma
->p
[i
].w
.num
/ chroma
->p
[i
].w
.den
+
198 cfg
->radius
* chroma
->p
[i
].h
.num
/ chroma
->p
[i
].h
.den
) / 2;
199 r
= VLC_CLIP((r
+ 1) & ~1, RADIUS_MIN
, RADIUS_MAX
);
200 if (__MIN(w
, h
) > 2 * r
&& cfg
->buf
) {
201 filter_plane(cfg
, dstp
->p_pixels
, srcp
->p_pixels
,
202 w
, h
, dstp
->i_pitch
, srcp
->i_pitch
, r
);
204 plane_CopyPixels(dstp
, srcp
);
209 static int Callback(vlc_object_t
*object
, char const *cmd
,
210 vlc_value_t oldval
, vlc_value_t newval
, void *data
)
212 filter_t
*filter
= (filter_t
*)object
;
213 filter_sys_t
*sys
= filter
->p_sys
;
214 VLC_UNUSED(oldval
); VLC_UNUSED(data
);
216 vlc_mutex_lock(&sys
->lock
);
217 if (!strcmp(cmd
, CFG_PREFIX
"strength"))
218 sys
->strength
= newval
.f_float
;
220 sys
->radius
= newval
.i_int
;
221 vlc_mutex_unlock(&sys
->lock
);