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

📄 vidcat.c

📁 此程序是一个通用的摄像头抓图程序
💻 C
📖 第 1 页 / 共 2 页
字号:
	}
	fflush (out);
}

/*
 * write pgm image to stdout / file
 */
void
put_image_pgm (FILE *out, char *image, int width, int height, int binary)
{
	int x, y, ls=0;
	unsigned char *p = (unsigned char *)image;
	if (!binary) {
		fprintf (out, "P2\n%d %d\n%d\n", width, height, 255);
		for (x = 0; x < width; x++) {
			for (y = 0; y < height; y++) {
				fprintf (out, "%03d ", p[0]);
				p++;
				if (ls++ > 4) {
					fprintf (out, "\n");
					ls = 0;
				}
			}
		}
		fprintf (out, "\n");
	} else {
		fprintf (out, "P5\n%d %d\n%d\n", width, height, 255);
		for (x = 0; x < width * height; x++) {
			fwrite (p, 1, 1, out);
			p++;
		}
	}
	fflush (out);
}

/*
 * write YUV4MPEG stream which is nice for mpeg2enc
 */
int
to_yuv (FILE *out, int fd, int width, int height)
{
	struct video_mbuf vid_buf;
	struct video_mmap vid_mmap;
	int do_read = 0;
	int done = 0;
	char *map;
	int size;
	int num = 0;
	double ms_time0, ms_time1;
	int tpf = 40;	/* 40 ms time per frame (= 25 fps) */

	if (ioctl (fd, VIDIOCGMBUF, &vid_buf) == -1) {
		do_read = 1;
	} else {
		fprintf (stderr, "buffsize=%d frames=%d\n",vid_buf.size,vid_buf.frames);
	}

	if (!do_read) {
		map = mmap (0, vid_buf.size, PROT_READ|PROT_WRITE,MAP_SHARED, fd, 0);
		if ((unsigned char *)-1 == (unsigned char *)map) {
			perror ("mmap()");
			return -1;
		}
		vid_mmap.format = VIDEO_PALETTE_YUV420P;
		vid_mmap.frame = 0;
		vid_mmap.width = width;
		vid_mmap.height =height;
		size = (width * height) + (width * height / 2);

		fprintf (stderr, "%dx%d bufsize=%d size=%d\n",
				width, height, vid_buf.size, size);

		printf ("YUV4MPEG%d %d %d\n", width, height, 3);

		if (ioctl (fd, VIDIOCMCAPTURE, &vid_mmap) == -1) {
			perror ("ioctl VIDIOCMCAPTURE");
			munmap (map, vid_buf.size);
			return -1;
		}
		vid_mmap.frame = 1;
		if (ioctl (fd, VIDIOCMCAPTURE, &vid_mmap) == -1) {
			perror ("ioctl VIDIOCMCAPTURE");
			munmap (map, vid_buf.size);
			return -1;
		}
		while (!done) {
			ms_time0 = ms_time(); /* milli seconds */
			vid_mmap.frame = vid_mmap.frame > 0 ? 0 : 1;
			if (ioctl (fd, VIDIOCSYNC, &vid_mmap.frame) == -1) {
				perror ("ioctl VIDIOCSYNC");
				munmap (map, vid_buf.size);
				return -1;
			}
			printf ("FRAME\n");
			fwrite (map + vid_buf.offsets[vid_mmap.frame], 1, size, stdout);
			if (ioctl (fd, VIDIOCMCAPTURE, &vid_mmap) == -1) {
				perror ("ioctl VIDIOCMCAPTURE");
				munmap (map, vid_buf.size);
				return -1;
			}
			num++;
			ms_time1 = ms_time () - ms_time0;
			if (ms_time1 < (double)tpf) {
				usleep (tpf - (int)ms_time1);
			} else {
				fprintf (stderr, "delayed: dt=%f\n",ms_time1 - (double)tpf);
			}
		}
		munmap (map, vid_buf.size);
	} else {
		fprintf (stderr, "still not implemented\n");
	}
	return 0;
}

/*
 * main()
 */
