root/modules/motion_detector.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. time_counter_capture
  2. action_stack_AS_MOTION_DETECTOR
  3. md_kbd_sched_immediate_shoot
  4. clip
  5. md_close_motion_detector
  6. md_save_calls_history
  7. mx_dump_memory
  8. md_running
  9. md_measure_y
  10. md_measure_u
  11. md_measure_v
  12. md_measure_r
  13. md_measure_g
  14. md_measure_b
  15. md_detect_motion
  16. md_get_cell_val
  17. md_get_cell_diff
  18. md_draw_grid
  19. _module_unloader
  20. _module_can_unload

   1 /*
   2 
   3 Motion detection module
   4 
   5 Author: mx3 (Max Sagaydachny) . win1251 ( Максим Сагайдачный )
   6 Email: win.drivers@gmail.com
   7 Skype: max_dtc
   8 ICQ#: 125-985-663
   9 Country: Ukraine
  10 Sity: Kharkiv
  11 
  12 20070912 mx3: first version
  13 
  14 20070918 mx3: speed optimization,
  15 
  16 20101201 CHDKLover: speed optimization
  17 
  18 20160710 62ndidiot: prelim digic 6 mods for test
  19                     need vid_get_viewport_byte_width() properly defined in lib.c to
  20                     override the non-digic 6 one in generic/wrappers.c
  21                     so correct width for 640x480 lcd in digic6 is 1280 bytes not 1080...
  22 20170207 62ndidiot: fix RGB calculation for Digic6
  23 
  24 */
  25 
  26 #ifdef OPT_MD_DEBUG
  27 #define MD_REC_CALLS_CNT 2048
  28 #define MD_INFO_BUF_SIZE 4096
  29 #endif
  30 
  31 #include "camera_info.h"
  32 #include "action_stack.h"
  33 #include "console.h"
  34 #include "keyboard.h"
  35 #include "clock.h"
  36 #include "viewport.h"
  37 #include "debug_led.h"
  38 #include "gui.h"
  39 #include "gui_draw.h"
  40 #include "script_api.h"
  41 #include "script.h"
  42 
  43 #include "motion_detector.h"
  44 #include "module_def.h"
  45 #include "gui_lang.h"
  46 
  47 // Forward references
  48 static int md_detect_motion(void);
  49 
  50 #define MD_XY2IDX(x,y) ((y)*motion_detector.columns+(x))
  51 
  52 enum
  53 {
  54     MD_MEASURE_MODE_U=0,
  55     MD_MEASURE_MODE_Y=1,
  56     MD_MEASURE_MODE_V=2,
  57     MD_MEASURE_MODE_R=3,
  58     MD_MEASURE_MODE_G=4,
  59     MD_MEASURE_MODE_B=5
  60 };
  61 
  62 // Bit values for motion_detector.parameters
  63 enum
  64 {
  65     MD_DO_IMMEDIATE_SHOOT=1,
  66     MD_MAKE_DEBUG_LOG_FILE=2,
  67     MD_MAKE_RAM_DUMP_FILE=4,
  68     MD_NO_SHUTTER_RELEASE_ON_SHOOT=8
  69 };
  70 
  71 enum
  72 {
  73     MD_REGION_NONE=0,
  74     MD_REGION_INCLUDE=1,
  75     MD_REGION_EXCLUDE=2
  76 };
  77 
  78 #define MOTION_DETECTOR_CELLS 1024
  79 
  80 struct motion_detector_s
  81 {
  82     int prev[MOTION_DETECTOR_CELLS];
  83     unsigned char diff[MOTION_DETECTOR_CELLS];
  84 
  85     int columns;
  86     int rows;
  87     int threshold;
  88     int pixel_measure_mode;
  89     int timeout;
  90     int measure_interval;
  91 
  92     int last_measure_time;
  93     int start_time;
  94 
  95     int running;
  96     int detected_cells;
  97 
  98     int draw_grid;
  99     int clipping_region_mode;
 100     int clipping_region_row1;
 101     int clipping_region_column1;
 102     int clipping_region_row2;
 103     int clipping_region_column2;
 104 
 105     int previous_picture_is_ready;
 106 
 107     int return_value;
 108     int parameters;
 109     int pixels_step;
 110     int msecs_before_trigger;
 111 
 112     int points;
 113 
 114     // debug
 115 #ifdef OPT_MD_DEBUG
 116     int comp_calls_cnt;
 117     int comp_calls[MD_REC_CALLS_CNT];
 118 #endif
 119 };
 120 
 121 static struct motion_detector_s motion_detector;
 122 
 123 static void time_counter_capture(time_counter *t)
 124 {
 125     t->last = get_tick_count() - t->tick_count;
 126     if (t->last < t->min)
 127         t->min = t->last;
 128     if (t->last > t->max)
 129         t->max = t->last;
 130     t->sum += t->last;
 131     t->count++;
 132 }
 133 
 134 // Stack process function for running MD logic
 135 static int action_stack_AS_MOTION_DETECTOR()
 136 {
 137     // MD testing with AF LED
 138     if (camera_info.perf.md_af_tuning)
 139     {
 140         if (camera_info.perf.af_led_on == 0)
 141         {
 142             camera_info.perf.af_led_on--;
 143             camera_info.perf.af_led.tick_count = get_tick_count();
 144             camera_set_led(camera_info.cam_af_led,1,200);
 145         }
 146         else if (camera_info.perf.af_led_on > 0)
 147         {
 148             camera_info.perf.af_led_on--;
 149         }
 150     }
 151 
 152     if (md_detect_motion() == 0)
 153     {
 154         if (motion_detector.return_value)
 155         {
 156             camera_info.perf.md_detect_tick = get_tick_count();
 157         }
 158 
 159         // MD testing with AF LED
 160         if (camera_info.perf.md_af_tuning)
 161         {
 162             camera_set_led(camera_info.cam_af_led,0,0);
 163             if (motion_detector.return_value)
 164             {
 165                 time_counter_capture(&camera_info.perf.af_led);
 166             }
 167         }
 168 
 169         // We need to recover the motion detector's
 170         // result and push it onto the thread's stack.
 171         libscriptapi->set_as_ret(motion_detector.return_value);
 172 
 173         action_pop_func(0);
 174         return 1;
 175     }
 176     return 0;
 177 }
 178 
 179 static void md_kbd_sched_immediate_shoot(int no_release)
 180 {
 181     action_pop_func(0);// REMOVE MD ITEM
 182 
 183     // stack operations are reversed!
 184     if (!no_release)  // only release shutter if allowed
 185     {
 186         action_push_release(KEY_SHOOT_FULL);
 187     }
 188     if (camera_info.cam_key_press_delay > 0)
 189         action_push_delay(camera_info.cam_key_press_delay);
 190     action_push_func(action_stack_AS_MOTION_DETECTOR); // it will removed right after exit from this function
 191     kbd_key_press(KEY_SHOOT_FULL); // not a stack operation... pressing right now
 192 
 193     // MD testing with AF LED
 194     if (camera_info.perf.md_af_tuning)
 195     {
 196         camera_info.perf.md_af_on_flag = 1;
 197     }
 198 }
 199 
 200 static int clip(int v)
 201 {
 202     if (v<0) return 0;
 203     if (v>255) return 255;
 204     return v;
 205 }
 206 
 207 // TODO add script interface, currently done when script ends
 208 void md_close_motion_detector()
 209 {
 210 }
 211 
 212 int md_init_motion_detector
 213 (
 214  int columns,
 215  int rows,
 216  int pixel_measure_mode,
 217  int detection_timeout,
 218  int measure_interval,
 219  int threshold,
 220  int draw_grid,
 221  int clipping_region_mode,
 222  int clipping_region_column1,
 223  int clipping_region_row1,
 224  int clipping_region_column2,
 225  int clipping_region_row2,
 226  int parameters,
 227  int pixels_step,
 228  int msecs_before_trigger
 229 )
 230 {
 231 #ifdef OPT_MD_DEBUG
 232     motion_detector.comp_calls_cnt=0;
 233 #endif
 234 
 235     if(     pixel_measure_mode != MD_MEASURE_MODE_Y
 236         &&  pixel_measure_mode != MD_MEASURE_MODE_U
 237         &&  pixel_measure_mode != MD_MEASURE_MODE_V
 238         &&  pixel_measure_mode != MD_MEASURE_MODE_R
 239         &&  pixel_measure_mode != MD_MEASURE_MODE_G
 240         &&  pixel_measure_mode != MD_MEASURE_MODE_B
 241         )
 242     {
 243         pixel_measure_mode = MD_MEASURE_MODE_Y;
 244     }
 245 
 246     // Sanity check on grid size
 247     if (columns < 1) columns = 3;
 248     if (rows < 1) rows = 3;
 249     // If too many grid cells, reduce larger of columns and rows until it fits
 250     while ((columns * rows) > MOTION_DETECTOR_CELLS)
 251     {
 252         if (columns > rows) columns--;
 253         else rows--;
 254     }
 255 
 256     if(msecs_before_trigger<0)
 257     {
 258         msecs_before_trigger=0;
 259     }
 260 
 261     if (pixels_step<1)
 262     {
 263         pixels_step=1;
 264     }
 265 #ifdef THUMB_FW
 266     if (((pixel_measure_mode == MD_MEASURE_MODE_U) || (pixel_measure_mode == MD_MEASURE_MODE_V)) && (pixels_step < 2))
 267     {
 268         pixels_step = 2;    //uv is sampled every 4 bytes in X, prevent double counting
 269     }
 270 #endif
 271 
 272     if(detection_timeout<0)
 273     {
 274         detection_timeout=0;
 275     }
 276 
 277     if(measure_interval<0)
 278     {
 279         measure_interval=0;
 280     }
 281 
 282     if(threshold<0)
 283     {
 284         threshold=0;
 285     }
 286 
 287     motion_detector.msecs_before_trigger = msecs_before_trigger;
 288     motion_detector.parameters = parameters;
 289     motion_detector.pixels_step = pixels_step;
 290     motion_detector.columns = columns;
 291     motion_detector.rows = rows;
 292     motion_detector.return_value = 0;
 293 
 294     motion_detector.pixel_measure_mode = pixel_measure_mode;
 295     motion_detector.timeout = detection_timeout;
 296     motion_detector.measure_interval = measure_interval;
 297     motion_detector.threshold = threshold;
 298     motion_detector.draw_grid = draw_grid;
 299 
 300     if (clipping_region_column1>clipping_region_column2)
 301     {
 302         motion_detector.clipping_region_column2 = clipping_region_column1;
 303         motion_detector.clipping_region_column1 = clipping_region_column2;
 304     }
 305     else
 306     {
 307         motion_detector.clipping_region_column2 = clipping_region_column2;
 308         motion_detector.clipping_region_column1 = clipping_region_column1;
 309     }
 310 
 311     if (clipping_region_row1>clipping_region_row2)
 312     {
 313         motion_detector.clipping_region_row2 = clipping_region_row1;
 314         motion_detector.clipping_region_row1 = clipping_region_row2;
 315     }
 316     else
 317     {
 318         motion_detector.clipping_region_row2 = clipping_region_row2;
 319         motion_detector.clipping_region_row1 = clipping_region_row1;
 320     }
 321 
 322     if (clipping_region_mode!=MD_REGION_NONE && clipping_region_mode!=MD_REGION_INCLUDE && clipping_region_mode!=MD_REGION_EXCLUDE)
 323     {
 324         clipping_region_mode=MD_REGION_NONE;
 325     }
 326     motion_detector.clipping_region_mode = clipping_region_mode;
 327 
 328     motion_detector.detected_cells = 0;
 329     motion_detector.previous_picture_is_ready = 0;
 330     motion_detector.start_time=get_tick_count();
 331 
 332     motion_detector.last_measure_time = motion_detector.start_time - motion_detector.measure_interval;
 333 
 334     motion_detector.running = 1;
 335 
 336     camera_info.perf.af_led_on = 100;
 337     action_push_func(action_stack_AS_MOTION_DETECTOR);
 338     gui_set_need_restore();
 339 
 340     return 1;
 341 }
 342 
 343 #ifdef OPT_MD_DEBUG
 344 
 345 static void md_save_calls_history(){
 346     char buf[200], fn[30];
 347     char big[MD_INFO_BUF_SIZE];
 348     int big_ln;
 349     int calls,i, ln, fd;
 350     static struct utimbuf t;
 351     static struct tm *ttm;
 352 
 353 
 354     if( (motion_detector.parameters & MD_MAKE_DEBUG_LOG_FILE) == 0 ){
 355         return;
 356     }
 357 
 358 
 359     strcpy(fn,"A/MD_INFO.TXT");//,BUILD_NUMBER,motion_detector.pixels_step);
 360     fd = open(fn, O_WRONLY|O_CREAT, 0777);
 361     if( fd>=0) {
 362         console_add_line("Writing info file...");
 363         lseek(fd,0,SEEK_END);
 364         ttm = get_localtime();
 365         big_ln=sprintf(big,
 366                 "\r\n--- %04u-%02u-%02u  %02u:%02u:%02u\r\n"
 367                 "CHDK Ver: %s [ #%s ]\r\nBuild Date: %s %s\r\nCamera:  %s [ %s ]\r\n"
 368                 "[%dx%d], threshold: %d, interval: %d, pixels step: %d\r\n"
 369                 "region: [%d,%d-%d,%d], region type: %d\r\n"
 370                 "wait interval: %d, parameters: %d, calls: %d, detected cells: %d\r\n",
 371                 1900+ttm->tm_year, ttm->tm_mon+1, ttm->tm_mday, ttm->tm_hour, ttm->tm_min, ttm->tm_sec,
 372                 camera_info.chdk_ver, camera_info.build_number, camera_info.build_date, camera_info.build_time, camera_info.platform, camera_info.platformsub,
 373                 motion_detector.columns, motion_detector.rows, motion_detector.threshold, motion_detector.measure_interval, motion_detector.pixels_step,
 374                 motion_detector.clipping_region_column1, motion_detector.clipping_region_row1, motion_detector.clipping_region_column2, motion_detector.clipping_region_row2, motion_detector.clipping_region_mode,
 375                 motion_detector.msecs_before_trigger, motion_detector.parameters, motion_detector.comp_calls_cnt,
 376                 motion_detector.detected_cells
 377         );
 378 
 379         calls = ( motion_detector.comp_calls_cnt < MD_REC_CALLS_CNT) ?motion_detector.comp_calls_cnt: MD_REC_CALLS_CNT;
 380 
 381         for(i=0;i<calls;i++){
 382             ln=sprintf(buf,"[%d] - %d\r\n",i,motion_detector.comp_calls[i]);
 383             if(big_ln+ln>MD_INFO_BUF_SIZE){
 384           write(fd,big,big_ln);
 385                 big_ln=0;
 386             }
 387             memcpy(big+big_ln,buf,ln+1);
 388             big_ln+=ln;
 389         }
 390     write(fd,big,big_ln);
 391         close(fd);
 392       t.actime = t.modtime = time(NULL);
 393     utime(fn, &t);
 394     }
 395 }
 396 
 397 static void mx_dump_memory(void *img)
 398 {
 399     char fn[36];
 400     int fd, i;
 401     static int cnt=0;
 402 
 403     started();
 404     mkdir("A/MD");
 405 
 406     do
 407     {
 408         cnt++;
 409         sprintf(fn, "A/MD/%04d.FB", cnt);
 410         fd = open(fn, O_RDONLY, 0777);
 411 
 412         if(fd>=0)
 413         {
 414             close(fd);
 415         }
 416     } while(fd>=0);
 417 
 418     sprintf(fn, "A/MD/%04d.FB", cnt );
 419     fd = open(fn, O_WRONLY|O_CREAT, 0777);
 420     if (fd>=0)
 421     {
 422         write(fd, img, vid_get_viewport_byte_width()*vid_get_viewport_height_proper());
 423         close(fd);
 424     }
 425     vid_bitmap_refresh();
 426     finished();
 427 }
 428 
 429 #else
 430 #define md_save_calls_history()
 431 #define mx_dump_memory(x)
 432 #endif
 433 
 434 
 435 static int md_running()
 436 {
 437     return motion_detector.running;
 438 }
 439 
 440 // Shared variable for the measure functions
 441 static unsigned char* img;
 442 static int x_start, x_end, x_step;
 443 static int y_start, y_end, y_step;
 444 
 445 // Pre Digic6:
 446 //      ARRAY of UYVYYY values
 447 //      6 bytes - 4 pixels
 448 // Digic6:
 449 //      ARRAY of UYVY values
 450 //      4 bytes - 2 pixels
 451 
 452 // Pre Digic6: U & V are signed char values (-128 - 127)
 453 //      R = Y + 1.402 * V + 0.5
 454 //      G = Y - 0.34414 * U - 0.71414 * V + 0.5
 455 //      B = Y + 1.772 * V + 0.5
 456 // Digi6: U & V are unsigned (0 - 255) subtract 128 to get signed value
 457 //      R = Y + 1.402 * (V-128) + 0.5
 458 //      G = Y - 0.34414 * (U-128) - 0.71414 * (V-128) + 0.5
 459 //      B = Y + 1.772 * (V-128) + 0.5
 460 
 461 // Functions for inner loops for each measure mode
 462 
 463 static int md_measure_y()
 464 {
 465     register int x, y;
 466     register int curr = 0;
 467 
 468     for (y=y_start; y<y_end; y+=y_step)
 469     {
 470         for (x=x_start; x<x_end; x+=x_step)
 471         {
 472             curr += img[y + x + 1];  //Y always 2nd byte in each block
 473         }
 474     }
 475 
 476     return curr;
 477 }
 478 
 479 static int md_measure_u()
 480 {
 481     register int x, y, uvx;
 482     register int curr = 0;
 483 
 484     for (y=y_start; y<y_end; y+=y_step)
 485     {
 486         for (x=x_start; x<x_end; x+=x_step)
 487         {
 488             // Calc offset to U & V components in uvx
 489 #ifdef THUMB_FW
 490             uvx = x & 0xFFFFFFFC;           // U is in 1st two bytes of each 4 byte block V is in 2nd two bytes
 491             curr += (int)img[y + uvx] - 128;    //U
 492 #else
 493             uvx = (x&1)?x-3:x;
 494             curr += (signed char)img[y + uvx];  //U
 495 #endif
 496         }
 497     }
 498 
 499     return curr;
 500 }
 501 
 502 static int md_measure_v()
 503 {
 504     register int x, y, uvx;
 505     register int curr = 0;
 506 
 507     for (y=y_start; y<y_end; y+=y_step)
 508     {
 509         for (x=x_start; x<x_end; x+=x_step)
 510         {
 511             // Calc offset to U & V components in uvx
 512 #ifdef THUMB_FW
 513             uvx = x & 0xFFFFFFFC;               // U is in 1st two bytes of each 4 byte block V is in 2nd two bytes
 514             curr += (int)img[y + uvx + 2] - 128;    //V
 515 #else
 516             uvx = (x&1)?x-3:x;
 517             curr += (signed char)img[y + uvx + 2];  //V
 518 #endif
 519         }
 520     }
 521 
 522     return curr;
 523 }
 524 
 525 static int md_measure_r()
 526 {
 527     register int x, y, uvx, cy, cv;
 528     register int curr = 0;
 529 
 530     for (y=y_start; y<y_end; y+=y_step)
 531     {
 532         for (x=x_start; x<x_end; x+=x_step)
 533         {
 534             cy = img[y + x + 1];
 535             // Calc offset to U & V components in uvx
 536 #ifdef THUMB_FW
 537             uvx = x & 0xFFFFFFFC;               // U is in 1st two bytes of each 4 byte block V is in 2nd two bytes
 538             cv = (int)img[y + uvx + 2] - 128;
 539 #else
 540             uvx = (x&1)?x-3:x;
 541             cv = (signed char)img[y + uvx + 2];
 542 #endif
 543             curr += clip(((cy<<12) + cv*5743 + 2048)>>12);      // R
 544         }
 545     }
 546 
 547     return curr;
 548 }
 549 
 550 static int md_measure_g()
 551 {
 552     register int x, y, uvx, cy, cu, cv;
 553     register int curr = 0;
 554 
 555     for (y=y_start; y<y_end; y+=y_step)
 556     {
 557         for (x=x_start; x<x_end; x+=x_step)
 558         {
 559             cy = img[y + x + 1];
 560             // Calc offset to U & V components in uvx
 561 #ifdef THUMB_FW
 562             uvx = x & 0xFFFFFFFC;               // U is in 1st two bytes of each 4 byte block V is in 2nd two bytes
 563             cu = (int)img[y + uvx] - 128;
 564             cv = (int)img[y + uvx + 2] - 128;
 565 #else
 566             uvx = (x&1)?x-3:x;
 567             cu = (signed char)img[y + uvx];
 568             cv = (signed char)img[y + uvx + 2];
 569 #endif
 570             curr += clip(((cy<<12) - cu*1411 - cv*2925 + 2048)>>12);    // G
 571         }
 572     }
 573 
 574     return curr;
 575 }
 576 
 577 static int md_measure_b()
 578 {
 579     register int x, y, uvx, cy, cu;
 580     register int curr = 0;
 581 
 582     for (y=y_start; y<y_end; y+=y_step)
 583     {
 584         for (x=x_start; x<x_end; x+=x_step)
 585         {
 586             cy = img[y + x + 1];
 587             // Calc offset to U & V components in uvx
 588 #ifdef THUMB_FW
 589             uvx = x & 0xFFFFFFFC;               // U is in 1st two bytes of each 4 byte block V is in 2nd two bytes
 590             cu = (int)img[y + uvx] - 128;
 591 #else
 592             uvx = (x&1)?x-3:x;
 593             cu = (signed char)img[y + uvx];
 594 #endif
 595             curr += clip(((cy<<12) + cu*7258 + 2048)>>12);      // B
 596         }
 597     }
 598 
 599     return curr;
 600 }
 601 
 602 static int md_detect_motion(void)
 603 {
 604     int idx, tick, rv;
 605 
 606     register int col, row;
 607 
 608     if(!md_running())
 609     {
 610         return 0;
 611     }
 612 
 613     tick = get_tick_count();
 614     rv = 1;
 615 
 616 #ifdef OPT_MD_DEBUG
 617     if(motion_detector.comp_calls_cnt < MD_REC_CALLS_CNT)
 618     {
 619         motion_detector.comp_calls[motion_detector.comp_calls_cnt]=tick;
 620     }
 621     motion_detector.comp_calls_cnt++;
 622 #endif
 623 
 624     if(motion_detector.start_time + motion_detector.timeout < tick )
 625     {
 626         md_save_calls_history();
 627         motion_detector.running = 0;
 628         return 0;
 629     }
 630 
 631     if(motion_detector.last_measure_time + motion_detector.measure_interval > tick)
 632     {
 633         // wait for the next time
 634         return 1;
 635     }
 636 
 637     motion_detector.last_measure_time = tick;
 638 
 639     img = vid_get_viewport_active_buffer();
 640     if (!img) return 0;
 641 
 642 #ifdef OPT_MD_DEBUG
 643     if(motion_detector.comp_calls_cnt==50 && (motion_detector.parameters & MD_MAKE_RAM_DUMP_FILE) != 0 )
 644     {
 645         mx_dump_memory((char*)img);
 646     }
 647 #endif
 648 
 649     motion_detector.detected_cells = 0;
 650 
 651     img += vid_get_viewport_image_offset();     // offset into viewport for when image size != viewport size (e.g. 16:9 image on 4:3 LCD)
 652 
 653     int vp_bw = vid_get_viewport_byte_width();
 654     int vp_h = vid_get_viewport_height_proper();
 655 
 656 #ifdef THUMB_FW
 657     int vp_w = vid_get_viewport_width_proper();
 658     x_step = motion_detector.pixels_step * 2;
 659     y_step = motion_detector.pixels_step * vp_bw;
 660 #else
 661     int vp_w = vid_get_viewport_width_proper() / 2; // Row width in 3 byte units (half UYVYYY block)
 662     x_step = motion_detector.pixels_step * 3;
 663     y_step = motion_detector.pixels_step * vp_bw * vid_get_viewport_yscale();
 664 #endif
 665 
 666     motion_detector.points = ((vp_w / motion_detector.columns + motion_detector.pixels_step - 1) / motion_detector.pixels_step) * ((vp_h / motion_detector.rows + motion_detector.pixels_step - 1) / motion_detector.pixels_step);
 667 
 668     for (idx=0, row=0; row < motion_detector.rows; row++)
 669     {
 670         // Calc img y start and end offsets (use same height for all cells so 'points' is consistent)
 671         y_start = ((row * vp_h) / motion_detector.rows) * vp_bw;
 672         y_end = y_start + ((vp_h / motion_detector.rows) * vp_bw);
 673 
 674         for (col=0; col < motion_detector.columns; col++, idx++)
 675         {
 676             int in_clipping_region=0;
 677 
 678             if (col+1 >= motion_detector.clipping_region_column1 &&
 679                 col+1 <= motion_detector.clipping_region_column2 &&
 680                 row+1 >= motion_detector.clipping_region_row1 &&
 681                 row+1 <= motion_detector.clipping_region_row2)
 682             {
 683                 in_clipping_region=1;
 684             }
 685 
 686             int curr = 0;
 687             int diff = 0;
 688 
 689             if (
 690                 (motion_detector.clipping_region_mode==MD_REGION_NONE) ||
 691                 (motion_detector.clipping_region_mode==MD_REGION_EXCLUDE && in_clipping_region==0) ||
 692                 (motion_detector.clipping_region_mode==MD_REGION_INCLUDE && in_clipping_region==1)
 693                )
 694             {
 695                 // Calc img x start and end offsets (use same width for all cells so 'points' is consistent)
 696 #ifdef THUMB_FW
 697                 x_start = ((col * vp_w) / motion_detector.columns) * 2;
 698                 x_end = x_start + ((vp_w / motion_detector.columns) * 2);
 699 #else
 700                 x_start = ((col * vp_w) / motion_detector.columns) * 3;
 701                 x_end = x_start + ((vp_w / motion_detector.columns) * 3);
 702 #endif
 703 
 704                 // Do mode check and call function to do inner loops for mode
 705                 // See comments above on mode calulations
 706                 switch (motion_detector.pixel_measure_mode)
 707                 {
 708                     case MD_MEASURE_MODE_Y:
 709                         curr += md_measure_y();
 710                         break;
 711                     case MD_MEASURE_MODE_U:
 712                         curr += md_measure_u();
 713                         break;
 714                     case MD_MEASURE_MODE_V:
 715                         curr += md_measure_v();
 716                         break;
 717                     case MD_MEASURE_MODE_R:
 718                         curr += md_measure_r();
 719                         break;
 720                     case MD_MEASURE_MODE_G:
 721                         curr += md_measure_g();
 722                         break;
 723                     case MD_MEASURE_MODE_B:
 724                         curr += md_measure_b();
 725                         break;
 726                 }
 727 
 728                 diff = (curr - motion_detector.prev[idx]) / motion_detector.points;
 729                 if (diff < 0) diff = -diff;
 730                 if ((diff > motion_detector.threshold) &&
 731                     (motion_detector.start_time+motion_detector.msecs_before_trigger < tick))
 732                 {
 733                     motion_detector.detected_cells++;
 734                 }
 735             }
 736 
 737             motion_detector.diff[idx] = diff;
 738             motion_detector.prev[idx] = curr;
 739         }
 740     }
 741 
 742     if (motion_detector.previous_picture_is_ready == 0)
 743     {
 744         motion_detector.previous_picture_is_ready = 1;
 745         motion_detector.start_time = get_tick_count();
 746         motion_detector.last_measure_time = motion_detector.start_time - motion_detector.measure_interval;
 747     }
 748     else if ( motion_detector.detected_cells > 0 )
 749     {
 750         if (motion_detector.start_time+motion_detector.msecs_before_trigger < tick)
 751         {
 752             motion_detector.running=0;
 753             motion_detector.return_value = motion_detector.detected_cells;
 754 
 755             if ((motion_detector.parameters&MD_DO_IMMEDIATE_SHOOT) != 0)
 756             {
 757                 //make shoot
 758                 md_kbd_sched_immediate_shoot(motion_detector.parameters&MD_NO_SHUTTER_RELEASE_ON_SHOOT);
 759             }
 760             rv = 0;
 761         }
 762     }
 763 
 764     return rv;
 765 }
 766 
 767 int md_get_cell_val(int column, int row)
 768 {
 769     if ((column<1 || column > motion_detector.columns) ||
 770         (row<1 || row > motion_detector.rows))
 771     {
 772         return 0;
 773     }
 774 
 775     return motion_detector.prev[ MD_XY2IDX(column-1,row-1) ]/motion_detector.points ;
 776 }
 777 
 778 int md_get_cell_diff(int column, int row)
 779 {
 780     if ((column<1 || column > motion_detector.columns) ||
 781         (row<1 || row > motion_detector.rows))
 782     {
 783         return 0;
 784     }
 785 
 786     return motion_detector.diff[ MD_XY2IDX(column-1,row-1) ];
 787 }
 788 
 789 void md_draw_grid()
 790 {
 791     int col, row;
 792     int i;
 793     char mdbuff[8];
 794 
 795     if (!md_running() || motion_detector.draw_grid==0 || camera_info.state.state_kbd_script_run==0)
 796     {
 797         return;
 798     }
 799 
 800     int xoffset = vid_get_viewport_display_xoffset();   // used when image size != viewport size
 801     int yoffset = vid_get_viewport_display_yoffset();   // used when image size != viewport size
 802 
 803     // display area size
 804     int x_size = camera_screen.width-xoffset * 2;
 805     int y_size = camera_screen.height-yoffset * 2;
 806 
 807     // initial display offsets
 808     int y_start, y_end = yoffset;
 809     int x_start, x_end;
 810 
 811     for (i=0, row=0; row < motion_detector.rows && camera_info.state.state_kbd_script_run; row++)
 812     {
 813         // Calc display start and end offsets
 814         y_start = y_end;    // reuse last end value as new start value
 815         y_end = yoffset + ((row + 1) * y_size) / motion_detector.rows;
 816 
 817         x_end = xoffset;
 818 
 819         for (col=0; col < motion_detector.columns; col++, i++)
 820         {
 821             // Calc display x start and end offsets
 822             x_start = x_end;    // reuse last end value as new start value
 823             x_end = xoffset + ((col + 1) * x_size) / motion_detector.columns;
 824 
 825             int in_clipping_region = 0;
 826             if ( col+1>=motion_detector.clipping_region_column1
 827                 && col+1<=motion_detector.clipping_region_column2
 828                 && row+1>=motion_detector.clipping_region_row1
 829                 && row+1<=motion_detector.clipping_region_row2
 830                 )
 831             {
 832                 in_clipping_region = 1;
 833             }
 834 
 835             if ((motion_detector.clipping_region_mode==MD_REGION_EXCLUDE && in_clipping_region==0) ||
 836                 (motion_detector.clipping_region_mode==MD_REGION_INCLUDE && in_clipping_region==1) ||
 837                 (motion_detector.clipping_region_mode==MD_REGION_NONE))
 838             {
 839                 int diff = motion_detector.diff[i];
 840 
 841                 twoColors c = MAKE_COLOR(COLOR_TRANSPARENT, COLOR_GREEN);
 842                 if (diff > motion_detector.threshold)
 843                 {
 844                     c = MAKE_COLOR(COLOR_TRANSPARENT, COLOR_RED);
 845                 }
 846 
 847                 if (motion_detector.draw_grid & 2)
 848                 {
 849                     sprintf(mdbuff,"%-3d", diff);
 850                     draw_string(x_start+4, y_start+2, mdbuff, c);
 851                 }
 852 
 853                 if (motion_detector.draw_grid & 1)
 854                 {
 855                     draw_rectangle(x_start+2, y_start+2, x_end-2, y_end-2, c, RECT_BORDER1);
 856                 }
 857             }
 858         }
 859     }
 860 }
 861 
 862 
 863 // =========  MODULE INIT =================
 864 
 865 /***************** BEGIN OF AUXILARY PART *********************
 866 ATTENTION: DO NOT REMOVE OR CHANGE SIGNATURES IN THIS SECTION
 867 **************************************************************/
 868 
 869 //---------------------------------------------------------
 870 // PURPOSE: Finalize module operations (close allocs, etc)
 871 // RETURN VALUE: 0-ok, 1-fail
 872 //---------------------------------------------------------
 873 int _module_unloader()
 874 {
 875     md_close_motion_detector();
 876     return 0;
 877 }
 878 
 879 int _module_can_unload()
 880 {
 881     return camera_info.state.state_kbd_script_run == SCRIPT_STATE_INACTIVE;
 882 }
 883 
 884 /******************** Module Information structure ******************/
 885 
 886 libmotiondetect_sym _libmotiondetect =
 887 {
 888     {
 889          0, _module_unloader, _module_can_unload, 0, 0
 890     },
 891 
 892     md_close_motion_detector,
 893     md_init_motion_detector,
 894     md_get_cell_diff,
 895     md_draw_grid,
 896     md_get_cell_val,
 897 };
 898 
 899 ModuleInfo _module_info =
 900 {
 901     MODULEINFO_V1_MAGICNUM,
 902     sizeof(ModuleInfo),
 903     MOTION_DETECTOR_VERSION,    // Module version
 904 
 905     ANY_CHDK_BRANCH, 0, OPT_ARCHITECTURE,           // Requirements of CHDK version
 906     ANY_PLATFORM_ALLOWED,       // Specify platform dependency
 907 
 908     -LANG_MODULE_MOTION_DETECT, // Module name
 909     MTYPE_EXTENSION,
 910 
 911     &_libmotiondetect.base,
 912 
 913     ANY_VERSION,                // CONF version
 914     CAM_SCREEN_VERSION,         // CAM SCREEN version
 915     ANY_VERSION,                // CAM SENSOR version
 916     CAM_INFO_VERSION,           // CAM INFO version
 917 };
 918 
 919 /*************** END OF AUXILARY PART *******************/

/* [<][>][^][v][top][bottom][index][help] */