3 * Copyright (C) 1997-2016 Adam Williams <broadcast at earthling dot net>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "bcsignals.h"
24 #include "interpolatevideo.h"
25 #include "interpolatewindow.h"
27 #include "motionscan-hv.h"
28 #include "opticflow.h"
29 #include "transportque.inc"
40 InterpolateVideoConfig::InterpolateVideoConfig()
42 input_rate = (double)30000 / 1001;
50 void InterpolateVideoConfig::copy_from(InterpolateVideoConfig *config)
52 this->input_rate = config->input_rate;
53 this->use_keyframes = config->use_keyframes;
54 this->optic_flow = config->optic_flow;
55 this->draw_vectors = config->draw_vectors;
56 this->search_radius = config->search_radius;
57 this->macroblock_size = config->macroblock_size;
60 int InterpolateVideoConfig::equivalent(InterpolateVideoConfig *config)
62 return EQUIV(this->input_rate, config->input_rate) &&
63 (this->use_keyframes == config->use_keyframes) &&
64 this->optic_flow == config->optic_flow &&
65 this->draw_vectors == config->draw_vectors &&
66 this->search_radius == config->search_radius &&
67 this->macroblock_size == config->macroblock_size;
77 REGISTER_PLUGIN(InterpolateVideo)
85 InterpolateVideo::InterpolateVideo(PluginServer *server)
86 : PluginVClient(server)
88 optic_flow_engine = 0;
91 bzero(frames, sizeof(VFrame*) * 2);
92 for(int i = 0; i < 2; i++)
96 last_macroblock_size = 0;
97 last_search_radius = 0;
98 total_macroblocks = 0;
102 InterpolateVideo::~InterpolateVideo()
104 delete optic_flow_engine;
107 if(frames[0]) delete frames[0];
108 if(frames[1]) delete frames[1];
109 macroblocks.remove_all_objects();
113 void InterpolateVideo::fill_border(double frame_rate, int64_t start_position)
115 // A border frame changed or the start position is not identical to the last
118 int64_t frame_start = range_start + (get_direction() == PLAY_REVERSE ? 1 : 0);
119 int64_t frame_end = range_end + (get_direction() == PLAY_REVERSE ? 1 : 0);
121 if( last_position == start_position && EQUIV(last_rate, frame_rate) &&
122 frame_number[0] >= 0 && frame_number[0] == frame_start &&
123 frame_number[1] >= 0 && frame_number[1] == frame_end ) return;
125 if( frame_start == frame_number[1] || frame_end == frame_number[0] )
127 int64_t n = frame_number[0];
128 frame_number[0] = frame_number[1];
130 VFrame *f = frames[0];
131 frames[0] = frames[1];
135 if( frame_start != frame_number[0] )
137 //printf("InterpolateVideo::fill_border 1 %lld\n", range_start);
138 read_frame(frames[0], 0, frame_start, active_input_rate, 0);
139 frame_number[0] = frame_start;
142 if( frame_end != frame_number[1] )
144 //printf("InterpolateVideo::fill_border 2 %lld\n", range_start);
145 read_frame(frames[1], 0, frame_end, active_input_rate, 0);
146 frame_number[1] = frame_end;
149 last_position = start_position;
150 last_rate = frame_rate;
157 void InterpolateVideo::draw_pixel(VFrame *frame, int x, int y)
159 if(!(x >= 0 && y >= 0 && x < frame->get_w() && y < frame->get_h())) return;
161 #define DRAW_PIXEL(x, y, components, do_yuv, max, type) \
163 type **rows = (type**)frame->get_rows(); \
164 rows[y][x * components] = max - rows[y][x * components]; \
167 rows[y][x * components + 1] = max - rows[y][x * components + 1]; \
168 rows[y][x * components + 2] = max - rows[y][x * components + 2]; \
172 rows[y][x * components + 1] = (max / 2 + 1) - rows[y][x * components + 1]; \
173 rows[y][x * components + 2] = (max / 2 + 1) - rows[y][x * components + 2]; \
175 if(components == 4) \
176 rows[y][x * components + 3] = max; \
180 switch(frame->get_color_model())
183 DRAW_PIXEL(x, y, 3, 0, 0xff, unsigned char);
186 DRAW_PIXEL(x, y, 4, 0, 0xff, unsigned char);
189 DRAW_PIXEL(x, y, 3, 0, 1.0, float);
192 DRAW_PIXEL(x, y, 4, 0, 1.0, float);
195 DRAW_PIXEL(x, y, 3, 1, 0xff, unsigned char);
198 DRAW_PIXEL(x, y, 4, 1, 0xff, unsigned char);
201 DRAW_PIXEL(x, y, 3, 0, 0xffff, uint16_t);
204 DRAW_PIXEL(x, y, 3, 1, 0xffff, uint16_t);
206 case BC_RGBA16161616:
207 DRAW_PIXEL(x, y, 4, 0, 0xffff, uint16_t);
209 case BC_YUVA16161616:
210 DRAW_PIXEL(x, y, 4, 1, 0xffff, uint16_t);
216 void InterpolateVideo::draw_line(VFrame *frame, int x1, int y1, int x2, int y2)
218 int w = labs(x2 - x1);
219 int h = labs(y2 - y1);
220 //printf("InterpolateVideo::draw_line 1 %d %d %d %d\n", x1, y1, x2, y2);
224 draw_pixel(frame, x1, y1);
229 // Flip coordinates so x1 < x2
239 int numerator = y2 - y1;
240 int denominator = x2 - x1;
241 for(int i = x1; i < x2; i++)
243 int y = y1 + (int64_t)(i - x1) * (int64_t)numerator / (int64_t)denominator;
244 draw_pixel(frame, i, y);
249 // Flip coordinates so y1 < y2
259 int numerator = x2 - x1;
260 int denominator = y2 - y1;
261 for(int i = y1; i < y2; i++)
263 int x = x1 + (int64_t)(i - y1) * (int64_t)numerator / (int64_t)denominator;
264 draw_pixel(frame, x, i);
267 //printf("InterpolateVideo::draw_line 2\n");
270 #define ARROW_SIZE 10
271 void InterpolateVideo::draw_arrow(VFrame *frame,
277 double angle = atan((float)(y2 - y1) / (float)(x2 - x1));
278 double angle1 = angle + (float)145 / 360 * 2 * 3.14159265;
279 double angle2 = angle - (float)145 / 360 * 2 * 3.14159265;
286 x3 = x2 - (int)(ARROW_SIZE * cos(angle1));
287 y3 = y2 - (int)(ARROW_SIZE * sin(angle1));
288 x4 = x2 - (int)(ARROW_SIZE * cos(angle2));
289 y4 = y2 - (int)(ARROW_SIZE * sin(angle2));
293 x3 = x2 + (int)(ARROW_SIZE * cos(angle1));
294 y3 = y2 + (int)(ARROW_SIZE * sin(angle1));
295 x4 = x2 + (int)(ARROW_SIZE * cos(angle2));
296 y4 = y2 + (int)(ARROW_SIZE * sin(angle2));
300 draw_line(frame, x1, y1, x2, y2);
301 // draw_line(frame, x1, y1 + 1, x2, y2 + 1);
304 if(abs(y2 - y1) || abs(x2 - x1)) draw_line(frame, x2, y2, x3, y3);
305 // draw_line(frame, x2, y2 + 1, x3, y3 + 1);
307 if(abs(y2 - y1) || abs(x2 - x1)) draw_line(frame, x2, y2, x4, y4);
308 // draw_line(frame, x2, y2 + 1, x4, y4 + 1);
311 void InterpolateVideo::draw_rect(VFrame *frame,
317 draw_line(frame, x1, y1, x2, y1);
318 draw_line(frame, x2, y1, x2, y2);
319 draw_line(frame, x2, y2, x1, y2);
320 draw_line(frame, x1, y2, x1, y1);
324 void InterpolateVideo::create_macroblocks()
326 // Get macroblock size
327 x_macroblocks = frames[0]->get_w() / config.macroblock_size;
328 y_macroblocks = frames[0]->get_h() / config.macroblock_size;
329 // printf("InterpolateVideo::create_macroblocks %d %d %d %d\n",
331 // config.macroblock_size,
335 if(config.macroblock_size * x_macroblocks < frames[0]->get_w())
340 if(config.macroblock_size * y_macroblocks < frames[0]->get_h())
345 total_macroblocks = x_macroblocks * y_macroblocks;
347 if(total_macroblocks != macroblocks.size())
349 macroblocks.remove_all_objects();
352 for(int i = 0; i < total_macroblocks; i++)
354 OpticFlowMacroblock *mb = 0;
355 if(macroblocks.size() > i)
357 mb = macroblocks.get(i);
361 mb = new OpticFlowMacroblock;
362 macroblocks.append(mb);
365 mb->x = (i % x_macroblocks) * config.macroblock_size + config.macroblock_size / 2;
366 mb->y = (i / x_macroblocks) * config.macroblock_size + config.macroblock_size / 2;
371 void InterpolateVideo::draw_vectors(int processed)
374 if(config.draw_vectors)
376 create_macroblocks();
378 for(int i = 0; i < total_macroblocks; i++)
380 OpticFlowMacroblock *mb = macroblocks.get(i);
381 // printf("InterpolateVideo::optic_flow %d x=%d y=%d dx=%d dy=%d\n",
385 // mb->dx / OVERSAMPLE,
386 // mb->dy / OVERSAMPLE);
390 draw_arrow(get_output(),
393 mb->x - mb->dx / OVERSAMPLE,
394 mb->y - mb->dy / OVERSAMPLE);
397 // if(mb->is_valid && mb->visible)
399 // draw_arrow(get_output(),
402 // mb->x - mb->dx / OVERSAMPLE + 1,
403 // mb->y - mb->dy / OVERSAMPLE + 1);
408 draw_pixel(get_output(),
414 // Draw center macroblock
415 OpticFlowMacroblock *mb = macroblocks.get(
416 x_macroblocks / 2 + y_macroblocks / 2 * x_macroblocks);
417 draw_rect(get_output(),
418 mb->x - config.macroblock_size / 2,
419 mb->y - config.macroblock_size / 2,
420 mb->x + config.macroblock_size / 2,
421 mb->y + config.macroblock_size / 2);
422 draw_rect(get_output(),
423 mb->x - config.macroblock_size / 2 - config.search_radius,
424 mb->y - config.macroblock_size / 2 - config.search_radius,
425 mb->x + config.macroblock_size / 2 + config.search_radius,
426 mb->y + config.macroblock_size / 2 + config.search_radius);
431 int InterpolateVideo::angles_overlap(float dst2_angle1,
436 if(dst2_angle1 < 0 || dst2_angle2 < 0)
438 dst2_angle1 += 2 * M_PI;
439 dst2_angle2 += 2 * M_PI;
442 if(dst1_angle1 < 0 || dst1_angle2 < 0)
444 dst1_angle1 += 2 * M_PI;
445 dst1_angle2 += 2 * M_PI;
448 if(dst1_angle1 < dst2_angle2 &&
449 dst1_angle2 > dst2_angle1) return 1;
456 void InterpolateVideo::blend_macroblock(int number)
458 OpticFlowMacroblock *src = macroblocks.get(number);
459 struct timeval start_time;
460 gettimeofday(&start_time, 0);
461 // printf("InterpolateVideo::blend_macroblock %d %d\n",
466 // Copy macroblock table to local thread
467 ArrayList<OpticFlowMacroblock*> local_macroblocks;
468 for(int i = 0; i < macroblocks.size(); i++)
470 OpticFlowMacroblock *mb = new OpticFlowMacroblock;
471 mb->copy_from(macroblocks.get(i));
472 local_macroblocks.append(mb);
475 // Get nearest macroblocks
476 for(int i = 0; i < local_macroblocks.size(); i++)
478 OpticFlowMacroblock *dst = local_macroblocks.get(i);
479 if(i != number && dst->is_valid)
482 // rough estimation of angle coverage
483 float angle = atan2(dst->y - src->y, dst->x - src->x);
484 float dist = sqrt(SQR(dst->y - src->y) + SQR(dst->x - src->x));
485 float span = sin((float)config.macroblock_size / dist);
486 dst->angle1 = angle - span / 2;
487 dst->angle2 = angle + span / 2;
489 // All macroblocks start as visible
492 // printf("InterpolateVideo::blend_macroblock %d %d x=%d y=%d span=%f angle1=%f angle2=%f dist=%f\n",
497 // span * 360 / 2 / M_PI,
498 // dst->angle1 * 360 / 2 / M_PI,
499 // dst->angle2 * 360 / 2 / M_PI,
504 for(int i = 0; i < local_macroblocks.size(); i++)
506 // Conceil macroblocks which are hidden
507 OpticFlowMacroblock *dst1 = local_macroblocks.get(i);
508 if(i != number && dst1->is_valid && dst1->visible)
510 // Find macroblock which is obstructing
511 for(int j = 0; j < local_macroblocks.size(); j++)
513 OpticFlowMacroblock *dst2 = local_macroblocks.get(j);
516 dst2->dist < dst1->dist &&
517 angles_overlap(dst2->angle1,
523 j = local_macroblocks.size();
529 // Blend all visible macroblocks
530 // Get distance metrics
535 for(int i = 0; i < local_macroblocks.size(); i++)
537 OpticFlowMacroblock *dst = local_macroblocks.get(i);
538 if(i != number && dst->is_valid && dst->visible)
543 min = max = dst->dist;
548 min = MIN(dst->dist, min);
549 max = MAX(dst->dist, max);
551 // printf("InterpolateVideo::blend_macroblock %d %d x=%d y=%d dist=%f\n",
561 // Invert distances to convert to weights
563 for(int i = 0; i < local_macroblocks.size(); i++)
565 OpticFlowMacroblock *dst = local_macroblocks.get(i);
566 if(i != number && dst->is_valid && dst->visible)
568 dst->dist = max - dst->dist + min;
570 // printf("InterpolateVideo::blend_macroblock %d %d x=%d y=%d dist=%f\n",
575 // max - dst->dist + min);
580 // Add weighted vectors
585 for(int i = 0; i < local_macroblocks.size(); i++)
587 OpticFlowMacroblock *dst = local_macroblocks.get(i);
588 if(i != number && dst->is_valid && dst->visible)
590 dx += dst->dist * dst->dx / total;
591 dy += dst->dist * dst->dy / total;
594 // printf("InterpolateVideo::blend_macroblock %d %d x=%d y=%d dist=%f\n",
599 // max - dst->dist + min);
605 local_macroblocks.remove_all_objects();
607 // printf("InterpolateVideo::blend_macroblock %d total=%f\n",
610 struct timeval end_time;
611 gettimeofday(&end_time, 0);
612 // printf("InterpolateVideo::blend_macroblock %d %d\n",
614 // end_time.tv_sec * 1000 + end_time.tv_usec / 1000 -
615 // start_time.tv_sec * 1000 - start_time.tv_usec / 1000);
620 void InterpolateVideo::optic_flow()
623 create_macroblocks();
627 if(!optic_flow_engine)
629 optic_flow_engine = new OpticFlow(this,
630 PluginClient::get_project_smp() + 1,
631 PluginClient::get_project_smp() + 1);
636 if(motion_number[0] == frame_number[0] &&
637 motion_number[1] == frame_number[1] &&
638 last_macroblock_size == config.macroblock_size &&
639 last_search_radius == config.search_radius)
644 // Calculate new vectors
651 optic_flow_engine->set_package_count(MIN(MAX_PACKAGES, total_macroblocks));
652 optic_flow_engine->process_packages();
654 // Fill in failed macroblocks
655 invalid_blocks.remove_all();
656 for(int i = 0; i < macroblocks.size(); i++)
658 if(!macroblocks.get(i)->is_valid
660 // && i >= 30 * x_macroblocks)
663 invalid_blocks.append(i);
667 //printf("InterpolateVideo::optic_flow %d %d\n", __LINE__, invalid_blocks.size());
668 if(invalid_blocks.size())
672 blend_engine = new BlendMacroblock(this,
673 PluginClient::get_project_smp() + 1,
674 PluginClient::get_project_smp() + 1);
677 blend_engine->set_package_count(MIN(PluginClient::get_project_smp() + 1,
678 invalid_blocks.size()));
679 blend_engine->process_packages();
685 // for(int i = 0; i < total_macroblocks; i++)
687 // OpticFlowPackage *pkg = (OpticFlowPackage*)optic_flow_engine->get_package(
689 // if((i / x_macroblocks) % 2)
704 warp_engine = new Warp(this,
705 PluginClient::get_project_smp() + 1,
706 PluginClient::get_project_smp() + 1);
709 warp_engine->process_packages();
711 motion_number[0] = frame_number[0];
712 motion_number[1] = frame_number[1];
713 last_macroblock_size = config.macroblock_size;
714 last_search_radius = config.search_radius;
718 // get_output()->copy_from(frames[1]);
725 #define AVERAGE(type, temp_type,components, max) \
727 temp_type fraction0 = (temp_type)(lowest_fraction * max); \
728 temp_type fraction1 = (temp_type)(max - fraction0); \
730 for(int i = 0; i < h; i++) \
732 type *prev_row0 = (type*)frames[0]->get_rows()[i]; \
733 type *next_row0 = (type*)frames[1]->get_rows()[i]; \
734 type *out_row = (type*)frame->get_rows()[i]; \
735 for(int j = 0; j < w * components; j++) \
737 *out_row++ = (*prev_row0++ * fraction0 + *next_row0++ * fraction1) / max; \
743 void InterpolateVideo::average()
745 VFrame *frame = get_output();
746 int w = frame->get_w();
747 int h = frame->get_h();
749 switch(frame->get_color_model())
752 AVERAGE(float, float, 3, 1);
756 AVERAGE(unsigned char, int, 3, 0xff);
759 AVERAGE(float, float, 4, 1);
763 AVERAGE(unsigned char, int, 4, 0xff);
769 int InterpolateVideo::process_buffer(VFrame *frame,
770 int64_t start_position,
773 if(get_direction() == PLAY_REVERSE) start_position--;
774 load_configuration();
778 for(int i = 0; i < 2; i++)
780 frames[i] = new VFrame(frame->get_w(), frame->get_h(),
781 frame->get_color_model(), 0);
784 //printf("InterpolateVideo::process_buffer 1 %lld %lld\n", range_start, range_end);
786 // Fraction of lowest frame in output
787 int64_t requested_range_start = (int64_t)((double)range_start *
788 frame_rate / active_input_rate);
789 int64_t requested_range_end = (int64_t)((double)range_end *
790 frame_rate / active_input_rate);
791 if(requested_range_start == requested_range_end)
793 read_frame(frame, 0, range_start, active_input_rate, 0);
798 // Fill border frames
799 fill_border(frame_rate, start_position);
801 float highest_fraction = (float)(start_position - requested_range_start) /
802 (requested_range_end - requested_range_start);
804 // Fraction of highest frame in output
805 lowest_fraction = 1.0 - highest_fraction;
807 CLAMP(highest_fraction, 0, 1);
808 CLAMP(lowest_fraction, 0, 1);
810 // printf("InterpolateVideo::process_buffer %lld %lld %lld %f %f %lld %lld %f %f\n",
813 // requested_range_start,
814 // requested_range_end,
816 // config.input_rate,
819 // highest_fraction);
821 if(start_position == (int64_t)(range_start * frame_rate / active_input_rate))
823 //printf("InterpolateVideo::process_buffer %d\n", __LINE__);
824 frame->copy_from(frames[0]);
826 if(config.optic_flow)
832 if(config.optic_flow)
834 //printf("InterpolateVideo::process_buffer %d\n", __LINE__);
848 NEW_WINDOW_MACRO(InterpolateVideo, InterpolateVideoWindow)
849 const char* InterpolateVideo::plugin_title() { return N_("Interpolate Video"); }
850 int InterpolateVideo::is_realtime() { return 1; }
852 int InterpolateVideo::load_configuration()
854 KeyFrame *prev_keyframe, *next_keyframe;
855 InterpolateVideoConfig old_config;
856 old_config.copy_from(&config);
858 next_keyframe = get_next_keyframe(get_source_position());
859 prev_keyframe = get_prev_keyframe(get_source_position());
860 // Previous keyframe stays in config object.
861 read_data(prev_keyframe);
864 int64_t prev_position = edl_to_local(prev_keyframe->position);
865 int64_t next_position = edl_to_local(next_keyframe->position);
866 if(prev_position == 0 && next_position == 0)
868 next_position = prev_position = get_source_start();
870 // printf("InterpolateVideo::load_configuration 1 %lld %lld %lld %lld\n",
871 // prev_keyframe->position,
872 // next_keyframe->position,
876 // Get range to average in requested rate
877 range_start = prev_position;
878 range_end = next_position;
881 // Use keyframes to determine range
882 if(config.use_keyframes)
884 active_input_rate = get_framerate();
885 // Between keyframe and edge of range or no keyframes
886 if(range_start == range_end)
888 // Between first keyframe and start of effect
889 if(get_source_position() >= get_source_start() &&
890 get_source_position() < range_start)
892 range_start = get_source_start();
895 // Between last keyframe and end of effect
896 if(get_source_position() >= range_start &&
897 get_source_position() < get_source_start() + get_total_len())
899 // Last frame should be inclusive of current effect
900 range_end = get_source_start() + get_total_len() - 1;
904 // Should never get here
910 // Make requested rate equal to input rate for this mode.
912 // Convert requested rate to input rate
913 // printf("InterpolateVideo::load_configuration 2 %lld %lld %f %f\n",
917 // config.input_rate);
918 // range_start = (int64_t)((double)range_start / get_framerate() * active_input_rate + 0.5);
919 // range_end = (int64_t)((double)range_end / get_framerate() * active_input_rate + 0.5);
924 active_input_rate = config.input_rate;
925 // Convert to input frame rate
926 range_start = (int64_t)(get_source_position() /
929 range_end = (int64_t)(get_source_position() /
931 active_input_rate) + 1;
934 // printf("InterpolateVideo::load_configuration 1 %lld %lld %lld %lld %lld %lld\n",
935 // prev_keyframe->position,
936 // next_keyframe->position,
943 return !config.equivalent(&old_config);
947 void InterpolateVideo::save_data(KeyFrame *keyframe)
951 // cause data to be stored directly in text
952 output.set_shared_output(keyframe->xbuf);
953 output.tag.set_title("INTERPOLATEVIDEO");
954 output.tag.set_property("INPUT_RATE", config.input_rate);
955 output.tag.set_property("USE_KEYFRAMES", config.use_keyframes);
956 output.tag.set_property("OPTIC_FLOW", config.optic_flow);
957 output.tag.set_property("DRAW_VECTORS", config.draw_vectors);
958 output.tag.set_property("SEARCH_RADIUS", config.search_radius);
959 output.tag.set_property("MACROBLOCK_SIZE", config.macroblock_size);
961 output.tag.set_title("/INTERPOLATEVIDEO");
963 output.append_newline();
964 output.terminate_string();
967 void InterpolateVideo::read_data(KeyFrame *keyframe)
971 input.set_shared_input(keyframe->xbuf);
973 while(!input.read_tag())
975 if(input.tag.title_is("INTERPOLATEVIDEO"))
977 config.input_rate = input.tag.get_property("INPUT_RATE", config.input_rate);
978 config.input_rate = Units::fix_framerate(config.input_rate);
979 config.use_keyframes = input.tag.get_property("USE_KEYFRAMES", config.use_keyframes);
980 config.optic_flow = input.tag.get_property("OPTIC_FLOW", config.optic_flow);
981 config.draw_vectors = input.tag.get_property("DRAW_VECTORS", config.draw_vectors);
982 config.search_radius = input.tag.get_property("SEARCH_RADIUS", config.search_radius);
983 config.macroblock_size = input.tag.get_property("MACROBLOCK_SIZE", config.macroblock_size);
988 void InterpolateVideo::update_gui()
992 if(load_configuration())
994 thread->window->lock_window("InterpolateVideo::update_gui");
995 ((InterpolateVideoWindow*)thread->window)->rate->update((float)config.input_rate);
996 ((InterpolateVideoWindow*)thread->window)->keyframes->update(config.use_keyframes);
997 ((InterpolateVideoWindow*)thread->window)->flow->update(config.optic_flow);
998 ((InterpolateVideoWindow*)thread->window)->vectors->update(config.draw_vectors);
999 ((InterpolateVideoWindow*)thread->window)->radius->update(config.search_radius);
1000 ((InterpolateVideoWindow*)thread->window)->size->update(config.macroblock_size);
1001 ((InterpolateVideoWindow*)thread->window)->update_enabled();
1002 thread->window->unlock_window();