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