int
main (int argc, char *argv[])
{
	int width = DEF_WIDTH, height = DEF_HEIGHT, size, dev = -1, c;
	char *image, *device = VIDEO_DEV, *file = NULL;
	int max_try = 5;	/* we try 5 seconds/times to open the device */
	int quality = QUAL_DEFAULT;	/* default jpeg quality setting */
	int input = INPUT_DEFAULT; /* this means take over current device settings*/
	int norm  = NORM_DEFAULT;
	int loop =0 ;
	int binary = 0;
	int palette = VIDEO_PALETTE_RGB24;
	//int palette = VIDEO_PALETTE_YUV420;
	int num = 0;
	FILE *out = stdout;
#ifdef HAVE_LIBJPEG
	int format = FMT_JPEG;
#else
#	ifdef HAVE_LIBPNG
	int format = FMT_PNG;
#	else
	int format = FMT_PPM;
#	endif
#endif

	while ((c = getopt (argc, argv, "bd:f:gi:ln:o:p:q:s:vV")) != EOF) {
		switch (c) {
			case 'b': /* PPM as binary file */
				binary = 1;
				break;
			case 'd': /* change default device */
				device = optarg;
				break;
			case 'f':
				if (strcasecmp ("yuv4mpeg", optarg) == 0)
					format = FMT_YUV4MPEG;
				else if (strcasecmp ("png", optarg) == 0)
					format = FMT_PNG;
				else if (strcasecmp ("ppm", optarg) == 0)
					format = FMT_PPM;
				else if (strcasecmp ("pgm", optarg) == 0) {
					format = FMT_PGM;
					palette = VIDEO_PALETTE_GREY;
				} else if (strcasecmp ("jpeg", optarg) == 0)
					format = FMT_JPEG;
				else
					format = FMT_UNKNOWN;
				break;
			case 'g':
				palette = VIDEO_PALETTE_GREY;
				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;
				} else {
					usage (argv[0]);
				}
				break;
			case 'l':
				loop = 1;
				break;
			case 'n':
				if (strcasecmp ("pal", optarg) == 0)
					norm = NORM_PAL;
				else if (strcasecmp ("ntsc", optarg) == 0)
					norm = NORM_NTSC;
				else if (strcasecmp ("secam", optarg) == 0)
					norm = NORM_SECAM;
				else
					usage (argv[0]);
				break;
			case 'o':
				file = optarg;
				break;
			case 'p':
				switch (*optarg) {
					case 'R':
					case 'c':
						palette = VIDEO_PALETTE_RGB24;
						break;
					case 'y':
						palette = VIDEO_PALETTE_YUV420P;
						break;
					case 'Y':
						palette = VIDEO_PALETTE_YUV422P;
						break;
					case 'g':
						palette = VIDEO_PALETTE_GREY;
						break;
					default:
						usage (argv[0]);
						break;
				}
				break;
			case 'q':
				sscanf (optarg, "%d", &quality);
				break;
			case 's':
				sscanf (optarg, "%dx%d", &width, &height);
				break;
			case 'v':
				verbose++;
				break;
			case 'V':
				printf ("Vidcat, Version %s\n", VERSION);
				exit (0);
				break;
			default:
				usage (argv[0]);
				break;
		}
	}
	if (verbose) {
		fprintf (stderr, "input palette: %s\n",
			palette == VIDEO_PALETTE_GREY ? "grey" :
			palette == VIDEO_PALETTE_RGB24 ? "rgb" :
			palette == VIDEO_PALETTE_YUV420P ? "yuv420" : "yuv422");
		fprintf (stderr, "size: %dx%d\n", width, height);
	}
	if (file) {
		out = fopen (file, "wb");
		if (!out) {
			perror (file);
			return 1;
		}
	}
again:
	/* open the video4linux device */
	while (max_try) {
		dev = open (device, O_RDWR);
		if (dev == -1) {
			if (!--max_try) {
				fprintf (stderr, "Can't open device %s\n", device);
				return (1);
			}
			sleep (1);
		} else { break; }
	}
	if (!num) {
		/* if we loop we have to do this only once. so
		 * check frame number and execute only for the
		 * frame number "0".
		 */
		if (v4l_set_input (dev, input, norm) == -1) {
			return (1);
		}
		if (v4l_check_size (dev, &width, &height) == -1) {
			return (1);
		}
		/*if (v4l_check_palette (dev, &palette) == -1) {
			return (1);
		}*/
	}
	switch (format) {
		case FMT_YUV4MPEG:
			if (palette == VIDEO_PALETTE_YUV420P)
				return to_yuv (out, dev, width, height);
			break;
	}
	image = get_image (dev, width, height, palette, &size); //从v4l设备获取rgb图像
	if (!size)
		close (dev);
	if (image) {
		switch (format) {
			case FMT_PPM:
				if (palette == VIDEO_PALETTE_GREY)
					put_image_pgm (out, image, width, height, binary);
				else
					put_image_ppm (out, image, width, height, binary);
				break;
			case FMT_PGM:
				put_image_pgm (out, image, width, height, binary);
				break;
			case FMT_PNG:
				put_image_png (out, image, width, height, palette);
				break;
			case FMT_JPEG:
				put_image_jpeg (out, image, width, height, quality, palette);
				break;
			default:
				fprintf (stderr, "Unknown format (%d)\n", format);
				break;
		}
		if (size) {
			munmap (image, size);
			close (dev);
		} else if (image) {
			free (image);
		}
		if (loop) {
			num++;
			goto again;
		}
	} else {
		fprintf (stderr, "Error: Can't get image\n");
	}
	return (0);
}


⌨️ 快捷键说明

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