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

📄 vidcat_ok_1.c

📁 此段代码实现了嵌入式arm平台下从摄像头连续抓图并且实时在LCD上动态显示
💻 C
字号:
/* * vidcat.c * * Copyright (C) 1998 - 2001 Rasca, Berlin * * 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 <sys/time.h>	/* gettimeofday() */#include <fcntl.h>#include <unistd.h>#include <linux/types.h>#include <linux/videodev.h>#include <signal.h>#include <jpeglib.h>#include "v4l.c"int end = 0;#define DEF_WIDTH	320	/* default width */#define DEF_HEIGHT	240	/* default height */#define FMT_UNKNOWN		0#define FMT_PPM			1#define FMT_PGM			2#define FMT_PNG			3#define FMT_JPEG		4#define FMT_YUV4MPEG	5#define FMT_RAW			6#define IN_TV			0#define IN_COMPOSITE	1#define IN_COMPOSITE2	2#define IN_SVIDEO		3#define NORM_PAL		0#define NORM_NTSC		1#define NORM_SECAM		2#define QUAL_DEFAULT	80#define VIDEO_DEV       "/dev/video0"#define VERSION         5#define BMP_BUF_LEN	(640 * 480 * 3)#define RGB565_BUF_LEN	(BMP_BUF_LEN* 2 / 3)void put_image_jpeg (FILE *out, char *image, int width, int height, int quality, int palette);int  to_yuv (FILE *out, int fd, int width, int height);int lcd_display(char *image,int width, int height,int startx,int starty);char *basename (const char *s);/* globals */static int verbose = 0;/* */doublems_time (void){	static struct timeval tod;	gettimeofday (&tod, NULL);	return ((double)tod.tv_sec * 1000.0 + (double)tod.tv_usec / 1000.0);	}#define TIMEOUT		200void alarm_timeout(int signum){	static int i = 0;	if  (i < TIMEOUT) {		i++;		alarm(1);	} else {		end = 1;		}		return;}	/* * read rgb image from v4l device * return: mmap'ed buffer and size */char *get_image (int dev, int width, int height, int palette, int *size, int pics, int timeout){	struct video_mbuf vid_buf;	struct video_mmap vid_mmap;	char *map, *convmap;	int len;	int bytes = 3;	char name[20];	FILE *fp;	sigset_t newset;	unsigned int total = 0;	unsigned int i;		if (pics > 0 && timeout > 0) {		fprintf(stderr, "can't assign both -t and -m options\n");		return NULL;	}			if (palette == VIDEO_PALETTE_GREY)		bytes = 1;	/* bytes per pixel */	if (ioctl (dev, VIDIOCGMBUF, &vid_buf) == -1) 	{		/* to do a normal read()		 */		struct video_window vid_win;		if (verbose) {			fprintf (stderr, "using read()\n");		}		if (ioctl (dev, VIDIOCGWIN, &vid_win) != -1) 		{			vid_win.width  = width;			vid_win.height = height;			if (ioctl (dev, VIDIOCSWIN, &vid_win) == -1) 			{				perror ("ioctl(VIDIOCSWIN)");				return (NULL);			}		}		map = malloc (width * height * bytes);		len = read (dev, map, width * height * bytes);		if (len <=  0) {			free (map);			return (NULL);		}		*size = 0;		if (palette == VIDEO_PALETTE_YUV420P) {			convmap = malloc ( width * height * bytes );			v4l_yuv420p2rgb (convmap, map, width, height, bytes * 8);			memcpy (map, convmap, (size_t) width * height * bytes);			free (convmap);		} else if (palette == VIDEO_PALETTE_YUV422P) {			convmap = malloc ( width * height * bytes );			v4l_yuv422p2rgb (convmap, map, width, height, bytes * 8);			memcpy (map, convmap, (size_t) width * height * bytes);			free (convmap);		}		return (map);	}		map = mmap (0, vid_buf.size, PROT_READ|PROT_WRITE,MAP_SHARED,dev,0);	if ((unsigned char *)-1 == (unsigned char *)map) {		perror ("mmap()");		return (NULL);	}	vid_mmap.format = palette;	vid_mmap.frame = 0;	vid_mmap.width = width;	vid_mmap.height = height;	convmap = malloc ( width * height * bytes );	if (!convmap) {		fprintf (stderr, "alloc convmap error");		munmap (map, vid_buf.size);		return NULL;	}		if (!timeout)		goto next;			/* 创建ALARM信号处理函数 */	if (sigemptyset(&newset)) {		fprintf (stderr, "init signale set error\n");		free(convmap);		munmap (map, vid_buf.size);		return (NULL);	}	if (sigaddset(&newset, SIGALRM)) {		fprintf (stderr, "add SIGALRM error\n");		free(convmap);		munmap (map, vid_buf.size);		return (NULL);	}	if (!sigismember(&newset, SIGALRM)) {		perror("SIGALRM is not in signale set");		free(convmap);		munmap (map, vid_buf.size);		return (NULL);	}	if (sigprocmask(SIG_UNBLOCK, &newset, NULL)) {		fprintf (stderr, "set signal mask error\n");		free(convmap);		munmap (map, vid_buf.size);		return (NULL);	}	if (signal(SIGALRM, alarm_timeout)) {		fprintf (stderr, "create signal handler error\n");		free(convmap);		munmap (map, vid_buf.size);		return (NULL);	}			alarm(1);next:	for (i = 0; i < pics || !end; i++, vid_mmap.frame = i & 1) {		if (ioctl (dev, VIDIOCMCAPTURE, &vid_mmap) < 0) {			perror ("VIDIOCMCAPTURE");			fprintf (stderr, "args: width=%d height=%d palette=%d\n",				vid_mmap.width, vid_mmap.height, vid_mmap.format);			free(convmap);							munmap (map, vid_buf.size);			return (NULL);		}				if (ioctl (dev, VIDIOCSYNC, &vid_mmap.frame) < 0) {			perror ("VIDIOCSYNC");			free(convmap);			munmap (map, vid_buf.size);			return (NULL);		}		*size = vid_buf.size;		/* 完成指定的实验数 */		if (timeout)			continue;		if (palette == VIDEO_PALETTE_YUV420P) 		{			if (verbose)				fprintf (stderr, "converting from YUV to RGB\n");			v4l_yuv420p2rgb (convmap, map, width, height, bytes * 8);		} 		else if (palette == VIDEO_PALETTE_YUV422P) 		{			if (verbose)				fprintf (stderr, "converting from YUV to RGB\n");			v4l_yuv422p2rgb (convmap, map, width, height, bytes * 8);		}		sprintf(name, "/tmp/%d.jpg", 1);		fp = fopen(name, "wr");		put_image_jpeg(fp, convmap, width, height, 80, palette);		fclose(fp);		lcd_display(convmap,width,height,128,128);	}	if (end)		fprintf (stderr, "FPS %f for %d, count %d\n", (float)i / TIMEOUT, TIMEOUT, i);			memcpy (map, convmap, (size_t) width * height * bytes);	free (convmap);	return (map);	if (verbose)		fprintf (stderr, "got picture\n");}/* */voidput_image_jpeg (FILE *out, char *image, int width, int height, int quality, int palette){//#ifdef HAVE_LIBJPEG	int y, x, line_width;	JSAMPROW row_ptr[1];	struct jpeg_compress_struct cjpeg;	struct jpeg_error_mgr jerr;	char *line;	line = malloc (width * 3);	if (!line)		return;	if (verbose)		fprintf (stderr, "writing JPEG data\n");	cjpeg.err = jpeg_std_error(&jerr);	jpeg_create_compress (&cjpeg);	cjpeg.image_width = width;	cjpeg.image_height= height;	if (palette == VIDEO_PALETTE_GREY) {		cjpeg.input_components = 1;		cjpeg.in_color_space = JCS_GRAYSCALE;	} 	else {		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, out);	jpeg_start_compress (&cjpeg, TRUE);	row_ptr[0] = line;	if (palette == VIDEO_PALETTE_GREY) 	{		line_width = width;		for ( y = 0; y < height; y++) 		{			row_ptr[0] = image;			jpeg_write_scanlines (&cjpeg, row_ptr, 1);			image += line_width;		}	} 	else 	{		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);//#endif}/* * write YUV4MPEG stream which is nice for mpeg2enc */intto_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;}/** Display RGB24 BMP map on lcd for play video*/int lcd_display(char *image,int width, int height,int startx,int starty){	int fd;	unsigned short *bgr565_buf_tmp;	unsigned int y, x;	bgr565_buf_tmp = (unsigned short *)malloc(RGB565_BUF_LEN);	for (y = 0; y <height  &&  (y+starty) < 480; y++)	{   		for (x = 0; x < width*3  &&  (startx+x/3) < 640; ) 		{			unsigned short b, g, r;			b=0;r=0;g=0;			b = image[x  + 0+width*y*3];			g = image[x  + 1+width*y*3];			r = image[x  + 2+width*y*3];			bgr565_buf_tmp[x/3+startx+640*(y+starty)] = (b >> 3) | ((g >> 2) << 5) | ((r >> 3) << 11);			x+=3;		}	}	fd = open("/dev/fb0", O_WRONLY);		write(fd, bgr565_buf_tmp, RGB565_BUF_LEN);	close(fd);	free(bgr565_buf_tmp);	return 0;}/* * main() */intmain (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_YUV420P;	int num = 0;	FILE *out = stdout;	int timeout = 0;	int pics = 0;	int format = FMT_JPEG;	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);	}	image = get_image (dev, width, height, palette, &size, pics, timeout);	if (!size)		close (dev);	if (image) 	{			put_image_jpeg (out, image, width, height, quality, palette);		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 + -