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>
38 #include <vlc_picture.h>
40 /*****************************************************************************
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")
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
)
73 /*****************************************************************************
75 *****************************************************************************/
76 #define FFMAX(a,b) __MAX(a,b)
77 #ifdef CAN_COMPILE_MMXEXT
82 #ifdef CAN_COMPILE_SSE2
87 #ifdef CAN_COMPILE_SSSE3
92 // FIXME too restrictive
98 #define av_clip_uint8 clip_uint8_vlc
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
{
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
);
124 filter_sys_t
*sys
= malloc(sizeof(*sys
));
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
);
136 struct vf_priv_s
*cfg
= &sys
->cfg
;
141 #if HAVE_SSE2 && HAVE_6REGS
143 cfg
->blur_line
= blur_line_sse2
;
146 cfg
->blur_line
= blur_line_c
;
149 cfg
->filter_line
= filter_line_ssse3
;
153 if (vlc_CPU_MMXEXT())
154 cfg
->filter_line
= filter_line_mmx2
;
157 cfg
->filter_line
= filter_line_c
;
160 filter
->pf_video_filter
= Filter
;
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
);
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
);
182 picture_Release(src
);
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
);
215 plane_CopyPixels(dstp
, srcp
);
219 picture_CopyProperties(dst
, src
);
220 picture_Release(src
);
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
;
235 sys
->radius
= newval
.i_int
;
236 vlc_mutex_unlock(&sys
->lock
);