⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mvc.c

📁 mvc源码
💻 C
字号:
/* * vidcat.c * * Copyright (C) 1998 Rasca, Berlin * EMail: thron@gmx.de * Modified: merlin@turbolinux.com.cn Jun.16, Jul.7, 2000 * * 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. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <getopt.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/ioctl.h>#include <sys/mman.h>#include <fcntl.h>#include <unistd.h>#include <linux/types.h>#include <linux/videodev.h>#include <time.h>#include <jpeglib.h>#include "mvc.h"/* * read rgb image from v4l device * return: mmap'ed buffer and size */char *get_image (int dev, int width, int height, int input, int norm, int fmt,	   int *size){  struct video_capability vid_caps;  struct video_mbuf vid_buf;  struct video_mmap vid_mmap;  struct video_channel vid_chnl;  char *map;  int len;  if (ioctl (dev, VIDIOCGCAP, &vid_caps) == -1)   {    perror ("ioctl (VIDIOCGCAP)");    return (NULL);  }  vid_chnl.channel = -1;  if (ioctl (dev, VIDIOCGCHAN, &vid_chnl) == -1)   {    perror ("ioctl (VIDIOCGCHAN)");  }  else   {	printf("get channel failed\n");    vid_chnl.channel = input;    vid_chnl.norm = norm;    if (ioctl (dev, VIDIOCSCHAN, &vid_chnl) == -1) 	{      perror ("ioctl (VIDIOCSCHAN)");      return (NULL);    }	else	  printf("get channel failed. but set channel success\n\n");  }  if (ioctl (dev, VIDIOCGMBUF, &vid_buf) == -1)   {    map = malloc (width * height * 3);    len = read (dev, map, width * height * 3);    if (len <= 0) 	{      free (map);      return (NULL);    }    *size = 0;    return (map);  }  //void  *  mmap(void *start, size_t length, int prot , int flags, int fd, off_t offset);  //int munmap(void *start, size_t length);  //mmap returns a pointer  to  the  mapped  area ,or MAP_FAILED  (-1)  is returned  map = mmap (0, vid_buf.size, PROT_READ | PROT_WRITE, MAP_SHARED, dev, 0);  if ((unsigned char *) -1 == (unsigned char *) map)  //???? what's the meaning?  {    perror ("mmap()");    return (NULL);  }  vid_mmap.format = fmt;  vid_mmap.frame = 0;  vid_mmap.width = width;  vid_mmap.height = height;  if (ioctl (dev, VIDIOCMCAPTURE, &vid_mmap) == -1)   {    perror ("VIDIOCMCAPTURE");    munmap (map, vid_buf.size);    return (NULL);  }  if (ioctl (dev, VIDIOCSYNC, &vid_mmap) == -1)   {    perror ("VIDIOCSYNC");    munmap (map, vid_buf.size);    return (NULL);  }  *size = vid_buf.size;  return (map);}/* * Write image buffer to timestamp named jpeg file. */voidput_image_jpeg (char *filename, char *image, int width, int height,		int quality){  int y, x, line_width;  JSAMPROW row_ptr[1];  struct jpeg_compress_struct cjpeg;  struct jpeg_error_mgr jerr;  char *line;  FILE *fd;  if ((fd = fopen (filename, "w+")) == NULL) {    fprintf (stderr, "Error: Can't Create File %s\n", filename);    exit (-2);  }  line = malloc (width * 3);  if (!line)    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, fd);  jpeg_start_compress (&cjpeg, TRUE);  row_ptr[0] = 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 (fd);}/* * main() */intmain (int argc, char *argv[]){  int width = DEF_WIDTH, height = DEF_HEIGHT, size, dev = -1, c, n = 0;  char *image, *oldimg, *device = VIDEO_DEV;  char lasttime[32], timename[32], filename[64];  time_t now;  struct tm *tm;  int max_try = 5;		/* we try 5 seconds/times to open the device */  int quality = QUAL_DEFAULT;	/* default jpeg quality setting */  int input = IN_DEFAULT;  int norm = NORM_DEFAULT;  int palette = VIDEO_PALETTE_RGB24;  int blk_x = 16;  int blk_y = 8;  int color_lim = 50;  int blk_lim = blk_x * blk_y / 64 + 1;  oldimg = malloc (width * height * 3);  while ((c = getopt (argc, argv, "s:q:a:b:c:n:i:d")) != EOF) {    switch (c) {    case 'd':      device = optarg;      break;    case 's':      sscanf (optarg, "%dx%d", &width, &height);      break;    case 'a':      sscanf (optarg, "%dx%d", &blk_x, &blk_y);      blk_lim = blk_x * blk_y / 64 + 1;      break;    case 'b':      sscanf (optarg, "%d", &blk_lim);      break;    case 'c':      sscanf (optarg, "%d", &color_lim);      break;    case 'n':      if (strcasecmp ("ntsc", optarg) == 0) {	norm = NORM_NTSC;      }      else if (strcasecmp ("pal", optarg) == 0) {	norm = NORM_PAL;      }      else if (strcasecmp ("secam", optarg) == 0) {	norm = NORM_SECAM;      }      break;    case 'q':      sscanf (optarg, "%d", &quality);      break;    case 'i':      if (strcasecmp ("tv", optarg) == 0) {	input = IN_TV;      }      else if (strcasecmp ("comp1", optarg) == 0) {	input = IN_COMPOSITE;      }      else if (strcasecmp ("comp2", optarg) == 0) {	input = IN_COMPOSITE2;      }      else if (strcasecmp ("s-video", optarg) == 0) {	input = IN_SVIDEO;      }      break;    default:      fprintf (stderr,	       "%s, Version %s\n"	       "Usage: %s <options>\n"	       " -s XxY define size of the output image (default: %dx%d)\n"	       " -a HxV define sense areas in Horizantal and Vertical (default: %dx%d)\n"	       " -i {tv|comp1|comp2|s-video} which input channel to use\n"	       " -n {pal|ntsc|secam}         which norm to use, default: PAL\n"	       " -q <quality>                only for jpeg: quality setting (1-100, default: %d)\n"	       " -d <device>                 video device (default: " VIDEO_DEV ")\n"	       " -b <diff_block_limit>       blocks different limit, default: %d\n"	       " -c <diff_color_limit>       color  different limit, default: %d\n",	       argv[0], VERSION, argv[0], DEF_WIDTH, DEF_HEIGHT, blk_x, blk_y,	       QUAL_DEFAULT, blk_lim, color_lim);      exit (1);      break;    }  }#ifdef DEBUG  fprintf (stderr, "-------------------- Debug Info ---------------------\n");  fprintf (stderr, " ImageSize:    %dx%d\n", width, height);  fprintf (stderr, " ImageQuality: %d\n", quality);  fprintf (stderr, " VideoDEV:     %s\n", device);  fprintf (stderr, " VideoInput(TV=0, COMP1=1, COMP2=2, SVIDEO=3): %d\n",	   input);  fprintf (stderr, " VideoNORM(PAL=0, NTSC=1, SECAM=2, AUTO=3): %d\n", norm);  fprintf (stderr, " SenseBlockSize: %dx%d\n", blk_x, blk_y);  fprintf (stderr, " ColorLimit:   %d\n", color_lim);  fprintf (stderr, " BlockLimit:   %d\n", blk_lim);  fprintf (stderr, "-----------------------------------------------------\n");#endifloop:  /* open the video4linux device */  max_try = 5;  while ((dev = open (device, O_RDWR)) == -1 && --max_try)    sleep (1);  if (dev == -1) {    fprintf (stderr, "Can't open device %s\n", VIDEO_DEV);    exit (-1);  }  else  {	  printf("device opening success!");  }  image = get_image (dev, width, height, input, norm, palette, &size);  if (image) {    if (cmp_img(image, oldimg, width, height, blk_x, blk_y, color_lim,	blk_lim) == 1) {      time (&now);      tm = localtime (&now);      strftime (timename, 31, "%Y%m%d-%H%M%S", tm);      if (strcmp (timename, lasttime) == 0)	n++;      else	n = 0;      strcpy (lasttime, timename);      sprintf (filename, "mvc%s-%d.jpg", timename, n);#ifdef DEBUG      printf ("Writing: %s \a\n", filename);#endif      put_image_jpeg (filename, image, width, height, quality);    }    memcpy (oldimg, image, width * height * 3);    if (size)      munmap (image, size);    else if (image)      free (image);  }  else {    fprintf (stderr, "Error: Can't get image\n");  }  close (dev);  usleep (500000);  goto loop;}/* * Compare image img1 and img2 by split blocks,  * if changed, return 1. */intcmp_img (char *img1, char *img2, int width, int height, int split_x,	 int split_y, int c_lim, int b_lim){  int i, count;  RGB a1[8192], a2[8192];  int color_diff[8192];  proc_img (a1, img1, width, height, split_x, split_y);  proc_img (a2, img2, width, height, split_x, split_y);  count = 0;  for (i = 0; i < split_x * split_y; i++) {    color_diff[i] = abs (a1[i].red - a2[i].red) +       abs (a1[i].green - a2[i].green) +      abs (a1[i].blue - a2[i].blue);    if (color_diff[i] > c_lim) {      count++;    }    if (count >= b_lim) {      return 1;    }  }  return 0;}/* * Split image buffer *img (width=w, height=h) into sx * sy blocks.  * For every splited block, calculate its average RGB color, then  * store this RGB color into array r. */intproc_img (RGB * r, char *img, int w, int h, int sx, int sy){  unsigned char *p;  int x, y, m, n;  int blk_wid = w / sx, blk_hgt = h / sy;  int x0, y0, x1, y1;  unsigned long s = blk_wid * blk_hgt;  unsigned long R, G, B;  for (n = 1; n <= sy; n++) {    for (m = 1; m <= sx; m++) {      x0 = (m - 1) * blk_wid;      y0 = (n - 1) * blk_hgt;      x1 = blk_wid * m - 1;      y1 = blk_hgt * n - 1;      R = G = B = 0;      for (y = y0; y <= y1; y++) {	for (x = x0; x <= x1; x++) {	  p = img + (y * w + x) * 3;	  R += *(p + 2);	  G += *(p + 1);	  B += *p;	}      }      r->red = R / s;      r->green = G / s;      r->blue = B / s;      r++;    }  }  return s;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -