1 #include "bcdisplayinfo.h"
6 #include "overlayframe.h"
11 #define _(String) gettext(String)
12 #define gettext_noop(String) String
13 #define N_(String) gettext_noop (String)
19 REGISTER_PLUGIN(MotionMain)
23 MotionConfig::MotionConfig()
32 int MotionConfig::equivalent(MotionConfig &that)
34 return search_radius == that.search_radius &&
36 block_size == that.block_size &&
37 magnitude == that.magnitude &&
38 return_speed == that.return_speed;
41 void MotionConfig::copy_from(MotionConfig &that)
43 search_radius = that.search_radius;
45 block_size = that.block_size;
46 magnitude = that.magnitude;
47 return_speed = that.return_speed;
50 void MotionConfig::interpolate(MotionConfig &prev,
54 int64_t current_frame)
67 PLUGIN_THREAD_OBJECT(MotionMain, MotionThread, MotionWindow)
71 MotionWindow::MotionWindow(MotionMain *plugin, int x, int y)
72 : BC_Window(plugin->gui_string,
82 this->plugin = plugin;
85 MotionWindow::~MotionWindow()
89 int MotionWindow::create_objects()
93 add_subwindow(new BC_Title(x, y, _("Search radius:")));
94 add_subwindow(radius = new MotionSearchRadius(plugin,
99 add_subwindow(new BC_Title(x, y, _("Block size:")));
100 add_subwindow(block_size = new MotionBlockSize(plugin,
105 add_subwindow(new BC_Title(x, y, _("Maximum absolute offset:")));
106 add_subwindow(magnitude = new MotionMagnitude(plugin,
111 add_subwindow(new BC_Title(x, y, _("Stabilizer settling time:")));
112 add_subwindow(return_speed = new MotionReturnSpeed(plugin,
117 add_subwindow(new BC_Title(x, y, _("Mode:")));
119 add_subwindow(track = new MotionTrack(plugin,
124 add_subwindow(stabilize = new MotionStabilize(plugin,
130 add_subwindow(vectors = new MotionDrawVectors(plugin,
140 void MotionWindow::update_mode()
142 stabilize->update(plugin->config.mode == MotionConfig::STABILIZE);
143 track->update(plugin->config.mode == MotionConfig::TRACK);
144 vectors->update(plugin->config.mode == MotionConfig::DRAW_VECTORS);
148 WINDOW_CLOSE_EVENT(MotionWindow)
159 MotionSearchRadius::MotionSearchRadius(MotionMain *plugin,
164 (int64_t)plugin->config.search_radius,
168 this->plugin = plugin;
172 int MotionSearchRadius::handle_event()
174 plugin->config.search_radius = get_value();
175 plugin->send_configure_change();
185 MotionBlockSize::MotionBlockSize(MotionMain *plugin,
190 (int64_t)plugin->config.block_size,
194 this->plugin = plugin;
197 int MotionBlockSize::handle_event()
199 plugin->config.block_size =get_value();
200 plugin->send_configure_change();
205 MotionMagnitude::MotionMagnitude(MotionMain *plugin,
210 (int64_t)plugin->config.magnitude,
214 this->plugin = plugin;
217 int MotionMagnitude::handle_event()
219 plugin->config.magnitude = get_value();
220 plugin->send_configure_change();
225 MotionReturnSpeed::MotionReturnSpeed(MotionMain *plugin,
230 (int64_t)plugin->config.return_speed,
234 this->plugin = plugin;
237 int MotionReturnSpeed::handle_event()
239 plugin->config.return_speed = get_value();
240 plugin->send_configure_change();
249 MotionStabilize::MotionStabilize(MotionMain *plugin,
255 plugin->config.mode == MotionConfig::STABILIZE,
259 this->plugin = plugin;
262 int MotionStabilize::handle_event()
264 plugin->config.mode = MotionConfig::STABILIZE;
266 plugin->send_configure_change();
274 MotionTrack::MotionTrack(MotionMain *plugin,
280 plugin->config.mode == MotionConfig::TRACK,
284 this->plugin = plugin;
287 int MotionTrack::handle_event()
289 plugin->config.mode = MotionConfig::TRACK;
291 plugin->send_configure_change();
299 MotionDrawVectors::MotionDrawVectors(MotionMain *plugin,
305 plugin->config.mode == MotionConfig::DRAW_VECTORS,
309 this->plugin = plugin;
312 int MotionDrawVectors::handle_event()
314 plugin->config.mode = MotionConfig::DRAW_VECTORS;
316 plugin->send_configure_change();
331 MotionMain::MotionMain(PluginServer *server)
332 : PluginVClient(server)
334 PLUGIN_CONSTRUCTOR_MACRO
338 total_macroblocks = 0;
347 MotionMain::~MotionMain()
349 PLUGIN_DESTRUCTOR_MACRO
350 if(engine) delete engine;
351 if(prev_frame) delete prev_frame;
352 if(macroblocks) delete [] macroblocks;
353 if(overlayer) delete overlayer;
354 if(search_area) delete [] search_area;
355 if(temp_frame) delete temp_frame;
358 char* MotionMain::plugin_title() { return _("Motion"); }
359 int MotionMain::is_realtime() { return 1; }
360 int MotionMain::is_multichannel() { return 1; }
362 NEW_PICON_MACRO(MotionMain)
364 SHOW_GUI_MACRO(MotionMain, MotionThread)
366 SET_STRING_MACRO(MotionMain)
368 RAISE_WINDOW_MACRO(MotionMain)
370 LOAD_CONFIGURATION_MACRO(MotionMain, MotionConfig)
374 void MotionMain::update_gui()
378 thread->window->lock_window();
379 load_configuration();
380 thread->window->radius->update(config.search_radius);
381 thread->window->block_size->update(config.block_size);
382 thread->window->magnitude->update(config.magnitude);
383 thread->window->return_speed->update(config.return_speed);
384 thread->window->update_mode();
385 thread->window->unlock_window();
390 int MotionMain::load_defaults()
392 char directory[1024], string[1024];
393 // set the default directory
394 sprintf(directory, "%smotion.rc", BCASTDIR);
397 defaults = new Defaults(directory);
400 config.block_size = defaults->get("BLOCK_SIZE", config.block_size);
401 config.search_radius = defaults->get("SEARCH_RADIUS", config.search_radius);
402 config.magnitude = defaults->get("MAGNITUDE", config.magnitude);
403 config.return_speed = defaults->get("RETURN_SPEED", config.return_speed);
404 config.mode = defaults->get("MODE", config.mode);
409 int MotionMain::save_defaults()
411 defaults->update("BLOCK_SIZE", config.block_size);
412 defaults->update("SEARCH_RADIUS", config.search_radius);
413 defaults->update("MAGNITUDE", config.magnitude);
414 defaults->update("RETURN_SPEED", config.return_speed);
415 defaults->update("MODE", config.mode);
422 void MotionMain::save_data(KeyFrame *keyframe)
426 // cause data to be stored directly in text
427 output.set_shared_string(keyframe->data, MESSAGESIZE);
428 output.tag.set_title("MOTION");
430 output.tag.set_property("BLOCK_SIZE", config.block_size);
431 output.tag.set_property("SEARCH_RADIUS", config.search_radius);
432 output.tag.set_property("MAGNITUDE", config.magnitude);
433 output.tag.set_property("RETURN_SPEED", config.return_speed);
434 output.tag.set_property("MODE", config.mode);
436 output.terminate_string();
439 void MotionMain::read_data(KeyFrame *keyframe)
443 input.set_shared_string(keyframe->data, strlen(keyframe->data));
449 result = input.read_tag();
453 if(input.tag.title_is("MOTION"))
455 config.block_size = input.tag.get_property("BLOCK_SIZE", config.block_size);
456 config.search_radius = input.tag.get_property("SEARCH_RADIUS", config.search_radius);
457 config.magnitude = input.tag.get_property("MAGNITUDE", config.magnitude);
458 config.return_speed = input.tag.get_property("RETURN_SPEED", config.return_speed);
459 config.mode = input.tag.get_property("MODE", config.mode);
468 void MotionMain::oversample(int32_t *dst,
477 #define DO_OVERSAMPLE(components, type) \
479 int oversample_w = (x2 - x1) * OVERSAMPLE; \
480 int oversample_h = (y2 - y1) * OVERSAMPLE; \
481 type **src_rows = (type**)src->get_rows(); \
483 for(int i = 0; i < oversample_h; i++) \
485 int row2_factor = i % OVERSAMPLE; \
486 int row1_factor = OVERSAMPLE - row2_factor; \
487 int row1_number = i / OVERSAMPLE + y1; \
488 int row2_number = row1_number + 1; \
489 row2_number = MIN(row2_number, y2 - 1); \
491 type *row1 = src_rows[row1_number]; \
492 type *row2 = src_rows[row2_number]; \
493 int32_t *dst_row = dst + i * dst_stride; \
495 for(int j = 0; j < oversample_w; j++) \
497 int pixel2_factor = j % OVERSAMPLE; \
498 int pixel1_factor = OVERSAMPLE - pixel2_factor; \
499 int pixel1_number = j / OVERSAMPLE + x1; \
500 int pixel2_number = pixel1_number + 1; \
501 pixel2_number = MIN(pixel2_number, x2 - 1); \
503 type *pixel1 = row1 + pixel1_number * components; \
504 type *pixel2 = row1 + pixel2_number * components; \
505 type *pixel3 = row2 + pixel1_number * components; \
506 type *pixel4 = row2 + pixel2_number * components; \
507 int32_t dst_pixel = 0; \
508 for(int k = 0; k < components; k++) \
510 dst_pixel += *pixel1++ * pixel1_factor * row1_factor; \
511 dst_pixel += *pixel2++ * pixel2_factor * row1_factor; \
512 dst_pixel += *pixel3++ * pixel1_factor * row2_factor; \
513 dst_pixel += *pixel4++ * pixel2_factor * row2_factor; \
515 *dst_row++ = dst_pixel; \
520 switch(src->get_color_model())
524 DO_OVERSAMPLE(3, unsigned char);
528 DO_OVERSAMPLE(3, uint16_t);
532 DO_OVERSAMPLE(4, unsigned char);
534 case BC_RGBA16161616:
535 case BC_YUVA16161616:
536 DO_OVERSAMPLE(4, uint16_t);
542 void MotionMain::draw_pixel(VFrame *frame, int x, int y)
544 if(!(x >= 0 && y >= 0 && x < frame->get_w() && y < frame->get_h())) return;
545 #define DRAW_PIXEL(x, y, components, do_yuv, max, type) \
547 type **rows = (type**)frame->get_rows(); \
548 rows[y][x * components] = max; \
551 rows[y][x * components + 1] = max; \
552 rows[y][x * components + 2] = max; \
554 if(components == 4) \
555 rows[y][x * components + 3] = max; \
559 switch(frame->get_color_model())
562 DRAW_PIXEL(x, y, 3, 0, 0xff, unsigned char);
565 DRAW_PIXEL(x, y, 3, 1, 0xff, unsigned char);
568 DRAW_PIXEL(x, y, 4, 0, 0xff, unsigned char);
571 DRAW_PIXEL(x, y, 4, 1, 0xff, unsigned char);
574 DRAW_PIXEL(x, y, 3, 0, 0xffff, uint16_t);
577 DRAW_PIXEL(x, y, 3, 1, 0xffff, uint16_t);
579 case BC_RGBA16161616:
580 DRAW_PIXEL(x, y, 4, 0, 0xffff, uint16_t);
582 case BC_YUVA16161616:
583 DRAW_PIXEL(x, y, 4, 1, 0xffff, uint16_t);
589 void MotionMain::draw_line(VFrame *frame, int x1, int y1, int x2, int y2)
591 int w = labs(x2 - x1);
592 int h = labs(y2 - y1);
593 //printf("MotionMain::draw_line %d %d %d %d\n", x1, y1, x2, y2);
597 draw_pixel(frame, x1, y1);
602 // Flip coordinates so x1 < x2
612 int numerator = y2 - y1;
613 int denominator = x2 - x1;
614 for(int i = x1; i < x2; i++)
616 int y = y1 + (i - x1) * numerator / denominator;
617 draw_pixel(frame, i, y);
622 // Flip coordinates so y1 < y2
632 int numerator = x2 - x1;
633 int denominator = y2 - y1;
634 for(int i = y1; i < y2; i++)
636 int x = x1 + (i - y1) * numerator / denominator;
637 draw_pixel(frame, x, i);
642 int MotionMain::process_realtime(VFrame **input_ptr, VFrame **output_ptr)
644 int need_reconfigure = load_configuration();
645 int bottom_layer = PluginClient::total_in_buffers - 1;
646 current_frame = input_ptr[bottom_layer];
647 int w = current_frame->get_w();
648 int h = current_frame->get_h();
649 int color_model = current_frame->get_color_model();
650 int skip_current = 0;
651 VFrame *input = input_ptr[0];
652 VFrame *output = output_ptr[0];
654 printf("MotionMain::process_realtime 1\n");
657 temp_frame = new VFrame(0,
660 input->get_color_model());
663 if(!engine) engine = new MotionEngine(this,
664 PluginClient::get_project_smp() + 1,
665 PluginClient::get_project_smp() + 1);
667 if(need_reconfigure) skip_current = 1;
670 prev_frame = new VFrame(0, w, h, color_model);
674 int new_total = (w / config.block_size) * (h / config.block_size);
675 if(total_macroblocks != new_total)
677 delete [] macroblocks;
683 total_macroblocks = new_total;
684 macroblocks = new macroblock_t[total_macroblocks];
686 bzero(macroblocks, sizeof(macroblock_t) * total_macroblocks);
687 int per_row = w / config.block_size;
688 for(int i = 0; i < total_macroblocks; i++)
690 macroblock_t *macroblock = ¯oblocks[i];
691 macroblock->x = config.block_size * (i % per_row);
692 macroblock->y = config.block_size * (i / per_row);
699 prev_frame->copy_from(input_ptr[PluginClient::total_in_buffers - 1]);
700 for(int i = 0; i < PluginClient::total_in_buffers; i++)
702 if(!output_ptr[i]->equals(input_ptr[i]))
703 output_ptr[i]->copy_from(input_ptr[i]);
708 // Create oversampled buffers
709 int new_search_size = current_frame->get_w() *
711 current_frame->get_h() *
713 if(new_search_size != search_size && search_area)
715 delete [] search_area;
721 search_area = new int32_t[new_search_size];
722 search_size = new_search_size;
725 MotionMain::oversample(search_area,
728 current_frame->get_w(),
730 current_frame->get_h(),
731 current_frame->get_w() * OVERSAMPLE);
733 // Get the motion vectors
734 //printf("MotionMain::process_realtime 1\n");
735 engine->set_package_count(total_macroblocks);
736 //printf("MotionMain::process_realtime 1\n");
737 engine->process_packages();
738 //printf("MotionMain::process_realtime 1\n");
740 // Put the current frame in the temporary for the next run
741 prev_frame->copy_from(current_frame);
743 //printf("MotionMain::process_realtime 1\n");
744 // Get average of all motion vectors
748 for(int i = 0; i < total_macroblocks; i++)
750 if(macroblocks[i].valid)
752 avg_dy += macroblocks[i].dy_oversampled;
753 avg_dx += macroblocks[i].dx_oversampled;
758 //printf("MotionMain::process_realtime 1 %d %d %d\n", avg_dx, avg_dy, total_valid);
761 avg_dx /= total_valid;
762 avg_dy /= total_valid;
765 if(!overlayer) overlayer = new OverlayFrame(
766 PluginClient::get_project_smp() + 1);
767 if(config.mode == MotionConfig::TRACK)
769 // Match top layer to bottom layer's motion
770 current_dx += avg_dx;
771 current_dy += avg_dy;
773 // Clamp to absolute limit
774 CLAMP(current_dx, -config.magnitude * OVERSAMPLE, config.magnitude * OVERSAMPLE);
775 CLAMP(current_dy, -config.magnitude * OVERSAMPLE, config.magnitude * OVERSAMPLE);
777 // Translate top layer
778 temp_frame->copy_from(input);
779 overlayer->overlay(output,
785 (float)current_dx / OVERSAMPLE,
786 (float)current_dy / OVERSAMPLE,
787 output->get_w() + (float)current_dx / OVERSAMPLE,
788 output->get_h() + (float)current_dy / OVERSAMPLE,
792 printf("MotionMain::process_realtime 10 %d %d\n", current_dx, current_dy);
795 if(config.mode == MotionConfig::STABILIZE)
797 // Move top layer opposite to bottom layer's motion
798 current_dx -= avg_dx;
799 current_dy -= avg_dy;
801 // Clamp to absolute limit
802 CLAMP(current_dx, -config.magnitude * OVERSAMPLE, config.magnitude * OVERSAMPLE);
803 CLAMP(current_dy, -config.magnitude * OVERSAMPLE, config.magnitude * OVERSAMPLE);
804 printf("MotionMain::process_realtime 100 %d %d %d %d\n", avg_dx, avg_dy, current_dx, current_dy);
806 // for(int i = 0; i < output->get_h(); i++)
808 // for(int j = 0; j < output->get_w(); j++)
810 // output->get_rows()[i][j * 3] = search_area[(i * 4) * w * OVERSAMPLE + j * 4] >> 4;
811 // output->get_rows()[i][j * 3 + 1] = search_area[(i * 4) * w * OVERSAMPLE + j * 4] >> 4;
812 // output->get_rows()[i][j * 3 + 2] = search_area[(i * 4) * w * OVERSAMPLE + j * 4] >> 4;
816 // Translate top layer
817 temp_frame->copy_from(input);
818 overlayer->overlay(output,
824 (float)current_dx / OVERSAMPLE,
825 (float)current_dy / OVERSAMPLE,
826 output->get_w() + (float)current_dx / OVERSAMPLE,
827 output->get_h() + (float)current_dy / OVERSAMPLE,
833 if(config.mode == MotionConfig::DRAW_VECTORS)
835 if(!output->equals(input))
836 output->copy_from(input);
837 printf("MotionMain::process_realtime 110 %d %d %d %d\n", avg_dx, avg_dy, current_dx, current_dy);
838 for(int i = 0; i < total_macroblocks; i++)
840 if(macroblocks[i].valid)
842 int x1 = macroblocks[i].x + config.block_size / 2;
843 int y1 = macroblocks[i].y + config.block_size / 2;
844 int x2 = x1 + macroblocks[i].dx_oversampled / OVERSAMPLE;
845 int y2 = y1 + macroblocks[i].dy_oversampled / OVERSAMPLE;
846 //printf("MotionMain::process_realtime 10 %d %d %d %d\n", x1, y1, x2, y2);
871 MotionPackage::MotionPackage()
879 MotionUnit::MotionUnit(MotionEngine *server,
883 this->plugin = plugin;
884 this->server = server;
888 scan_result_size = 0;
891 MotionUnit::~MotionUnit()
893 if(block_area) delete [] block_area;
894 if(scan_result) delete [] scan_result;
899 int64_t MotionUnit::abs_diff(int32_t *search_pixel,
900 int32_t *block_pixel,
905 for(int i = 0; i < block_side; i++)
907 for(int j = 0; j < block_side; j++)
910 difference = search_pixel[j] - block_pixel[j];
912 result -= difference;
914 result += difference;
916 search_pixel += search_side;
917 block_pixel += block_side;
922 void MotionUnit::process_package(LoadPackage *package)
924 MotionPackage *pkg = (MotionPackage*)package;
925 macroblock_t *macroblock = pkg->macroblock;
926 int w = plugin->current_frame->get_w();
927 int h = plugin->current_frame->get_h();
928 int search_w = plugin->config.search_radius * 2;
929 int search_h = plugin->config.search_radius * 2;
930 int block_w = plugin->config.block_size;
931 int block_h = plugin->config.block_size;
932 int new_block_size = block_w * OVERSAMPLE * block_h * OVERSAMPLE;
935 if(new_block_size != block_size && block_area)
937 delete [] block_area;
943 block_area = new int32_t[new_block_size];
944 block_size = new_block_size;
947 int new_result_size = search_w * OVERSAMPLE * search_h * OVERSAMPLE;
948 if(new_result_size != scan_result_size && scan_result)
950 delete [] scan_result;
955 scan_result = new int64_t[new_result_size];
956 scan_result_size = new_result_size;
959 for(int i = 0; i < scan_result_size; i++)
962 // Get coordinates in current frame for search data
963 int search_x1 = macroblock->x +
964 plugin->config.block_size / 2 -
965 plugin->config.search_radius;
966 int search_x2 = search_x1 +
968 plugin->config.block_size;
969 int search_y1 = macroblock->y +
970 plugin->config.block_size / 2 -
971 plugin->config.search_radius;
972 int search_y2 = search_y1 +
974 plugin->config.block_size;
975 search_x1 = MAX(search_x1, 0);
976 search_x2 = MIN(search_x2, w);
977 search_y1 = MAX(search_y1, 0);
978 search_y2 = MIN(search_y2, h);
979 int search_w_oversampled = (search_x2 - search_x1) * OVERSAMPLE;
980 int search_h_oversampled = (search_y2 - search_y1) * OVERSAMPLE;
981 int block_side_oversampled = plugin->config.block_size * OVERSAMPLE;
982 //printf("MotionUnit::process_package 1\n");
984 // Transfer images to temporaries with oversampling
986 MotionMain::oversample(block_area,
989 macroblock->x + plugin->config.block_size,
991 macroblock->y + plugin->config.block_size,
992 block_side_oversampled);
995 int64_t least_difference = -1;
996 int64_t most_difference = -1;
997 int least_x = (macroblock->x - search_x1) * OVERSAMPLE;
998 int least_y = (macroblock->y - search_y1) * OVERSAMPLE;
1003 // Zigzag motion estimation in the oversampled area.
1005 for(int i = 0; i < search_h_oversampled - block_side_oversampled; i++)
1007 for(int j = 0; j < search_w_oversampled - block_side_oversampled; j++)
1009 int32_t *search_pixel = search_area +
1010 i * search_w_oversampled +
1012 int32_t *block_pixel = block_area;
1013 int64_t current_difference = abs_diff(search_pixel,
1015 search_w_oversampled,
1016 block_side_oversampled);
1017 if(least_difference < 0 || current_difference < least_difference)
1019 //printf("MotionUnit::process_package %lld %d %d\n", current_difference, j, i);
1020 least_difference = current_difference;
1029 // Log motion estimation in the oversampled area
1030 // Get motion estimation range
1031 int scan_x1 = search_x1 * OVERSAMPLE;
1032 int scan_x2 = search_x2 * OVERSAMPLE - block_side_oversampled;
1033 int scan_y1 = search_y1 * OVERSAMPLE;
1034 int scan_y2 = search_y2 * OVERSAMPLE - block_side_oversampled;
1035 #define INIT_SCAN_STEPS 4
1036 int scan_step_x = block_side_oversampled / INIT_SCAN_STEPS;
1037 int scan_step_y = block_side_oversampled / INIT_SCAN_STEPS;
1038 if(scan_step_x > (scan_x2 - scan_x1) / INIT_SCAN_STEPS) scan_step_x = (scan_x2 - scan_x1) / INIT_SCAN_STEPS;
1039 if(scan_step_y > (scan_y2 - scan_y1) / INIT_SCAN_STEPS) scan_step_y = (scan_y2 - scan_y1) / INIT_SCAN_STEPS;
1040 scan_step_x = MAX(1, scan_step_x);
1041 scan_step_y = MAX(1, scan_step_y);
1043 // Do original position first
1044 int i = macroblock->y * OVERSAMPLE;
1045 int j = macroblock->x * OVERSAMPLE;
1046 int32_t *search_pixel = plugin->search_area +
1047 i * OVERSAMPLE * w +
1049 // Top left of macroblock
1050 int64_t *scan_result_ptr = &scan_result[(i - search_y1 * OVERSAMPLE) * search_w * OVERSAMPLE + j - search_x1 * OVERSAMPLE];
1051 int32_t *block_pixel = block_area;
1052 int64_t current_difference;
1053 least_difference = current_difference = *scan_result_ptr =
1054 abs_diff(search_pixel,
1057 block_side_oversampled);
1062 // Scan logarithmically
1066 //printf("MotionUnit::process_package 20 %d %d\n", scan_step_x, scan_step_y);
1067 // Scan top to bottom
1068 for(int i = scan_y1; i < scan_y2; i += scan_step_y)
1070 // Scan left to right
1071 for(int j = scan_x1; j < scan_x2; j += scan_step_x)
1073 // printf("MotionUnit::process_package 10 %d %d %d %d\n",
1076 // search_w_oversampled - block_side_oversampled,
1077 // search_h_oversampled - block_side_oversampled);
1079 &scan_result[(i - search_y1 * OVERSAMPLE) * search_w * OVERSAMPLE + j - search_x1 * OVERSAMPLE];
1080 if(*scan_result_ptr >= 0)
1082 current_difference = *scan_result_ptr;
1086 // Top left of search area
1087 search_pixel = plugin->search_area +
1088 i * w * OVERSAMPLE +
1090 // Top left of macroblock
1091 block_pixel = block_area;
1092 current_difference = abs_diff(search_pixel,
1095 block_side_oversampled);
1096 *scan_result_ptr = current_difference;
1099 if(least_difference < 0 || current_difference < least_difference)
1101 // printf("%d, %d %lld\n",
1102 // j - macroblock->x * OVERSAMPLE,
1103 // i - macroblock->y * OVERSAMPLE,
1104 // current_difference);
1105 least_difference = current_difference;
1110 if(most_difference < 0 || current_difference > most_difference)
1111 most_difference = current_difference;
1115 if(scan_step_x == 1 && scan_step_y == 1) break;
1119 scan_step_x = MAX(scan_step_x, 1);
1120 scan_step_y = MAX(scan_step_y, 1);
1122 // Reduce scan range around hot zone
1123 int new_x_range = (scan_x2 - scan_x1) >> 1;
1124 int new_y_range = (scan_y2 - scan_y1) >> 1;
1126 new_x_range = MAX(new_x_range, 1);
1127 new_y_range = MAX(new_y_range, 1);
1128 scan_x1 = least_x - new_x_range / 2;
1129 scan_x2 = scan_x1 + new_x_range;
1130 scan_y1 = least_y - new_y_range / 2;
1131 scan_y2 = scan_y1 + new_y_range;
1132 CLAMP(scan_x1, search_x1 * OVERSAMPLE, search_x2 * OVERSAMPLE - block_side_oversampled);
1133 CLAMP(scan_y1, search_y1 * OVERSAMPLE, search_y2 * OVERSAMPLE - block_side_oversampled);
1134 CLAMP(scan_x2, search_x1 * OVERSAMPLE, search_x2 * OVERSAMPLE - block_side_oversampled);
1135 CLAMP(scan_y2, search_y1 * OVERSAMPLE, search_y2 * OVERSAMPLE - block_side_oversampled);
1137 //printf("MotionUnit::process_package 50\n");
1140 if(least_difference < most_difference / 4 &&
1141 most_difference > block_side_oversampled * block_side_oversampled)
1143 macroblock->dx_oversampled =
1145 macroblock->x * OVERSAMPLE;
1146 macroblock->dy_oversampled =
1148 macroblock->y * OVERSAMPLE;
1149 macroblock->valid = 1;
1153 macroblock->dx_oversampled = 0;
1154 macroblock->dy_oversampled = 0;
1156 // printf("MotionUnit::process_package 100 %lld %lld %d %d %d %d\n",
1157 // least_difference,
1171 MotionEngine::MotionEngine(MotionMain *plugin,
1176 total_clients, total_packages
1179 this->plugin = plugin;
1182 void MotionEngine::init_packages()
1184 for(int i = 0; i < get_total_packages(); i++)
1186 MotionPackage *package = (MotionPackage*)get_package(i);
1187 package->macroblock = &plugin->macroblocks[i];
1191 LoadClient* MotionEngine::new_client()
1193 return new MotionUnit(this, plugin);
1196 LoadPackage* MotionEngine::new_package()
1198 return new MotionPackage;