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

📄 grab.c

📁 网络摄像头的webserver
💻 C
字号:
#include <errno.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <unistd.h>#include <pthread.h>#include <dlfcn.h>#include <libxml/parser.h>#include <sys/time.h>#include <sys/ioctl.h>#include <sys/wait.h>#include "config.h"#include "grab.h"#include "configfile.h"#include "mod_handle.h"#include "image.h"#include "unpalette.h"#include "filter.h"#include "xmlhelp.h"/* $Id: grab.c,v 1.33 2003/04/20 21:53:34 dfx Exp $ */static void grab_glob_filters(struct image *);static struct grabthread *find_thread(const char *);static void *grab_thread(void *);static void firecmd(struct grabthread *, int);/* The grabimage struct and its only instance current_img. * (Private data now, not directly accessible by threads.) * This is where the grabbing thread stores the frames. * Every time a new frame is grabbed, the index is * incremented by one. The function grab_get_image is * provided to make it easy for a worker thread to read * images out of this. * * The grabber thread works like this: *  1) Acquire mutex. *  2) If request != 0, skip to step 5. *  3) Wait on request_cond, releasing mutex. *  4) Wake up from request_cond, reacquiring the mutex. *  5) Release mutex. *  6) Read frame from device into private local buffer, *     convert it to rgb palette, apply any global filters. *  7) Acquire mutex. *  8) Put new frame into current_img, increase index and *     set request = 0; *  9) Broadcast signal on ready_cond. * 10) Release mutex. * 11) Jump back to step 1. */struct grabimage{	pthread_mutex_t mutex;	struct image img;	struct grab_ctx ctx;		int request;	pthread_cond_t request_cond;	pthread_cond_t ready_cond;};struct grabthread {	struct grabthread *next;	char *name;	struct grabimage curimg;	struct grab_camdev gcamdev;	xmlNodePtr node;	int (*opendev)(xmlNodePtr, struct grab_camdev *);	unsigned char *(*input)(struct grab_camdev *);	void (*postprocess)(struct grab_camdev *, struct image *);	void (*capdump)(xmlNodePtr, struct grab_camdev *);	char *cmd;	int cmdtimeout;	int cmdfired;};static struct grabthread *grabthreadshead;intgrab_threads_init(){	xmlNodePtr node;	char *name, *active;	struct grabthread *newthread;	int ret = 0;	struct module *mod;	char *plugin, *cmd;	void *opendev, *input;	xmlNodePtr subnode;	int cmdtimeout;		node = xml_root(configdoc);	for (node = node->xml_children; node; node = node->next) {		if (!xml_isnode(node, "camdev"))			continue;					active = xml_attrval(node, "active");		if (active && strcmp(active, "yes"))			continue;				name = xml_attrval(node, "name");		if (!name)			name = "default";		if (find_thread(name)) {			printf("Duplicate <camdev> name '%s', skipping\n", name);			continue;		}				plugin = cmd = NULL;		cmdtimeout = 0;		for (subnode = node->xml_children; subnode; subnode = subnode->next) {			if (xml_isnode(subnode, "plugin"))				plugin = xml_getcontent(subnode);			else if (xml_isnode(subnode, "cmd"))				cmd = config_homedir(xml_getcontent(subnode));			else if (xml_isnode(subnode, "cmdtimeout"))				cmdtimeout = xml_atoi(subnode, 0) * 1000000;		}				if (!plugin || !(mod = mod_find(plugin, NULL))) {			printf("Invalid or missing \"plugin\" attribute for '%s'\n", name);			continue;		}				opendev = dlsym(mod->dlhand, "opendev");		input = dlsym(mod->dlhand, "input");		if (!opendev || !input) {			printf("Module \"%s\" has no \"opendev\" or \"input\" routine\n", plugin);			continue;		}				newthread = malloc(sizeof(*newthread));		memset(newthread, 0, sizeof(*newthread));		newthread->name = name;		newthread->node = node;		newthread->opendev = opendev;		newthread->input = input;		newthread->postprocess = dlsym(mod->dlhand, "postprocess");		newthread->capdump = dlsym(mod->dlhand, "capdump");		newthread->cmd = cmd;		newthread->cmdtimeout = cmdtimeout;		pthread_mutex_init(&newthread->curimg.mutex, NULL);		pthread_cond_init(&newthread->curimg.request_cond, NULL);		pthread_cond_init(&newthread->curimg.ready_cond, NULL);				newthread->next = grabthreadshead;		grabthreadshead = newthread;				ret++;	}		return ret;}staticstruct grabthread *find_thread(const char *name){	struct grabthread *thread;		for (thread = grabthreadshead; thread; thread = thread->next) {		if (!strcmp(name, thread->name))			return thread;	}		return NULL;}intgrab_open_all(){	int ret;	struct grabthread *thread;		for (thread = grabthreadshead; thread; thread = thread->next) {		ret = thread->opendev(thread->node, &thread->gcamdev);		if (ret == -1) {			printf("Failed to open device for <camdev name=\"%s\">\n", thread->name);			return -1;		}	}		return 0;}voidgrab_dump_all(){	struct grabthread *thread;		printf("\n");	for (thread = grabthreadshead; thread; thread = thread->next) {		if (thread->capdump)			thread->capdump(thread->node, &thread->gcamdev);		else			printf("Device \"%s\" doesn't support capabilities dumping.\n", thread->name);		printf("\n");	}}voidgrab_start_all(void){	struct grabthread *thread;	pthread_t grab_tid;	pthread_attr_t attr;	for (thread = grabthreadshead; thread; thread = thread->next) {		pthread_attr_init(&attr);		pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);		pthread_create(&grab_tid, &attr, grab_thread, thread);		pthread_attr_destroy(&attr);	}}staticvoidfirecmd(struct grabthread *thread, int onoff){	int ret;		if (!thread->cmd || thread->cmdtimeout <= 0)		return;	if (thread->cmdfired && onoff)		return;	if (!thread->cmdfired && !onoff)		return;	ret = fork();	if (!ret) {		ret = fork();		if (ret)			_exit(0);		close(STDIN_FILENO);		for (ret = 3; ret < 1024; ret++)			close(ret);		execlp(thread->cmd, thread->cmd,			onoff ? "start" : "end", thread->name, thread->gcamdev.name,			NULL);		printf("exec(\"%s\") failed: %s\n", thread->cmd, strerror(errno));		_exit(0);	}		waitpid(ret, NULL, 0);	thread->cmdfired = onoff;}staticvoid *grab_thread(void *arg){	int ret;	struct grabthread *thread;	unsigned char *rawimg;	struct image newimg;	struct timeval tvnow;	struct timespec abstime;		thread = arg;	printf("Camsource " VERSION " ready to grab images for device '%s'...\n", thread->name);		for (;;)	{		pthread_mutex_lock(&thread->curimg.mutex);		while (!thread->curimg.request) {			gettimeofday(&tvnow, NULL);			abstime.tv_sec = tvnow.tv_sec + 1;			abstime.tv_nsec = tvnow.tv_usec;						ret = pthread_cond_timedwait(&thread->curimg.request_cond, &thread->curimg.mutex, &abstime);						pthread_mutex_unlock(&thread->curimg.mutex);						if (ret == ETIMEDOUT) {				gettimeofday(&tvnow, NULL);				if (timeval_diff(&tvnow, &thread->curimg.ctx.tv) > thread->cmdtimeout)					firecmd(thread, 0);			}						pthread_mutex_lock(&thread->curimg.mutex);		}		pthread_mutex_unlock(&thread->curimg.mutex);				firecmd(thread, 1);				rawimg = thread->input(&thread->gcamdev);		if (!rawimg) {			printf("Device '%s' returned no image\n", thread->name);			continue;		}				image_new(&newimg, thread->gcamdev.x, thread->gcamdev.y);		thread->gcamdev.pal->routine(&newimg, rawimg);		if (thread->postprocess)			thread->postprocess(&thread->gcamdev, &newimg);				grab_glob_filters(&newimg);		filter_apply(&newimg, thread->node);		pthread_mutex_lock(&thread->curimg.mutex);		image_move(&thread->curimg.img, &newimg);				thread->curimg.ctx.idx++;		if (thread->curimg.ctx.idx == 0)			thread->curimg.ctx.idx++;		gettimeofday(&thread->curimg.ctx.tv, NULL);				thread->curimg.request = 0;		pthread_cond_broadcast(&thread->curimg.ready_cond);		pthread_mutex_unlock(&thread->curimg.mutex);	}	return 0;}staticvoidgrab_glob_filters(struct image *img){	xmlNodePtr node;	node = xml_root(configdoc);	filter_apply(img, node);}voidgrab_get_image(struct image *img, struct grab_ctx *ctx, const char *name){	struct timeval now;	long diff;	struct grabthread *thread;		if (!img)		return;		thread = find_thread(name);	if (!thread) {		printf("Warning: trying to grab from non-existant device '%s'\n", name);		/* dont crash */		image_new(img, 1, 1);		return;	}		pthread_mutex_lock(&thread->curimg.mutex);		if (ctx)	{		if (!ctx->idx || ctx->idx == thread->curimg.ctx.idx)		{request:			thread->curimg.request = 1;			pthread_cond_signal(&thread->curimg.request_cond);			pthread_cond_wait(&thread->curimg.ready_cond, &thread->curimg.mutex);		}		else		{			gettimeofday(&now, NULL);			diff = timeval_diff(&now, &ctx->tv);			if (diff < 0 || diff >= 500000)				goto request;	/* considered harmful (!) */		}		memcpy(ctx, &thread->curimg.ctx, sizeof(*ctx));	}		image_copy(img, &thread->curimg.img);	pthread_mutex_unlock(&thread->curimg.mutex);}longtimeval_diff(struct timeval *a, struct timeval *b){	long ret;		ret = a->tv_sec - b->tv_sec;	ret *= 1000000;	ret += a->tv_usec - b->tv_usec;		return ret;}

⌨️ 快捷键说明

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