4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
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.
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.
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
27 #include "seltempavg.h"
28 #include "seltempavgwindow.h"
34 REGISTER_PLUGIN(SelTempAvgMain)
37 //////////////////////////////////////////////////////////////////////
38 SelTempAvgConfig::SelTempAvgConfig()
41 method = SelTempAvgConfig::METHOD_SELTEMPAVG;
42 offsetmode = SelTempAvgConfig::OFFSETMODE_RESTARTMARKERSYS;
45 offset_restartmarker_keyframe = 0;
46 offset_fixed_value = -15;
49 avg_threshold_RY = 0; avg_threshold_GU = 0; avg_threshold_BV = 0;
50 std_threshold_RY = 0; std_threshold_GU = 0; std_threshold_BV = 0;
51 mask_RY = 0; mask_GU = 0; mask_BV = 0;
54 void SelTempAvgConfig::copy_from(SelTempAvgConfig *src)
56 this->frames = src->frames;
57 this->method = src->method;
58 this->offsetmode = src->offsetmode;
59 this->paranoid = src->paranoid;
60 this->nosubtract = src->nosubtract;
61 this->offset_restartmarker_keyframe = src->offset_restartmarker_keyframe;
62 this->offset_fixed_value = src->offset_fixed_value;
63 this->gain = src->gain;
64 this->avg_threshold_RY = src->avg_threshold_RY; this->avg_threshold_GU = src->avg_threshold_GU;
65 this->avg_threshold_BV = src->avg_threshold_BV; this->std_threshold_RY = src->std_threshold_RY;
66 this->std_threshold_GU = src->std_threshold_GU; this->std_threshold_BV = src->std_threshold_BV;
68 this->mask_BV = src->mask_BV; this->mask_RY = src->mask_RY; this->mask_GU = src->mask_GU;
71 int SelTempAvgConfig::equivalent(SelTempAvgConfig *src)
73 return frames == src->frames &&
74 method == src->method &&
75 offsetmode == src->offsetmode &&
76 paranoid == src->paranoid &&
77 offset_restartmarker_keyframe == src->offset_restartmarker_keyframe &&
78 offset_fixed_value == src->offset_fixed_value &&
80 this->avg_threshold_RY == src->avg_threshold_RY && this->avg_threshold_GU == src->avg_threshold_GU &&
81 this->avg_threshold_BV == src->avg_threshold_BV && this->std_threshold_RY == src->std_threshold_RY &&
82 this->std_threshold_GU == src->std_threshold_GU && this->std_threshold_BV == src->std_threshold_BV &&
83 this->mask_RY == src->mask_RY && this->mask_GU == src->mask_GU && this->mask_BV == src->mask_BV;
87 //////////////////////////////////////////////////////////////////////
88 SelTempAvgMain::SelTempAvgMain(PluginServer *server)
89 : PluginVClient(server)
95 history_start = -0x7fffffff;
101 SelTempAvgMain::~SelTempAvgMain()
107 delete [] accumulation;
108 delete [] accumulation_sq;
112 for(int i = 0; i < config.frames; i++)
116 if(history_frame) delete [] history_frame;
117 if(history_valid) delete [] history_valid;
120 const char* SelTempAvgMain::plugin_title() { return N_("Selective Temporal Averaging"); }
121 int SelTempAvgMain::is_realtime() { return 1; }
124 NEW_WINDOW_MACRO(SelTempAvgMain, SelTempAvgWindow);
126 int SelTempAvgMain::process_buffer(VFrame *frame,
127 int64_t start_position,
130 int h = frame->get_h();
131 int w = frame->get_w();
132 int color_model = frame->get_color_model();
133 load_configuration();
135 // Allocate accumulation
138 accumulation = new unsigned char[w *
140 BC_CModels::components(color_model) *
143 accumulation_sq = new unsigned char[w *
147 clear_accum(w, h, color_model);
150 if(!config.nosubtract)
152 // Reallocate history
155 if(config.frames != history_size)
158 int64_t *history_frame2;
160 history2 = new VFrame*[config.frames];
161 history_frame2 = new int64_t[config.frames];
162 history_valid2 = new int[config.frames];
164 // Copy existing frames over
166 for(i = 0, j = 0; i < config.frames && j < history_size; i++, j++)
168 history2[i] = history[j];
169 history_frame2[i] = history_frame[i];
170 history_valid2[i] = history_valid[i];
173 // Delete extra previous frames and subtract from accumulation
174 for( ; j < history_size; j++)
176 subtract_accum(history[j]);
180 delete [] history_frame;
181 delete [] history_valid;
185 for( ; i < config.frames; i++)
187 history2[i] = new VFrame(w, h, color_model, 0);
188 history_frame2[i] = -0x7fffffff;
189 history_valid2[i] = 0;
193 history_frame = history_frame2;
194 history_valid = history_valid2;
196 history_size = config.frames;
202 history = new VFrame*[config.frames];
203 for(int i = 0; i < config.frames; i++)
204 history[i] = new VFrame(w, h, color_model, 0);
205 history_size = config.frames;
206 history_frame = new int64_t[config.frames];
207 bzero(history_frame, sizeof(int64_t) * config.frames);
208 history_valid = new int[config.frames];
209 bzero(history_valid, sizeof(int) * config.frames);
217 // Create new history frames based on current frame
218 int64_t *new_history_frames = new int64_t[history_size];
220 int64_t theoffset = (int64_t) config.offset_fixed_value;
221 if (config.offsetmode == SelTempAvgConfig::OFFSETMODE_RESTARTMARKERSYS)
222 theoffset = (int64_t) restartoffset;
224 for(int i = 0; i < history_size; i++)
226 new_history_frames[history_size - i - 1] = start_position + theoffset + i;
229 // Subtract old history frames which are not in the new vector
231 for(int i = 0; i < history_size; i++)
233 // Old frame is valid
237 for(int j = 0; j < history_size; j++)
239 // Old frame is equal to a new frame
240 if(history_frame[i] == new_history_frames[j])
247 // Didn't find old frame in new frames
250 subtract_accum(history[i]);
251 history_valid[i] = 0;
256 // If all frames are still valid, assume tweek occurred upstream and reload.
257 if(config.paranoid && no_change)
259 for(int i = 0; i < history_size; i++)
261 history_valid[i] = 0;
263 clear_accum(w, h, color_model);
266 // Add new history frames which are not in the old vector
267 for(int i = 0; i < history_size; i++)
269 // Find new frame in old vector
271 for(int j = 0; j < history_size; j++)
273 if(history_valid[j] && history_frame[j] == new_history_frames[i])
280 // Didn't find new frame in old vector
283 // Get first unused entry
284 for(int j = 0; j < history_size; j++)
286 if(!history_valid[j])
288 // Load new frame into it
289 history_frame[j] = new_history_frames[i];
290 history_valid[j] = 1;
291 read_frame(history[j],
296 add_accum(history[j]);
302 delete [] new_history_frames;
307 // Force reload if not repositioned or just started
308 if( (config.paranoid && prev_frame == start_position) ||
311 prev_frame = start_position - config.frames + 1;
312 prev_frame = MAX(0, prev_frame);
313 clear_accum(w, h, color_model);
316 for(int64_t i = prev_frame; i <= start_position; i++)
324 //printf("SelTempAvgMain::process_buffer 1 %lld %lld %lld\n", prev_frame, start_position, i);
327 prev_frame = start_position;
332 // Read current frame into buffer (needed for the std-deviation tool)
340 // Transfer accumulation to output with division if average is desired.
341 transfer_accum(frame);
343 //printf("SelTempAvgMain::process_buffer 2\n");
358 // Reset accumulation
359 #define CLEAR_ACCUM(type, components, chroma) \
361 float *row = (float*)accumulation; \
362 float *row_sq = (float*)accumulation_sq; \
365 for(int i = 0; i < w * h; i++) \
370 if(components == 4) *row++ = 0x0; \
378 bzero(row, w * h * sizeof(type) * components); \
379 bzero(row_sq, w * h * 3 * sizeof(float)); \
384 void SelTempAvgMain::clear_accum(int w, int h, int color_model)
389 CLEAR_ACCUM(int, 3, 0x0)
392 CLEAR_ACCUM(float, 3, 0x0)
395 CLEAR_ACCUM(int, 4, 0x0)
398 CLEAR_ACCUM(float, 4, 0x0)
401 CLEAR_ACCUM(int, 3, 0x80)
404 CLEAR_ACCUM(int, 4, 0x80)
407 CLEAR_ACCUM(int, 3, 0x8000)
409 case BC_YUVA16161616:
410 CLEAR_ACCUM(int, 4, 0x8000)
414 #define C2_IS(frame_row,chroma,max) (float)(frame_row)/max
417 #define SUBTRACT_ACCUM(type, \
424 for(int i = 0; i < h; i++) \
426 float *accum_row = (float*)accumulation + \
427 i * w * components; \
428 float *accum_row_sq = (float*)accumulation_sq + \
430 type *frame_row = (type*)frame->get_rows()[i]; \
432 for(int j = 0; j < w; j++) \
434 c1 = ( (float)*frame_row )/max; \
436 c2 = ( (float)*frame_row )/max; \
438 c3 = ( (float)(*frame_row -0) )/max; \
447 if(components == 4) { *accum_row -= ((float)*frame_row++)/max; accum_row++; } \
449 *accum_row_sq++ -= c1*c1; \
450 *accum_row_sq++ -= c2*c2; \
451 *accum_row_sq++ -= c3*c3; \
458 void SelTempAvgMain::subtract_accum(VFrame *frame)
461 if(config.nosubtract) return;
462 int w = frame->get_w();
463 int h = frame->get_h();
465 switch(frame->get_color_model())
468 SUBTRACT_ACCUM(unsigned char, 3, 0x0, 0xff)
471 SUBTRACT_ACCUM(float, 3, 0x0, 1.0)
474 SUBTRACT_ACCUM(unsigned char, 4, 0x0, 0xff)
477 SUBTRACT_ACCUM(float, 4, 0x0, 1.0)
480 SUBTRACT_ACCUM(unsigned char, 3, 0x80, 0xff)
483 SUBTRACT_ACCUM(unsigned char, 4, 0x80, 0xff)
486 SUBTRACT_ACCUM(uint16_t, 3, 0x8000, 0xffff)
488 case BC_YUVA16161616:
489 SUBTRACT_ACCUM(uint16_t, 4, 0x8000, 0xffff)
495 // The behavior has to be very specific to the color model because we rely on
496 // the value of full black to determine what pixel to show.
497 #define ADD_ACCUM(type, components, chroma, max) \
502 for(int i = 0; i < h; i++) \
504 float *accum_row = (float*)accumulation + \
505 i * w * components; \
506 float *accum_row_sq = (float*)accumulation_sq + \
508 type *frame_row = (type*)frame->get_rows()[i]; \
509 for(int j = 0; j < w; j++) \
511 c1 = ( (float)*frame_row )/max; \
513 c2 = ( (float)*frame_row )/max; \
515 c3 = ( (float)*frame_row )/max; \
524 if(components == 4) { *accum_row += ((float)*frame_row++)/max; accum_row++; } \
526 *accum_row_sq++ += c1*c1; \
527 *accum_row_sq++ += c2*c2; \
528 *accum_row_sq++ += c3*c3; \
535 void SelTempAvgMain::add_accum(VFrame *frame)
537 int w = frame->get_w();
538 int h = frame->get_h();
540 switch(frame->get_color_model())
543 ADD_ACCUM(unsigned char, 3, 0x0, 0xff)
546 ADD_ACCUM(float, 3, 0x0, 1.0)
549 ADD_ACCUM(unsigned char, 4, 0x0, 0xff)
552 ADD_ACCUM(float, 4, 0x0, 1.0)
555 ADD_ACCUM(unsigned char, 3, 0x80, 0xff)
558 ADD_ACCUM(unsigned char, 4, 0x80, 0xff)
561 ADD_ACCUM(uint16_t, 3, 0x8000, 0xffff)
563 case BC_YUVA16161616:
564 ADD_ACCUM(uint16_t, 4, 0x8000, 0xffff)
569 #define MASKER(type, avg_thresh, std_thresh, c_now, c_mean, c_stddev, mask, gain, frame_rowp, max) \
571 if ( (avg_thresh > fabs(c_now - c_mean)) && (std_thresh > c_stddev) ) \
575 frame_rowp = (type)(c_mean*max*gain); \
580 frame_rowp = (type)(c_now*max*gain); \
583 #define TRANSFER_ACCUM(type, components, chroma, max, c1_gain, c2_gain, c3_gain) \
585 if(config.method == SelTempAvgConfig::METHOD_SELTEMPAVG) \
587 float denominator = config.frames; \
588 float c1_now, c2_now, c3_now; \
589 float c1_mean, c2_mean, c3_mean; \
590 float c1_stddev, c2_stddev, c3_stddev; \
591 for(int i = 0; i < h; i++) \
593 float *accum_row = (float*)accumulation + i * w * components; \
594 float *accum_row_sq = (float*)accumulation_sq + i * w * 3; \
596 type *frame_row = (type*)frame->get_rows()[i]; \
597 for(int j = 0; j < w; j++) \
599 c1_now = (float)(*frame_row)/max; \
601 c2_now = (float)(*frame_row)/max; \
603 c3_now = (float)(*frame_row)/max; \
606 c1_mean = *accum_row/denominator; \
608 c2_mean = *accum_row/denominator; \
610 c3_mean = *accum_row/denominator; \
612 if(components == 4) { accum_row++; } \
614 c1_stddev = (*accum_row_sq++)/denominator - c1_mean*c1_mean; \
615 c2_stddev = (*accum_row_sq++)/denominator - c2_mean*c2_mean; \
616 c3_stddev = (*accum_row_sq++)/denominator - c3_mean*c3_mean; \
619 config.avg_threshold_RY, \
620 config.std_threshold_RY, \
621 c1_now, c1_mean, c1_stddev, config.mask_RY, c1_gain,\
624 config.avg_threshold_GU, \
625 config.std_threshold_GU, \
626 c2_now, c2_mean, c2_stddev, config.mask_GU, c2_gain,\
629 config.avg_threshold_BV, \
630 config.std_threshold_BV, \
631 c3_now, c3_mean, c3_stddev, config.mask_BV, c3_gain,\
633 if(components == 4) *frame_row++ = max; \
638 if(config.method == SelTempAvgConfig::METHOD_AVERAGE) \
640 float denominator = config.frames; \
641 for(int i = 0; i < h; i++) \
643 float *accum_row = (float*)accumulation + i * w * components; \
644 type *frame_row = (type*)frame->get_rows()[i]; \
645 for(int j = 0; j < w; j++) \
648 *frame_row++ = (type)( (*accum_row++ / denominator)*c1_gain*max ); \
649 *frame_row++ = (type)( (*accum_row++ / denominator)*c2_gain*max ); \
650 *frame_row++ = (type)( (*accum_row++ / denominator)*c3_gain*max ); \
651 if(components == 4) *frame_row++ = (type)((*accum_row++/denominator)*max ); \
656 if(config.method == SelTempAvgConfig::METHOD_STDDEV) \
658 float c1_mean, c2_mean, c3_mean; \
659 float c1_stddev, c2_stddev, c3_stddev; \
660 float denominator = config.frames; \
661 for(int i = 0; i < h; i++) \
663 float *accum_row = (float*)accumulation + i * w * components; \
664 float *accum_row_sq = (float*)accumulation_sq + i * w * 3; \
665 type *frame_row = (type*)frame->get_rows()[i]; \
666 for(int j = 0; j < w; j++) \
669 c1_mean = *accum_row/denominator; \
671 c2_mean = *accum_row/denominator; \
673 c3_mean = *accum_row/denominator; \
675 if(components == 4) { accum_row++; } \
677 c1_stddev = (*accum_row_sq++)/denominator - c1_mean*c1_mean; \
678 c2_stddev = (*accum_row_sq++)/denominator - c2_mean*c2_mean; \
679 c3_stddev = (*accum_row_sq++)/denominator - c3_mean*c3_mean; \
681 *frame_row++ = (type)( c1_stddev*c1_gain*max ); \
682 *frame_row++ = (type)( c2_stddev*c2_gain*max ); \
683 *frame_row++ = (type)( c3_stddev*c3_gain*max ); \
684 if(components == 4) *frame_row++ = max; \
691 void SelTempAvgMain::transfer_accum(VFrame *frame)
693 int w = frame->get_w();
694 int h = frame->get_h();
696 switch(frame->get_color_model())
699 TRANSFER_ACCUM(unsigned char, 3 , 0x0 , 0xff , config.gain, config.gain, config.gain)
702 TRANSFER_ACCUM(float , 3 , 0x0 , 1 , config.gain, config.gain, config.gain)
705 TRANSFER_ACCUM(unsigned char, 4 , 0x0 , 0xff , config.gain, config.gain, config.gain)
708 TRANSFER_ACCUM(float , 4 , 0x0 , 1 , config.gain, config.gain, config.gain)
711 TRANSFER_ACCUM(unsigned char, 3 , 0x80 , 0xff , config.gain, 1.0 , 1.0)
714 TRANSFER_ACCUM(unsigned char, 4 , 0x80 , 0xff , config.gain, 1.0 , 1.0)
717 TRANSFER_ACCUM(uint16_t , 3 , 0x8000, 0xffff, config.gain, 1.0 , 1.0)
719 case BC_YUVA16161616:
720 TRANSFER_ACCUM(uint16_t , 4 , 0x8000, 0xffff, config.gain, 1.0 , 1.0)
727 int SelTempAvgMain::load_configuration()
729 KeyFrame *prev_keyframe;
730 KeyFrame *temp_keyframe;
732 SelTempAvgConfig old_config;
733 old_config.copy_from(&config);
735 int64_t curpos = get_source_position();
736 prev_keyframe = get_prev_keyframe(curpos);
737 read_data(prev_keyframe);
739 if (curpos == prev_keyframe->position)
744 int64_t next_restart_keyframe = curpos + config.frames;
745 int64_t prev_restart_keyframe = curpos - config.frames;
747 for (int i = curpos; i < curpos + config.frames; i++)
749 temp_keyframe = get_next_keyframe(i);
751 (temp_keyframe->position < curpos + config.frames/2) &&
752 (temp_keyframe->position > curpos) &&
753 nextkeyframeisoffsetrestart(temp_keyframe)
756 next_restart_keyframe = temp_keyframe->position;
757 i = curpos + config.frames;
758 } else if (temp_keyframe->position > i)
759 i = temp_keyframe->position;
762 for (int i = curpos; i > curpos - config.frames; i--)
764 temp_keyframe = get_prev_keyframe(i);
766 (temp_keyframe->position > curpos - config.frames/2) &&
767 (temp_keyframe->position < curpos) &&
768 nextkeyframeisoffsetrestart(temp_keyframe)
771 prev_restart_keyframe = temp_keyframe->position;
772 i = curpos - config.frames;
773 } else if (temp_keyframe->position < i)
774 i = temp_keyframe->position;
777 restartoffset = -config.frames/2;
779 if (onakeyframe && config.offset_restartmarker_keyframe)
781 else if ((curpos - prev_restart_keyframe) < config.frames/2)
782 restartoffset = prev_restart_keyframe - curpos;
783 else if ((next_restart_keyframe - curpos) < config.frames/2) {
784 restartoffset = (next_restart_keyframe - curpos) - config.frames;
785 // Probably should put another if in here, (when two "restart" keyframes are close together
788 return !old_config.equivalent(&config);
791 void SelTempAvgMain::save_data(KeyFrame *keyframe)
795 // cause data to be stored directly in text
796 output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
797 output.tag.set_title("SELECTIVE_TEMPORAL_AVERAGE");
798 output.tag.set_property("FRAMES", config.frames);
799 output.tag.set_property("METHOD", config.method);
800 output.tag.set_property("OFFSETMODE", config.offsetmode);
801 output.tag.set_property("PARANOID", config.paranoid);
802 output.tag.set_property("NOSUBTRACT", config.nosubtract);
803 output.tag.set_property("OFFSETMODE_RESTARTMODE_KEYFRAME", config.offset_restartmarker_keyframe);
804 output.tag.set_property("OFFSETMODE_FIXED_VALUE", config.offset_fixed_value);
805 output.tag.set_property("GAIN", config.gain);
808 output.tag.set_property("AVG_THRESHOLD_RY", config.avg_threshold_RY);
809 output.tag.set_property("AVG_THRESHOLD_GU", config.avg_threshold_GU);
810 output.tag.set_property("AVG_THRESHOLD_BV", config.avg_threshold_BV);
811 output.tag.set_property("STD_THRESHOLD_RY", config.std_threshold_RY);
812 output.tag.set_property("STD_THRESHOLD_GU", config.std_threshold_GU);
813 output.tag.set_property("STD_THRESHOLD_BV", config.std_threshold_BV);
815 output.tag.set_property("MASK_RY", config.mask_RY);
816 output.tag.set_property("MASK_GU", config.mask_GU);
817 output.tag.set_property("MASK_BV", config.mask_BV);
820 output.tag.set_title("/SELECTIVE_TEMPORAL_AVERAGE");
822 output.append_newline();
823 output.terminate_string();
826 void SelTempAvgMain::read_data(KeyFrame *keyframe)
830 input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
832 while(!input.read_tag())
834 if(input.tag.title_is("SELECTIVE_TEMPORAL_AVERAGE"))
836 config.frames = input.tag.get_property("FRAMES", config.frames);
837 config.method = input.tag.get_property("METHOD", config.method);
838 config.offsetmode = input.tag.get_property("OFFSETMODE", config.offsetmode);
839 config.paranoid = input.tag.get_property("PARANOID", config.paranoid);
840 config.nosubtract = input.tag.get_property("NOSUBTRACT", config.nosubtract);
841 config.offset_restartmarker_keyframe = input.tag.get_property("OFFSETMODE_RESTARTMODE_KEYFRAME", config.offset_restartmarker_keyframe);
842 config.offset_fixed_value = input.tag.get_property("OFFSETMODE_FIXED_VALUE", config.offset_fixed_value);
843 config.gain = input.tag.get_property("gain", config.gain);
845 config.avg_threshold_RY = input.tag.get_property("AVG_THRESHOLD_RY", config.avg_threshold_RY);
846 config.avg_threshold_GU = input.tag.get_property("AVG_THRESHOLD_GU", config.avg_threshold_GU);
847 config.avg_threshold_BV = input.tag.get_property("AVG_THRESHOLD_BV", config.avg_threshold_BV);
848 config.std_threshold_RY = input.tag.get_property("STD_THRESHOLD_RY", config.std_threshold_RY);
849 config.std_threshold_GU = input.tag.get_property("STD_THRESHOLD_GU", config.std_threshold_GU);
850 config.std_threshold_BV = input.tag.get_property("STD_THRESHOLD_BV", config.std_threshold_BV);
852 config.mask_RY = input.tag.get_property("MASK_RY", config.mask_RY);
853 config.mask_GU = input.tag.get_property("MASK_GU", config.mask_GU);
854 config.mask_BV = input.tag.get_property("MASK_BV", config.mask_BV);
862 int SelTempAvgMain::nextkeyframeisoffsetrestart(KeyFrame *keyframe)
866 input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
868 while(!input.read_tag())
870 if(input.tag.title_is("SELECTIVE_TEMPORAL_AVERAGE"))
872 return(input.tag.get_property("OFFSETMODE_RESTARTMODE_KEYFRAME", config.offset_restartmarker_keyframe));
880 void SelTempAvgMain::update_gui()
884 if(load_configuration())
886 ((SelTempAvgWindow*)thread->window)->lock_window("SelTempAvgMain::update_gui");
887 ((SelTempAvgWindow*)thread->window)->total_frames->update(config.frames);
889 ((SelTempAvgWindow*)thread->window)->method_none->update( config.method == SelTempAvgConfig::METHOD_NONE);
890 ((SelTempAvgWindow*)thread->window)->method_seltempavg->update( config.method == SelTempAvgConfig::METHOD_SELTEMPAVG);
891 ((SelTempAvgWindow*)thread->window)->method_average->update( config.method == SelTempAvgConfig::METHOD_AVERAGE);
892 ((SelTempAvgWindow*)thread->window)->method_stddev->update( config.method == SelTempAvgConfig::METHOD_STDDEV);
894 ((SelTempAvgWindow*)thread->window)->offset_fixed->update( config.offsetmode == SelTempAvgConfig::OFFSETMODE_FIXED);
895 ((SelTempAvgWindow*)thread->window)->offset_restartmarker->update(config.offsetmode == SelTempAvgConfig::OFFSETMODE_RESTARTMARKERSYS);
898 ((SelTempAvgWindow*)thread->window)->paranoid->update(config.paranoid);
899 ((SelTempAvgWindow*)thread->window)->no_subtract->update(config.nosubtract);
901 ((SelTempAvgWindow*)thread->window)->offset_fixed_value->update((int64_t)config.offset_fixed_value);
902 ((SelTempAvgWindow*)thread->window)->gain->update(config.gain);
904 ((SelTempAvgWindow*)thread->window)->avg_threshold_RY->update((float)config.avg_threshold_RY);
905 ((SelTempAvgWindow*)thread->window)->avg_threshold_GU->update((float)config.avg_threshold_GU);
906 ((SelTempAvgWindow*)thread->window)->avg_threshold_BV->update((float)config.avg_threshold_BV);
907 ((SelTempAvgWindow*)thread->window)->std_threshold_RY->update((float)config.std_threshold_RY);
908 ((SelTempAvgWindow*)thread->window)->std_threshold_GU->update((float)config.std_threshold_GU);
909 ((SelTempAvgWindow*)thread->window)->std_threshold_BV->update((float)config.std_threshold_BV);
911 ((SelTempAvgWindow*)thread->window)->mask_RY->update(config.mask_RY);
912 ((SelTempAvgWindow*)thread->window)->mask_GU->update(config.mask_GU);
913 ((SelTempAvgWindow*)thread->window)->mask_BV->update(config.mask_BV);
914 ((SelTempAvgWindow*)thread->window)->unlock_window();
916 ((SelTempAvgWindow*)thread->window)->offset_restartmarker_pos->update((int64_t)restartoffset);
917 ((SelTempAvgWindow*)thread->window)->offset_restartmarker_keyframe->update((config.offset_restartmarker_keyframe) && (onakeyframe));