This source file includes following definitions.
- time_counter_capture
- action_stack_AS_MOTION_DETECTOR
- md_kbd_sched_immediate_shoot
- clip
- md_close_motion_detector
- md_save_calls_history
- mx_dump_memory
- md_running
- md_measure_y
- md_measure_u
- md_measure_v
- md_measure_r
- md_measure_g
- md_measure_b
- md_detect_motion
- md_get_cell_val
- md_get_cell_diff
- md_draw_grid
- _module_unloader
- _module_can_unload
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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
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
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
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
135 static int action_stack_AS_MOTION_DETECTOR()
136 {
137
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
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
170
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);
182
183
184 if (!no_release)
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);
191 kbd_key_press(KEY_SHOOT_FULL);
192
193
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
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
247 if (columns < 1) columns = 3;
248 if (rows < 1) rows = 3;
249
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;
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");
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
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
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
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];
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
489 #ifdef THUMB_FW
490 uvx = x & 0xFFFFFFFC;
491 curr += (int)img[y + uvx] - 128;
492 #else
493 uvx = (x&1)?x-3:x;
494 curr += (signed char)img[y + uvx];
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
512 #ifdef THUMB_FW
513 uvx = x & 0xFFFFFFFC;
514 curr += (int)img[y + uvx + 2] - 128;
515 #else
516 uvx = (x&1)?x-3:x;
517 curr += (signed char)img[y + uvx + 2];
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
536 #ifdef THUMB_FW
537 uvx = x & 0xFFFFFFFC;
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);
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
561 #ifdef THUMB_FW
562 uvx = x & 0xFFFFFFFC;
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);
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
588 #ifdef THUMB_FW
589 uvx = x & 0xFFFFFFFC;
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);
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
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();
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;
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
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
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
705
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
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();
801 int yoffset = vid_get_viewport_display_yoffset();
802
803
804 int x_size = camera_screen.width-xoffset * 2;
805 int y_size = camera_screen.height-yoffset * 2;
806
807
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
814 y_start = y_end;
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
822 x_start = x_end;
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
864
865
866
867
868
869
870
871
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
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,
904
905 ANY_CHDK_BRANCH, 0, OPT_ARCHITECTURE,
906 ANY_PLATFORM_ALLOWED,
907
908 -LANG_MODULE_MOTION_DETECT,
909 MTYPE_EXTENSION,
910
911 &_libmotiondetect.base,
912
913 ANY_VERSION,
914 CAM_SCREEN_VERSION,
915 ANY_VERSION,
916 CAM_INFO_VERSION,
917
918 0,
919 };
920
921