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 = -1000;
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);
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);
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],
295 add_accum(history[j]);
301 delete [] new_history_frames;
306 // Force reload if not repositioned or just started
307 if( (config.paranoid && prev_frame == start_position) ||
310 prev_frame = start_position - config.frames + 1;
311 prev_frame = MAX(0, prev_frame);
312 clear_accum(w, h, color_model);
315 for(int64_t i = prev_frame; i <= start_position; i++)
322 //printf("SelTempAvgMain::process_buffer 1 %lld %lld %lld\n", prev_frame, start_position, i);
325 prev_frame = start_position;
330 // Read current frame into buffer (needed for the std-deviation tool)
337 // Transfer accumulation to output with division if average is desired.
338 transfer_accum(frame);
340 //printf("SelTempAvgMain::process_buffer 2\n");
355 // Reset accumulation
356 #define CLEAR_ACCUM(type, components, chroma) \
358 float *row = (float*)accumulation; \
359 float *row_sq = (float*)accumulation_sq; \
362 for(int i = 0; i < w * h; i++) \
367 if(components == 4) *row++ = 0x0; \
375 bzero(row, w * h * sizeof(type) * components); \
376 bzero(row_sq, w * h * 3 * sizeof(float)); \
381 void SelTempAvgMain::clear_accum(int w, int h, int color_model)
386 CLEAR_ACCUM(int, 3, 0x0)
389 CLEAR_ACCUM(float, 3, 0x0)
392 CLEAR_ACCUM(int, 4, 0x0)
395 CLEAR_ACCUM(float, 4, 0x0)
398 CLEAR_ACCUM(int, 3, 0x80)
401 CLEAR_ACCUM(int, 4, 0x80)
404 CLEAR_ACCUM(int, 3, 0x8000)
406 case BC_YUVA16161616:
407 CLEAR_ACCUM(int, 4, 0x8000)
411 #define C2_IS(frame_row,chroma,max) (float)(frame_row)/max
414 #define SUBTRACT_ACCUM(type, \
421 for(int i = 0; i < h; i++) \
423 float *accum_row = (float*)accumulation + \
424 i * w * components; \
425 float *accum_row_sq = (float*)accumulation_sq + \
427 type *frame_row = (type*)frame->get_rows()[i]; \
429 for(int j = 0; j < w; j++) \
431 c1 = ( (float)*frame_row )/max; \
433 c2 = ( (float)*frame_row )/max; \
435 c3 = ( (float)(*frame_row -0) )/max; \
444 if(components == 4) { *accum_row -= ((float)*frame_row++)/max; accum_row++; } \
446 *accum_row_sq++ -= c1*c1; \
447 *accum_row_sq++ -= c2*c2; \
448 *accum_row_sq++ -= c3*c3; \
455 void SelTempAvgMain::subtract_accum(VFrame *frame)
458 if(config.nosubtract) return;
459 int w = frame->get_w();
460 int h = frame->get_h();
462 switch(frame->get_color_model())
465 SUBTRACT_ACCUM(unsigned char, 3, 0x0, 0xff)
468 SUBTRACT_ACCUM(float, 3, 0x0, 1.0)
471 SUBTRACT_ACCUM(unsigned char, 4, 0x0, 0xff)
474 SUBTRACT_ACCUM(float, 4, 0x0, 1.0)
477 SUBTRACT_ACCUM(unsigned char, 3, 0x80, 0xff)
480 SUBTRACT_ACCUM(unsigned char, 4, 0x80, 0xff)
483 SUBTRACT_ACCUM(uint16_t, 3, 0x8000, 0xffff)
485 case BC_YUVA16161616:
486 SUBTRACT_ACCUM(uint16_t, 4, 0x8000, 0xffff)
492 // The behavior has to be very specific to the color model because we rely on
493 // the value of full black to determine what pixel to show.
494 #define ADD_ACCUM(type, components, chroma, max) \
499 for(int i = 0; i < h; i++) \
501 float *accum_row = (float*)accumulation + \
502 i * w * components; \
503 float *accum_row_sq = (float*)accumulation_sq + \
505 type *frame_row = (type*)frame->get_rows()[i]; \
506 for(int j = 0; j < w; j++) \
508 c1 = ( (float)*frame_row )/max; \
510 c2 = ( (float)*frame_row )/max; \
512 c3 = ( (float)*frame_row )/max; \
521 if(components == 4) { *accum_row += ((float)*frame_row++)/max; accum_row++; } \
523 *accum_row_sq++ += c1*c1; \
524 *accum_row_sq++ += c2*c2; \
525 *accum_row_sq++ += c3*c3; \
532 void SelTempAvgMain::add_accum(VFrame *frame)
534 int w = frame->get_w();
535 int h = frame->get_h();
537 switch(frame->get_color_model())
540 ADD_ACCUM(unsigned char, 3, 0x0, 0xff)
543 ADD_ACCUM(float, 3, 0x0, 1.0)
546 ADD_ACCUM(unsigned char, 4, 0x0, 0xff)
549 ADD_ACCUM(float, 4, 0x0, 1.0)
552 ADD_ACCUM(unsigned char, 3, 0x80, 0xff)
555 ADD_ACCUM(unsigned char, 4, 0x80, 0xff)
558 ADD_ACCUM(uint16_t, 3, 0x8000, 0xffff)
560 case BC_YUVA16161616:
561 ADD_ACCUM(uint16_t, 4, 0x8000, 0xffff)
566 #define MASKER(type, avg_thresh, std_thresh, c_now, c_mean, c_stddev, mask, gain, frame_rowp, max) \
568 if ( (avg_thresh > fabs(c_now - c_mean)) && (std_thresh > c_stddev) ) \
572 frame_rowp = (type)(c_mean*max*gain); \
577 frame_rowp = (type)(c_now*max*gain); \
580 #define TRANSFER_ACCUM(type, components, chroma, max, c1_gain, c2_gain, c3_gain) \
582 if(config.method == SelTempAvgConfig::METHOD_SELTEMPAVG) \
584 float denominator = config.frames; \
585 float c1_now, c2_now, c3_now; \
586 float c1_mean, c2_mean, c3_mean; \
587 float c1_stddev, c2_stddev, c3_stddev; \
588 for(int i = 0; i < h; i++) \
590 float *accum_row = (float*)accumulation + i * w * components; \
591 float *accum_row_sq = (float*)accumulation_sq + i * w * 3; \
593 type *frame_row = (type*)frame->get_rows()[i]; \
594 for(int j = 0; j < w; j++) \
596 c1_now = (float)(*frame_row)/max; \
598 c2_now = (float)(*frame_row)/max; \
600 c3_now = (float)(*frame_row)/max; \
603 c1_mean = *accum_row/denominator; \
605 c2_mean = *accum_row/denominator; \
607 c3_mean = *accum_row/denominator; \
609 if(components == 4) { accum_row++; } \
611 c1_stddev = (*accum_row_sq++)/denominator - c1_mean*c1_mean; \
612 c2_stddev = (*accum_row_sq++)/denominator - c2_mean*c2_mean; \
613 c3_stddev = (*accum_row_sq++)/denominator - c3_mean*c3_mean; \
616 config.avg_threshold_RY, \
617 config.std_threshold_RY, \
618 c1_now, c1_mean, c1_stddev, config.mask_RY, c1_gain,\
621 config.avg_threshold_GU, \
622 config.std_threshold_GU, \
623 c2_now, c2_mean, c2_stddev, config.mask_GU, c2_gain,\
626 config.avg_threshold_BV, \
627 config.std_threshold_BV, \
628 c3_now, c3_mean, c3_stddev, config.mask_BV, c3_gain,\
630 if(components == 4) *frame_row++ = max; \
635 if(config.method == SelTempAvgConfig::METHOD_AVERAGE) \
637 float denominator = config.frames; \
638 for(int i = 0; i < h; i++) \
640 float *accum_row = (float*)accumulation + i * w * components; \
641 type *frame_row = (type*)frame->get_rows()[i]; \
642 for(int j = 0; j < w; j++) \
645 *frame_row++ = (type)( (*accum_row++ / denominator)*c1_gain*max ); \
646 *frame_row++ = (type)( (*accum_row++ / denominator)*c2_gain*max ); \
647 *frame_row++ = (type)( (*accum_row++ / denominator)*c3_gain*max ); \
648 if(components == 4) *frame_row++ = (type)((*accum_row++/denominator)*max ); \
653 if(config.method == SelTempAvgConfig::METHOD_STDDEV) \
655 float c1_mean, c2_mean, c3_mean; \
656 float c1_stddev, c2_stddev, c3_stddev; \
657 float denominator = config.frames; \
658 for(int i = 0; i < h; i++) \
660 float *accum_row = (float*)accumulation + i * w * components; \
661 float *accum_row_sq = (float*)accumulation_sq + i * w * 3; \
662 type *frame_row = (type*)frame->get_rows()[i]; \
663 for(int j = 0; j < w; j++) \
666 c1_mean = *accum_row/denominator; \
668 c2_mean = *accum_row/denominator; \
670 c3_mean = *accum_row/denominator; \
672 if(components == 4) { accum_row++; } \
674 c1_stddev = (*accum_row_sq++)/denominator - c1_mean*c1_mean; \
675 c2_stddev = (*accum_row_sq++)/denominator - c2_mean*c2_mean; \
676 c3_stddev = (*accum_row_sq++)/denominator - c3_mean*c3_mean; \
678 *frame_row++ = (type)( c1_stddev*c1_gain*max ); \
679 *frame_row++ = (type)( c2_stddev*c2_gain*max ); \
680 *frame_row++ = (type)( c3_stddev*c3_gain*max ); \
681 if(components == 4) *frame_row++ = max; \
688 void SelTempAvgMain::transfer_accum(VFrame *frame)
690 int w = frame->get_w();
691 int h = frame->get_h();
693 switch(frame->get_color_model())
696 TRANSFER_ACCUM(unsigned char, 3 , 0x0 , 0xff , config.gain, config.gain, config.gain)
699 TRANSFER_ACCUM(float , 3 , 0x0 , 1 , config.gain, config.gain, config.gain)
702 TRANSFER_ACCUM(unsigned char, 4 , 0x0 , 0xff , config.gain, config.gain, config.gain)
705 TRANSFER_ACCUM(float , 4 , 0x0 , 1 , config.gain, config.gain, config.gain)
708 TRANSFER_ACCUM(unsigned char, 3 , 0x80 , 0xff , config.gain, 1.0 , 1.0)
711 TRANSFER_ACCUM(unsigned char, 4 , 0x80 , 0xff , config.gain, 1.0 , 1.0)
714 TRANSFER_ACCUM(uint16_t , 3 , 0x8000, 0xffff, config.gain, 1.0 , 1.0)
716 case BC_YUVA16161616:
717 TRANSFER_ACCUM(uint16_t , 4 , 0x8000, 0xffff, config.gain, 1.0 , 1.0)
724 int SelTempAvgMain::load_configuration()
726 KeyFrame *prev_keyframe;
727 KeyFrame *temp_keyframe;
729 SelTempAvgConfig old_config;
730 old_config.copy_from(&config);
732 int64_t curpos = get_source_position();
733 prev_keyframe = get_prev_keyframe(curpos);
734 read_data(prev_keyframe);
736 if (curpos == prev_keyframe->position)
741 int64_t next_restart_keyframe = curpos + config.frames;
742 int64_t prev_restart_keyframe = curpos - config.frames;
744 for (int i = curpos; i < curpos + config.frames; i++)
746 temp_keyframe = get_next_keyframe(i);
748 (temp_keyframe->position < curpos + config.frames/2) &&
749 (temp_keyframe->position > curpos) &&
750 nextkeyframeisoffsetrestart(temp_keyframe)
753 next_restart_keyframe = temp_keyframe->position;
754 i = curpos + config.frames;
755 } else if (temp_keyframe->position > i)
756 i = temp_keyframe->position;
759 for (int i = curpos; i > curpos - config.frames; i--)
761 temp_keyframe = get_prev_keyframe(i);
763 (temp_keyframe->position > curpos - config.frames/2) &&
764 (temp_keyframe->position < curpos) &&
765 nextkeyframeisoffsetrestart(temp_keyframe)
768 prev_restart_keyframe = temp_keyframe->position;
769 i = curpos - config.frames;
770 } else if (temp_keyframe->position < i)
771 i = temp_keyframe->position;
774 restartoffset = -config.frames/2;
776 if (onakeyframe && config.offset_restartmarker_keyframe)
778 else if ((curpos - prev_restart_keyframe) < config.frames/2)
779 restartoffset = prev_restart_keyframe - curpos;
780 else if ((next_restart_keyframe - curpos) < config.frames/2) {
781 restartoffset = (next_restart_keyframe - curpos) - config.frames;
782 // Probably should put another if in here, (when two "restart" keyframes are close together
785 return !old_config.equivalent(&config);
788 void SelTempAvgMain::save_data(KeyFrame *keyframe)
792 // cause data to be stored directly in text
793 output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
794 output.tag.set_title("SELECTIVE_TEMPORAL_AVERAGE");
795 output.tag.set_property("FRAMES", config.frames);
796 output.tag.set_property("METHOD", config.method);
797 output.tag.set_property("OFFSETMODE", config.offsetmode);
798 output.tag.set_property("PARANOID", config.paranoid);
799 output.tag.set_property("NOSUBTRACT", config.nosubtract);
800 output.tag.set_property("OFFSETMODE_RESTARTMODE_KEYFRAME", config.offset_restartmarker_keyframe);
801 output.tag.set_property("OFFSETMODE_FIXED_VALUE", config.offset_fixed_value);
802 output.tag.set_property("GAIN", config.gain);
805 output.tag.set_property("AVG_THRESHOLD_RY", config.avg_threshold_RY);
806 output.tag.set_property("AVG_THRESHOLD_GU", config.avg_threshold_GU);
807 output.tag.set_property("AVG_THRESHOLD_BV", config.avg_threshold_BV);
808 output.tag.set_property("STD_THRESHOLD_RY", config.std_threshold_RY);
809 output.tag.set_property("STD_THRESHOLD_GU", config.std_threshold_GU);
810 output.tag.set_property("STD_THRESHOLD_BV", config.std_threshold_BV);
812 output.tag.set_property("MASK_RY", config.mask_RY);
813 output.tag.set_property("MASK_GU", config.mask_GU);
814 output.tag.set_property("MASK_BV", config.mask_BV);
817 output.terminate_string();
820 void SelTempAvgMain::read_data(KeyFrame *keyframe)
824 input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
826 while(!input.read_tag())
828 if(input.tag.title_is("SELECTIVE_TEMPORAL_AVERAGE"))
830 config.frames = input.tag.get_property("FRAMES", config.frames);
831 config.method = input.tag.get_property("METHOD", config.method);
832 config.offsetmode = input.tag.get_property("OFFSETMODE", config.offsetmode);
833 config.paranoid = input.tag.get_property("PARANOID", config.paranoid);
834 config.nosubtract = input.tag.get_property("NOSUBTRACT", config.nosubtract);
835 config.offset_restartmarker_keyframe = input.tag.get_property("OFFSETMODE_RESTARTMODE_KEYFRAME", config.offset_restartmarker_keyframe);
836 config.offset_fixed_value = input.tag.get_property("OFFSETMODE_FIXED_VALUE", config.offset_fixed_value);
837 config.gain = input.tag.get_property("gain", config.gain);
839 config.avg_threshold_RY = input.tag.get_property("AVG_THRESHOLD_RY", config.avg_threshold_RY);
840 config.avg_threshold_GU = input.tag.get_property("AVG_THRESHOLD_GU", config.avg_threshold_GU);
841 config.avg_threshold_BV = input.tag.get_property("AVG_THRESHOLD_BV", config.avg_threshold_BV);
842 config.std_threshold_RY = input.tag.get_property("STD_THRESHOLD_RY", config.std_threshold_RY);
843 config.std_threshold_GU = input.tag.get_property("STD_THRESHOLD_GU", config.std_threshold_GU);
844 config.std_threshold_BV = input.tag.get_property("STD_THRESHOLD_BV", config.std_threshold_BV);
846 config.mask_RY = input.tag.get_property("MASK_RY", config.mask_RY);
847 config.mask_GU = input.tag.get_property("MASK_GU", config.mask_GU);
848 config.mask_BV = input.tag.get_property("MASK_BV", config.mask_BV);
856 int SelTempAvgMain::nextkeyframeisoffsetrestart(KeyFrame *keyframe)
860 input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
862 while(!input.read_tag())
864 if(input.tag.title_is("SELECTIVE_TEMPORAL_AVERAGE"))
866 return(input.tag.get_property("OFFSETMODE_RESTARTMODE_KEYFRAME", config.offset_restartmarker_keyframe));
874 void SelTempAvgMain::update_gui()
878 if(load_configuration())
880 ((SelTempAvgWindow*)thread->window)->lock_window("SelTempAvgMain::update_gui");
881 ((SelTempAvgWindow*)thread->window)->total_frames->update(config.frames);
883 ((SelTempAvgWindow*)thread->window)->method_none->update( config.method == SelTempAvgConfig::METHOD_NONE);
884 ((SelTempAvgWindow*)thread->window)->method_seltempavg->update( config.method == SelTempAvgConfig::METHOD_SELTEMPAVG);
885 ((SelTempAvgWindow*)thread->window)->method_average->update( config.method == SelTempAvgConfig::METHOD_AVERAGE);
886 ((SelTempAvgWindow*)thread->window)->method_stddev->update( config.method == SelTempAvgConfig::METHOD_STDDEV);
888 ((SelTempAvgWindow*)thread->window)->offset_fixed->update( config.offsetmode == SelTempAvgConfig::OFFSETMODE_FIXED);
889 ((SelTempAvgWindow*)thread->window)->offset_restartmarker->update(config.offsetmode == SelTempAvgConfig::OFFSETMODE_RESTARTMARKERSYS);
892 ((SelTempAvgWindow*)thread->window)->paranoid->update(config.paranoid);
893 ((SelTempAvgWindow*)thread->window)->no_subtract->update(config.nosubtract);
895 ((SelTempAvgWindow*)thread->window)->offset_fixed_value->update((int64_t)config.offset_fixed_value);
896 ((SelTempAvgWindow*)thread->window)->gain->update(config.gain);
898 ((SelTempAvgWindow*)thread->window)->avg_threshold_RY->update((float)config.avg_threshold_RY);
899 ((SelTempAvgWindow*)thread->window)->avg_threshold_GU->update((float)config.avg_threshold_GU);
900 ((SelTempAvgWindow*)thread->window)->avg_threshold_BV->update((float)config.avg_threshold_BV);
901 ((SelTempAvgWindow*)thread->window)->std_threshold_RY->update((float)config.std_threshold_RY);
902 ((SelTempAvgWindow*)thread->window)->std_threshold_GU->update((float)config.std_threshold_GU);
903 ((SelTempAvgWindow*)thread->window)->std_threshold_BV->update((float)config.std_threshold_BV);
905 ((SelTempAvgWindow*)thread->window)->mask_RY->update(config.mask_RY);
906 ((SelTempAvgWindow*)thread->window)->mask_GU->update(config.mask_GU);
907 ((SelTempAvgWindow*)thread->window)->mask_BV->update(config.mask_BV);
908 ((SelTempAvgWindow*)thread->window)->unlock_window();
910 ((SelTempAvgWindow*)thread->window)->offset_restartmarker_pos->update((int64_t)restartoffset);
911 ((SelTempAvgWindow*)thread->window)->offset_restartmarker_keyframe->update((config.offset_restartmarker_keyframe) && (onakeyframe));