Fixed initialisation of tf in file_open(). Without setting the memory to 0,
[cinelerra_cv/mob.git] / plugins / denoiseseltempavg / seltempavg.C
blobccbfd78bb63a43c3b5a82ebfaf5d85617c62c3a8
1 #include "clip.h"
2 #include "bchash.h"
3 #include "filexml.h"
4 #include "keyframe.h"
5 #include "language.h"
6 #include "picon_png.h"
7 #include "seltempavg.h"
8 #include "seltempavgwindow.h"
9 #include "vframe.h"
11 #include <stdint.h>
12 #include <string.h>
14 REGISTER_PLUGIN(SelTempAvgMain)
17 //////////////////////////////////////////////////////////////////////
18 SelTempAvgConfig::SelTempAvgConfig()
20         frames = 1;
21         method = SelTempAvgConfig::METHOD_SELTEMPAVG;
22         offsetmode = SelTempAvgConfig::OFFSETMODE_RESTARTMARKERSYS;
23         paranoid = 0;
24         nosubtract = 0;
25         offset_restartmarker_keyframe = 0;
26         offset_fixed_value = -15;
27         gain = 1.00;
29         avg_threshold_RY = 0; avg_threshold_GU = 0; avg_threshold_BV = 0;
30         std_threshold_RY = 0; std_threshold_GU = 0; std_threshold_BV = 0;
31         mask_RY = 0; mask_GU = 0; mask_BV = 0;
34 void SelTempAvgConfig::copy_from(SelTempAvgConfig *src)
36         this->frames = src->frames;
37         this->method = src->method;
38         this->offsetmode = src->offsetmode;
39         this->paranoid = src->paranoid;
40         this->nosubtract = src->nosubtract;
41         this->offset_restartmarker_keyframe = src->offset_restartmarker_keyframe;
42         this->offset_fixed_value = src->offset_fixed_value;
43         this->gain = src->gain;
44         this->avg_threshold_RY = src->avg_threshold_RY; this->avg_threshold_GU = src->avg_threshold_GU; 
45         this->avg_threshold_BV = src->avg_threshold_BV; this->std_threshold_RY = src->std_threshold_RY; 
46         this->std_threshold_GU = src->std_threshold_GU; this->std_threshold_BV = src->std_threshold_BV;
48         this->mask_BV = src->mask_BV; this->mask_RY = src->mask_RY; this->mask_GU = src->mask_GU;
51 int SelTempAvgConfig::equivalent(SelTempAvgConfig *src)
53   return frames == src->frames &&
54           method == src->method &&
55           offsetmode == src->offsetmode &&
56           paranoid == src->paranoid &&
57           offset_restartmarker_keyframe == src->offset_restartmarker_keyframe &&
58           offset_fixed_value == src->offset_fixed_value &&
59           gain == src->gain &&
60           this->avg_threshold_RY == src->avg_threshold_RY && this->avg_threshold_GU == src->avg_threshold_GU &&
61           this->avg_threshold_BV == src->avg_threshold_BV && this->std_threshold_RY == src->std_threshold_RY &&
62           this->std_threshold_GU == src->std_threshold_GU && this->std_threshold_BV == src->std_threshold_BV &&
63           this->mask_RY == src->mask_RY && this->mask_GU == src->mask_GU && this->mask_BV == src->mask_BV;
67 //////////////////////////////////////////////////////////////////////
68 SelTempAvgMain::SelTempAvgMain(PluginServer *server)
69  : PluginVClient(server)
71         PLUGIN_CONSTRUCTOR_MACRO
72         accumulation = 0;
73         history = 0;
74         history_size = 0;
75         history_start = -0x7fffffff;
76         history_frame = 0;
77         history_valid = 0;
78         prev_frame = -1;
81 SelTempAvgMain::~SelTempAvgMain()
83         PLUGIN_DESTRUCTOR_MACRO
85         if(accumulation) 
86         {
87                 delete [] accumulation;
88                 delete [] accumulation_sq;
89         }
90         if(history)
91         {
92                 for(int i = 0; i < config.frames; i++)
93                         delete history[i];
94                 delete [] history;
95         }
96         if(history_frame) delete [] history_frame;
97         if(history_valid) delete [] history_valid;
100 char* SelTempAvgMain::plugin_title() { return N_("Selective Temporal Averaging"); }
101 int SelTempAvgMain::is_realtime() { return 1; }
104 NEW_PICON_MACRO(SelTempAvgMain)
106 SHOW_GUI_MACRO(SelTempAvgMain, SelTempAvgThread)
108 SET_STRING_MACRO(SelTempAvgMain)
110 RAISE_WINDOW_MACRO(SelTempAvgMain);
112 int SelTempAvgMain::process_buffer(VFrame *frame,
113                 int64_t start_position,
114                 double frame_rate)
116         int h = frame->get_h();
117         int w = frame->get_w();
118         int color_model = frame->get_color_model();
119         load_configuration();
121 // Allocate accumulation
122         if(!accumulation)
123         {
124                 accumulation = new unsigned char[w * 
125                                                  h * 
126                                                  cmodel_components(color_model) *
127                                                  sizeof(float)];
129                 accumulation_sq = new unsigned char[w * 
130                                                     h *
131                                                     3 *
132                                                     sizeof(float)];
133                 clear_accum(w, h, color_model);
134         }
136         if(!config.nosubtract)
137         {
138 // Reallocate history
139                 if(history)
140                 {
141                         if(config.frames != history_size)
142                         {
143                                 VFrame **history2;
144                                 int64_t *history_frame2;
145                                 int *history_valid2;
146                                 history2 = new VFrame*[config.frames];
147                                 history_frame2 = new int64_t[config.frames];
148                                 history_valid2 = new int[config.frames];
150 // Copy existing frames over
151                                 int i, j;
152                                 for(i = 0, j = 0; i < config.frames && j < history_size; i++, j++)
153                                 {
154                                         history2[i] = history[j];
155                                         history_frame2[i] = history_frame[i];
156                                         history_valid2[i] = history_valid[i];
157                                 }
159 // Delete extra previous frames and subtract from accumulation
160                                 for( ; j < history_size; j++)
161                                 {
162                                         subtract_accum(history[j]);
163                                         delete history[j];
164                                 }
165                                 delete [] history;
166                                 delete [] history_frame;
167                                 delete [] history_valid;
170 // Create new frames
171                                 for( ; i < config.frames; i++)
172                                 {
173                                         history2[i] = new VFrame(0, w, h, color_model);
174                                         history_frame2[i] = -0x7fffffff;
175                                         history_valid2[i] = 0;
176                                 }
178                                 history = history2;
179                                 history_frame = history_frame2;
180                                 history_valid = history_valid2;
182                                 history_size = config.frames;
183                         }
184                 }
185                 else
186 // Allocate history
187                 {
188                         history = new VFrame*[config.frames];
189                         for(int i = 0; i < config.frames; i++)
190                                 history[i] = new VFrame(0, w, h, color_model);
191                         history_size = config.frames;
192                         history_frame = new int64_t[config.frames];
193                         bzero(history_frame, sizeof(int64_t) * config.frames);
194                         history_valid = new int[config.frames];
195                         bzero(history_valid, sizeof(int) * config.frames);
196                 }
203 // Create new history frames based on current frame
204                 int64_t *new_history_frames = new int64_t[history_size];
206                 int64_t theoffset = (int64_t) config.offset_fixed_value;
207                 if (config.offsetmode == SelTempAvgConfig::OFFSETMODE_RESTARTMARKERSYS)
208                         theoffset = (int64_t) restartoffset;
210                 for(int i = 0; i < history_size; i++)
211                 {
212                         new_history_frames[history_size - i - 1] = start_position + theoffset + i;
213                 }
215 // Subtract old history frames which are not in the new vector
216                 int no_change = 1;
217                 for(int i = 0; i < history_size; i++)
218                 {
219 // Old frame is valid
220                         if(history_valid[i])
221                         {
222                                 int got_it = 0;
223                                 for(int j = 0; j < history_size; j++)
224                                 {
225 // Old frame is equal to a new frame
226                                         if(history_frame[i] == new_history_frames[j]) 
227                                         {
228                                                 got_it = 1;
229                                                 break;
230                                         }
231                                 }
233 // Didn't find old frame in new frames
234                                 if(!got_it)
235                                 {
236                                         subtract_accum(history[i]);
237                                         history_valid[i] = 0;
238                                         no_change = 0;
239                                 }
240                         }
241                 }
242 // If all frames are still valid, assume tweek occurred upstream and reload.
243                 if(config.paranoid && no_change)
244                 {
245                         for(int i = 0; i < history_size; i++)
246                         {
247                                 history_valid[i] = 0;
248                         }
249                         clear_accum(w, h, color_model);
250                 }
252 // Add new history frames which are not in the old vector
253                 for(int i = 0; i < history_size; i++)
254                 {
255 // Find new frame in old vector
256                         int got_it = 0;
257                         for(int j = 0; j < history_size; j++)
258                         {
259                                 if(history_valid[j] && history_frame[j] == new_history_frames[i])
260                                 {
261                                         got_it = 1;
262                                         break;
263                                 }
264                         }
266 // Didn't find new frame in old vector
267                         if(!got_it)
268                         {
269 // Get first unused entry
270                                 for(int j = 0; j < history_size; j++)
271                                 {
272                                         if(!history_valid[j])
273                                         {
274 // Load new frame into it
275                                                 history_frame[j] = new_history_frames[i];
276                                                 history_valid[j] = 1;
277                                                 read_frame(history[j],
278                                                         0,
279                                                         history_frame[j],
280                                                         frame_rate);
281                                                 add_accum(history[j]);
282                                                 break;
283                                         }
284                                 }
285                         }
286                 }
287                 delete [] new_history_frames;
288         }
289         else
290 // No subtraction
291         {
292 // Force reload if not repositioned or just started
293                 if(config.paranoid && prev_frame == start_position ||
294                         prev_frame < 0)
295                 {
296                         prev_frame = start_position - config.frames + 1;
297                         prev_frame = MAX(0, prev_frame);
298                         clear_accum(w, h, color_model);
299                 }
301                 for(int64_t i = prev_frame; i <= start_position; i++)
302                 {
303                         read_frame(frame,
304                                 0,
305                                 i,
306                                 frame_rate);
307                         add_accum(frame);
308 //printf("SelTempAvgMain::process_buffer 1 %lld %lld %lld\n", prev_frame, start_position, i);
309                 }
311                 prev_frame = start_position;
312         }
316         // Read current frame into buffer (needed for the std-deviation tool)
317         read_frame(frame,
318                         0,
319                         start_position,
320                         frame_rate);
323 // Transfer accumulation to output with division if average is desired.
324         transfer_accum(frame);
326 //printf("SelTempAvgMain::process_buffer 2\n");
329         return 0;
341 // Reset accumulation
342 #define CLEAR_ACCUM(type, components, chroma) \
343 { \
344         float *row = (float*)accumulation; \
345         float *row_sq = (float*)accumulation_sq; \
346         if(chroma) \
347         { \
348                 for(int i = 0; i < w * h; i++) \
349                 { \
350                         *row++ = 0x0; \
351                         *row++ = 0x0; \
352                         *row++ = 0x0; \
353                         if(components == 4) *row++ = 0x0; \
354                         *row_sq++ = 0x0; \
355                         *row_sq++ = 0x0; \
356                         *row_sq++ = 0x0; \
357                 } \
358         } \
359         else \
360         { \
361                 bzero(row, w * h * sizeof(type) * components); \
362                 bzero(row_sq, w * h * 3 * sizeof(float)); \
363         } \
367 void SelTempAvgMain::clear_accum(int w, int h, int color_model)
369         switch(color_model)
370         {
371                 case BC_RGB888:
372                         CLEAR_ACCUM(int, 3, 0x0)
373                         break;
374                 case BC_RGB_FLOAT:
375                         CLEAR_ACCUM(float, 3, 0x0)
376                         break;
377                 case BC_RGBA8888:
378                         CLEAR_ACCUM(int, 4, 0x0)
379                         break;
380                 case BC_RGBA_FLOAT:
381                         CLEAR_ACCUM(float, 4, 0x0)
382                         break;
383                 case BC_YUV888:
384                         CLEAR_ACCUM(int, 3, 0x80)
385                         break;
386                 case BC_YUVA8888:
387                         CLEAR_ACCUM(int, 4, 0x80)
388                         break;
389                 case BC_YUV161616:
390                         CLEAR_ACCUM(int, 3, 0x8000)
391                         break;
392                 case BC_YUVA16161616:
393                         CLEAR_ACCUM(int, 4, 0x8000)
394                         break;
395         }
397 #define C2_IS(frame_row,chroma,max)  (float)(frame_row)/max 
400 #define SUBTRACT_ACCUM(type, \
401         components, \
402         chroma, \
403         max) \
404 { \
405         if(1) \
406         { \
407                 for(int i = 0; i < h; i++) \
408                 { \
409                         float *accum_row = (float*)accumulation + \
410                                 i * w * components; \
411                         float *accum_row_sq = (float*)accumulation_sq + \
412                                 i * w *3; \
413                         type *frame_row = (type*)frame->get_rows()[i]; \
414                         float c1, c2, c3; \
415                         for(int j = 0; j < w; j++) \
416                         { \
417                                 c1 = ( (float)*frame_row )/max; \
418                                 frame_row++; \
419                                 c2 = ( (float)*frame_row )/max; \
420                                 frame_row++; \
421                                 c3 = ( (float)(*frame_row -0) )/max; \
422                                 frame_row++; \
424                                 *accum_row -= c1; \
425                                 accum_row++; \
426                                 *accum_row -= c2; \
427                                 accum_row++; \
428                                 *accum_row -= c3; \
429                                 accum_row++; \
430                                 if(components == 4) { *accum_row -= ((float)*frame_row++)/max; accum_row++; } \
432                                 *accum_row_sq++ -= c1*c1; \
433                                 *accum_row_sq++ -= c2*c2; \
434                                 *accum_row_sq++ -= c3*c3; \
435                         } \
436                 } \
437         } \
441 void SelTempAvgMain::subtract_accum(VFrame *frame)
443 // Just accumulate
444         if(config.nosubtract) return;
445         int w = frame->get_w();
446         int h = frame->get_h();
448         switch(frame->get_color_model())
449         {
450                 case BC_RGB888:
451                         SUBTRACT_ACCUM(unsigned char, 3, 0x0, 0xff)
452                         break;
453                 case BC_RGB_FLOAT:
454                         SUBTRACT_ACCUM(float, 3, 0x0, 1.0)
455                         break;
456                 case BC_RGBA8888:
457                         SUBTRACT_ACCUM(unsigned char, 4, 0x0, 0xff)
458                         break;
459                 case BC_RGBA_FLOAT:
460                         SUBTRACT_ACCUM(float, 4, 0x0, 1.0)
461                         break;
462                 case BC_YUV888:
463                         SUBTRACT_ACCUM(unsigned char, 3, 0x80, 0xff)
464                         break;
465                 case BC_YUVA8888:
466                         SUBTRACT_ACCUM(unsigned char, 4, 0x80, 0xff)
467                         break;
468                 case BC_YUV161616:
469                         SUBTRACT_ACCUM(uint16_t, 3, 0x8000, 0xffff)
470                         break;
471                 case BC_YUVA16161616:
472                         SUBTRACT_ACCUM(uint16_t, 4, 0x8000, 0xffff)
473                         break;
474         }
478 // The behavior has to be very specific to the color model because we rely on
479 // the value of full black to determine what pixel to show.
480 #define ADD_ACCUM(type, components, chroma, max) \
481 { \
482         float c1, c2, c3; \
483         if(1) \
484         { \
485                 for(int i = 0; i < h; i++) \
486                 { \
487                         float *accum_row = (float*)accumulation + \
488                                 i * w * components; \
489                         float *accum_row_sq = (float*)accumulation_sq + \
490                                 i * w *3; \
491                         type *frame_row = (type*)frame->get_rows()[i]; \
492                         for(int j = 0; j < w; j++) \
493                         { \
494                                 c1 = ( (float)*frame_row )/max; \
495                                 frame_row++; \
496                                 c2 = ( (float)*frame_row )/max; \
497                                 frame_row++; \
498                                 c3 = ( (float)*frame_row )/max; \
499                                 frame_row++; \
501                                 *accum_row += c1; \
502                                 accum_row++; \
503                                 *accum_row += c2; \
504                                 accum_row++; \
505                                 *accum_row += c3; \
506                                 accum_row++; \
507                                 if(components == 4) { *accum_row += ((float)*frame_row++)/max; accum_row++; } \
509                                 *accum_row_sq++ += c1*c1; \
510                                 *accum_row_sq++ += c2*c2; \
511                                 *accum_row_sq++ += c3*c3; \
512                         } \
513                 } \
514         } \
518 void SelTempAvgMain::add_accum(VFrame *frame)
520         int w = frame->get_w();
521         int h = frame->get_h();
523         switch(frame->get_color_model())
524         {
525                 case BC_RGB888:
526                         ADD_ACCUM(unsigned char, 3, 0x0, 0xff)
527                         break;
528                 case BC_RGB_FLOAT:
529                         ADD_ACCUM(float, 3, 0x0, 1.0)
530                         break;
531                 case BC_RGBA8888:
532                         ADD_ACCUM(unsigned char, 4, 0x0, 0xff)
533                         break;
534                 case BC_RGBA_FLOAT:
535                         ADD_ACCUM(float, 4, 0x0, 1.0)
536                         break;
537                 case BC_YUV888:
538                         ADD_ACCUM(unsigned char, 3, 0x80, 0xff)
539                         break;
540                 case BC_YUVA8888:
541                         ADD_ACCUM(unsigned char, 4, 0x80, 0xff)
542                         break;
543                 case BC_YUV161616:
544                         ADD_ACCUM(uint16_t, 3, 0x8000, 0xffff)
545                         break;
546                 case BC_YUVA16161616:
547                         ADD_ACCUM(uint16_t, 4, 0x8000, 0xffff)
548                         break;
549         }
552 #define MASKER(type, avg_thresh, std_thresh, c_now, c_mean, c_stddev, mask, gain, frame_rowp, max) \
553 { \
554       if ( (avg_thresh > fabs(c_now - c_mean)) &&  (std_thresh > c_stddev) ) \
555              if (mask) \
556                    frame_rowp = max; \
557              else \
558                    frame_rowp = (type)(c_mean*max*gain); \
559       else \
560              if (mask) \
561                    frame_rowp = 0; \
562              else \
563                    frame_rowp = (type)(c_now*max*gain); \
566 #define TRANSFER_ACCUM(type, components, chroma, max, c1_gain, c2_gain, c3_gain) \
567 { \
568         if(config.method == SelTempAvgConfig::METHOD_SELTEMPAVG) \
569         { \
570                 float denominator = config.frames; \
571                 float c1_now, c2_now, c3_now, c4_now; \
572                 float c1_mean, c2_mean, c3_mean, c4_mean; \
573                 float c1_stddev, c2_stddev, c3_stddev; \
574                 for(int i = 0; i < h; i++) \
575                 { \
576                         float *accum_row = (float*)accumulation + i * w * components; \
577                         float *accum_row_sq = (float*)accumulation_sq + i * w * 3; \
579                         type *frame_row = (type*)frame->get_rows()[i]; \
580                         for(int j = 0; j < w; j++) \
581                         { \
582                                 c1_now = (float)(*frame_row)/max; \
583                                 *frame_row++; \
584                                 c2_now = (float)(*frame_row)/max; \
585                                 *frame_row++; \
586                                 c3_now = (float)(*frame_row)/max; \
587                                 frame_row -= 2; \
589                                 c1_mean = *accum_row/denominator; \
590                                 accum_row++; \
591                                 c2_mean = *accum_row/denominator; \
592                                 accum_row++; \
593                                 c3_mean = *accum_row/denominator; \
594                                 accum_row++; \
595                                 if(components == 4) { c4_mean = *accum_row/denominator; accum_row++; } \
597                                 c1_stddev = (*accum_row_sq++)/denominator - c1_mean*c1_mean; \
598                                 c2_stddev = (*accum_row_sq++)/denominator - c2_mean*c2_mean; \
599                                 c3_stddev = (*accum_row_sq++)/denominator - c3_mean*c3_mean; \
601                                 MASKER(type,  \
602                                        config.avg_threshold_RY, \
603                                        config.std_threshold_RY, \
604                                        c1_now, c1_mean, c1_stddev, config.mask_RY, c1_gain,\
605                                        *frame_row++, max)\
606                                 MASKER(type,  \
607                                        config.avg_threshold_GU, \
608                                        config.std_threshold_GU, \
609                                        c2_now, c2_mean, c2_stddev, config.mask_GU, c2_gain,\
610                                        *frame_row++, max)\
611                                 MASKER(type,  \
612                                        config.avg_threshold_BV, \
613                                        config.std_threshold_BV, \
614                                        c3_now, c3_mean, c3_stddev, config.mask_BV, c3_gain,\
615                                        *frame_row++, max)\
616                                 if(components == 4)  *frame_row++ = max; \
617                         } \
618                 } \
619         } \
620         else \
621         if(config.method == SelTempAvgConfig::METHOD_AVERAGE) \
622         { \
623                 float denominator = config.frames; \
624                 for(int i = 0; i < h; i++) \
625                 { \
626                         float *accum_row = (float*)accumulation + i * w * components; \
627                         type *frame_row = (type*)frame->get_rows()[i]; \
628                         for(int j = 0; j < w; j++) \
629                         { \
631                                 *frame_row++ = (type)( (*accum_row++ / denominator)*c1_gain*max ); \
632                                 *frame_row++ = (type)( (*accum_row++ / denominator)*c2_gain*max ); \
633                                 *frame_row++ = (type)( (*accum_row++ / denominator)*c3_gain*max ); \
634                                 if(components == 4) *frame_row++ = (type)((*accum_row++/denominator)*max ); \
635                         } \
636                 } \
637         } \
638         else \
639         if(config.method == SelTempAvgConfig::METHOD_STDDEV) \
640         { \
641                 float c1_mean, c2_mean, c3_mean, c4_mean; \
642                 float c1_stddev, c2_stddev, c3_stddev; \
643                 float denominator = config.frames; \
644                 for(int i = 0; i < h; i++) \
645                 { \
646                         float *accum_row = (float*)accumulation + i * w * components; \
647                         float *accum_row_sq = (float*)accumulation_sq + i * w * 3; \
648                         type *frame_row = (type*)frame->get_rows()[i]; \
649                         for(int j = 0; j < w; j++) \
650                         { \
652                                 c1_mean = *accum_row/denominator; \
653                                 accum_row++; \
654                                 c2_mean = *accum_row/denominator; \
655                                 accum_row++; \
656                                 c3_mean = *accum_row/denominator; \
657                                 accum_row++; \
658                                 if(components == 4) { c4_mean = *accum_row/denominator; accum_row++; } \
660                                 c1_stddev = (*accum_row_sq++)/denominator - c1_mean*c1_mean; \
661                                 c2_stddev = (*accum_row_sq++)/denominator - c2_mean*c2_mean; \
662                                 c3_stddev = (*accum_row_sq++)/denominator - c3_mean*c3_mean; \
664                                 *frame_row++ = (type)( c1_stddev*c1_gain*max ); \
665                                 *frame_row++ = (type)( c2_stddev*c2_gain*max ); \
666                                 *frame_row++ = (type)( c3_stddev*c3_gain*max ); \
667                                 if(components == 4) *frame_row++ = max; \
668                         } \
669                 } \
670         } \
674 void SelTempAvgMain::transfer_accum(VFrame *frame)
676         int w = frame->get_w();
677         int h = frame->get_h();
679         switch(frame->get_color_model())
680         {
681                 case BC_RGB888:
682                         TRANSFER_ACCUM(unsigned char, 3  , 0x0   , 0xff  , config.gain, config.gain, config.gain)
683                         break;
684                 case BC_RGB_FLOAT:
685                         TRANSFER_ACCUM(float        , 3  , 0x0   , 1     , config.gain, config.gain, config.gain)
686                         break;
687                 case BC_RGBA8888:
688                         TRANSFER_ACCUM(unsigned char, 4  , 0x0   , 0xff  , config.gain, config.gain, config.gain)
689                         break;
690                 case BC_RGBA_FLOAT:
691                         TRANSFER_ACCUM(float        , 4  , 0x0   , 1     , config.gain, config.gain, config.gain)
692                         break;
693                 case BC_YUV888:
694                         TRANSFER_ACCUM(unsigned char, 3  , 0x80  , 0xff  , config.gain, 1.0        , 1.0)
695                         break;
696                 case BC_YUVA8888:
697                         TRANSFER_ACCUM(unsigned char, 4  , 0x80  , 0xff  , config.gain, 1.0        , 1.0)
698                         break;
699                 case BC_YUV161616:
700                         TRANSFER_ACCUM(uint16_t     , 3  , 0x8000, 0xffff, config.gain, 1.0        , 1.0)
701                         break;
702                 case BC_YUVA16161616:
703                         TRANSFER_ACCUM(uint16_t     , 4  , 0x8000, 0xffff, config.gain, 1.0        , 1.0)
704                         break;
705         }
709 int SelTempAvgMain::load_defaults()
711         char directory[BCTEXTLEN], string[BCTEXTLEN];
712 // set the default directory
713         sprintf(directory, "%sdenoiseseltempavg.rc", BCASTDIR);
715 // load the defaults
716         defaults = new BC_Hash(directory);
717         defaults->load();
719         config.frames = defaults->get("FRAMES", config.frames);
720         config.method = defaults->get("METHOD", config.method);
721         config.offsetmode = defaults->get("OFFSETMODE", config.offsetmode);
722         config.paranoid = defaults->get("PARANOID", config.paranoid);
723         config.nosubtract = defaults->get("NOSUBTRACT", config.nosubtract);
724         config.offset_restartmarker_keyframe = defaults->get("OFFSETMODE_RESTARTMODE_KEYFRAME", config.offset_restartmarker_keyframe);
725         config.offset_fixed_value = defaults->get("OFFSETMODE_FIXED_VALUE", config.offset_fixed_value);
726         config.gain = defaults->get("GAIN", config.gain);
728         config.avg_threshold_RY = defaults->get("AVG_THRESHOLD_RY", config.avg_threshold_GU); 
729         config.avg_threshold_GU = defaults->get("AVG_THRESHOLD_GU", config.avg_threshold_GU); 
730         config.avg_threshold_BV = defaults->get("AVG_THRESHOLD_BV", config.avg_threshold_BV); 
731         config.std_threshold_RY = defaults->get("STD_THRESHOLD_RY", config.std_threshold_RY); 
732         config.std_threshold_GU = defaults->get("STD_THRESHOLD_GU", config.std_threshold_GU); 
733         config.std_threshold_BV = defaults->get("STD_THRESHOLD_BV", config.std_threshold_BV);
734         config.mask_RY = defaults->get("MASK_RY", config.mask_GU); 
735         config.mask_GU = defaults->get("MASK_GU", config.mask_GU); 
736         config.mask_BV = defaults->get("MASK_BV", config.mask_BV); 
737         return 0;
740 int SelTempAvgMain::save_defaults()
742         defaults->update("FRAMES", config.frames);
743         defaults->update("METHOD", config.method);
744         defaults->update("OFFSETMODE", config.offsetmode);
745         defaults->update("PARANOID", config.paranoid);
746         defaults->update("NOSUBTRACT", config.nosubtract);
747         defaults->update("OFFSETMODE_RESTARTMODE_KEYFRAME", config.offset_restartmarker_keyframe);
748         defaults->update("OFFSETMODE_FIXED_VALUE", config.offset_fixed_value);
749         defaults->update("GAIN", config.gain);
751         defaults->update("AVG_THRESHOLD_RY", config.avg_threshold_RY); 
752         defaults->update("AVG_THRESHOLD_GU", config.avg_threshold_GU);
753         defaults->update("AVG_THRESHOLD_BV", config.avg_threshold_BV); 
754         defaults->update("STD_THRESHOLD_RY", config.std_threshold_RY);
755         defaults->update("STD_THRESHOLD_GU", config.std_threshold_GU); 
756         defaults->update("STD_THRESHOLD_BV", config.std_threshold_BV);
758         defaults->update("MASK_RY", config.mask_RY);
759         defaults->update("MASK_GU", config.mask_GU); 
760         defaults->update("MASK_BV", config.mask_BV);
762         defaults->save();
763         return 0;
766 int SelTempAvgMain::load_configuration()
768         KeyFrame *prev_keyframe;
769         KeyFrame *temp_keyframe;
771         SelTempAvgConfig old_config;
772         old_config.copy_from(&config);
774         int64_t curpos = get_source_position();
775         prev_keyframe = get_prev_keyframe(curpos);
776         read_data(prev_keyframe);
778         if (curpos == prev_keyframe->position) 
779                 onakeyframe = 1; 
780         else 
781                 onakeyframe = 0;
783         int64_t next_restart_keyframe     = curpos + config.frames;
784         int64_t prev_restart_keyframe     = curpos - config.frames;
786         for (int i = curpos; i < curpos + config.frames; i++) 
787         {
788                 temp_keyframe = get_next_keyframe(i);
789                 if ( 
790                         (temp_keyframe->position < curpos + config.frames/2) && 
791                         (temp_keyframe->position > curpos) &&
792                         nextkeyframeisoffsetrestart(temp_keyframe) 
793                         ) 
794                 {
795                         next_restart_keyframe = temp_keyframe->position; 
796                         i = curpos + config.frames;
797                 } else if (temp_keyframe->position > i)
798                         i = temp_keyframe->position;
799         }
800         
801         for (int i = curpos; i > curpos - config.frames; i--) 
802         {
803                 temp_keyframe = get_prev_keyframe(i);
804                 if ( 
805                         (temp_keyframe->position > curpos - config.frames/2) && 
806                         (temp_keyframe->position < curpos) && 
807                         nextkeyframeisoffsetrestart(temp_keyframe) 
808                         ) 
809                 {
810                         prev_restart_keyframe = temp_keyframe->position; 
811                         i = curpos - config.frames;
812                 } else if (temp_keyframe->position < i)
813                         i = temp_keyframe->position;
814         }
816         restartoffset = -config.frames/2;
817         
818         if (onakeyframe && config.offset_restartmarker_keyframe)
819                 restartoffset = 0;
820         else if ((curpos - prev_restart_keyframe) < config.frames/2) 
821                 restartoffset = prev_restart_keyframe - curpos;
822         else if ((next_restart_keyframe - curpos) < config.frames/2) {
823                 restartoffset = (next_restart_keyframe - curpos) - config.frames;
824                 // Probably should put another if in here, (when two "restart" keyframes are close together
825         }
827         return !old_config.equivalent(&config);
830 void SelTempAvgMain::save_data(KeyFrame *keyframe)
832         FileXML output;
834 // cause data to be stored directly in text
835         output.set_shared_string(keyframe->data, MESSAGESIZE);
836         output.tag.set_title("SELECTIVE_TEMPORAL_AVERAGE");
837         output.tag.set_property("FRAMES", config.frames);
838         output.tag.set_property("METHOD", config.method);
839         output.tag.set_property("OFFSETMODE", config.offsetmode);
840         output.tag.set_property("PARANOID", config.paranoid);
841         output.tag.set_property("NOSUBTRACT", config.nosubtract);
842         output.tag.set_property("OFFSETMODE_RESTARTMODE_KEYFRAME", config.offset_restartmarker_keyframe);
843         output.tag.set_property("OFFSETMODE_FIXED_VALUE", config.offset_fixed_value);
844         output.tag.set_property("GAIN", config.gain);
847         output.tag.set_property("AVG_THRESHOLD_RY", config.avg_threshold_RY); 
848         output.tag.set_property("AVG_THRESHOLD_GU", config.avg_threshold_GU); 
849         output.tag.set_property("AVG_THRESHOLD_BV", config.avg_threshold_BV); 
850         output.tag.set_property("STD_THRESHOLD_RY", config.std_threshold_RY); 
851         output.tag.set_property("STD_THRESHOLD_GU", config.std_threshold_GU); 
852         output.tag.set_property("STD_THRESHOLD_BV", config.std_threshold_BV);
854         output.tag.set_property("MASK_RY", config.mask_RY); 
855         output.tag.set_property("MASK_GU", config.mask_GU); 
856         output.tag.set_property("MASK_BV", config.mask_BV);
858         output.append_tag();
859         output.terminate_string();
862 void SelTempAvgMain::read_data(KeyFrame *keyframe)
864         FileXML input;
866         input.set_shared_string(keyframe->data, strlen(keyframe->data));
868         int result = 0;
870         while(!input.read_tag())
871         {
872                 if(input.tag.title_is("SELECTIVE_TEMPORAL_AVERAGE"))
873                 {
874                         config.frames = input.tag.get_property("FRAMES", config.frames);
875                         config.method = input.tag.get_property("METHOD", config.method);
876                         config.offsetmode = input.tag.get_property("OFFSETMODE", config.offsetmode);
877                         config.paranoid = input.tag.get_property("PARANOID", config.paranoid);
878                         config.nosubtract = input.tag.get_property("NOSUBTRACT", config.nosubtract);
879                         config.offset_restartmarker_keyframe = input.tag.get_property("OFFSETMODE_RESTARTMODE_KEYFRAME", config.offset_restartmarker_keyframe);
880                         config.offset_fixed_value = input.tag.get_property("OFFSETMODE_FIXED_VALUE", config.offset_fixed_value);
881                         config.gain = input.tag.get_property("gain", config.gain);
883                         config.avg_threshold_RY = input.tag.get_property("AVG_THRESHOLD_RY", config.avg_threshold_RY); 
884                         config.avg_threshold_GU = input.tag.get_property("AVG_THRESHOLD_GU", config.avg_threshold_GU); 
885                         config.avg_threshold_BV = input.tag.get_property("AVG_THRESHOLD_BV", config.avg_threshold_BV); 
886                         config.std_threshold_RY = input.tag.get_property("STD_THRESHOLD_RY", config.std_threshold_RY); 
887                         config.std_threshold_GU = input.tag.get_property("STD_THRESHOLD_GU", config.std_threshold_GU); 
888                         config.std_threshold_BV = input.tag.get_property("STD_THRESHOLD_BV", config.std_threshold_BV);
890                         config.mask_RY = input.tag.get_property("MASK_RY", config.mask_RY); 
891                         config.mask_GU = input.tag.get_property("MASK_GU", config.mask_GU); 
892                         config.mask_BV = input.tag.get_property("MASK_BV", config.mask_BV);
894                 }
895         }
900 int SelTempAvgMain::nextkeyframeisoffsetrestart(KeyFrame *keyframe)
902         FileXML input;
904         input.set_shared_string(keyframe->data, strlen(keyframe->data));
906         int result = 0;
908         while(!input.read_tag())
909         {
910                 if(input.tag.title_is("SELECTIVE_TEMPORAL_AVERAGE"))
911                 {
912                         return(input.tag.get_property("OFFSETMODE_RESTARTMODE_KEYFRAME", config.offset_restartmarker_keyframe));
913                 }
914         }
915         return (0);
920 void SelTempAvgMain::update_gui()
922         if(thread) 
923         {
924                 if(load_configuration())
925                 {
926                         thread->window->lock_window("SelTempAvgMain::update_gui");
927                         thread->window->total_frames->update(config.frames);
929                         thread->window->method_none->update(         config.method == SelTempAvgConfig::METHOD_NONE);
930                         thread->window->method_seltempavg->update(   config.method == SelTempAvgConfig::METHOD_SELTEMPAVG);
931                         thread->window->method_average->update(      config.method == SelTempAvgConfig::METHOD_AVERAGE);
932                         thread->window->method_stddev->update(       config.method == SelTempAvgConfig::METHOD_STDDEV);
934                         thread->window->offset_fixed->update(        config.offsetmode == SelTempAvgConfig::OFFSETMODE_FIXED);
935                         thread->window->offset_restartmarker->update(config.offsetmode == SelTempAvgConfig::OFFSETMODE_RESTARTMARKERSYS);
938                         thread->window->paranoid->update(config.paranoid);
939                         thread->window->no_subtract->update(config.nosubtract);
941                         thread->window->offset_fixed_value->update((int64_t)config.offset_fixed_value);
942                         thread->window->gain->update(config.gain);
944                         thread->window->avg_threshold_RY->update((float)config.avg_threshold_RY);
945                         thread->window->avg_threshold_GU->update((float)config.avg_threshold_GU);
946                         thread->window->avg_threshold_BV->update((float)config.avg_threshold_BV);
947                         thread->window->std_threshold_RY->update((float)config.std_threshold_RY);
948                         thread->window->std_threshold_GU->update((float)config.std_threshold_GU);
949                         thread->window->std_threshold_BV->update((float)config.std_threshold_BV);
951                         thread->window->mask_RY->update(config.mask_RY);
952                         thread->window->mask_GU->update(config.mask_GU);
953                         thread->window->mask_BV->update(config.mask_BV);
954                         thread->window->unlock_window();
955                 }
956                 thread->window->offset_restartmarker_pos->update((int64_t)restartoffset);
957                 thread->window->offset_restartmarker_keyframe->update((config.offset_restartmarker_keyframe) && (onakeyframe));
958         }