/* * cam.c * * * * Copyright (C) 2002 - 2002 Benninghaus, Rottweil * EMail: el@eb-themen.de * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef _cam_c #define _cam_c #ifdef __cplusplus extern "C" { #endif #include #include int v_device = -1; struct video_capability vid_caps; int v_imgsize = 0; char *v_image = NULL; int v_len = 0; unsigned char * v_imagebuf = NULL; unsigned char * v_firstbuf = NULL; unsigned char * v_savebuf = NULL; long count = 0; void freeBuffers( void ) { if(v_imagebuf != NULL){ free(v_imagebuf); v_imagebuf = NULL; } if(v_firstbuf != NULL){ free(v_firstbuf); v_firstbuf = NULL; } if(v_savebuf != NULL){ free(v_savebuf); v_savebuf = NULL; } } int createBuffers( void ) { freeBuffers(); v_imagebuf = (unsigned char *)malloc( GENSIZE ); v_firstbuf = (unsigned char *)malloc( GENSIZE ); v_savebuf = (unsigned char *)malloc( GENSIZE ); if( ( v_imagebuf == NULL ) || ( v_firstbuf == NULL ) || ( v_savebuf == NULL ) ) { freeBuffers(); fprintf(stdout,"\nNot enough memory\n"); return(0); } return(1); } void close_video(){ if (v_image && v_imgsize) { munmap (v_image, v_imgsize); v_imgsize = 0; v_image = NULL; } if(v_image != NULL){ free(v_image); v_image = NULL; } if(v_device != -1){ close(v_device); v_device = -1; } v_imgsize = 0; } int open_video() { int max_try = 5; if(v_device != -1){ return(1); } while (max_try) { v_device = open ( cfg.devicefile, O_RDWR); if (v_device == -1) { if (!--max_try) { return(0);; } sleep (1); } else { break; } } #ifndef VIEW if (ioctl (v_device, VIDIOCGCAP, &vid_caps) == -1) { perror ("ioctl (VIDIOCGCAP)"); close_video(); return (0); } fprintf(stdout,"\nName: %s\n",vid_caps.name); fprintf(stdout,"Type: %d\n",vid_caps.type); fprintf(stdout,"Nr channels: %d\n",vid_caps.channels); fprintf(stdout,"MaxWidht: %d\n",vid_caps.maxwidth); fprintf(stdout,"MaxHeight: %d\n",vid_caps.maxheight); fprintf(stdout,"MinWidht: %d\n",vid_caps.minwidth); fprintf(stdout,"MinHeight: %d\n",vid_caps.minheight); #endif count = 0; return(1); } /* * read image from v4l device * return: mmap'ed buffer and size */ char * get_image (int width, int height,int norm,int fmt,int *size) { struct video_mbuf vid_buf; struct video_mmap vid_mmap; struct video_channel vid_chnl; char *map; int len; v_len = 0; if (ioctl (v_device, VIDIOCGMBUF, &vid_buf) == -1) { /* to do a normal read() */ struct video_window vid_win; if (ioctl (v_device, VIDIOCGWIN, &vid_win) != -1) { vid_win.width = width; vid_win.height = height; if (ioctl (v_device, VIDIOCSWIN, &vid_win) == -1) return (NULL); } if(fmt == VIDEO_PALETTE_GREY) { map = (char *)malloc (width * height * 1); len = read (v_device, map, width * height * 1); } else { map = (char *)malloc (width * height * 3); len = read (v_device, map, width * height * 3); } if (len <= 0) { free (map); return (NULL); } v_len = len; *size = 0; return (map); } map = (char *)mmap (0, vid_buf.size, PROT_READ|PROT_WRITE,MAP_SHARED,v_device,0); if ((unsigned char *)-1 == (unsigned char *)map) { perror ("mmap()"); return (NULL); } vid_mmap.format = fmt; vid_mmap.frame = 0; vid_mmap.width = width; vid_mmap.height = height; if (ioctl (v_device, VIDIOCMCAPTURE, &vid_mmap) == -1) { perror ("VIDIOCMCAPTURE"); munmap (map, vid_buf.size); return (NULL); } if (ioctl (v_device, VIDIOCSYNC, &vid_mmap) == -1) { perror ("VIDIOCSYNC"); munmap (map, vid_buf.size); return (NULL); } *size = vid_buf.size; v_len = vid_buf.size; return (map); } /*@@@@@@@@@@@@@*/ int vicount = 0; time_t vistart = 0; /*@@@@@@@@@@@@@*/ char * get_video_image() { if(v_device == -1){ return(NULL); } if (v_image && v_imgsize) { munmap (v_image, v_imgsize); v_imgsize = 0; v_image = NULL; } if(v_image){ free(v_image); v_image = NULL; } v_image = get_image (WIDTH, HEIGHT, 0, VIDEO_PALETTE_RGB24, &v_imgsize); /*@@@@@@@@@@@@@@@@*/ if(v_image){ vicount++; if(vistart == 0){ vistart = time(&vistart); vicount = 0; } else { if(time(NULL) >= ( vistart + 10 )){ fprintf(stderr,"\n%d per 10 sec, %d per sec\n",vicount, vicount / 10 ); vistart = 0; vicount = 0; } } } /*@@@@@@@@@@@@@@@@*/ return(v_image); } int prepare_image( ) { int x = 0; int y = 0; unsigned char *p,*v; if(v_image == NULL){ return(0); } if(v_len < 1){ return(0); } p = (unsigned char *)v_image; v = (unsigned char *)v_imagebuf; while( y < HEIGHT ) { x = 0; while( x < WIDTH ) { v[0] = p[2]; p = p + 3; v++; x++; } y++; } if( count < cfg.calcstart ){ memcpy(v_firstbuf,v_imagebuf,GENSIZE); } if(cfg.savebuf){ memcpy(v_savebuf,v_imagebuf,GENSIZE); } count++; return(1); } /* snapping functions */ /* ----------------------------------------------------------------------------------*/ void put_image_jpeg (char *_image, int width, int height, int quality, char *filename) { int y, x, line_width; JSAMPROW row_ptr[1]; struct jpeg_compress_struct cjpeg; struct jpeg_error_mgr jerr; char *line; FILE *fp; char *image = _image; fp = fopen(filename,"wb"); if(fp == NULL){ return; } line = (char *)malloc (width * 3); if (!line){ fclose(fp); return; } cjpeg.err = jpeg_std_error(&jerr); jpeg_create_compress (&cjpeg); cjpeg.image_width = width; cjpeg.image_height= height; cjpeg.input_components = 3; cjpeg.in_color_space = JCS_RGB; jpeg_set_defaults (&cjpeg); jpeg_set_quality (&cjpeg, quality, TRUE); cjpeg.dct_method = JDCT_FASTEST; jpeg_stdio_dest (&cjpeg, fp); jpeg_start_compress (&cjpeg, TRUE); row_ptr[0] = (JSAMPROW)line; line_width = width * 3; for ( y = 0; y < height; y++) { for (x = 0; x < line_width; x+=3) { line[x] = image[x+2]; line[x+1] = image[x+1]; line[x+2] = image[x]; } jpeg_write_scanlines (&cjpeg, row_ptr, 1); image += line_width; } jpeg_finish_compress (&cjpeg); jpeg_destroy_compress (&cjpeg); free (line); fclose(fp); } long cursnapcount = 0; void snap_image( void ) { char tmptxt[258]; int width,height,x,y; char *image; unsigned char *buf,*p,*v; int imgsize; if( ( cfg.maxsnap ) && ( cursnapcount > cfg.maxsnap ) ){ return; } if(v_device == -1){ return; } switch(cfg.snapsize){ case 0: width = 160;height = 120;/*QSIF*/ break; case 1: width = 176;height = 144;/*QCIF*/ break; case 2: width = 320;height = 240;/*SIF*/ break; case 3: width = 352;height = 288;/*CIF*/ break; case 4: width = 640;height = 480;/*VGA*/ break; default: width = 160;height = 120; break; } image = NULL; buf = NULL; imgsize = 0; image = get_image (width, height, 0, VIDEO_PALETTE_RGB24, &imgsize); if(image && imgsize){ buf = (unsigned char *)malloc( width * height * 3 ); if(buf){ p = (unsigned char *)image; v = (unsigned char *)buf; y = 0; while( y < height ) { x = 0; while( x < width ) { v[0] = p[2]; v[1] = p[1]; v[2] = p[0]; p = p + 3; v = v + 3; x++; } y++; } sprintf(tmptxt,"%s/%s%ld.jpg",cfg.snapdir,cfg.snapprefix,cursnapcount); put_image_jpeg ((char *)buf, width, height, cfg.snapquality, tmptxt); cursnapcount++; } munmap( image, imgsize ); image = NULL; imgsize = 0; } if(image){ free(image); image = NULL; } if(buf){ free(buf); buf = NULL; } } #ifdef __cplusplus } #endif #endif /*_cam_c*/