1 /*
2 * (c) 1998-2002 Gerd Knorr
3 *
4 * capture a image, compress as jpeg and upload to the webserver
5 * using the ftp utility or ssh
6 *
7 */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
13 #include <errno.h>
14 #include <fcntl.h>
15 #include <limits.h>
16 #include <pthread.h>
17 #include <math.h>
18 #include <sys/time.h>
19 #include <sys/mman.h>
20 #include <sys/ioctl.h>
21 #include <sys/stat.h>
22
23 #include "grab-ng.h"
24 #include "jpeglib.h"
25 #include "ftp.h"
26 #include "parseconfig.h"
27 #include "list.h"
28
29
30 /* ---------------------------------------------------------------------- */
31 /* configuration */
32
33 int daemonize = 0;
34 char *archive = NULL;
35 char *tmpdir;
36 struct list_head connections;
37
38 char *grab_text = "webcam %Y-%m-%d %H:%M:%S"; /* strftime */
39 char *grab_infofile = NULL;
40 int grab_width = 320;
41 int grab_height = 240;
42 int grab_delay = 3;
43 int grab_wait = 0;
44 int grab_rotate = 0;
45 int grab_top = -1;
46 int grab_left = -1;
47 int grab_bottom = -1;
48 int grab_right = -1;
49 int grab_quality= 75;
50 int grab_trigger= 0;
51 int grab_times = -1;
52 int grab_fg_r = 255;
53 int grab_fg_g = 255;
54 int grab_fg_b = 255;
55 int grab_bg_r = -1;
56 int grab_bg_g = -1;
57 int grab_bg_b = -1;
58 char *grab_input = NULL;
59 char *grab_norm = NULL;
60
61 /* ---------------------------------------------------------------------- */
62 /* jpeg stuff */
63
64 static int
65 write_file(int fd, unsigned char *data, int width, int height)
66 {
67 struct jpeg_compress_struct cinfo;
68 struct jpeg_error_mgr jerr;
69 FILE *fp;
70 int i;
71 unsigned char *line;
72
73 fp = fdopen(fd,"w");
74 cinfo.err = jpeg_std_error(&jerr);
75 jpeg_create_compress(&cinfo);
76 jpeg_stdio_dest(&cinfo, fp);
77 cinfo.image_width = width;
78 cinfo.image_height = height;
79 cinfo.input_components = 3;
80 cinfo.in_color_space = JCS_RGB;
81 jpeg_set_defaults(&cinfo);
82 jpeg_set_quality(&cinfo, grab_quality, TRUE);
83 jpeg_start_compress(&cinfo, TRUE);
84
85 for (i = 0, line = data; i < height; i++, line += width*3)
86 jpeg_write_scanlines(&cinfo, &line, 1);
87
88 jpeg_finish_compress(&(cinfo));
89 jpeg_destroy_compress(&(cinfo));
90 fclose(fp);
91
92 return 0;
93 }
94
95 /* ---------------------------------------------------------------------- */
96 /* image transfer */
97
98 struct xfer_ops;
99
100 struct xfer_state {
101 char *name;
102 struct list_head list;
103
104 /* xfer options */
105 char *host;
106 char *user;
107 char *pass;
108 char *dir;
109 char *file;
110 char *tmpfile;
111 int debug;
112
113 /* ftp options */
114 int passive,autologin;
115
116 /* function pointers + private date */
117 struct xfer_ops *ops;
118 void *data;
119 };
120
121 struct xfer_ops {
122 int (*open)(struct xfer_state*);
123 void (*info)(struct xfer_state*);
124 int (*xfer)(struct xfer_state*, char *image, int width, int height);
125 void (*close)(struct xfer_state*);
126 };
127
128 static int ftp_open(struct xfer_state *s)
129 {
130 s->data = ftp_init(s->name,s->autologin,s->passive,s->debug);
131 ftp_connect(s->data,s->host,s->user,s->pass,s->dir);
132 return 0;
133 }
134
135 static void ftp_info(struct xfer_state *s)
136 {
137 fprintf(stderr,"ftp config [%s]:\n %s@%s:%s\n %s => %s\n",
138 s->name,s->user,s->host,s->dir,s->tmpfile,s->file);
139 }
140
141 static int ftp_xfer(struct xfer_state *s, char *image, int width, int height)
142 {
143 char filename[1024];
144 int fh;
145
146 sprintf(filename,"%s/webcamXXXXXX",tmpdir);
147 if (-1 == (fh = mkstemp(filename))) {
148 perror("mkstemp");
149 exit(1);
150 }
151 write_file(fh, image, width, height);
152 if (ftp_connected(s->data))
153 ftp_connect(s->data,s->host,s->user,s->pass,s->dir);
154 ftp_upload(s->data,filename,s->file,s->tmpfile);
155 unlink(filename);
156 return 0;
157 }
158
159 static void ftp_close(struct xfer_state *s)
160 {
161 ftp_fini(s->data);
162 }
163
164 static struct xfer_ops ftp_ops = {
165 open: ftp_open,
166 info: ftp_info,
167 xfer: ftp_xfer,
168 close: ftp_close,
169 };
170
171 static int ssh_open(struct xfer_state *s)
172 {
173 s->data = malloc(strlen(s->user)+strlen(s->host)+strlen(s->tmpfile)*2+
174 strlen(s->dir)+strlen(s->file)+32);
175 sprintf(s->data, "ssh %s@%s \"cat >%s && mv %s %s/%s\"",
176 s->user,s->host,s->tmpfile,s->tmpfile,s->dir,s->file);
177 return 0;
178 }
179
180 static void ssh_info(struct xfer_state *s)
181 {
182 fprintf(stderr,"ssh config [%s]:\n %s@%s:%s\n %s => %s\n",
183 s->name,s->user,s->host,s->dir,s->tmpfile,s->file);
184 }
185
186 static int ssh_xfer(struct xfer_state *s, char *image, int width, int height)
187 {
188 char filename[1024];
189 char *cmd = s->data;
190 unsigned char buf[4096];
191 FILE *sshp, *imgdata;
192 int len,fh;
193
194 sprintf(filename,"%s/webcamXXXXXX",tmpdir);
195 if (-1 == (fh = mkstemp(filename))) {
196 perror("mkstemp");
197 exit(1);
198 }
199 write_file(fh, image, width, height);
200
201 if ((sshp=popen(cmd, "w")) == NULL) {
202 perror("popen");
203 exit(1);
204 }
205 if ((imgdata = fopen(filename,"rb"))==NULL) {
206 perror("fopen");
207 exit(1);
208 }
209 for (;;) {
210 len = fread(buf,1,sizeof(buf),imgdata);
211 if (len <= 0)
212 break;
213 fwrite(buf,1,len,sshp);
214 }
215 fclose(imgdata);
216 pclose(sshp);
217
218 unlink(filename);
219 return 0;
220 }
221
222 static void ssh_close(struct xfer_state *s)
223 {
224 char *cmd = s->data;
225 free(cmd);
226 }
227
228 static struct xfer_ops ssh_ops = {
229 open: ssh_open,
230 info: ssh_info,
231 xfer: ssh_xfer,
232 close: ssh_close,
233 };
234
235 static int local_open(struct xfer_state *s)
236 {
237 char *t;
238
239 if (s->dir != NULL && s->dir[0] != '\0' ) {
240 t = malloc(strlen(s->tmpfile)+strlen(s->dir)+2);
241 sprintf(t, "%s/%s", s->dir, s->tmpfile);
242 s->tmpfile = t;
243
244 t = malloc(strlen(s->file)+strlen(s->dir)+2);
245 sprintf(t, "%s/%s", s->dir, s->file);
246 s->file = t;
247 }
248 return 0;
249 }
250
251 static void local_info(struct xfer_state *s)
252 {
253 fprintf(stderr,"write config [%s]:\n local transfer %s => %s\n",
254 s->name,s->tmpfile,s->file);
255 }
256
257 static int local_xfer(struct xfer_state *s, char *image, int width, int height)
258 {
259 int fh;
260
261 if (-1 == (fh = open(s->tmpfile,O_CREAT|O_WRONLY|O_TRUNC,0666))) {
262 fprintf(stderr,"open %s: %s\n",s->tmpfile,strerror(errno));
263 exit(1);
264 }
265 write_file(fh, image, width, height);
266 if (rename(s->tmpfile, s->file) ) {
267 fprintf(stderr, "can't move %s -> %s\n", s->tmpfile, s->file);
268 exit(1);
269 }
270 return 0;
271 }
272
273 static void local_close(struct xfer_state *s)
274 {
275 /* nothing */
276 }
277
278 static struct xfer_ops local_ops = {
279 open: local_open,
280 info: local_info,
281 xfer: local_xfer,
282 close: local_close,
283 };
284
285 /* ---------------------------------------------------------------------- */
286 /* capture stuff */
287
288 const struct ng_vid_driver *drv;
289 void *h_drv;
290 struct ng_video_fmt fmt,gfmt;
291 struct ng_video_conv *conv;
292 void *hconv;
293
294 static void
295 grab_init(void)
296 {
297 struct ng_attribute *attr;
298 int val,i;
299
300 drv = ng_vid_open(ng_dev.video,NULL,NULL,0,&h_drv);
301 if (NULL == drv) {
302 fprintf(stderr,"no grabber device available\n");
303 exit(1);
304 }
305 if (!(drv->capabilities(h_drv) & CAN_CAPTURE)) {
306 fprintf(stderr,"device does'nt support capture\n");
307 exit(1);
308 }
309
310 if (grab_input) {
311 attr = ng_attr_byid(drv->list_attrs(h_drv),ATTR_ID_INPUT);
312 val = ng_attr_getint(attr,grab_input);
313 if (-1 == val) {
314 fprintf(stderr,"invalid input: %s\n",grab_input);
315 exit(1);
316 }
317 attr->write(attr,val);
318 }
319 if (grab_norm) {
320 attr = ng_attr_byid(drv->list_attrs(h_drv),ATTR_ID_NORM);
321 val = ng_attr_getint(attr,grab_norm);
322 if (-1 == val) {
323 fprintf(stderr,"invalid norm: %s\n",grab_norm);
324 exit(1);
325 }
326 attr->write(attr,val);
327 }
328
329 /* try native */
330 fmt.fmtid = VIDEO_RGB24;
331 fmt.width = grab_width;
332 fmt.height = grab_height;
333 if (0 == drv->setformat(h_drv,&fmt))
334 return;
335
336 /* check all available conversion functions */
337 fmt.bytesperline = fmt.width*ng_vfmt_to_depth[fmt.fmtid]/8;
338 for (i = 0;;) {
339 conv = ng_conv_find_to(fmt.fmtid, &i);
340 if (NULL == conv)
341 break;
342 gfmt = fmt;
343 gfmt.fmtid = conv->fmtid_in;
344 gfmt.bytesperline = 0;
345 if (0 == drv->setformat(h_drv,&gfmt)) {
346 fmt.width = gfmt.width;
347 fmt.height = gfmt.height;
348 hconv = conv->init(&fmt,conv->priv);
349 return;
350 }
351 }
352 fprintf(stderr,"can't get rgb24 data\n");
353 exit(1);
354 }
355
356 static unsigned char*
357 grab_one(int *width, int *height)
358 {
359 static struct ng_video_buf *cap,*buf;
360
361 if (NULL != buf)
362 ng_release_video_buf(buf);
363 if (NULL == (cap = drv->getimage(h_drv))) {
364 fprintf(stderr,"capturing image failed\n");
365 exit(1);
366 }
367
368 if (NULL != conv) {
369 buf = ng_malloc_video_buf(&fmt,3*fmt.width*fmt.height);
370 conv->frame(hconv,buf,cap);
371 buf->info = cap->info;
372 ng_release_video_buf(cap);
373 } else {
374 buf = cap;
375 }
376
377 *width = buf->fmt.width;
378 *height = buf->fmt.height;
379 return buf->data;
380 }
381
382 /* ---------------------------------------------------------------------- */
383
384 #define MSG_MAXLEN 256
385
386 #define CHAR_HEIGHT 11
387 #define CHAR_WIDTH 6
388 #define CHAR_START 4
389 #include "font-6x11.h"
390
391 static char*
392 get_message(void)
393 {
394 static char buffer[MSG_MAXLEN+1];
395 FILE *fp;
396 char *p;
397
398 if (NULL == grab_infofile)
399 return grab_text;
400
401 if (NULL == (fp = fopen(grab_infofile, "r"))) {
402 fprintf(stderr,"open %s: %s\n",grab_infofile,strerror(errno));
403 return grab_text;
404 }
405
406 fgets(buffer, MSG_MAXLEN, fp);
407 fclose(fp);
408 if (NULL != (p = strchr(buffer,'\n')))
409 *p = '\0';
410 return buffer;
411 }
412
413 static void
414 add_text(char *image, int width, int height)
415 {
416 time_t t;
417 struct tm *tm;
418 char line[MSG_MAXLEN+1],*ptr;
419 int i,x,y,f,len;
420
421 time(&t);
422 tm = localtime(&t);
423 len = strftime(line,MSG_MAXLEN,get_message(),tm);
424 // fprintf(stderr,"%s\n",line);
425
426 for (y = 0; y < CHAR_HEIGHT; y++) {
427 ptr = image + 3 * width * (height-CHAR_HEIGHT-2+y) + 12;
428 for (x = 0; x < len; x++) {
429 f = fontdata[line[x] * CHAR_HEIGHT + y];
430 for (i = CHAR_WIDTH-1; i >= 0; i--) {
431 if (f & (CHAR_START << i)) {
432 ptr[0] = grab_fg_r;
433 ptr[1] = grab_fg_g;
434 ptr[2] = grab_fg_b;
435 } else if (grab_bg_r != -1) {
436 ptr[0] = grab_bg_r;
437 ptr[1] = grab_bg_g;
438 ptr[2] = grab_bg_b;
439 }
440 ptr += 3;
441 }
442 }
443 }
444 }
445
446 /* ---------------------------------------------------------------------- */
447 /* Frederic Helin <Frederic.Helin@inrialpes.fr> - 15/07/2002 */
448 /* Correction fonction of stereographic radial distortion */
449
450 int grab_dist_on = 0;
451 int grab_dist_k = 700;
452 int grab_dist_cx = -1;
453 int grab_dist_cy = -1;
454 int grab_dist_zoom = 50;
455 int grab_dist_sensorw = 640;
456 int grab_dist_sensorh = 480;
457
458 static unsigned char *
459 correct_distor(unsigned char * in, int width, int height,
460 int grab_zoom, int grap_k, int cx, int cy,
461 int grab_sensorw, int grab_sensorh)
462 {
463 static unsigned char * corrimg = NULL;
464
465 int i, j, di, dj;
466 float dr, cr,ca, sensor_w, sensor_h, sx, zoom, k;
467
468 sensor_w = grab_dist_sensorw/100.0;
469 sensor_h = grab_dist_sensorh/100.0;
470 zoom = grab_zoom / 100.0;
471 k = grap_k / 100.0;
472
473 if (corrimg == NULL && (corrimg = malloc(width*height*3)) == NULL ) {
474 fprintf(stderr, "out of memory\n");
475 exit(1);
476 }
477
478 sensor_w = 6.4;
479 sensor_h = 4.8;
480
481 // calc ratio x/y
482 sx = width * sensor_h / (height * sensor_w);
483
484 // calc new value of k in the coordonates systeme of computer
485 k = k * height / sensor_h;
486
487 // Clear image
488 for (i = 0; i < height*width*3; i++) corrimg[i] = 255;
489
490 for (j = 0; j < height ; j++) {
491 for (i = 0; i < width ; i++) {
492
493 // compute radial distortion / parameters of center of image
494 cr = sqrt((i-cx)/sx*(i-cx)/sx+(j-cy)*(j-cy));
495 ca = atan(cr/k/zoom);
496 dr = k * tan(ca/2);
497
498 if (i == cx && j == cy) {di = cx; dj = cy;}
499 else {
500 di = (i-cx) * dr / cr + cx;
501 dj = (j-cy) * dr / cr + cy;
502 }
503
504 if (dj<height && di < width && di >= 0 && dj >= 0 &&
505 j<height && i < width && i >= 0 && j >= 0 ) {
506 corrimg[3*(j*width + i) ] = in[3*(dj*width + di) ];
507 corrimg[3*(j*width + i)+1] = in[3*(dj*width + di)+1];
508 corrimg[3*(j*width + i)+2] = in[3*(dj*width + di)+2];
509 }
510 }
511 }
512 return corrimg;
513 }
514
515 /* ---------------------------------------------------------------------- */
516
517 static unsigned int
518 compare_images(unsigned char *last, unsigned char *current,
519 int width, int height)
520 {
521 unsigned char *p1 = last;
522 unsigned char *p2 = current;
523 int avg, diff, max, i = width*height*3;
524
525 for (max = 0, avg = 0; --i; p1++,p2++) {
526 diff = (*p1 < *p2) ? (*p2 - *p1) : (*p1 - *p2);
527 avg += diff;
528 if (diff > max)
529 max = diff;
530 }
531 avg = avg / width / height;
532 fprintf(stderr,"compare: max=%d,avg=%d\n",max,avg);
533 /* return avg */
534 return max;
535 }
536
537
538 static unsigned char *
539 rotate_image(unsigned char * in, int *wp, int *hp, int rot,
540 int top, int left, int bottom, int right)
541 {
542 static unsigned char * rotimg = NULL;
543
544 int i, j;
545
546 int w = *wp;
547 int ow = (right-left);
548 int oh = (bottom-top);
549
550 if (rotimg == NULL && (rotimg = malloc(ow*oh*3)) == NULL ) {
551 fprintf(stderr, "out of memory\n");
552 exit(1);
553 }
554 switch (rot) {
555 default:
556 case 0:
557 for (j = 0; j < oh; j++) {
558 int ir = (j+top)*w+left;
559 int or = j*ow;
560 for (i = 0; i < ow; i++) {
561 rotimg[3*(or + i)] = in[3*(ir+i)];
562 rotimg[3*(or + i)+1] = in[3*(ir+i)+1];
563 rotimg[3*(or + i)+2] = in[3*(ir+i)+2];
564 }
565 }
566 *wp = ow;
567 *hp = oh;
568 break;
569 case 1:
570 for (i = 0; i < ow; i++) {
571 int rr = (ow-1-i)*oh;
572 int ic = i+left;
573 for (j = 0; j < oh; j++) {
574 rotimg[3*(rr+j)] = in[3*((j+top)*w+ic)];
575 rotimg[3*(rr+j)+1] = in[3*((j+top)*w+ic)+1];
576 rotimg[3*(rr+j)+2] = in[3*((j+top)*w+ic)+2];
577 }
578 }
579 *wp = oh;
580 *hp = ow;
581 break;
582 case 2:
583 for (j = 0; j < oh; j++) {
584 int ir = (j+top)*w;
585 for (i = 0; i < ow; i++) {
586 rotimg[3*((oh-1-j)*ow + (ow-1-i))] = in[3*(ir+i+left)];
587 rotimg[3*((oh-1-j)*ow + (ow-1-i))+1] = in[3*(ir+i+left)+1];
588 rotimg[3*((oh-1-j)*ow + (ow-1-i))+2] = in[3*(ir+i+left)+2];
589 }
590 }
591 *wp = ow;
592 *hp = oh;
593 break;
594 case 3:
595 for (i = 0; i < ow; i++) {
596 int rr = i*oh;
597 int ic = i+left;
598 rr += oh-1;
599 for (j = 0; j < oh; j++) {
600 rotimg[3*(rr-j)] = in[3*((j+top)*w+ic)];
601 rotimg[3*(rr-j)+1] = in[3*((j+top)*w+ic)+1];
602 rotimg[3*(rr-j)+2] = in[3*((j+top)*w+ic)+2];
603 }
604 }
605 *wp = oh;
606 *hp = ow;
607 break;
608 }
609 return rotimg;
610 }
611
612
613 /* ---------------------------------------------------------------------- */
614
615 static int make_dirs(char *filename)
616 {
617 char *dirname,*h;
618 int retval = -1;
619
620 dirname = strdup(filename);
621 if (NULL == dirname)
622 goto done;
623 h = strrchr(dirname,'/');
624 if (NULL == h)
625 goto done;
626 *h = 0;
627
628 if (-1 == (retval = mkdir(dirname,0777)))
629 if (ENOENT == errno)
630 if (0 == make_dirs(dirname))
631 retval = mkdir(dirname,0777);
632
633 done:
634 free(dirname);
635 return retval;
636 }
637
638 int
639 main(int argc, char *argv[])
640 {
641 unsigned char *image,*val,*gimg,*lastimg = NULL;
642 int width, height, i, fh;
643 char filename[1024];
644 char **sections;
645 struct list_head *item;
646 struct xfer_state *s;
647
648 /* read config */
649 if (argc > 1) {
650 strcpy(filename,argv[1]);
651 } else {
652 sprintf(filename,"%s/%s",getenv("HOME"),".webcamrc");
653 }
654 fprintf(stderr,"reading config file: %s\n",filename);
655 cfg_parse_file(filename);
656 ng_init();
657
658 if (NULL != (val = cfg_get_str("grab","device")))
659 ng_dev.video = val;
660 if (NULL != (val = cfg_get_str("grab","text")))
661 grab_text = val;
662 if (NULL != (val = cfg_get_str("grab","infofile")))
663 grab_infofile = val;
664 if (NULL != (val = cfg_get_str("grab","input")))
665 grab_input = val;
666 if (NULL != (val = cfg_get_str("grab","norm")))
667 grab_norm = val;
668 if (-1 != (i = cfg_get_int("grab","width")))
669 grab_width = i;
670 if (-1 != (i = cfg_get_int("grab","height")))
671 grab_height = i;
672 if (-1 != (i = cfg_get_int("grab","delay")))
673 grab_delay = i;
674 if (-1 != (i = cfg_get_int("grab","wait")))
675 grab_wait = i;
676 if (-1 != (i = cfg_get_int("grab","rotate")))
677 grab_rotate = i;
678 if (-1 != (i = cfg_get_int("grab","top")))
679 grab_top = i;
680 if (-1 != (i = cfg_get_int("grab","left")))
681 grab_left = i;
682 grab_bottom = cfg_get_int("grab","bottom");
683 grab_right = cfg_get_int("grab","right");
684 if (-1 != (i = cfg_get_int("grab","quality")))
685 grab_quality = i;
686 if (-1 != (i = cfg_get_int("grab","trigger")))
687 grab_trigger = i;
688 if (-1 != (i = cfg_get_int("grab","once")))
689 if (i > 0)
690 grab_times = 1;
691 if (-1 != (i = cfg_get_int("grab","times")))
692 grab_times = i;
693 if (NULL != (val = cfg_get_str("grab","archive")))
694 archive = val;
695
696 if (-1 != (i = cfg_get_int("grab","fg_red")))
697 if (i >= 0 && i <= 255)
698 grab_fg_r = i;
699 if (-1 != (i = cfg_get_int("grab","fg_green")))
700 if (i >= 0 && i <= 255)
701 grab_fg_g = i;
702 if (-1 != (i = cfg_get_int("grab","fg_blue")))
703 if (i >= 0 && i <= 255)
704 grab_fg_b = i;
705 if (-1 != (i = cfg_get_int("grab","bg_red")))
706 if (i >= 0 && i <= 255)
707 grab_bg_r = i;
708 if (-1 != (i = cfg_get_int("grab","bg_green")))
709 if (i >= 0 && i <= 255)
710 grab_bg_g = i;
711 if (-1 != (i = cfg_get_int("grab","bg_blue")))
712 if (i >= 0 && i <= 255)
713 grab_bg_b = i;
714
715 if (-1 != (i = cfg_get_int("grab","distor")))
716 grab_dist_on = i;
717 if (-1 != (i = cfg_get_int("grab","distor_k")))
718 grab_dist_k = i;
719 if (-1 != (i = cfg_get_int("grab","distor_cx")))
720 grab_dist_cx = i;
721 if (-1 != (i = cfg_get_int("grab","distor_cy")))
722 grab_dist_cy = i;
723 if (-1 != (i = cfg_get_int("grab","distor_zoom")))
724 grab_dist_zoom =i;
725 if (-1 != (i = cfg_get_int("grab","distor_sensorw")))
726 grab_dist_sensorw = i;
727 if (-1 != (i = cfg_get_int("grab","distor_sensorh")))
728 grab_dist_sensorh = i;
729
730 /* defaults */
731 if (grab_top < 0) grab_top = 0;
732 if (grab_left < 0) grab_left = 0;
733 if (grab_bottom < 0) grab_bottom = grab_height;
734 if (grab_right < 0) grab_right = grab_width;
735
736 if (grab_bottom > grab_height) grab_bottom = grab_height;
737 if (grab_right > grab_width) grab_right = grab_width;
738
739 if (grab_top >= grab_bottom) {
740 fprintf(stderr, "config error: top must be smaller than bottom\n");
741 exit(1);
742 }
743 if (grab_left >= grab_right) {
744 fprintf(stderr, "config error: left must be smaller than right\n");
745 exit(1);
746 }
747
748 if (grab_dist_k < 1 || grab_dist_k > 10000)
749 grab_dist_k = 700;
750 if (grab_dist_cx < 0 || grab_dist_cx > grab_width)
751 grab_dist_cx = grab_width / 2;
752 if (grab_dist_cy < 0 || grab_dist_cy > grab_height)
753 grab_dist_cy = grab_height / 2;
754 if (grab_dist_zoom < 1 || grab_dist_zoom > 1000)
755 grab_dist_zoom = 100;
756 if (grab_dist_sensorw < 1 || grab_dist_sensorw >9999)
757 grab_dist_sensorw = 640;
758 if (grab_dist_sensorh < 1 || grab_dist_sensorh >9999)
759 grab_dist_sensorh = 480;
760
761 INIT_LIST_HEAD(&connections);
762 for (sections = cfg_list_sections(); *sections != NULL; sections++) {
763 if (0 == strcasecmp(*sections,"grab"))
764 continue;
765
766 /* init + set defaults */
767 s = malloc(sizeof(*s));
768 memset(s,0,sizeof(*s));
769 s->name = *sections;
770 s->host = "www";
771 s->user = "webcam";
772 s->pass = "xxxxxx";
773 s->dir = "public_html/images";
774 s->file = "webcam.jpeg";
775 s->tmpfile = "uploading.jpeg";
776 s->passive = 1;
777 s->autologin = 0;
778 s->ops = &ftp_ops;
779
780 /* from config */
781 if (NULL != (val = cfg_get_str(*sections,"host")))
782 s->host = val;
783 if (NULL != (val = cfg_get_str(*sections,"user")))
784 s->user = val;
785 if (NULL != (val = cfg_get_str(*sections,"pass")))
786 s->pass = val;
787 if (NULL != (val = cfg_get_str(*sections,"dir")))
788 s->dir = val;
789 if (NULL != (val = cfg_get_str(*sections,"file")))
790 s->file = val;
791 if (NULL != (val = cfg_get_str(*sections,"tmp")))
792 s->tmpfile = val;
793 if (-1 != (i = cfg_get_int(*sections,"passive")))
794 s->passive = i;
795 if (-1 != (i = cfg_get_int(*sections,"auto")))
796 s->autologin = i;
797 if (-1 != (i = cfg_get_int(*sections,"debug")))
798 s->debug = i;
799 if (-1 != (i = cfg_get_int(*sections,"local")))
800 if (i)
801 s->ops = &local_ops;
802 if (-1 != (i = cfg_get_int(*sections,"ssh")))
803 if (i)
804 s->ops = &ssh_ops;
805
806 /* all done */
807 list_add_tail(&s->list,&connections);
808 }
809
810 /* init everything */
811 grab_init();
812 sleep(grab_wait);
813 tmpdir = (NULL != getenv("TMPDIR")) ? getenv("TMPDIR") : "/tmp";
814 list_for_each(item,&connections) {
815 s = list_entry(item, struct xfer_state, list);
816 s->ops->open(s);
817 }
818
819 /* print config */
820 fprintf(stderr,"video4linux webcam v1.5 - (c) 1998-2002 Gerd Knorr\n");
821 fprintf(stderr,"grabber config:\n size %dx%d [%s]\n",
822 fmt.width,fmt.height,ng_vfmt_to_desc[gfmt.fmtid]);
823 fprintf(stderr," input %s, norm %s, jpeg quality %d\n",
824 grab_input,grab_norm, grab_quality);
825 fprintf(stderr," rotate=%d, top=%d, left=%d, bottom=%d, right=%d\n",
826 grab_rotate, grab_top, grab_left, grab_bottom, grab_right);
827 list_for_each(item,&connections) {
828 s = list_entry(item, struct xfer_state, list);
829 s->ops->info(s);
830 }
831
832 /* run as daemon - detach from terminal */
833 if (daemonize) {
834 switch (fork()) {
835 case -1:
836 perror("fork");
837 exit(1);
838 case 0:
839 close(0); close(1); close(2); setsid();
840 break;
841 default:
842 exit(0);
843 }
844 }
845
846 /* main loop */
847 for (;;) {
848 /* grab a new one */
849 gimg = grab_one(&width,&height);
850
851 if (grab_dist_on)
852 gimg = correct_distor(gimg, width, height,
853 grab_dist_zoom, grab_dist_k,
854 grab_dist_cx, grab_dist_cy,
855 grab_dist_sensorw, grab_dist_sensorh);
856
857 image = rotate_image(gimg, &width, &height, grab_rotate,
858 grab_top, grab_left, grab_bottom, grab_right);
859
860 if (grab_trigger) {
861 /* look if it has changed */
862 if (NULL != lastimg) {
863 i = compare_images(lastimg,image,width,height);
864 if (i < grab_trigger)
865 continue;
866 } else {
867 lastimg = malloc(width*height*3);
868 }
869 memcpy(lastimg,image,width*height*3);
870 }
871
872 /* ok, label it and upload */
873 add_text(image,width,height);
874 list_for_each(item,&connections) {
875 s = list_entry(item, struct xfer_state, list);
876 s->ops->xfer(s,image,width,height);
877 }
878 if (archive) {
879 time_t t;
880 struct tm *tm;
881
882 time(&t);
883 tm = localtime(&t);
884 strftime(filename,sizeof(filename)-1,archive,tm);
885 again:
886 if (-1 == (fh = open(filename,O_CREAT|O_WRONLY|O_TRUNC,0666))) {
887 if (ENOENT == errno) {
888 if (0 == make_dirs(filename))
889 goto again;
890 }
891 fprintf(stderr,"open %s: %s\n",filename,strerror(errno));
892 exit(1);
893 }
894 write_file(fh, image, width, height);
895 }
896
897 if (-1 != grab_times && --grab_times == 0)
898 break;
899 if (grab_delay > 0)
900 sleep(grab_delay);
901 }
902 list_for_each(item,&connections) {
903 s = list_entry(item, struct xfer_state, list);
904 s->ops->close(s);
905 }
906 return 0;
907 }
908
|
This page was automatically generated by the
LXR engine.
|