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

📄 streamer.c

📁 Nemesis a complete Linux video security system. It s idea is a cheap replacement for your commercia
💻 C
字号:
/* Nemesis * Copyright (C) 1999 John Ferlito <johnf@inodes.org> * Copyright (C) 1997 Gerd Knorr <kraxel@goldbach.in-berlin.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. * */#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <math.h>#include <errno.h>#include <fcntl.h>#include <string.h>#include <ctype.h>#include <signal.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/time.h>#include <sys/ioctl.h>#include <sys/stat.h>#include <sys/mman.h>#include <sys/shm.h>#include <sys/ipc.h>#include <sys/wait.h>#include <gtk/gtk.h>#include <Imlib.h>#include <setjmp.h>#include <asm/types.h>		/* XXX glibc */#include <linux/videodev.h>#include "streamer.h"#include "colorspace.h"#include "writefile.h"#include <X11/Xlib.h>#define DEVNAME "/dev/video"#define JPEG_MUL 3#define JPEG_DIV 1jmp_buf env;int sigs;ImlibData *id;ImlibImage *im;Window x_window;/* ---------------------------------------------------------------------- */static struct video_capability capability;static struct video_channel channel;static struct video_window window;static unsigned char *map = NULL;static struct video_mmap gb1, gb2;static struct video_mbuf gb_buffers = {2 * 0x151000, 0,				      {0, 0x151000}};static unsigned char *buffers;static int bufsize;static int bfirst = 0;static int blast = 0;static int bufcount = 6;static int wtalk, rtalk;static int wsync, rsync, synctime = 500;static struct timeval start;static int tvnorm = VIDEO_MODE_PAL;static int input = -1;static char *device = DEVNAME;static char *filename = NULL;static int single = 1, absframes = 1, x11 = 0;static int fd = -1, width = 320, height = 240, quiet = 0, fps = 30;static int signaled = 0;/* ---------------------------------------------------------------------- */void usage(char *prog){	char *h;		if (NULL != (h = strrchr(prog, '/')))		prog = h + 1;		fprintf(stderr,					"%s grabs image(s) from a bt848 card\n"					"\n"					"usage: %s [ options ]\n"					"\n"					"options:\n"					"  -q          quiet operation\n"					"  -c device   specify device              [%s]\n"					"  -s size     specify size                [%dx%d]\n"					"  -b buffers  specify # of buffers        [%d]\n"					"  -t times    number of frames            [%d]\n"					"  -r fps      frame rate                  [%d]\n"					"  -o file     output file name            [%s]\n"					"  -i input    set input source (int)      [no change]\n"					"\n"					"If the filename has some digits, %s will write multiple files,\n"					"otherwise one huge file.  Writing to one file works with raw\n"					"data only."					"\n"					"funny chars:\n"					"  +      grabbed picture queued to fifo\n"					"  o      grabbed picture not queued (fifo full)\n"					"  -      picture written to disk and dequeued from fifo\n"					"  s      sync\n"					"  xx/yy  (at end of line) xx frames queued, yy frames grabbed\n"					"\n"					"examples:\n"					"  %s -o image.jpg                             write single image\n"					"  %s | display -size 320x240                  write image to stdout\n"					"  %s -s 320x240 -t 5 -o frame000.jpg          write 5 image files\n"					"\n"					"--\n"					"(c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>\n"					"(c) 1999 Glengarry Castle specific hacks John Ferlito <johnf@zip.com.au>\n",					prog, prog, device,					width, height, bufcount, absframes, fps,					filename ? filename : "stdout",					prog, prog, prog, prog);}/* ---------------------------------------------------------------------- */void writer(){	char buffer;	int fd = -1;	signal(SIGINT, SIG_IGN);	if (single) {		if (filename) {			if (-1 == (fd = open(filename, O_RDWR | O_CREAT, 0666))) {			fprintf(stderr, "writer: open %s: %s\n", filename, strerror(errno));			exit(1);		    }		}	}	for (;;) {		/* wait for frame */		switch (read(rtalk, &buffer, 1)) {		 case -1:	    		perror("writer: read socket");	    		exit(1);		 case 0:	    		if (!quiet)				fprintf(stderr, "writer: done\n");	    		exit(0);	    		return;		}		/* write out */		write_jpeg(filename, buffers + buffer * bufsize, width, height);		patch_up(filename);		/* Display on screen */		if(x11) {			im = Imlib_create_image_from_data(id, buffers + buffer * bufsize, NULL, width, height);			Imlib_apply_image(id, im, x_window);			Imlib_destroy_image(id, im);			XFlush(dpy);		}			/* free buffer */		if (1 != write(wtalk, &buffer, 1)) {	    		perror("writer: write socket");	    		exit(1);		}		if (!quiet)	    		fprintf(stderr, "-");	}	}/* ---------------------------------------------------------------------- */void syncer(){	char dummy;		signal(SIGINT, SIG_IGN);	for (;;) {		switch (read(rsync, &dummy, 1)) {		 case -1:	    		perror("syncer: read socket");	    		exit(1);		 case 0:	    		if (!quiet)			fprintf(stderr, "syncer: done\n");	    		exit(0);		 default:	    		if (!quiet)				fprintf(stderr, "s");	   		 sync();		}	}}/* ---------------------------------------------------------------------- */int putbuffer(char *src){	static int lastsec, lastsync, secframes, secqueued, absqueued,	timediff;	char buffer;	unsigned char *dest;	struct timeval tv;		/* Work out the time */	gettimeofday(&tv, NULL);	timediff = (tv.tv_sec - start.tv_sec) * 1000;	timediff += (tv.tv_usec - start.tv_usec) / 1000;	if (absqueued * 1000 / fps > timediff)		return absqueued;		/* Do we need to sync */	if (timediff > lastsync + synctime) {		/* sync */		lastsync = timediff - timediff % synctime;		if (1 != write(wsync, &bfirst, 1)) {	    		perror("grabber: write socket");	    		exit(1);		}	}	if (timediff > lastsec + 1000) {		/* statistics */		if (!quiet && secframes)	    		fprintf(stderr, " %2d/%2d\n", secqueued, secframes);		lastsec = timediff - timediff % 1000;		secqueued = 0;		secframes = 0;	}	/* check for free buffers */	switch (read(rtalk, &buffer, 1)) {	 case -1:		if (errno != EAGAIN) {	    		perror("grabber: read socket");	    		exit(1);		}		break;	 case 0:		/* nothing */		break;	 default:		blast++;		if (blast == bufcount)	    blast = 0;		break;	}		secframes++;	if ((bfirst + 1) % bufcount == blast) {		/* no buffer free */		if (!quiet)	    		fprintf(stderr, "o");		return absqueued;	}	/* copy / convert */	dest = buffers + bufsize * bfirst;	rgb24_to_bgr24(dest, src, width, height);		/* queue buffer */	if (1 != write(wtalk, &bfirst, 1)) {		perror("grabber: write socket");		exit(1);	}	secqueued++;	absqueued++;	bfirst++;	if (bfirst == bufcount)		bfirst = 0;	if (!quiet)		fprintf(stderr, "+");	return absqueued;}/* ---------------------------------------------------------------------- */void ctrlc(int signal){	static char text[] = "^C - one moment please\n";		write(2, text, strlen(text));	signaled = 1;}int main(int argc, char **argv){	int shm_id, c, s, count = 0, i, n, p1[2], p2[2], queued = 0;	static struct video_picture     pict;	int one=1;		for (;;) {		if (-1 == (c = getopt(argc, argv, "qs:c:o:i:t:b:r:xh")))	    		break;		switch (c) {		 case 'q':	    		quiet = 1;	    		break;		 case 's':	    		if (2 != sscanf(optarg, "%dx%d", &width, &height))				width = height = 0;	    		break;		 case 'c':	    		device = optarg;	    		break;		 case 'o':	    		filename = optarg;	    		for (i = 0, n = strlen(filename); i < n; i++) {				if (isdigit(filename[i]))					single = 0;	    		}			break;		 case 'i':	    		input = atoi(optarg);	    		break;		 case 't':	    		absframes = atoi(optarg);	    		break;		 case 'b':		   	bufcount = atoi(optarg);		    	break;		 case 'r':	    		fps = atoi(optarg);	    		break;		 case 'x':	    		x11 = 1;	    		break;		 case 'h':		 default:	    		usage(argv[0]);	    		exit(1);		}	}		if(filename == NULL) {		usage(argv[0]);		exit(1);	}	/* Gtk Window */	if(x11) {				x_window = create_window(width, height);	}	/* Open Device */	if (-1 == fd && -1 == (fd = open(device, O_RDWR))) {		fprintf(stderr, "open %s: %s\n", device, strerror(errno));		exit(1);	}	/* Get Settings */	if (-1 == ioctl(fd, VIDIOCGCAP, &capability)) {		perror("ioctl VIDIOCGCAP");		exit(1);	}	if (-1 == ioctl(fd, VIDIOCGCHAN, &channel))		perror("ioctl VIDIOCGCHAN");	if (-1 == ioctl(fd, VIDIOCGWIN, &window))		perror("ioctl VIDIOCGWIN");		/* Set Channel Info */	if (tvnorm != -1 || input != -1) {		if (tvnorm != -1)	    		channel.norm = tvnorm;		if (input != -1)	    		channel.channel = input;		if (-1 == ioctl(fd, VIDIOCSCHAN, &channel))	    		perror("ioctl VIDIOCSCHAN");	}	/* mmap() buffer */	if (-1 == ioctl(fd, VIDIOCGMBUF, &gb_buffers)) {		perror("ioctl VIDIOCGMBUF");	}	map = mmap(0, gb_buffers.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);	if ((unsigned char *) -1 == map) {		perror("mmap");	} else {		if (!quiet)	 	   fprintf(stderr, "v4l: mmap()'ed buffer size = 0x%x\n",		       	   gb_buffers.size);	}		/* buffer initialisation */	if (absframes < bufcount)		bufcount = absframes + 1;	bufsize = width * height * JPEG_MUL / JPEG_DIV;	if (-1 == (shm_id = shmget(IPC_PRIVATE, bufsize * bufcount, IPC_CREAT | 0700))) {		perror("shmget");		exit(1);	}	buffers = shmat(shm_id, 0, 0);	if ((void *) -1 == buffers) {		perror("shmat");		exit(1);	}	shmctl(shm_id, IPC_RMID, 0);		/* start up writer */	if (-1 == pipe(p1) || -1 == pipe(p2)) {		perror("pipe");		exit(1);	}	switch (fork()) {	 case -1:		perror("fork");		exit(1);	 case 0:		close(p1[0]);		close(p2[1]);		wtalk = p1[1];		rtalk = p2[0];		fcntl(rtalk, F_SETFL, 0);		nice(5);		writer();		exit(0);	 default:		close(p2[0]);		close(p1[1]);		wtalk = p2[1];		rtalk = p1[0];		fcntl(rtalk, F_SETFL, O_NONBLOCK);		break;	}		/* start up syncer */	if (-1 == pipe(p1)) {		perror("pipe");		exit(1);	}	switch (fork()) {	 case -1:		perror("fork");		exit(1);	 case 0:		close(p1[1]);		rsync = p1[0];		fcntl(rsync, F_SETFL, 0);		nice(10);		syncer();		exit(0);	 default:		close(p1[0]);		wsync = p1[1];		break;	}		/* catch ^C */	signal(SIGINT, ctrlc);		/* prepare for grabbing */        if (-1 == ioctl(fd,VIDIOCGPICT,&pict))	        perror("ioctl VIDIOCGPICT");	/* No need ti change brightness anymore */	/* pict.contrast = 56678;	 * pict.brightness = 35867;	 */	pict.palette = VIDEO_PALETTE_RGB24; 	if (-1 == ioctl(fd,VIDIOCSPICT,&pict))		        perror("ioctl VIDIOCSPICT");	gb1.format = VIDEO_PALETTE_RGB24;	gb1.frame = 0;	gb1.width = width;	gb1.height = height;		gb2.format = VIDEO_PALETTE_RGB24;	gb2.frame = 1;	gb2.width = width;	gb2.height = height;		if (-1 == ioctl(fd, VIDIOCMCAPTURE, &gb1)) {		if (errno == EAGAIN)	     		fprintf(stderr, "grabber chip can't sync (no station tuned in?)\n");		else	    		perror("ioctl VIDIOCMCAPTURE");		exit(1);	}	count++;		/* main loop */	gettimeofday(&start, NULL);	for (; queued < absframes && !signaled; count++) {				if (-1 == ioctl(fd, VIDIOCMCAPTURE, (count % 2) ? &gb2 : &gb1)) {	    		if (errno == EAGAIN)				fprintf(stderr, "grabber chip can't sync (no station tuned in?)\n");	    		else				perror("ioctl VIDIOCMCAPTURE");	    		exit(1);		}		if (-1 == ioctl(fd, VIDIOCSYNC, (count % 2) ? &gb1.frame : &gb2.frame)) {	    		perror("ioctl VIDIOCSYNC");	    		exit(1);		}		queued = putbuffer(map + gb_buffers.offsets[(count % 2) ? 0 : 1]);	}		if (-1 == ioctl(fd, VIDIOCSYNC, (count % 2) ? &gb1.frame : &gb2.frame)) {		perror("ioctl VIDIOCSYNC");		exit(1);	}	/* done */	if (!quiet)		fprintf(stderr, "\n");	close(fd);	close(wtalk);	close(wsync);	wait(&s);	wait(&s);	return 0;}void clicked(void){	siglongjmp(env, -1);}

⌨️ 快捷键说明

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