00001 #include "clip.h"
00002 #include "bchash.h"
00003 #include "filexml.h"
00004 #include "keyframe.h"
00005 #include "language.h"
00006 #include "picon_png.h"
00007 #include "seltempavg.h"
00008 #include "seltempavgwindow.h"
00009 #include "vframe.h"
00010
00011 #include <stdint.h>
00012 #include <string.h>
00013
00014 REGISTER_PLUGIN(SelTempAvgMain)
00015
00016
00017
00018 SelTempAvgConfig::SelTempAvgConfig()
00019 {
00020 frames = 1;
00021 method = SelTempAvgConfig::METHOD_SELTEMPAVG;
00022 offsetmode = SelTempAvgConfig::OFFSETMODE_RESTARTMARKERSYS;
00023 paranoid = 0;
00024 nosubtract = 0;
00025 offset_restartmarker_keyframe = 0;
00026 offset_fixed_value = -15;
00027 gain = 1.00;
00028
00029 avg_threshold_RY = 0; avg_threshold_GU = 0; avg_threshold_BV = 0;
00030 std_threshold_RY = 0; std_threshold_GU = 0; std_threshold_BV = 0;
00031 mask_RY = 0; mask_GU = 0; mask_BV = 0;
00032 }
00033
00034 void SelTempAvgConfig::copy_from(SelTempAvgConfig *src)
00035 {
00036 this->frames = src->frames;
00037 this->method = src->method;
00038 this->offsetmode = src->offsetmode;
00039 this->paranoid = src->paranoid;
00040 this->nosubtract = src->nosubtract;
00041 this->offset_restartmarker_keyframe = src->offset_restartmarker_keyframe;
00042 this->offset_fixed_value = src->offset_fixed_value;
00043 this->gain = src->gain;
00044 this->avg_threshold_RY = src->avg_threshold_RY; this->avg_threshold_GU = src->avg_threshold_GU;
00045 this->avg_threshold_BV = src->avg_threshold_BV; this->std_threshold_RY = src->std_threshold_RY;
00046 this->std_threshold_GU = src->std_threshold_GU; this->std_threshold_BV = src->std_threshold_BV;
00047
00048 this->mask_BV = src->mask_BV; this->mask_RY = src->mask_RY; this->mask_GU = src->mask_GU;
00049 }
00050
00051 int SelTempAvgConfig::equivalent(SelTempAvgConfig *src)
00052 {
00053 return frames == src->frames &&
00054 method == src->method &&
00055 offsetmode == src->offsetmode &&
00056 paranoid == src->paranoid &&
00057 offset_restartmarker_keyframe == src->offset_restartmarker_keyframe &&
00058 offset_fixed_value == src->offset_fixed_value &&
00059 gain == src->gain &&
00060 this->avg_threshold_RY == src->avg_threshold_RY && this->avg_threshold_GU == src->avg_threshold_GU &&
00061 this->avg_threshold_BV == src->avg_threshold_BV && this->std_threshold_RY == src->std_threshold_RY &&
00062 this->std_threshold_GU == src->std_threshold_GU && this->std_threshold_BV == src->std_threshold_BV &&
00063 this->mask_RY == src->mask_RY && this->mask_GU == src->mask_GU && this->mask_BV == src->mask_BV;
00064 }
00065
00066
00068 SelTempAvgMain::SelTempAvgMain(PluginServer *server)
00069 : PluginVClient(server)
00070 {
00071 PLUGIN_CONSTRUCTOR_MACRO
00072 accumulation = 0;
00073 history = 0;
00074 history_size = 0;
00075 history_start = -0x7fffffff;
00076 history_frame = 0;
00077 history_valid = 0;
00078 prev_frame = -1;
00079 }
00080
00081 SelTempAvgMain::~SelTempAvgMain()
00082 {
00083 PLUGIN_DESTRUCTOR_MACRO
00084
00085 if(accumulation)
00086 {
00087 delete [] accumulation;
00088 delete [] accumulation_sq;
00089 }
00090 if(history)
00091 {
00092 for(int i = 0; i < config.frames; i++)
00093 delete history[i];
00094 delete [] history;
00095 }
00096 if(history_frame) delete [] history_frame;
00097 if(history_valid) delete [] history_valid;
00098 }
00099
00100 char* SelTempAvgMain::plugin_title() { return N_("Selective Temporal Averaging"); }
00101 int SelTempAvgMain::is_realtime() { return 1; }
00102
00103
00104 NEW_PICON_MACRO(SelTempAvgMain)
00105
00106 SHOW_GUI_MACRO(SelTempAvgMain, SelTempAvgThread)
00107
00108 SET_STRING_MACRO(SelTempAvgMain)
00109
00110 RAISE_WINDOW_MACRO(SelTempAvgMain);
00111
00112 int SelTempAvgMain::process_buffer(VFrame *frame,
00113 int64_t start_position,
00114 double frame_rate)
00115 {
00116 int h = frame->get_h();
00117 int w = frame->get_w();
00118 int color_model = frame->get_color_model();
00119 load_configuration();
00120
00121
00122 if(!accumulation)
00123 {
00124 accumulation = new unsigned char[w *
00125 h *
00126 cmodel_components(color_model) *
00127 sizeof(float)];
00128
00129 accumulation_sq = new unsigned char[w *
00130 h *
00131 3 *
00132 sizeof(float)];
00133 clear_accum(w, h, color_model);
00134 }
00135
00136 if(!config.nosubtract)
00137 {
00138
00139 if(history)
00140 {
00141 if(config.frames != history_size)
00142 {
00143 VFrame **history2;
00144 int64_t *history_frame2;
00145 int *history_valid2;
00146 history2 = new VFrame*[config.frames];
00147 history_frame2 = new int64_t[config.frames];
00148 history_valid2 = new int[config.frames];
00149
00150
00151 int i, j;
00152 for(i = 0, j = 0; i < config.frames && j < history_size; i++, j++)
00153 {
00154 history2[i] = history[j];
00155 history_frame2[i] = history_frame[i];
00156 history_valid2[i] = history_valid[i];
00157 }
00158
00159
00160 for( ; j < history_size; j++)
00161 {
00162 subtract_accum(history[j]);
00163 delete history[j];
00164 }
00165 delete [] history;
00166 delete [] history_frame;
00167 delete [] history_valid;
00168
00169
00170
00171 for( ; i < config.frames; i++)
00172 {
00173 history2[i] = new VFrame(0, w, h, color_model);
00174 history_frame2[i] = -0x7fffffff;
00175 history_valid2[i] = 0;
00176 }
00177
00178 history = history2;
00179 history_frame = history_frame2;
00180 history_valid = history_valid2;
00181
00182 history_size = config.frames;
00183 }
00184 }
00185 else
00186
00187 {
00188 history = new VFrame*[config.frames];
00189 for(int i = 0; i < config.frames; i++)
00190 history[i] = new VFrame(0, w, h, color_model);
00191 history_size = config.frames;
00192 history_frame = new int64_t[config.frames];
00193 bzero(history_frame, sizeof(int64_t) * config.frames);
00194 history_valid = new int[config.frames];
00195 bzero(history_valid, sizeof(int) * config.frames);
00196 }
00197
00198
00199
00200
00201
00202
00203
00204 int64_t *new_history_frames = new int64_t[history_size];
00205
00206 int64_t theoffset = (int64_t) config.offset_fixed_value;
00207 if (config.offsetmode == SelTempAvgConfig::OFFSETMODE_RESTARTMARKERSYS)
00208 theoffset = (int64_t) restartoffset;
00209
00210 for(int i = 0; i < history_size; i++)
00211 {
00212 new_history_frames[history_size - i - 1] = start_position + theoffset + i;
00213 }
00214
00215
00216 int no_change = 1;
00217 for(int i = 0; i < history_size; i++)
00218 {
00219
00220 if(history_valid[i])
00221 {
00222 int got_it = 0;
00223 for(int j = 0; j < history_size; j++)
00224 {
00225
00226 if(history_frame[i] == new_history_frames[j])
00227 {
00228 got_it = 1;
00229 break;
00230 }
00231 }
00232
00233
00234 if(!got_it)
00235 {
00236 subtract_accum(history[i]);
00237 history_valid[i] = 0;
00238 no_change = 0;
00239 }
00240 }
00241 }
00242
00243 if(config.paranoid && no_change)
00244 {
00245 for(int i = 0; i < history_size; i++)
00246 {
00247 history_valid[i] = 0;
00248 }
00249 clear_accum(w, h, color_model);
00250 }
00251
00252
00253 for(int i = 0; i < history_size; i++)
00254 {
00255
00256 int got_it = 0;
00257 for(int j = 0; j < history_size; j++)
00258 {
00259 if(history_valid[j] && history_frame[j] == new_history_frames[i])
00260 {
00261 got_it = 1;
00262 break;
00263 }
00264 }
00265
00266
00267 if(!got_it)
00268 {
00269
00270 for(int j = 0; j < history_size; j++)
00271 {
00272 if(!history_valid[j])
00273 {
00274
00275 history_frame[j] = new_history_frames[i];
00276 history_valid[j] = 1;
00277 read_frame(history[j],
00278 0,
00279 history_frame[j],
00280 frame_rate);
00281 add_accum(history[j]);
00282 break;
00283 }
00284 }
00285 }
00286 }
00287 delete [] new_history_frames;
00288 }
00289 else
00290
00291 {
00292
00293 if(config.paranoid && prev_frame == start_position ||
00294 prev_frame < 0)
00295 {
00296 prev_frame = start_position - config.frames + 1;
00297 prev_frame = MAX(0, prev_frame);
00298 clear_accum(w, h, color_model);
00299 }
00300
00301 for(int64_t i = prev_frame; i <= start_position; i++)
00302 {
00303 read_frame(frame,
00304 0,
00305 i,
00306 frame_rate);
00307 add_accum(frame);
00308
00309 }
00310
00311 prev_frame = start_position;
00312 }
00313
00314
00315
00316
00317 read_frame(frame,
00318 0,
00319 start_position,
00320 frame_rate);
00321
00322
00323
00324 transfer_accum(frame);
00325
00326
00327
00328
00329 return 0;
00330 }
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342 #define CLEAR_ACCUM(type, components, chroma) \
00343 { \
00344 float *row = (float*)accumulation; \
00345 float *row_sq = (float*)accumulation_sq; \
00346 if(chroma) \
00347 { \
00348 for(int i = 0; i < w * h; i++) \
00349 { \
00350 *row++ = 0x0; \
00351 *row++ = 0x0; \
00352 *row++ = 0x0; \
00353 if(components == 4) *row++ = 0x0; \
00354 *row_sq++ = 0x0; \
00355 *row_sq++ = 0x0; \
00356 *row_sq++ = 0x0; \
00357 } \
00358 } \
00359 else \
00360 { \
00361 bzero(row, w * h * sizeof(type) * components); \
00362 bzero(row_sq, w * h * 3 * sizeof(float)); \
00363 } \
00364 }
00365
00366
00367 void SelTempAvgMain::clear_accum(int w, int h, int color_model)
00368 {
00369 switch(color_model)
00370 {
00371 case BC_RGB888:
00372 CLEAR_ACCUM(int, 3, 0x0)
00373 break;
00374 case BC_RGB_FLOAT:
00375 CLEAR_ACCUM(float, 3, 0x0)
00376 break;
00377 case BC_RGBA8888:
00378 CLEAR_ACCUM(int, 4, 0x0)
00379 break;
00380 case BC_RGBA_FLOAT:
00381 CLEAR_ACCUM(float, 4, 0x0)
00382 break;
00383 case BC_YUV888:
00384 CLEAR_ACCUM(int, 3, 0x80)
00385 break;
00386 case BC_YUVA8888:
00387 CLEAR_ACCUM(int, 4, 0x80)
00388 break;
00389 case BC_YUV161616:
00390 CLEAR_ACCUM(int, 3, 0x8000)
00391 break;
00392 case BC_YUVA16161616:
00393 CLEAR_ACCUM(int, 4, 0x8000)
00394 break;
00395 }
00396 }
00397 #define C2_IS(frame_row,chroma,max) (float)(frame_row)/max
00398
00399
00400 #define SUBTRACT_ACCUM(type, \
00401 components, \
00402 chroma, \
00403 max) \
00404 { \
00405 if(1) \
00406 { \
00407 for(int i = 0; i < h; i++) \
00408 { \
00409 float *accum_row = (float*)accumulation + \
00410 i * w * components; \
00411 float *accum_row_sq = (float*)accumulation_sq + \
00412 i * w *3; \
00413 type *frame_row = (type*)frame->get_rows()[i]; \
00414 float c1, c2, c3; \
00415 for(int j = 0; j < w; j++) \
00416 { \
00417 c1 = ( (float)*frame_row )/max; \
00418 frame_row++; \
00419 c2 = ( (float)*frame_row )/max; \
00420 frame_row++; \
00421 c3 = ( (float)(*frame_row -0) )/max; \
00422 frame_row++; \
00423 \
00424 *accum_row -= c1; \
00425 accum_row++; \
00426 *accum_row -= c2; \
00427 accum_row++; \
00428 *accum_row -= c3; \
00429 accum_row++; \
00430 if(components == 4) { *accum_row -= ((float)*frame_row++)/max; accum_row++; } \
00431 \
00432 *accum_row_sq++ -= c1*c1; \
00433 *accum_row_sq++ -= c2*c2; \
00434 *accum_row_sq++ -= c3*c3; \
00435 } \
00436 } \
00437 } \
00438 }
00439
00440
00441 void SelTempAvgMain::subtract_accum(VFrame *frame)
00442 {
00443
00444 if(config.nosubtract) return;
00445 int w = frame->get_w();
00446 int h = frame->get_h();
00447
00448 switch(frame->get_color_model())
00449 {
00450 case BC_RGB888:
00451 SUBTRACT_ACCUM(unsigned char, 3, 0x0, 0xff)
00452 break;
00453 case BC_RGB_FLOAT:
00454 SUBTRACT_ACCUM(float, 3, 0x0, 1.0)
00455 break;
00456 case BC_RGBA8888:
00457 SUBTRACT_ACCUM(unsigned char, 4, 0x0, 0xff)
00458 break;
00459 case BC_RGBA_FLOAT:
00460 SUBTRACT_ACCUM(float, 4, 0x0, 1.0)
00461 break;
00462 case BC_YUV888:
00463 SUBTRACT_ACCUM(unsigned char, 3, 0x80, 0xff)
00464 break;
00465 case BC_YUVA8888:
00466 SUBTRACT_ACCUM(unsigned char, 4, 0x80, 0xff)
00467 break;
00468 case BC_YUV161616:
00469 SUBTRACT_ACCUM(uint16_t, 3, 0x8000, 0xffff)
00470 break;
00471 case BC_YUVA16161616:
00472 SUBTRACT_ACCUM(uint16_t, 4, 0x8000, 0xffff)
00473 break;
00474 }
00475 }
00476
00477
00478
00479
00480 #define ADD_ACCUM(type, components, chroma, max) \
00481 { \
00482 float c1, c2, c3; \
00483 if(1) \
00484 { \
00485 for(int i = 0; i < h; i++) \
00486 { \
00487 float *accum_row = (float*)accumulation + \
00488 i * w * components; \
00489 float *accum_row_sq = (float*)accumulation_sq + \
00490 i * w *3; \
00491 type *frame_row = (type*)frame->get_rows()[i]; \
00492 for(int j = 0; j < w; j++) \
00493 { \
00494 c1 = ( (float)*frame_row )/max; \
00495 frame_row++; \
00496 c2 = ( (float)*frame_row )/max; \
00497 frame_row++; \
00498 c3 = ( (float)*frame_row )/max; \
00499 frame_row++; \
00500 \
00501 *accum_row += c1; \
00502 accum_row++; \
00503 *accum_row += c2; \
00504 accum_row++; \
00505 *accum_row += c3; \
00506 accum_row++; \
00507 if(components == 4) { *accum_row += ((float)*frame_row++)/max; accum_row++; } \
00508 \
00509 *accum_row_sq++ += c1*c1; \
00510 *accum_row_sq++ += c2*c2; \
00511 *accum_row_sq++ += c3*c3; \
00512 } \
00513 } \
00514 } \
00515 }
00516
00517
00518 void SelTempAvgMain::add_accum(VFrame *frame)
00519 {
00520 int w = frame->get_w();
00521 int h = frame->get_h();
00522
00523 switch(frame->get_color_model())
00524 {
00525 case BC_RGB888:
00526 ADD_ACCUM(unsigned char, 3, 0x0, 0xff)
00527 break;
00528 case BC_RGB_FLOAT:
00529 ADD_ACCUM(float, 3, 0x0, 1.0)
00530 break;
00531 case BC_RGBA8888:
00532 ADD_ACCUM(unsigned char, 4, 0x0, 0xff)
00533 break;
00534 case BC_RGBA_FLOAT:
00535 ADD_ACCUM(float, 4, 0x0, 1.0)
00536 break;
00537 case BC_YUV888:
00538 ADD_ACCUM(unsigned char, 3, 0x80, 0xff)
00539 break;
00540 case BC_YUVA8888:
00541 ADD_ACCUM(unsigned char, 4, 0x80, 0xff)
00542 break;
00543 case BC_YUV161616:
00544 ADD_ACCUM(uint16_t, 3, 0x8000, 0xffff)
00545 break;
00546 case BC_YUVA16161616:
00547 ADD_ACCUM(uint16_t, 4, 0x8000, 0xffff)
00548 break;
00549 }
00550 }
00551
00552 #define MASKER(type, avg_thresh, std_thresh, c_now, c_mean, c_stddev, mask, gain, frame_rowp, max) \
00553 { \
00554 if ( (avg_thresh > fabs(c_now - c_mean)) && (std_thresh > c_stddev) ) \
00555 if (mask) \
00556 frame_rowp = max; \
00557 else \
00558 frame_rowp = (type)(c_mean*max*gain); \
00559 else \
00560 if (mask) \
00561 frame_rowp = 0; \
00562 else \
00563 frame_rowp = (type)(c_now*max*gain); \
00564 }
00565
00566 #define TRANSFER_ACCUM(type, components, chroma, max, c1_gain, c2_gain, c3_gain) \
00567 { \
00568 if(config.method == SelTempAvgConfig::METHOD_SELTEMPAVG) \
00569 { \
00570 float denominator = config.frames; \
00571 float c1_now, c2_now, c3_now, c4_now; \
00572 float c1_mean, c2_mean, c3_mean, c4_mean; \
00573 float c1_stddev, c2_stddev, c3_stddev; \
00574 for(int i = 0; i < h; i++) \
00575 { \
00576 float *accum_row = (float*)accumulation + i * w * components; \
00577 float *accum_row_sq = (float*)accumulation_sq + i * w * 3; \
00578 \
00579 type *frame_row = (type*)frame->get_rows()[i]; \
00580 for(int j = 0; j < w; j++) \
00581 { \
00582 c1_now = (float)(*frame_row)/max; \
00583 *frame_row++; \
00584 c2_now = (float)(*frame_row)/max; \
00585 *frame_row++; \
00586 c3_now = (float)(*frame_row)/max; \
00587 frame_row -= 2; \
00588 \
00589 c1_mean = *accum_row/denominator; \
00590 accum_row++; \
00591 c2_mean = *accum_row/denominator; \
00592 accum_row++; \
00593 c3_mean = *accum_row/denominator; \
00594 accum_row++; \
00595 if(components == 4) { c4_mean = *accum_row/denominator; accum_row++; } \
00596 \
00597 c1_stddev = (*accum_row_sq++)/denominator - c1_mean*c1_mean; \
00598 c2_stddev = (*accum_row_sq++)/denominator - c2_mean*c2_mean; \
00599 c3_stddev = (*accum_row_sq++)/denominator - c3_mean*c3_mean; \
00600 \
00601 MASKER(type, \
00602 config.avg_threshold_RY, \
00603 config.std_threshold_RY, \
00604 c1_now, c1_mean, c1_stddev, config.mask_RY, c1_gain,\
00605 *frame_row++, max)\
00606 MASKER(type, \
00607 config.avg_threshold_GU, \
00608 config.std_threshold_GU, \
00609 c2_now, c2_mean, c2_stddev, config.mask_GU, c2_gain,\
00610 *frame_row++, max)\
00611 MASKER(type, \
00612 config.avg_threshold_BV, \
00613 config.std_threshold_BV, \
00614 c3_now, c3_mean, c3_stddev, config.mask_BV, c3_gain,\
00615 *frame_row++, max)\
00616 if(components == 4) *frame_row++ = max; \
00617 } \
00618 } \
00619 } \
00620 else \
00621 if(config.method == SelTempAvgConfig::METHOD_AVERAGE) \
00622 { \
00623 float denominator = config.frames; \
00624 for(int i = 0; i < h; i++) \
00625 { \
00626 float *accum_row = (float*)accumulation + i * w * components; \
00627 type *frame_row = (type*)frame->get_rows()[i]; \
00628 for(int j = 0; j < w; j++) \
00629 { \
00630 \
00631 *frame_row++ = (type)( (*accum_row++ / denominator)*c1_gain*max ); \
00632 *frame_row++ = (type)( (*accum_row++ / denominator)*c2_gain*max ); \
00633 *frame_row++ = (type)( (*accum_row++ / denominator)*c3_gain*max ); \
00634 if(components == 4) *frame_row++ = (type)((*accum_row++/denominator)*max ); \
00635 } \
00636 } \
00637 } \
00638 else \
00639 if(config.method == SelTempAvgConfig::METHOD_STDDEV) \
00640 { \
00641 float c1_mean, c2_mean, c3_mean, c4_mean; \
00642 float c1_stddev, c2_stddev, c3_stddev; \
00643 float denominator = config.frames; \
00644 for(int i = 0; i < h; i++) \
00645 { \
00646 float *accum_row = (float*)accumulation + i * w * components; \
00647 float *accum_row_sq = (float*)accumulation_sq + i * w * 3; \
00648 type *frame_row = (type*)frame->get_rows()[i]; \
00649 for(int j = 0; j < w; j++) \
00650 { \
00651 \
00652 c1_mean = *accum_row/denominator; \
00653 accum_row++; \
00654 c2_mean = *accum_row/denominator; \
00655 accum_row++; \
00656 c3_mean = *accum_row/denominator; \
00657 accum_row++; \
00658 if(components == 4) { c4_mean = *accum_row/denominator; accum_row++; } \
00659 \
00660 c1_stddev = (*accum_row_sq++)/denominator - c1_mean*c1_mean; \
00661 c2_stddev = (*accum_row_sq++)/denominator - c2_mean*c2_mean; \
00662 c3_stddev = (*accum_row_sq++)/denominator - c3_mean*c3_mean; \
00663 \
00664 *frame_row++ = (type)( c1_stddev*c1_gain*max ); \
00665 *frame_row++ = (type)( c2_stddev*c2_gain*max ); \
00666 *frame_row++ = (type)( c3_stddev*c3_gain*max ); \
00667 if(components == 4) *frame_row++ = max; \
00668 } \
00669 } \
00670 } \
00671 }
00672
00673
00674 void SelTempAvgMain::transfer_accum(VFrame *frame)
00675 {
00676 int w = frame->get_w();
00677 int h = frame->get_h();
00678
00679 switch(frame->get_color_model())
00680 {
00681 case BC_RGB888:
00682 TRANSFER_ACCUM(unsigned char, 3 , 0x0 , 0xff , config.gain, config.gain, config.gain)
00683 break;
00684 case BC_RGB_FLOAT:
00685 TRANSFER_ACCUM(float , 3 , 0x0 , 1 , config.gain, config.gain, config.gain)
00686 break;
00687 case BC_RGBA8888:
00688 TRANSFER_ACCUM(unsigned char, 4 , 0x0 , 0xff , config.gain, config.gain, config.gain)
00689 break;
00690 case BC_RGBA_FLOAT:
00691 TRANSFER_ACCUM(float , 4 , 0x0 , 1 , config.gain, config.gain, config.gain)
00692 break;
00693 case BC_YUV888:
00694 TRANSFER_ACCUM(unsigned char, 3 , 0x80 , 0xff , config.gain, 1.0 , 1.0)
00695 break;
00696 case BC_YUVA8888:
00697 TRANSFER_ACCUM(unsigned char, 4 , 0x80 , 0xff , config.gain, 1.0 , 1.0)
00698 break;
00699 case BC_YUV161616:
00700 TRANSFER_ACCUM(uint16_t , 3 , 0x8000, 0xffff, config.gain, 1.0 , 1.0)
00701 break;
00702 case BC_YUVA16161616:
00703 TRANSFER_ACCUM(uint16_t , 4 , 0x8000, 0xffff, config.gain, 1.0 , 1.0)
00704 break;
00705 }
00706 }
00707
00708
00709 int SelTempAvgMain::load_defaults()
00710 {
00711 char directory[BCTEXTLEN], string[BCTEXTLEN];
00712
00713 sprintf(directory, "%sdenoiseseltempavg.rc", BCASTDIR);
00714
00715
00716 defaults = new BC_Hash(directory);
00717 defaults->load();
00718
00719 config.frames = defaults->get("FRAMES", config.frames);
00720 config.method = defaults->get("METHOD", config.method);
00721 config.offsetmode = defaults->get("OFFSETMODE", config.offsetmode);
00722 config.paranoid = defaults->get("PARANOID", config.paranoid);
00723 config.nosubtract = defaults->get("NOSUBTRACT", config.nosubtract);
00724 config.offset_restartmarker_keyframe = defaults->get("OFFSETMODE_RESTARTMODE_KEYFRAME", config.offset_restartmarker_keyframe);
00725 config.offset_fixed_value = defaults->get("OFFSETMODE_FIXED_VALUE", config.offset_fixed_value);
00726 config.gain = defaults->get("GAIN", config.gain);
00727
00728 config.avg_threshold_RY = defaults->get("AVG_THRESHOLD_RY", config.avg_threshold_GU);
00729 config.avg_threshold_GU = defaults->get("AVG_THRESHOLD_GU", config.avg_threshold_GU);
00730 config.avg_threshold_BV = defaults->get("AVG_THRESHOLD_BV", config.avg_threshold_BV);
00731 config.std_threshold_RY = defaults->get("STD_THRESHOLD_RY", config.std_threshold_RY);
00732 config.std_threshold_GU = defaults->get("STD_THRESHOLD_GU", config.std_threshold_GU);
00733 config.std_threshold_BV = defaults->get("STD_THRESHOLD_BV", config.std_threshold_BV);
00734 config.mask_RY = defaults->get("MASK_RY", config.mask_GU);
00735 config.mask_GU = defaults->get("MASK_GU", config.mask_GU);
00736 config.mask_BV = defaults->get("MASK_BV", config.mask_BV);
00737 return 0;
00738 }
00739
00740 int SelTempAvgMain::save_defaults()
00741 {
00742 defaults->update("FRAMES", config.frames);
00743 defaults->update("METHOD", config.method);
00744 defaults->update("OFFSETMODE", config.offsetmode);
00745 defaults->update("PARANOID", config.paranoid);
00746 defaults->update("NOSUBTRACT", config.nosubtract);
00747 defaults->update("OFFSETMODE_RESTARTMODE_KEYFRAME", config.offset_restartmarker_keyframe);
00748 defaults->update("OFFSETMODE_FIXED_VALUE", config.offset_fixed_value);
00749 defaults->update("GAIN", config.gain);
00750
00751 defaults->update("AVG_THRESHOLD_RY", config.avg_threshold_RY);
00752 defaults->update("AVG_THRESHOLD_GU", config.avg_threshold_GU);
00753 defaults->update("AVG_THRESHOLD_BV", config.avg_threshold_BV);
00754 defaults->update("STD_THRESHOLD_RY", config.std_threshold_RY);
00755 defaults->update("STD_THRESHOLD_GU", config.std_threshold_GU);
00756 defaults->update("STD_THRESHOLD_BV", config.std_threshold_BV);
00757
00758 defaults->update("MASK_RY", config.mask_RY);
00759 defaults->update("MASK_GU", config.mask_GU);
00760 defaults->update("MASK_BV", config.mask_BV);
00761
00762 defaults->save();
00763 return 0;
00764 }
00765
00766 int SelTempAvgMain::load_configuration()
00767 {
00768 KeyFrame *prev_keyframe;
00769 KeyFrame *temp_keyframe;
00770
00771 SelTempAvgConfig old_config;
00772 old_config.copy_from(&config);
00773
00774 int64_t curpos = get_source_position();
00775 prev_keyframe = get_prev_keyframe(curpos);
00776 read_data(prev_keyframe);
00777
00778 if (curpos == prev_keyframe->position)
00779 onakeyframe = 1;
00780 else
00781 onakeyframe = 0;
00782
00783 int64_t next_restart_keyframe = curpos + config.frames;
00784 int64_t prev_restart_keyframe = curpos - config.frames;
00785
00786 for (int i = curpos; i < curpos + config.frames; i++)
00787 {
00788 temp_keyframe = get_next_keyframe(i);
00789 if (
00790 (temp_keyframe->position < curpos + config.frames/2) &&
00791 (temp_keyframe->position > curpos) &&
00792 nextkeyframeisoffsetrestart(temp_keyframe)
00793 )
00794 {
00795 next_restart_keyframe = temp_keyframe->position;
00796 i = curpos + config.frames;
00797 } else if (temp_keyframe->position > i)
00798 i = temp_keyframe->position;
00799 }
00800
00801 for (int i = curpos; i > curpos - config.frames; i--)
00802 {
00803 temp_keyframe = get_prev_keyframe(i);
00804 if (
00805 (temp_keyframe->position > curpos - config.frames/2) &&
00806 (temp_keyframe->position < curpos) &&
00807 nextkeyframeisoffsetrestart(temp_keyframe)
00808 )
00809 {
00810 prev_restart_keyframe = temp_keyframe->position;
00811 i = curpos - config.frames;
00812 } else if (temp_keyframe->position < i)
00813 i = temp_keyframe->position;
00814 }
00815
00816 restartoffset = -config.frames/2;
00817
00818 if (onakeyframe && config.offset_restartmarker_keyframe)
00819 restartoffset = 0;
00820 else if ((curpos - prev_restart_keyframe) < config.frames/2)
00821 restartoffset = prev_restart_keyframe - curpos;
00822 else if ((next_restart_keyframe - curpos) < config.frames/2) {
00823 restartoffset = (next_restart_keyframe - curpos) - config.frames;
00824
00825 }
00826
00827 return !old_config.equivalent(&config);
00828 }
00829
00830 void SelTempAvgMain::save_data(KeyFrame *keyframe)
00831 {
00832 FileXML output;
00833
00834
00835 output.set_shared_string(keyframe->data, MESSAGESIZE);
00836 output.tag.set_title("SELECTIVE_TEMPORAL_AVERAGE");
00837 output.tag.set_property("FRAMES", config.frames);
00838 output.tag.set_property("METHOD", config.method);
00839 output.tag.set_property("OFFSETMODE", config.offsetmode);
00840 output.tag.set_property("PARANOID", config.paranoid);
00841 output.tag.set_property("NOSUBTRACT", config.nosubtract);
00842 output.tag.set_property("OFFSETMODE_RESTARTMODE_KEYFRAME", config.offset_restartmarker_keyframe);
00843 output.tag.set_property("OFFSETMODE_FIXED_VALUE", config.offset_fixed_value);
00844 output.tag.set_property("GAIN", config.gain);
00845
00846
00847 output.tag.set_property("AVG_THRESHOLD_RY", config.avg_threshold_RY);
00848 output.tag.set_property("AVG_THRESHOLD_GU", config.avg_threshold_GU);
00849 output.tag.set_property("AVG_THRESHOLD_BV", config.avg_threshold_BV);
00850 output.tag.set_property("STD_THRESHOLD_RY", config.std_threshold_RY);
00851 output.tag.set_property("STD_THRESHOLD_GU", config.std_threshold_GU);
00852 output.tag.set_property("STD_THRESHOLD_BV", config.std_threshold_BV);
00853
00854 output.tag.set_property("MASK_RY", config.mask_RY);
00855 output.tag.set_property("MASK_GU", config.mask_GU);
00856 output.tag.set_property("MASK_BV", config.mask_BV);
00857
00858 output.append_tag();
00859 output.tag.set_title("/SELECTIVE_TEMPORAL_AVERAGE");
00860 output.append_tag();
00861 output.terminate_string();
00862 }
00863
00864 void SelTempAvgMain::read_data(KeyFrame *keyframe)
00865 {
00866 FileXML input;
00867
00868 input.set_shared_string(keyframe->data, strlen(keyframe->data));
00869
00870 int result = 0;
00871
00872 while(!input.read_tag())
00873 {
00874 if(input.tag.title_is("SELECTIVE_TEMPORAL_AVERAGE"))
00875 {
00876 config.frames = input.tag.get_property("FRAMES", config.frames);
00877 config.method = input.tag.get_property("METHOD", config.method);
00878 config.offsetmode = input.tag.get_property("OFFSETMODE", config.offsetmode);
00879 config.paranoid = input.tag.get_property("PARANOID", config.paranoid);
00880 config.nosubtract = input.tag.get_property("NOSUBTRACT", config.nosubtract);
00881 config.offset_restartmarker_keyframe = input.tag.get_property("OFFSETMODE_RESTARTMODE_KEYFRAME", config.offset_restartmarker_keyframe);
00882 config.offset_fixed_value = input.tag.get_property("OFFSETMODE_FIXED_VALUE", config.offset_fixed_value);
00883 config.gain = input.tag.get_property("gain", config.gain);
00884
00885 config.avg_threshold_RY = input.tag.get_property("AVG_THRESHOLD_RY", config.avg_threshold_RY);
00886 config.avg_threshold_GU = input.tag.get_property("AVG_THRESHOLD_GU", config.avg_threshold_GU);
00887 config.avg_threshold_BV = input.tag.get_property("AVG_THRESHOLD_BV", config.avg_threshold_BV);
00888 config.std_threshold_RY = input.tag.get_property("STD_THRESHOLD_RY", config.std_threshold_RY);
00889 config.std_threshold_GU = input.tag.get_property("STD_THRESHOLD_GU", config.std_threshold_GU);
00890 config.std_threshold_BV = input.tag.get_property("STD_THRESHOLD_BV", config.std_threshold_BV);
00891
00892 config.mask_RY = input.tag.get_property("MASK_RY", config.mask_RY);
00893 config.mask_GU = input.tag.get_property("MASK_GU", config.mask_GU);
00894 config.mask_BV = input.tag.get_property("MASK_BV", config.mask_BV);
00895
00896 }
00897 }
00898 }
00899
00900
00901
00902 int SelTempAvgMain::nextkeyframeisoffsetrestart(KeyFrame *keyframe)
00903 {
00904 FileXML input;
00905
00906 input.set_shared_string(keyframe->data, strlen(keyframe->data));
00907
00908 int result = 0;
00909
00910 while(!input.read_tag())
00911 {
00912 if(input.tag.title_is("SELECTIVE_TEMPORAL_AVERAGE"))
00913 {
00914 return(input.tag.get_property("OFFSETMODE_RESTARTMODE_KEYFRAME", config.offset_restartmarker_keyframe));
00915 }
00916 }
00917 return (0);
00918 }
00919
00920
00921
00922 void SelTempAvgMain::update_gui()
00923 {
00924 if(thread)
00925 {
00926 if(load_configuration())
00927 {
00928 thread->window->lock_window("SelTempAvgMain::update_gui");
00929 thread->window->total_frames->update(config.frames);
00930
00931 thread->window->method_none->update( config.method == SelTempAvgConfig::METHOD_NONE);
00932 thread->window->method_seltempavg->update( config.method == SelTempAvgConfig::METHOD_SELTEMPAVG);
00933 thread->window->method_average->update( config.method == SelTempAvgConfig::METHOD_AVERAGE);
00934 thread->window->method_stddev->update( config.method == SelTempAvgConfig::METHOD_STDDEV);
00935
00936 thread->window->offset_fixed->update( config.offsetmode == SelTempAvgConfig::OFFSETMODE_FIXED);
00937 thread->window->offset_restartmarker->update(config.offsetmode == SelTempAvgConfig::OFFSETMODE_RESTARTMARKERSYS);
00938
00939
00940 thread->window->paranoid->update(config.paranoid);
00941 thread->window->no_subtract->update(config.nosubtract);
00942
00943 thread->window->offset_fixed_value->update((int64_t)config.offset_fixed_value);
00944 thread->window->gain->update(config.gain);
00945
00946 thread->window->avg_threshold_RY->update((float)config.avg_threshold_RY);
00947 thread->window->avg_threshold_GU->update((float)config.avg_threshold_GU);
00948 thread->window->avg_threshold_BV->update((float)config.avg_threshold_BV);
00949 thread->window->std_threshold_RY->update((float)config.std_threshold_RY);
00950 thread->window->std_threshold_GU->update((float)config.std_threshold_GU);
00951 thread->window->std_threshold_BV->update((float)config.std_threshold_BV);
00952
00953 thread->window->mask_RY->update(config.mask_RY);
00954 thread->window->mask_GU->update(config.mask_GU);
00955 thread->window->mask_BV->update(config.mask_BV);
00956 thread->window->unlock_window();
00957 }
00958 thread->window->offset_restartmarker_pos->update((int64_t)restartoffset);
00959 thread->window->offset_restartmarker_keyframe->update((config.offset_restartmarker_keyframe) && (onakeyframe));
00960 }
00961 }
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971