1 /*****************************************************************************
2 * hqdn3d.c : high-quality denoise 3D ported from MPlayer
3 *****************************************************************************
4 * Copyright (C) 2011 VLC authors and VideoLAN
7 * Authors: Cheng Sun <chengsun9@gmail.com>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
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 Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
32 #include <vlc_common.h>
33 #include <vlc_plugin.h>
34 #include <vlc_filter.h>
35 #include <vlc_picture.h>
36 #include "filter_picture.h"
41 /*****************************************************************************
43 *****************************************************************************/
44 static int Open (vlc_object_t
*);
45 static void Close (vlc_object_t
*);
46 static picture_t
*Filter (filter_t
*, picture_t
*);
47 static int DenoiseCallback( vlc_object_t
*p_this
, char const *psz_var
,
48 vlc_value_t oldval
, vlc_value_t newval
,
51 /*****************************************************************************
53 *****************************************************************************/
55 #define FILTER_PREFIX "hqdn3d-"
57 #define LUMA_SPAT_TEXT N_("Spatial luma strength (0-254)")
58 #define CHROMA_SPAT_TEXT N_("Spatial chroma strength (0-254)")
59 #define LUMA_TEMP_TEXT N_("Temporal luma strength (0-254)")
60 #define CHROMA_TEMP_TEXT N_("Temporal chroma strength (0-254)")
63 set_shortname(N_("HQ Denoiser 3D"))
64 set_description(N_("High Quality 3D Denoiser filter"))
65 set_capability("video filter", 0)
66 set_category(CAT_VIDEO
)
67 set_subcategory(SUBCAT_VIDEO_VFILTER
)
69 add_float_with_range(FILTER_PREFIX
"luma-spat", 4.0, 0.0, 254.0,
70 LUMA_SPAT_TEXT
, LUMA_SPAT_TEXT
, false)
71 add_float_with_range(FILTER_PREFIX
"chroma-spat", 3.0, 0.0, 254.0,
72 CHROMA_SPAT_TEXT
, CHROMA_SPAT_TEXT
, false)
73 add_float_with_range(FILTER_PREFIX
"luma-temp", 6.0, 0.0, 254.0,
74 LUMA_TEMP_TEXT
, LUMA_TEMP_TEXT
, false)
75 add_float_with_range(FILTER_PREFIX
"chroma-temp", 4.5, 0.0, 254.0,
76 CHROMA_TEMP_TEXT
, CHROMA_TEMP_TEXT
, false)
78 add_shortcut("hqdn3d")
80 set_callbacks(Open
, Close
)
83 static const char *const filter_options
[] = {
84 "luma-spat", "chroma-spat", "luma-temp", "chroma-temp", NULL
87 /*****************************************************************************
89 *****************************************************************************/
92 const vlc_chroma_description_t
*chroma
;
97 vlc_mutex_t coefs_mutex
;
98 float luma_spat
, luma_temp
, chroma_spat
, chroma_temp
;
101 /*****************************************************************************
103 *****************************************************************************/
104 static int Open(vlc_object_t
*this)
106 filter_t
*filter
= (filter_t
*)this;
108 struct vf_priv_s
*cfg
;
109 const video_format_t
*fmt_in
= &filter
->fmt_in
.video
;
110 const video_format_t
*fmt_out
= &filter
->fmt_out
.video
;
111 const vlc_fourcc_t fourcc_in
= fmt_in
->i_chroma
;
112 const vlc_fourcc_t fourcc_out
= fmt_out
->i_chroma
;
115 const vlc_chroma_description_t
*chroma
=
116 vlc_fourcc_GetChromaDescription(fourcc_in
);
117 if (!chroma
|| chroma
->plane_count
!= 3 || chroma
->pixel_size
!= 1) {
118 msg_Err(filter
, "Unsupported chroma (%4.4s)", (char*)&fourcc_in
);
122 if (fourcc_in
!= fourcc_out
) {
123 msg_Err(filter
, "Input and output chromas don't match");
127 /* Allocate structure */
128 sys
= calloc(1, sizeof(filter_sys_t
));
134 sys
->chroma
= chroma
;
136 for (int i
= 0; i
< 3; ++i
) {
137 sys
->w
[i
] = fmt_in
->i_width
* chroma
->p
[i
].w
.num
/ chroma
->p
[i
].w
.den
;
138 if (sys
->w
[i
] > wmax
) wmax
= sys
->w
[i
];
139 sys
->h
[i
] = fmt_out
->i_height
* chroma
->p
[i
].h
.num
/ chroma
->p
[i
].h
.den
;
141 cfg
->Line
= malloc(wmax
*sizeof(unsigned int));
147 config_ChainParse(filter
, FILTER_PREFIX
, filter_options
,
151 vlc_mutex_init( &sys
->coefs_mutex
);
152 sys
->b_recalc_coefs
= true;
153 sys
->luma_spat
= var_CreateGetFloatCommand(filter
, FILTER_PREFIX
"luma-spat");
154 sys
->chroma_spat
= var_CreateGetFloatCommand(filter
, FILTER_PREFIX
"chroma-spat");
155 sys
->luma_temp
= var_CreateGetFloatCommand(filter
, FILTER_PREFIX
"luma-temp");
156 sys
->chroma_temp
= var_CreateGetFloatCommand(filter
, FILTER_PREFIX
"chroma-temp");
159 filter
->pf_video_filter
= Filter
;
161 var_AddCallback( filter
, FILTER_PREFIX
"luma-spat", DenoiseCallback
, sys
);
162 var_AddCallback( filter
, FILTER_PREFIX
"chroma-spat", DenoiseCallback
, sys
);
163 var_AddCallback( filter
, FILTER_PREFIX
"luma-temp", DenoiseCallback
, sys
);
164 var_AddCallback( filter
, FILTER_PREFIX
"chroma-temp", DenoiseCallback
, sys
);
169 /*****************************************************************************
171 *****************************************************************************/
172 static void Close(vlc_object_t
*this)
174 filter_t
*filter
= (filter_t
*)this;
175 filter_sys_t
*sys
= filter
->p_sys
;
176 struct vf_priv_s
*cfg
= &sys
->cfg
;
178 var_DelCallback( filter
, FILTER_PREFIX
"luma-spat", DenoiseCallback
, sys
);
179 var_DelCallback( filter
, FILTER_PREFIX
"chroma-spat", DenoiseCallback
, sys
);
180 var_DelCallback( filter
, FILTER_PREFIX
"luma-temp", DenoiseCallback
, sys
);
181 var_DelCallback( filter
, FILTER_PREFIX
"chroma-temp", DenoiseCallback
, sys
);
183 vlc_mutex_destroy( &sys
->coefs_mutex
);
185 for (int i
= 0; i
< 3; ++i
) {
192 /*****************************************************************************
194 *****************************************************************************/
195 static picture_t
*Filter(filter_t
*filter
, picture_t
*src
)
198 filter_sys_t
*sys
= filter
->p_sys
;
199 struct vf_priv_s
*cfg
= &sys
->cfg
;
202 if (!src
) return NULL
;
204 dst
= filter_NewPicture(filter
);
205 if ( unlikely(!dst
) ) {
206 picture_Release(src
);
209 vlc_mutex_lock( &sys
->coefs_mutex
);
210 recalc
= sys
->b_recalc_coefs
;
211 sys
->b_recalc_coefs
= false;
213 if( unlikely( recalc
) )
215 msg_Dbg( filter
, "Changing coefs to %.2f %.2f %.2f %.2f",
216 sys
->luma_spat
, sys
->luma_temp
, sys
->chroma_spat
, sys
->chroma_temp
);
217 PrecalcCoefs(cfg
->Coefs
[0], sys
->luma_spat
);
218 PrecalcCoefs(cfg
->Coefs
[1], sys
->luma_temp
);
219 PrecalcCoefs(cfg
->Coefs
[2], sys
->chroma_spat
);
220 PrecalcCoefs(cfg
->Coefs
[3], sys
->chroma_temp
);
222 vlc_mutex_unlock( &sys
->coefs_mutex
);
224 deNoise(src
->p
[0].p_pixels
, dst
->p
[0].p_pixels
,
225 cfg
->Line
, &cfg
->Frame
[0], sys
->w
[0], sys
->h
[0],
226 src
->p
[0].i_pitch
, dst
->p
[0].i_pitch
,
230 deNoise(src
->p
[1].p_pixels
, dst
->p
[1].p_pixels
,
231 cfg
->Line
, &cfg
->Frame
[1], sys
->w
[1], sys
->h
[1],
232 src
->p
[1].i_pitch
, dst
->p
[1].i_pitch
,
236 deNoise(src
->p
[2].p_pixels
, dst
->p
[2].p_pixels
,
237 cfg
->Line
, &cfg
->Frame
[2], sys
->w
[2], sys
->h
[2],
238 src
->p
[2].i_pitch
, dst
->p
[2].i_pitch
,
243 if(unlikely(!cfg
->Frame
[0] || !cfg
->Frame
[1] || !cfg
->Frame
[2]))
245 picture_Release( src
);
246 picture_Release( dst
);
250 return CopyInfoAndRelease(dst
, src
);
254 static int DenoiseCallback( vlc_object_t
*p_this
, char const *psz_var
,
255 vlc_value_t oldval
, vlc_value_t newval
,
258 VLC_UNUSED(p_this
); VLC_UNUSED(oldval
);
260 filter_sys_t
*sys
= (filter_sys_t
*)p_data
;
262 /* Just take values and flag for recalc so we don't block UI thread calling this
263 * and don't right thread safety calcing coefs in here without mutex*/
264 vlc_mutex_lock( &sys
->coefs_mutex
);
265 if( !strcmp( psz_var
, FILTER_PREFIX
"luma-spat") )
266 sys
->luma_spat
= newval
.f_float
;
267 else if( !strcmp( psz_var
, FILTER_PREFIX
"luma-temp") )
268 sys
->luma_temp
= newval
.f_float
;
269 else if( !strcmp( psz_var
, FILTER_PREFIX
"chroma-temp") )
270 sys
->chroma_spat
= newval
.f_float
;
271 else if( !strcmp( psz_var
, FILTER_PREFIX
"chroma-spat") )
272 sys
->chroma_temp
= newval
.f_float
;
273 sys
->b_recalc_coefs
= true;
274 vlc_mutex_unlock( &sys
->coefs_mutex
);