Credit Andrew - fix vorbis audio which was scratchy and ensure aging plugin does...
[goodguy/cinelerra.git] / cinelerra-5.1 / plugins / denoisemjpeg / denoisemjpeg.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "clip.h"
23 #include "bchash.h"
24 #include "denoisemjpeg.h"
25 #include "filexml.h"
26 #include "guicast.h"
27 #include "keyframe.h"
28 #include "language.h"
29 #include "vframe.h"
30
31
32 #include <stdint.h>
33 #include <string.h>
34
35
36
37 REGISTER_PLUGIN(DenoiseMJPEG)
38
39
40
41 DenoiseMJPEGConfig::DenoiseMJPEGConfig()
42 {
43         radius = 8;
44         threshold = 5;
45         threshold2 = 4;
46         sharpness = 125;
47         lcontrast = 100;
48         ccontrast = 100;
49         deinterlace = 0;
50         mode = 0;
51         delay = 3;
52 }
53
54 int DenoiseMJPEGConfig::equivalent(DenoiseMJPEGConfig &that)
55 {
56         return
57                 that.radius == radius &&
58                 that.threshold == threshold &&
59                 that.threshold2 == threshold2 &&
60                 that.sharpness == sharpness &&
61                 that.lcontrast == lcontrast &&
62                 that.ccontrast == ccontrast &&
63                 that.deinterlace == deinterlace &&
64                 that.mode == mode &&
65                 that.delay == delay;
66 }
67
68 void DenoiseMJPEGConfig::copy_from(DenoiseMJPEGConfig &that)
69 {
70         radius = that.radius;
71         threshold = that.threshold;
72         threshold2 = that.threshold2;
73         sharpness = that.sharpness;
74         lcontrast = that.lcontrast;
75         ccontrast = that.ccontrast;
76         deinterlace = that.deinterlace;
77         mode = that.mode;
78         delay = that.delay;
79 }
80
81 void DenoiseMJPEGConfig::interpolate(DenoiseMJPEGConfig &prev,
82         DenoiseMJPEGConfig &next,
83         long prev_frame,
84         long next_frame,
85         long current_frame)
86 {
87         double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
88         double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
89
90         this->radius = (int)(prev.radius * prev_scale + next.radius * next_scale);
91         this->threshold = (int)(prev.threshold * prev_scale + next.threshold * next_scale);
92         this->threshold2 = (int)(prev.threshold2 * prev_scale + next.threshold2 * next_scale);
93         this->sharpness = (int)(prev.sharpness * prev_scale + next.sharpness * next_scale);
94         this->lcontrast = (int)(prev.lcontrast * prev_scale + next.lcontrast * next_scale);
95         this->ccontrast = (int)(prev.ccontrast * prev_scale + next.ccontrast * next_scale);
96         this->deinterlace = prev.deinterlace;
97         this->mode = prev.mode;
98         this->delay = (int)(prev.delay * prev_scale + next.delay * next_scale);
99 }
100
101
102
103
104
105
106 DenoiseMJPEGRadius::DenoiseMJPEGRadius(DenoiseMJPEG *plugin, int x, int y)
107  : BC_IPot(x,
108         y,
109         plugin->config.radius,
110         8,
111         24)
112 {
113         this->plugin = plugin;
114 }
115
116 int DenoiseMJPEGRadius::handle_event()
117 {
118         int result = get_value();
119         plugin->config.radius = result;
120         plugin->send_configure_change();
121         return 1;
122 }
123
124
125
126
127
128
129 DenoiseMJPEGThresh::DenoiseMJPEGThresh(DenoiseMJPEG *plugin, int x, int y)
130  : BC_IPot(x,
131         y,
132         plugin->config.threshold,
133         0,
134         255)
135 {
136         this->plugin = plugin;
137 }
138
139 int DenoiseMJPEGThresh::handle_event()
140 {
141         int result = get_value();
142         plugin->config.threshold = result;
143         plugin->send_configure_change();
144         return 1;
145 }
146
147
148
149
150
151
152 DenoiseMJPEGThresh2::DenoiseMJPEGThresh2(DenoiseMJPEG *plugin, int x, int y)
153  : BC_IPot(x,
154         y,
155         plugin->config.threshold2,
156         0,
157         255)
158 {
159         this->plugin = plugin;
160 }
161
162 int DenoiseMJPEGThresh2::handle_event()
163 {
164         int result = get_value();
165         plugin->config.threshold2 = result;
166         plugin->send_configure_change();
167         return 1;
168 }
169
170
171
172
173
174
175 DenoiseMJPEGSharp::DenoiseMJPEGSharp(DenoiseMJPEG *plugin, int x, int y)
176  : BC_IPot(x,
177         y,
178         plugin->config.sharpness,
179         0,
180         255)
181 {
182         this->plugin = plugin;
183 }
184
185 int DenoiseMJPEGSharp::handle_event()
186 {
187         int result = get_value();
188         plugin->config.sharpness = result;
189         plugin->send_configure_change();
190         return 1;
191 }
192
193
194
195
196
197
198 DenoiseMJPEGLContrast::DenoiseMJPEGLContrast(DenoiseMJPEG *plugin, int x, int y)
199  : BC_IPot(x,
200         y,
201         plugin->config.lcontrast,
202         0,
203         255)
204 {
205         this->plugin = plugin;
206 }
207
208 int DenoiseMJPEGLContrast::handle_event()
209 {
210         int result = get_value();
211         plugin->config.lcontrast = result;
212         plugin->send_configure_change();
213         return 1;
214 }
215
216
217
218
219
220
221 DenoiseMJPEGCContrast::DenoiseMJPEGCContrast(DenoiseMJPEG *plugin, int x, int y)
222  : BC_IPot(x,
223         y,
224         plugin->config.ccontrast,
225         0,
226         255)
227 {
228         this->plugin = plugin;
229 }
230
231 int DenoiseMJPEGCContrast::handle_event()
232 {
233         int result = get_value();
234         plugin->config.ccontrast = result;
235         plugin->send_configure_change();
236         return 1;
237 }
238
239
240
241
242
243
244 DenoiseMJPEGDeinterlace::DenoiseMJPEGDeinterlace(DenoiseMJPEG *plugin, int x, int y)
245  : BC_CheckBox(x,
246         y,
247         plugin->config.deinterlace,
248         _("Deinterlace"))
249 {
250         this->plugin = plugin;
251 }
252
253 int DenoiseMJPEGDeinterlace::handle_event()
254 {
255         int result = get_value();
256         plugin->config.deinterlace = result;
257         plugin->send_configure_change();
258         return 1;
259 }
260
261
262
263
264
265
266 DenoiseMJPEGModeProgressive::DenoiseMJPEGModeProgressive(DenoiseMJPEG *plugin, DenoiseMJPEGWindow *gui, int x, int y)
267  : BC_Radial(x,
268         y,
269         plugin->config.mode == 0,
270         _("Progressive"))
271 {
272         this->plugin = plugin;
273         this->gui = gui;
274 }
275
276 int DenoiseMJPEGModeProgressive::handle_event()
277 {
278         int result = get_value();
279         if(result) gui->update_mode(0);
280         plugin->send_configure_change();
281         return 1;
282 }
283
284
285 DenoiseMJPEGModeInterlaced::DenoiseMJPEGModeInterlaced(DenoiseMJPEG *plugin, DenoiseMJPEGWindow *gui, int x, int y)
286  : BC_Radial(x,
287         y,
288         plugin->config.mode == 1,
289         _("Interlaced"))
290 {
291         this->plugin = plugin;
292         this->gui = gui;
293 }
294
295 int DenoiseMJPEGModeInterlaced::handle_event()
296 {
297         int result = get_value();
298         if(result) gui->update_mode(1);
299         plugin->send_configure_change();
300         return 1;
301 }
302
303
304 DenoiseMJPEGModeFast::DenoiseMJPEGModeFast(DenoiseMJPEG *plugin, DenoiseMJPEGWindow *gui, int x, int y)
305  : BC_Radial(x,
306         y,
307         plugin->config.mode == 2,
308         _("Fast"))
309 {
310         this->plugin = plugin;
311         this->gui = gui;
312 }
313
314 int DenoiseMJPEGModeFast::handle_event()
315 {
316         int result = get_value();
317         if(result) gui->update_mode(2);
318         plugin->send_configure_change();
319         return 1;
320 }
321
322
323
324
325
326
327 DenoiseMJPEGDelay::DenoiseMJPEGDelay(DenoiseMJPEG *plugin, int x, int y)
328  : BC_IPot(x,
329         y,
330         plugin->config.delay,
331         1,
332         8)
333 {
334         this->plugin = plugin;
335 }
336
337 int DenoiseMJPEGDelay::handle_event()
338 {
339         int result = get_value();
340         plugin->config.delay = result;
341         plugin->send_configure_change();
342         return 1;
343 }
344
345
346
347
348
349
350
351
352
353
354
355 DenoiseMJPEGWindow::DenoiseMJPEGWindow(DenoiseMJPEG *plugin)
356  : PluginClientWindow(plugin, xS(250), yS(350), 0, 0, 1)
357 {
358         this->plugin = plugin;
359 }
360
361
362 void DenoiseMJPEGWindow::create_objects()
363 {
364         int xs10 = xS(10), xs25 = xS(25), xs30 = xS(30), xs140 = xS(140), xs180 = xS(180);
365         int ys10 = yS(10), ys20 = yS(20);
366         int x1 = xs10, y1 = ys20, x2 = xs140, x3 = xs180, y2 = ys10, margin = xs30, margin2 = xs25;
367         add_subwindow(new BC_Title(x1, y1, _("Search radius:")));
368         add_subwindow(radius = new DenoiseMJPEGRadius(plugin, x2, y2));
369         y1 += margin;
370         y2 += margin;
371         add_subwindow(new BC_Title(x1, y1, _("Pass 1 threshold:")));
372         add_subwindow(threshold1 = new DenoiseMJPEGThresh(plugin, x3, y2));
373         y1 += margin;
374         y2 += margin;
375         add_subwindow(new BC_Title(x1, y1, _("Pass 2 threshold:")));
376         add_subwindow(threshold2 = new DenoiseMJPEGThresh2(plugin, x2, y2));
377         y1 += margin;
378         y2 += margin;
379         add_subwindow(new BC_Title(x1, y1, _("Sharpness:")));
380         add_subwindow(sharpness = new DenoiseMJPEGSharp(plugin, x3, y2));
381         y1 += margin;
382         y2 += margin;
383         add_subwindow(new BC_Title(x1, y1, _("Luma contrast:")));
384         add_subwindow(lcontrast = new DenoiseMJPEGLContrast(plugin, x2, y2));
385         y1 += margin;
386         y2 += margin;
387         add_subwindow(new BC_Title(x1, y1, _("Chroma contrast:")));
388         add_subwindow(ccontrast = new DenoiseMJPEGCContrast(plugin, x3, y2));
389         y1 += margin;
390         y2 += margin;
391         add_subwindow(new BC_Title(x1, y1, _("Delay frames:")));
392         add_subwindow(delay = new DenoiseMJPEGDelay(plugin, x2, y2));
393         y1 += margin;
394         y2 += margin;
395         add_subwindow(new BC_Title(x1, y1, _("Mode:")));
396         add_subwindow(interlaced = new DenoiseMJPEGModeInterlaced(plugin, this, x2, y1));
397         y1 += margin2;
398         y2 += margin2;
399         add_subwindow(progressive = new DenoiseMJPEGModeProgressive(plugin, this, x2, y1));
400         y1 += margin2;
401         y2 += margin2;
402         add_subwindow(fast = new DenoiseMJPEGModeFast(plugin, this, x2, y1));
403         y1 += margin;
404         y2 += margin;
405         add_subwindow(deinterlace = new DenoiseMJPEGDeinterlace(plugin, x1, y1));
406
407         show_window();
408         flush();
409 }
410
411 void DenoiseMJPEGWindow::update_mode(int value)
412 {
413         plugin->config.mode = value;
414         progressive->update(value == 0);
415         interlaced->update(value == 1);
416         fast->update(value == 2);
417 }
418
419 int DenoiseMJPEGWindow::close_event()
420 {
421         set_done(1);
422         return 1;
423 }
424
425
426
427
428 DenoiseMJPEG::DenoiseMJPEG(PluginServer *server)
429  : PluginVClient(server)
430 {
431
432         accumulation = 0;
433 }
434
435
436 DenoiseMJPEG::~DenoiseMJPEG()
437 {
438
439
440         if(accumulation) delete [] accumulation;
441 }
442
443 int DenoiseMJPEG::process_realtime(VFrame *input, VFrame *output)
444 {
445         load_configuration();
446         return 0;
447 }
448
449 const char* DenoiseMJPEG::plugin_title() { return N_("Denoise video2"); }
450 int DenoiseMJPEG::is_realtime() { return 1; }
451
452 void DenoiseMJPEG::update_gui()
453 {
454         if(thread)
455         {
456                 load_configuration();
457                 DenoiseMJPEGWindow *window = (DenoiseMJPEGWindow *)thread->window;
458                 window->lock_window();
459                 window->delay->update(config.delay);
460                 window->threshold1->update(config.threshold);
461                 window->unlock_window();
462         }
463 }
464
465
466 NEW_WINDOW_MACRO(DenoiseMJPEG, DenoiseMJPEGWindow)
467 LOAD_CONFIGURATION_MACRO(DenoiseMJPEG, DenoiseMJPEGConfig)
468
469
470 void DenoiseMJPEG::save_data(KeyFrame *keyframe)
471 {
472         FileXML output;
473
474 // cause data to be stored directly in text
475         output.set_shared_output(keyframe->xbuf);
476         output.tag.set_title("DENOISE_VIDEO2");
477         output.tag.set_property("RADIUS", config.radius);
478         output.tag.set_property("THRESHOLD", config.threshold);
479         output.tag.set_property("THRESHOLD2", config.threshold2);
480         output.tag.set_property("SHARPNESS", config.sharpness);
481         output.tag.set_property("LCONTRAST", config.lcontrast);
482         output.tag.set_property("CCONTRAST", config.ccontrast);
483         output.tag.set_property("DEINTERLACE", config.deinterlace);
484         output.tag.set_property("MODE", config.mode);
485         output.tag.set_property("DELAY", config.delay);
486         output.append_tag();
487         output.tag.set_title("/DENOISE_VIDEO2");
488         output.append_tag();
489         output.append_newline();
490         output.terminate_string();
491 }
492
493 void DenoiseMJPEG::read_data(KeyFrame *keyframe)
494 {
495         FileXML input;
496
497         input.set_shared_input(keyframe->xbuf);
498
499         while(!input.read_tag())
500         {
501                 if(input.tag.title_is("DENOISE_VIDEO2"))
502                 {
503                         config.radius = input.tag.get_property("RADIUS", config.radius);
504                         config.threshold = input.tag.get_property("THRESHOLD", config.threshold);
505                         config.threshold2 = input.tag.get_property("THRESHOLD2", config.threshold2);
506                         config.sharpness = input.tag.get_property("SHARPNESS", config.sharpness);
507                         config.lcontrast = input.tag.get_property("LCONTRAST", config.lcontrast);
508                         config.ccontrast = input.tag.get_property("CCONTRAST", config.ccontrast);
509                         config.deinterlace = input.tag.get_property("DEINTERLACE", config.deinterlace);
510                         config.mode = input.tag.get_property("MODE", config.mode);
511                         config.delay = input.tag.get_property("DELAY", config.delay);
512                 }
513         }
514 }
515
516
517
518