1/* 2 * Landscape camera software for iPAQ H3600 Mercury Backpaq 3 * MODIFIED by Amay Champaneria for use with general video4linux devices 4 * Compile with ANYCAM #defined for general cameras 5 * 6 * Copyright 2001 Compaq Computer Corporation. 7 * 8 * Use consistent with the GNU GPL is permitted, 9 * provided that this copyright notice is 10 * preserved in its entirety in all copies and derived works. 11 * 12 * COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED, 13 * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS 14 * FITNESS FOR ANY PARTICULAR PURPOSE. 15 * 16 * Author: Andrew Christian 17 * <andrew.christian@compaq.com> 18 * 4 June 2001 19 */ 20 21#ifdef HAVE_CONFIG_H 22# include <config.h> 23#endif 24 25#include <unistd.h> 26#include <stdio.h> 27 28#include <string.h> 29#include <getopt.h> 30#include <sys/types.h> 31#include <sys/stat.h> 32#include <sys/poll.h> 33#include <sys/ioctl.h> 34#include <sys/mman.h> 35#include <fcntl.h> 36#include <pthread.h> 37#include <linux/types.h> 38#include <signal.h> 39#include <sys/wait.h> 40#include <errno.h> 41#include <sys/socket.h> 42#include <netinet/in.h> 43#include <arpa/inet.h> 44#include <syslog.h> 45#include <glib.h> // for GList 46 47#ifdef WL600 48#include <jpeglib.h> 49#endif 50 51#include "rcamd.h" 52 53#define MYCLAMP(x,y,z) ((x<y) ? (x=y) : ((x>z) ? (x=z) : 0)) 54 55gboolean gQuitFlag = FALSE; 56gboolean gResetCounters = FALSE; 57struct CaptureData gCamera; 58 59#define JPEGBUFFERSIZE 640*480*3 60 61// cmdline args 62int max_diff = 30; 63int debug = 0; 64int seconds = 1; 65int port = 12000; 66int quality = 75; 67int framesize = 2; 68int width = 640; 69int height = 480; 70int gain = 1; 71int brightness = 400; 72int cameratype = 0; 73 74#ifdef WL600 75long recordtime=3600; /* 60 minutes */ 76int recordindex; 77char recordfile[64]; 78int alertflag; 79int tmp_alertflag; 80pid_t mypid; 81pid_t watchdogpid=-1; 82int alertstart=-3; 83int alertcount=-1; 84char alertfiles[256]; 85int clientinfo; 86long max_count; 87long imagecount=0; 88int retryflag; 89int image_cycle=2; 90#define ALERT_DISABLED 0 // Alert is disabled 91#define ALERT_ONTIME 1 // Alert is enabled and on time 92#define ALERT_OFFTIME 2 // Alert is enabled but off time 93#define ALERT_MAIL 3 // Alert is enabled and sendding mail 94#define CLIENT_STATE_SLEEP 0 95#define CLIENT_STATE_ACTIVE 1 96#define CLIENT_STATE_QUIT 2 97int grab_retry=0; 98int gcount=0; 99#endif 100 101int sockfd = -1; 102GList *clients; 103int newclient = 1; 104int idletimeout = 0; 105int is_grabed=0; 106int first_grabed=0; 107pthread_mutex_t clients_lock; 108pthread_t server_thread; 109 110/* 111 * logmessage 112 * 113 */ 114void logmessage(char *logheader, char *fmt, ...) 115{ 116 va_list args; 117 char buf[256]; 118 119 va_start(args, fmt); 120 vsnprintf(buf, sizeof(buf), fmt, args); 121 openlog(logheader, 0, 0); 122 syslog(0, buf); 123 closelog(); 124 va_end(args); 125} 126 127 128 129void 130handle_sig_pipe(int i) 131{ 132 if (debug) printf("SIGPIPE"); 133 return; 134} 135 136int 137server(void) 138{ 139 int clilen, newsockfd, ret=0; 140 struct sockaddr_in serv_addr, cli_addr; 141 struct sigaction act; 142 clientdata *curclient = NULL; 143 char *curaddress = NULL; 144 145 // initialize clients 146 clients = NULL; 147 148 // set up sigpipe handler 149 act.sa_handler = handle_sig_pipe; 150 sigemptyset(&act.sa_mask); 151 act.sa_flags = SA_SIGINFO; 152 sigaction(SIGPIPE, &act, NULL); 153 154 sockfd = socket(AF_INET, SOCK_STREAM, 0); 155 if (sockfd < 0) { 156 printf("Error opening socket\n"); 157 return -1; 158 } 159 160 bzero((char *)&serv_addr, sizeof(serv_addr)); 161 serv_addr.sin_family = AF_INET; 162 serv_addr.sin_addr.s_addr = INADDR_ANY; 163 serv_addr.sin_port = htons(port); 164 if (bind(sockfd, (struct sockaddr *) &serv_addr, 165 sizeof(serv_addr)) < 0) { 166 printf("Error on binding\n"); 167 return -1; 168 } 169 170 listen(sockfd, 5); 171 172 while (1) { 173 clilen = sizeof(cli_addr); 174 newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen); 175 if (newsockfd < 0) { 176 if (debug) printf("Error on accept\n"); 177 } else { 178 179 // create a new clientdata item 180 curclient = malloc(sizeof(clientdata)); 181 if (curclient==NULL) 182 { 183 close(newsockfd); 184 continue; 185 } 186 curclient->sockfd = newsockfd; 187 curaddress = inet_ntoa(cli_addr.sin_addr); 188 if (curaddress==NULL) 189 { 190 curaddress = unknown_address; 191 } 192 curclient->address = malloc((strlen(curaddress)+1)*sizeof(char)); 193 if (curclient->address==NULL) 194 { 195 free(curclient); 196 close(newsockfd); 197 continue; 198 } 199 strcpy(curclient->address, curaddress); 200#ifdef NONBLOCK 201 //ret = fcntl(curclient->sockfd, F_SETFL, O_NONBLOCK); 202 ret = 1; 203 if (ioctl(curclient->sockfd, FIONBIO, &ret)) 204 { 205 if (debug) printf("Can't mark socket nonblocking\n"); 206 //logmessage("USB Webcam", "can't mark socket nonblocking\n"); 207 } 208#endif 209 if (debug>1) 210 printf("Accepted connection from %s (fcntl ret=%d).\n", curclient->address, ret); 211 logmessage("USB webcam", "Accepted connection from %s\n", curclient->address); 212 213 pthread_mutex_lock(&clients_lock); 214 215#ifdef WL600 216 curclient->written = 0; 217 curclient->errcount = 0; 218 219 /* handle record and mail alert while the first client connect */ 220 if (clients==NULL) 221 { 222 if (debug>1) 223 printf("The first client is connected %d\n", mypid); 224 //kill(mypid, 30); 225 } 226#endif 227 clients = g_list_append(clients, curclient); 228 newclient = 1; 229 pthread_mutex_unlock(&clients_lock); 230 } 231 } 232} 233 234 235void 236closesocklist() 237{ 238 GList *cur; 239 clientdata *curclient; 240 241 pthread_mutex_lock(&clients_lock); 242 cur = clients; 243 244 while (cur) 245 { 246 curclient = (clientdata *)cur->data; 247 if (curclient!=NULL && curclient->sockfd>0) close(curclient->sockfd); 248 cur = cur->next; 249 } 250 pthread_mutex_unlock(&clients_lock); 251} 252 253void 254printlist() 255{ 256 GList *cur = clients; 257 clientdata *curclient; 258 while (cur) 259 { 260 curclient = (clientdata *)cur->data; 261 //printf("Cur %p data=%p (%d,%s) {%p, %p}\n", cur, curclient, curclient->sockfd, curclient->address, cur->prev, cur->next); 262 cur = cur->next; 263 } 264} 265 266int writeImage(clientdata *client, char *buf, int size) 267{ 268 int ret, csize, written; 269 struct pollfd pfd; 270 int fd; 271 int header; 272 int rsize; 273 unsigned short *len; 274 275 if (cameratype==2) 276 { 277 header = 0xffff; 278 len = (unsigned short *)(&buf[0]); 279 rsize = *len; 280 } 281 else 282 { 283 header = size; 284 rsize = size; 285 } 286 287 fd = client->sockfd; 288 written = client->written; 289 if (written>=sizeof(int)) 290 { 291 buf += (written - sizeof(int)); 292 csize = rsize - written + 4; 293 } 294 else csize = rsize - written; 295 296 //logmessage("USB webcam", "dump image %s\n", client->address); 297 //sleep(2); 298 299 while(csize>0) 300 { 301 //logmessage("USB webcam", "de1\n"); 302 //printf("Write: %d\n", written); 303 if (written==0) // Write size first 304 ret = send(fd, &header, sizeof(int), MSG_DONTWAIT); 305 else // 306 ret = send(fd, buf, csize, MSG_DONTWAIT); 307 308 //printf("Set: %d %d\n", ret, written); 309 310 //logmessage("USB webcam", "de2\n"); 311 312 if (ret<=0) 313 { 314 if (debug) printf("ERR: %d %d %d %d\n", ret, errno, size, csize); 315 if (ret==0 || (ret<0 && (errno==EAGAIN || errno==EWOULDBLOCK))) 316 { 317 memset(&pfd, 0, sizeof(pfd)); 318 pfd.fd = fd; 319 pfd.events = POLLOUT | POLLERR | POLLHUP; 320 321 ret = poll(&pfd, 1, 500); 322 323 if (ret>0 && (pfd.events&POLLOUT)) continue; 324 else return 0; 325 } 326 return -1; 327 } 328 else 329 { 330 if (debug>1) printf("Written: %d %d %d\n", ret, csize, written); 331 written+=ret; 332 client->written = written; 333 if (csize<=ret) 334 { 335 return written; 336 } 337 if (written>sizeof(int)) 338 { 339 csize -= ret; 340 buf+=ret; 341 } 342 } 343 } 344 return csize; 345} 346 347int 348sender(unsigned char *yuvcap, int size) 349{ 350 int numwritten, i=0; 351 GList *cur,*old,*del=NULL; 352 clientdata *curclient; 353 354 pthread_mutex_lock(&clients_lock); 355 356 cur = clients; 357 if (debug) printlist(clients); 358 359 while (cur) { 360 curclient = (clientdata *)cur->data; 361 if (curclient==NULL && debug>1) 362 printf("BAD!!!!!!!!!!!!!! curclient is null!!!!\n"); 363 364 if (curclient->sockfd > 0) 365 { 366 if (debug>1) 367 printf("Writing %d bytes to %s %d\n", size, curclient->address, curclient->written); 368 369 numwritten = writeImage(curclient, yuvcap, size); 370 371 if (numwritten > 0) 372 { 373 if (debug>1) 374 printf("sender: Wrote %d to %s %d\n", numwritten, curclient->address, curclient->written); 375 curclient->errcount = 0; 376 if (numwritten == size + sizeof(int)) 377 { 378 curclient->written = 0; 379 } 380 } 381 else 382 { 383 // release this client 384 //printf("Error written: %d %d\n", curclient->written, curclient->errcount); 385 if (numwritten==0) 386 { 387 curclient->errcount++; 388 389 if (curclient->errcount<15) 390 { 391 goto finish; 392 } 393 } 394 395 if (debug) 396 { 397 printf("errcount %d %d\n", curclient->errcount, errno); 398 printf("sender: Could not write to client %s\n", curclient->address); 399 } 400 401 close(curclient->sockfd); 402 403 // mark this node for deletion 404 del = g_list_append(del, cur); 405finish: 406 } 407 } 408 i++; 409 cur = cur->next; 410 } 411 412 // delete all marked nodes 413 cur = del; 414 while (cur) 415 { 416 old = (GList *)cur->data; 417 clients = g_list_remove_link(clients, old); 418 curclient = (clientdata *)old->data; 419 logmessage("USB webcam", "Remove connection from %s\n", curclient->address); 420 free(curclient->address); 421 free(curclient); 422 g_list_free_1(old); 423 cur = cur->next; 424 } 425 g_list_free(del); 426 pthread_mutex_unlock(&clients_lock); 427#ifdef WL600 428 /* handle record time and mail alert if the last client is removed */ 429 if (clients==NULL) 430 { 431 if (debug) 432 { 433 printf("The last client is removed\n"); 434 //kill(mypid, SIGUSR1); 435 } 436 } 437#endif 438 return 0; 439} 440 441/***************************************/ 442 443#define CAMERA_IOCTL(TYPE,DATA) \ 444 do { int result; do { \ 445 result = ioctl(camera->video_fd, TYPE, &camera->DATA); \ 446 if ( result && errno != ENODEV ) { \ 447 perror("ioctl: Unable to " #TYPE); \ 448 exit(1); \ 449 } \ 450 } while ( result ); } while (0) 451 452void set_camera_info( struct CaptureData *camera ) 453{ 454 CAMERA_IOCTL( VIDIOCGWIN, vwin ); 455 CAMERA_IOCTL( VIDIOCGPICT, vpic ); 456 457 camera->desired.capture_size = framesize; 458 camera->vwin.width = width; 459 camera->vwin.height = height; 460 461 if (cameratype==2) 462 { 463 camera->vpic.palette = VIDEO_PALETTE_RGB24; 464 } 465 else 466 { 467 camera->vpic.palette = VIDEO_PALETTE_YUV420P; 468 } 469 //camera->vpic.palette = VIDEO_PALETTE_RGB24; 470 //camera->vpic.palette = VIDEO_PALETTE_GREY; 471 //camera->vpic.brightness = camera->desired.brightness; 472 473 if (cameratype ==0) 474 { 475#define PWC_FPS_SHIFT 16 476#define PWC_FPS_MASK 0x00FF0000 477#define PWC_FPS_FRMASK 0x003F0000 478#define PWC_FPS_SNAPSHOT 0x00400000 479 /* Set new framerate */ 480 camera->vwin.flags &= ~PWC_FPS_FRMASK; 481 camera->vwin.flags |= (5 << PWC_FPS_SHIFT); 482 if (debug) printf("PWC type Camera has framerate setting; limit to %d fps\n", (camera->vwin.flags & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT); 483 } 484 else { 485 if (debug) printf("OV511 type Camera has framerate setting; max fps\n"); 486 CAMERA_IOCTL( VIDIOCSPICT, vpic ); 487 } 488 489 CAMERA_IOCTL( VIDIOCSWIN, vwin ); 490} 491 492void get_camera_info( struct CaptureData *camera ) 493{ 494 CAMERA_IOCTL( VIDIOCGWIN, vwin ); 495 CAMERA_IOCTL( VIDIOCGPICT, vpic ); 496 497} 498 499/***************************************/ 500/* Open and close the camera */ 501/***************************************/ 502 503void open_camera( struct CaptureData *camera ) 504{ 505 camera->video_fd = open( "/dev/video", O_RDWR); 506 if ( camera->video_fd < 0 ) { 507 perror("Unable to open /dev/video"); 508 exit(1); 509 } 510 if ( ioctl(camera->video_fd, VIDIOCGCAP, &camera->vcap) != 0 ) { 511 perror("ioctl VIDIOCGCAP"); 512 exit(1); 513 } 514 get_camera_info( camera ); 515} 516 517void close_camera( struct CaptureData *camera ) 518{ 519 //printf("Close camera\n"); 520 if ( camera->video_fd > 0 ) { 521 printf("Close Camera: %d\n", close(camera->video_fd)); 522 //camera->video_fd = 0; 523 } 524 //camera->drv->stopvideo(camera->h_drv); 525} 526 527/***************************************/ 528/* Display thread */ 529/***************************************/ 530 531int grab_image( struct CaptureData *camera ) 532{ 533 /* Move preferences over */ 534 pthread_mutex_lock( &camera->desired.lock ); 535 // Wait until the pause is over 536 while (camera->desired.pause) 537 pthread_cond_wait( &camera->desired.cond, &camera->desired.lock ); 538 539 if (camera->desired.dirty){ 540 set_camera_info(camera); 541 get_camera_info(camera); 542 camera->desired.dirty = FALSE; 543 } 544 545 camera->vmap[camera->grab_frame].width = camera->vwin.width; 546 camera->vmap[camera->grab_frame].height = camera->vwin.height; 547 camera->vmap[camera->grab_frame].format = camera->vpic.palette; 548 pthread_mutex_unlock( &camera->desired.lock ); 549 550 while ( ioctl(camera->video_fd, 551 VIDIOCMCAPTURE, 552 &camera->vmap[camera->grab_frame]) != 0 ) { 553 //perror("Unable to CAPTURE frame!\n"); 554 if (debug) printf("Can't get image\n"); 555 usleep( 250000 ); 556 grab_retry++; 557 558 if (grab_retry>10) 559 { 560 logmessage("USB webcam", "webcam capture no frame\n"); 561 return 0; 562 } 563 564 } 565 grab_retry=0; 566 return 1; 567} 568 569void process_image( struct CaptureData *camera ) 570{ 571 int last, cur, diff; 572 unsigned char *data; 573 struct ImageData *image = &(camera->image); 574 FILE *fp; 575 576 /* Copy the parameters and data used in the capture */ 577 pthread_mutex_lock(&image->lock); 578 memcpy( &image->vmap, &camera->vmap[camera->grab_frame], sizeof(image->vmap)); 579 580 data = camera->videoBuffer + camera->vmbuf.offsets[camera->grab_frame]; 581 582 if (cameratype==2) 583 { 584 unsigned short *len = (unsigned short *)(&(image->data[image->cur][0])); 585 image->size = *len; 586 memcpy( image->data[image->cur], data, image->size); 587 } 588 else 589 { 590 image->size = image->vmap.width * image->vmap.height * 3 / 2; 591 memcpy( image->data[image->cur], data, image->size); 592 } 593 594 cur = image->cur; 595 last = (image->cur+1)%2; 596 597 /* Now we have the color-corrected image in image->data 598 Compress it and signal sender to send it off... 599 */ 600#ifdef WL600 601 if ((diff = compare_images(image->data[cur], image->data[last], image->vmap.width, image->vmap.height))>max_count || newclient || idletimeout>5) 602#else 603 if ((diff = compare_images(image->data[cur], image->data[last], image->vmap.width, image->vmap.height))>max_diff || newclient || idletimeout>5) 604#endif 605 { 606 idletimeout = 0; 607 608 if (newclient) 609 newclient = 0; 610 611 image->cur = last; 612 613 //printf("Send image %d %d %d %d\n", imagecount++, last, image->cur, cur); 614 add_time(&image->data[cur], image->vmap.width, image->vmap.height); 615 616 if (clients) 617 { 618 /* Image : size + data */ 619 sender(image->data[cur], image->size); 620 } 621#ifdef WL600 622 if (clients == NULL || recordtime == 0) 623 { 624 // When to record image: 625 // 1. Mail alert and there is difference 626 // 2. No mail alert, but record time reach 627 628 if (!(tmp_alertflag==ALERT_ONTIME&&diff<=max_count)) 629 { 630 recordindex = (recordindex+1)%image_cycle; 631 sprintf(recordfile, "/var/tmp/record%d.jpg", recordindex); 632 add_time(image->data[cur], image->vmap.width, image->vmap.height); 633 put_image_jpeg(recordfile, image->data[cur], image->vmap.width, image->vmap.height, 50); 634 unlink("/var/tmp/display.jpg"); 635 symlink(recordfile, "/var/tmp/display.jpg"); 636 fp = fopen("/var/tmp/webcam.log","w"); 637 if (fp!=NULL) 638 { 639 fprintf(fp, "WebPic=\"%d\"\n", recordindex); 640 fclose(fp); 641 } 642 } 643 644 if (clients==NULL && tmp_alertflag==ALERT_ONTIME) 645 { 646 alertstart++; 647 648 if (diff>max_count) 649 { 650 alertcount++; 651 if (alertcount==1) 652 { 653 sprintf(alertfiles, "sendalarm %s", recordfile); 654 if (debug) printf("Start to collect alert message\n"); 655 } 656 else 657 { 658 sprintf(alertfiles, "%s %s", alertfiles, recordfile); 659 // 20030812 by Joey, if image is too large, send less images 660 if (alertcount>=image_cycle) 661 { 662 alertstart = 12; 663 } 664 if (debug) printf("Alert :%d\n", alertstart); 665 } 666 } 667 } 668 if (debug) printf("Save to file : %s\n", recordfile); 669 } 670#endif 671 } else { 672 if (debug>1) 673 printf("not different enough %d %d\n", cur, last); 674 idletimeout++; 675 } 676#ifdef WL600 677 //printf("Alert? : %x %x %x\n", tmp_alertflag, alertstart, watchdogpid); 678 679 if (tmp_alertflag==ALERT_ONTIME && alertstart>=12) 680 { 681 FILE *fp; 682 int pid; 683 684 fp = fopen("/var/tmp/runshell", "w"); 685 fprintf(fp, "%s &", alertfiles); 686 fclose(fp); 687 688 //fp = fopen("/etc/linuxigd/runshell1", "w"); 689 //fprintf(fp, "%s &", alertfiles); 690 //fclose(fp); 691 692 //printf("Alertfile: %s\n", alertfiles); 693 if (watchdogpid==-1) 694 { 695 fp = fopen("/var/run/watchdog.pid", "r"); 696 if (fp!=NULL) 697 { 698 fscanf(fp, "%d", &watchdogpid); 699 } 700 fclose(fp); 701 } 702 if (watchdogpid!=-1) 703 { 704 kill(watchdogpid, SIGUSR2); 705 tmp_alertflag = ALERT_OFFTIME; 706 } 707 alertstart = 0; 708 alertcount = 0; 709 } 710#endif 711 712 pthread_mutex_unlock(&image->lock); 713 714 /* Set up alarm for VIDIOCSYNC */ 715 alarm(2); 716 ioctl(camera->video_fd, VIDIOCSYNC, &camera->vmap[camera->grab_frame]); 717 /* Release alarm for VIDIOCSYNC */ 718 alarm(0); 719 camera->grab_frame = 1 - camera->grab_frame; 720} 721 722unsigned int 723compare_images(unsigned char *last, unsigned char *current, 724 int width, int height) 725{ 726 unsigned char *p1 = last; 727 unsigned char *p2 = current; 728 int avg, diff, max, i = width*height*3/2; /* divide by 2 is for YUV420P CAPTURE */ 729 int count; 730 731 count = 0; 732 733 for (max = 0, avg = 0; --i; p1++,p2++) 734 { 735 diff = (*p1 < *p2) ? (*p2 - *p1) : (*p1 - *p2); 736 avg += diff; 737 if (diff > max) 738 max = diff; 739 740 if (diff>max_diff) count++; 741 } 742 743 avg = avg / width / height; 744 if (debug>1) 745 printf("compare: max=%d,avg=%d,count=%d\n",max,avg,count); 746 /* return avg */ 747#ifdef WL600 748 /* Modify by Joey to return count that more than threshold */ 749 return count; 750#else 751 return max; 752#endif 753} 754 755 756/************************************************************************/ 757 758int setup_memory_mapping( struct CaptureData *camera ) 759{ 760 int retval = 0; 761 762 if ( (retval = ioctl(camera->video_fd,VIDIOCGMBUF,&camera->vmbuf)) < 0 ) { 763 perror("failed VIDIOCGMBUF\n"); 764 return -1; 765 } 766 767 camera->videoBuffer = (unsigned char *) mmap(0, camera->vmbuf.size, 768 PROT_READ|PROT_WRITE, 769 MAP_SHARED, camera->video_fd, 0); 770 if ( camera->videoBuffer == MAP_FAILED ) { 771 perror("unable to map memory\n"); 772 return -1; 773 } 774 camera->vmap[0].frame = 0; 775 camera->vmap[0].format = camera->vpic.palette; 776 camera->vmap[0].width = camera->vwin.width; 777 camera->vmap[0].height = camera->vwin.height; 778 779 camera->vmap[1].frame = 1; 780 camera->vmap[1].format = camera->vpic.palette; 781 camera->vmap[1].width = camera->vwin.width; 782 camera->vmap[1].height = camera->vwin.height; 783 return 0; 784} 785 786#ifdef WL600 787static char rgbimage[160*120*3]; 788 789/* 790 * Write image buffer to timestamp named jpeg file. 791 */ 792 793void 794put_image_jpeg (char *filename, char *image, int width, int height, int quality) 795{ 796 int y, x, line_width; 797 JSAMPROW row_ptr[1]; 798 struct jpeg_compress_struct cjpeg; 799 struct jpeg_error_mgr jerr; 800 char *line; 801 char *imageptr; 802 int index, gray; 803 FILE *fd; 804 805 if ((fd = fopen (filename, "w+")) == NULL) { 806 fprintf (stderr, "Error: Can't Create File %s\n", filename); 807 //exit (-2); 808 return; 809 } 810 811 /* Add by Joey to handle OV519 frame */ 812#ifndef REMOVE 813 if (cameratype==2) 814 { 815 unsigned short *len; 816 817 len = (unsigned short *)(&image[0]); 818 *len = (*len)<<3; 819 //printf("OV519 : len: %x\n", *len); 820 fwrite(image + 2, sizeof(unsigned char), *len, fd); 821 fclose(fd); 822 return; 823 } 824#endif 825 gray = 0; 826 827 if (cameratype!=2) 828 { 829 if (width<=160&&height<=120) 830 { 831 ccvt_420p_bgr24(width, height, image, image + width*height, image + (width*height)+(width*height/4), rgbimage); 832 imageptr=rgbimage; 833 } 834 else 835 { 836 gray = 1; 837 imageptr=image; 838 } 839 } 840 else 841 { 842 imageptr = image; 843 } 844 845 line = malloc (width * 3); 846 if (!line) return; 847 cjpeg.err = jpeg_std_error (&jerr); 848 jpeg_create_compress (&cjpeg); 849 cjpeg.image_width = width; 850 cjpeg.image_height = height; 851 cjpeg.input_components = 3; 852 cjpeg.in_color_space = JCS_RGB; 853 jpeg_set_defaults (&cjpeg); 854 855 jpeg_set_quality (&cjpeg, quality, TRUE); 856 //cjpeg.dct_method = JDCT_FASTEST; 857 cjpeg.dct_method = JDCT_DEFAULT; 858 jpeg_stdio_dest (&cjpeg, fd); 859 860 jpeg_start_compress (&cjpeg, TRUE); 861 862 row_ptr[0] = line; 863 line_width = width * 3; 864 index = 0; 865 866 for (y = 0; y < height; y++) 867 { 868 //imageptr = image + width; 869 for (x = 0; x < line_width; x+=3) 870 { 871 if (gray) 872 { 873 line[x]=imageptr[0]; 874 line[x+1]=imageptr[0]; 875 line[x+2]=imageptr[0]; 876 imageptr+=1; 877 } 878 else 879 { 880 line[x]=imageptr[2]; 881 line[x+1]=imageptr[1]; 882 line[x+2]=imageptr[0]; 883 imageptr+=3; 884 } 885 } 886 jpeg_write_scanlines (&cjpeg, row_ptr, 1); 887 //image += line_width; 888 //image += width; 889 } 890 891 jpeg_finish_compress (&cjpeg); 892 jpeg_destroy_compress (&cjpeg); 893 free (line); 894 fclose (fd); 895} 896 897void sig_usr(int sig) 898{ 899 //printf("Signal %d\n", sig); 900 FILE *fp; 901 902 if (sig==SIGUSR1) 903 { 904 if ((fp=fopen("/var/run/rcamd.pid","r"))==NULL) 905 { 906 closesocklist(); 907 munmap(gCamera.videoBuffer, gCamera.vmbuf.size); 908 close_camera( &gCamera ); 909 g_timer_stop( gCamera.timer ); 910 g_timer_destroy(gCamera.timer); 911 pthread_mutex_destroy( &gCamera.desired.lock ); 912 pthread_cond_destroy( &gCamera.desired.cond ); 913 pthread_mutex_destroy( &gCamera.image.lock ); 914 pthread_mutex_destroy(&clients_lock); 915 exit(0); 916 } 917 else 918 { 919 fclose(fp); 920 /* Used to enable alert */ 921 if (alertflag) 922 { 923 tmp_alertflag = ALERT_ONTIME; 924 } 925 } 926 } 927 else if(sig==SIGUSR2) 928 { 929 /* Used to disable alert */ 930 if (clients==NULL) 931 { 932 if (tmp_alertflag == ALERT_ONTIME) 933 { 934 alertstart = alertcount = 0; 935 tmp_alertflag = ALERT_OFFTIME; 936 } 937 } 938 } 939 if (debug) printf("Signal: %d %d\n", sig, tmp_alertflag); 940} 941 942void sig_alrm(int sig) 943{ 944 closesocklist(); 945 munmap(gCamera.videoBuffer, gCamera.vmbuf.size); 946 close_camera( &gCamera ); 947 g_timer_stop( gCamera.timer ); 948 g_timer_destroy(gCamera.timer); 949 pthread_mutex_destroy( &gCamera.desired.lock ); 950 pthread_cond_destroy( &gCamera.desired.cond ); 951 pthread_mutex_destroy( &gCamera.image.lock ); 952 pthread_mutex_destroy(&clients_lock); 953 if (debug) printf("Signal SIGALRM\n"); 954} 955#endif 956 957int main (int argc, char *argv[]) 958{ 959 int i, nFrames=0, waittime; 960 gdouble prevTime, curTime; 961 sigset_t sig; 962 FILE *fp; 963 964 // parse cmdline args 965 while((i = getopt(argc, argv, "t:d:m:s:f:p:hg:b: 966#ifdef WL600 967 r:a:c:z: 968#endif 969 ")) != EOF) { 970 971 switch(i) { 972 case 't': 973 cameratype = atoi(optarg); 974 break; 975 case 'd': 976 debug = atoi(optarg); 977 break; 978 case 'm': 979 max_diff = atoi(optarg); 980 break; 981 case 's': 982 seconds = atoi(optarg); 983 break; 984 case 'f': 985 sscanf (optarg, "%dx%d", &width, &height); 986 if (width>320) image_cycle = 2; 987 else image_cycle = 6; 988 break; 989 case 'p': 990 port = atoi(optarg); 991 break; 992 case 'b': 993 brightness = atoi(optarg); 994 MYCLAMP(brightness, 1, 500); 995 break; 996 case 'g': 997 gain = atoi(optarg); 998 MYCLAMP(gain, 0, 4); 999 gain = (0x1<<gain)>>1; 1000 break; 1001#ifdef WL600 1002 case 'r': 1003 recordtime = (long )atoi(optarg); 1004 recordtime = recordtime*60; 1005 recordindex=0; 1006 //printf("Record Time: %d\n", recordtime); 1007 break; 1008 case 'a': 1009 alertflag = atoi(optarg); 1010 if (alertflag) 1011 tmp_alertflag = ALERT_OFFTIME; 1012 else 1013 tmp_alertflag = ALERT_DISABLED; 1014 break; 1015 case 'c': 1016 max_count = atoi(optarg); 1017 break; 1018 case 'z': 1019 setenv("TZ", optarg, 1); 1020 break; 1021#endif 1022 case 'h': 1023 default: 1024 printf("Usage: rcamd [options]\n"\ 1025 " -d <debug level>\n"\ 1026 " -m <max difference threshold=0-255> (lower->more updates, default=30)\n"\ 1027 " -s <seconds between frames> (default==1)\n"\ 1028 " -f <WidthxHeight obey supported size> define size of the output image (default:640x480)\n"\ 1029 " -p <port to listen for connections>\n"\ 1030 " -b <brightness=1-500> (default=400 available only cameratype=1)\n"\ 1031 " -g <gain=0-4> corresponding to a gain of 2^<gain> (default=0)\n"\ 1032 " -t <cameratype=0,1> corresponding to a camera driver (0:pwc or 1:ov511 default=0)\n"\ 1033 " -r <record interval=0-65535> (default=60 minutes)\n"\ 1034 " -a <alert=0,1> define if alert is on or off)\n"\ 1035 " -s <max count for difference threshold=0-999999> (default=100)\n"\ 1036 " -z <time zone string>\n"); 1037 exit(0); 1038 } 1039 } 1040 1041 grab_retry = 0; 1042 1043 if (debug) printf("RCAMD 0.06 using debug=%d, maxdiff=%d, secs=%d, size=%dx%d, port=%d, bright=%d, gain=%d, cameratype=%d\n", debug, max_diff, seconds, width, height, port, brightness, gain, cameratype); 1044 1045#ifdef WL600 1046 //if (daemon(NULL, 1) == -1) 1047 //{ 1048 // perror("daemon"); 1049 // exit(errno); 1050 //} 1051 1052 /* Add signal handle for timer, mode change */ 1053 mypid = getpid(); 1054 sigemptyset(&sig); 1055 sigaddset(&sig, SIGPIPE); 1056 sigprocmask(SIG_BLOCK, &sig, NULL); 1057 signal(SIGUSR1, sig_usr); 1058 signal(SIGUSR2, sig_usr); 1059 signal(SIGALRM, sig_alrm); 1060 1061 if ((fp=fopen("/var/run/rcamd.pid","w"))!=NULL) 1062 { 1063 fprintf(fp, "%d", mypid); 1064 fclose(fp); 1065 } 1066#endif 1067 1068Retry: 1069 // Initialize the storage structures 1070 memset(&gCamera,0,sizeof(struct CaptureData)); 1071 gCamera.current_display = SMALL_IMAGE; 1072 1073 pthread_mutex_init(&gCamera.desired.lock, NULL ); 1074 pthread_cond_init(&gCamera.desired.cond, NULL ); 1075 pthread_mutex_init(&gCamera.image.lock, NULL ); 1076 1077 if (!retryflag) 1078 { 1079 pthread_mutex_init(&clients_lock, NULL ); 1080 } 1081 1082 open_camera( &gCamera); 1083 set_camera_info(&gCamera); 1084 get_camera_info(&gCamera); 1085 1086 if (!retryflag) 1087 { 1088 pthread_create(&server_thread, NULL, (void *)&server, NULL); 1089 } 1090 1091 if ( setup_memory_mapping( &gCamera )) 1092 exit(1); 1093 1094 gCamera.timer = g_timer_new(); 1095 g_timer_start( gCamera.timer ); 1096 1097 prevTime = g_timer_elapsed(gCamera.timer, NULL); 1098 gCamera.image.cur=0; 1099 1100 retryflag = 0; 1101 1102 while (1) 1103 { 1104 if (retryflag) 1105 { 1106 //logmessage("USB webcam", "Reset Webcam\n"); 1107 break; 1108 } 1109#ifdef WL600 1110 if (clients==NULL) 1111 { 1112 if (recordtime>0&&tmp_alertflag!=ALERT_ONTIME) 1113 { 1114 int rt; 1115 1116 rt = recordtime; 1117 //printf("Fall in sleep %d\n", recordtime); 1118 while(rt) 1119 { 1120 sleep(1); 1121 rt--; 1122 if (clients || tmp_alertflag == ALERT_ONTIME) break; 1123 } 1124 //printf("Wake up\n"); 1125 } 1126 } 1127 if (debug) printf("Status: %d %d %d\n", tmp_alertflag, alertstart, alertcount); 1128#endif 1129 if (!grab_image( &gCamera )) 1130 { 1131 is_grabed=0; 1132 retryflag=1; 1133 continue; 1134 } 1135 else 1136 { 1137 first_grabed=1; 1138 is_grabed=1; 1139 } 1140 1141 process_image( &gCamera ); 1142 //printf("End of process image outside\n"); 1143 curTime = g_timer_elapsed(gCamera.timer, NULL); 1144 //sleep until next capture 1145 if (seconds!=0) { 1146 waittime = (int)(1000000.0*(double)seconds-1000000.0*(curTime-prevTime)); 1147 if (debug) 1148 printf("Waiting %f %f %f %d - %d = %d seconds\n", curTime, prevTime, curTime-prevTime, 1000000*seconds, (int)(1000000.0*(curTime-prevTime)), waittime); 1149 if (waittime > 0) 1150 usleep(waittime); 1151 } 1152 1153 curTime = g_timer_elapsed(gCamera.timer, NULL); 1154 if (curTime != 0.0 && curTime > prevTime) 1155 { 1156 if (debug) 1157 printf("Speed: avg(%6.2f fps) cur(%6.2f fps)\n", 1158 ++nFrames/curTime, 1.0/(curTime - prevTime)); 1159 } 1160 prevTime = curTime; 1161 } 1162 1163 gQuitFlag = TRUE; 1164 closesocklist(); 1165 close_camera( &gCamera ); 1166 g_timer_stop( gCamera.timer ); 1167 g_timer_destroy(gCamera.timer); 1168 pthread_mutex_destroy( &gCamera.desired.lock ); 1169 pthread_cond_destroy( &gCamera.desired.cond ); 1170 pthread_mutex_destroy( &gCamera.image.lock ); 1171 pthread_mutex_destroy(&clients_lock); 1172 return 0; 1173} 1174 1175decompress_jpeg(char *buf, int size, char *data) 1176{ 1177 1178} 1179