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

📄 w3camd.c

📁 一个嵌入式Linux下面摄像头抓取图片的源代码程序
💻 C
字号:
/* * w3camd.c * * Copyright (C) 1998 - 2000 Rasca, Berlin * EMail: thron@gmx.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 <unistd.h>#include <getopt.h>#include <stdlib.h>#include <string.h>#include <pthread.h>#include <signal.h>#include <jpeglib.h>#include "w3socket.h"#include "w3http.h"#include "w3v4l.h"#include "w3jpeg.h"#include "w3log.h"#ifndef CAM_PORT#define CAM_PORT 8999#endif#define forever() while(1)#define MAX_WIDTH	768#define MAX_HEIGHT	576#define SERVER_NAME	"w3camd/0.3"#define SLEEP(n)	usleep((int)(n * 1000000))#define OFF -1enum {	ST_NONE,	ST_ERROR,	ST_BUSY,	ST_READY,	ST_EXIT,};typedef struct {	int childs;	pthread_mutex_t childs_lock;	pthread_cond_t childs_cond;	int state;	int width;				/* image width */	int height;				/* image height */	int input;	unsigned char *img;		/* image data for the childs */	pthread_mutex_t img_lock;	pthread_cond_t img_cond;} image_t;typedef struct {	int fd;					/* fd for the incoming connection */	int verbose;	char *url;	char *image;	int image_size;	image_t *img;	pthread_t thread;	/* */	float refresh;	int quality;} conn_t;typedef struct {	char *dev;	image_t *img;} camera_t;/* * show possible parameters */voidusage (char *pname) {	fprintf (stderr,		"Usage: %s [-v] [-p #] [-h host] [-s #x#] [-m #] [-i #] [-d device] \n",		pname);	exit (1);}/* * write jpeg file to filedescriptor fd */intwrite_jpeg (image_t *img, int fd, int quality){	JSAMPROW row_ptr[1];	struct jpeg_compress_struct jpeg;	struct jpeg_error_mgr jerr;	char *line, *image;	int y, x, line_width;#ifdef DEBUG	fprintf (stderr, "%s: write_jpeg() width=%d height=%d\n",		__FILE__, img->width, img->height);#endif	line = malloc (img->width * 3);	if (!line)		return 0;	jpeg.err = jpeg_std_error (&jerr);	jpeg_create_compress (&jpeg);	jpeg.image_width = img->width;	jpeg.image_height= img->height;	jpeg.input_components = 3;	jpeg.in_color_space = JCS_RGB;	jpeg_set_defaults (&jpeg);	jpeg_set_quality (&jpeg, quality, TRUE);	jpeg.dct_method = JDCT_FASTEST;	jpeg_io_dest (&jpeg, fd);	/* this is in w3jpeg.c */	jpeg_start_compress (&jpeg, TRUE);	row_ptr[0] = line;	line_width = img->width * 3;	image = img->img;	for (y = 0; y < img->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];		}		if (!jpeg_write_scanlines (&jpeg, row_ptr, 1)) {			jpeg_destroy_compress (&jpeg);			free (line);			return 0;		}		image += line_width;	}	jpeg_finish_compress (&jpeg);	jpeg_destroy_compress (&jpeg);	free (line);	return 1;}/* * capture images continously */void *image_thread (void *data){	camera_t *cam = (camera_t *) data;	image_t *img = cam->img;	video_t *vid;#ifdef DEBUG	printf ("%s: image_thread() img->childs=%d\n", __FILE__, img->childs);	printf ("%s:  pid = %d\n", __FILE__, getpid());#endifWAIT:	img->state = ST_NONE;	pthread_mutex_lock (&img->childs_lock);	forever () {		pthread_cond_wait (&img->childs_cond, &img->childs_lock);		log_print ("%s: no. of childs changed: childs=%d\n", __FILE__, img->childs);		if (img->childs > 0)			break;	}	pthread_mutex_unlock (&img->childs_lock);	if (!(vid = v4l_init(cam->dev, img->input, img->width, img->height))) {		img->state = ST_ERROR;		/* pthread_cond_broadcast (&img->img_cond); */		log_print("%s: can't init v4l\n", __FILE__);		goto WAIT;	}	vid->width = img->width;	vid->height= img->height;	while (img->childs > 0) {		if (!v4l_image(vid)) {			img->state = ST_ERROR;			log_print ("image_thread() error\n");		} else {			img->state = ST_BUSY;			pthread_mutex_lock (&img->img_lock);			printf ("0x%X 0x%X %dx%d\n", img, vid->mem,vid->width, vid->height);			memcpy (img->img, vid->mem, vid->width * vid->height * 3);			printf ("done ..\n");#ifdef DEBUG			printf ("%s: unlocking img..\n", __FILE__);#endif			pthread_mutex_unlock (&img->img_lock);			img->state = ST_READY;			pthread_cond_broadcast (&img->img_cond);			SLEEP(0.005);		}	}	v4l_fini (vid);	goto WAIT;	return (NULL);}/* */voide_help (conn_t *cn){	char buf[16];	char *e =		"Usage:\n"		"  /image[?quality=<#>[&stream]] - retrieve an image\n"		"  /help                - see these lines\n";	sprintf (buf, "%d", strlen (e));	http_status (cn->fd, HTTP_OK);	http_header (cn->fd, HTTP_SERVER, SERVER_NAME);	http_header (cn->fd, HTTP_CONTENT_TYPE, "text/plain");	http_header (cn->fd, HTTP_CONTENT_LENGTH, buf);	http_header (cn->fd, HTTP_HEADER_END, NULL);	write (cn->fd, e, strlen(e));}/* */voide_wrong_url (conn_t *cn){	char buf[16];	char *e = "wrong url!\n  try \"/help\"\n";	sprintf (buf, "%d", strlen (e));	http_status (cn->fd, HTTP_BAD_REQUEST);	http_header (cn->fd, HTTP_SERVER, SERVER_NAME);	http_header (cn->fd, HTTP_CONTENT_TYPE, "text/plain");	http_header (cn->fd, HTTP_CONTENT_LENGTH, buf);	http_header (cn->fd, HTTP_HEADER_END, NULL);	write (cn->fd, e, strlen(e));}/* */voide_error (conn_t *cn){	char buf[64];	http_status (cn->fd, HTTP_BAD_REQUEST);	http_header (cn->fd, HTTP_SERVER, SERVER_NAME);	http_header (cn->fd, HTTP_CONTENT_TYPE, "text/plain");	http_header (cn->fd, HTTP_HEADER_END, NULL);	sprintf (buf, "can't read image! device busy?!\n");	write (cn->fd, buf, strlen(buf));}/* * process the requested url */voidprocess_url (conn_t *cn){	char rfc1123[64];	time_t gmt;	int stream = 0;	char buf[128];#	define BOUNDARY "--w3camd-ns-boundary--may-not-work-with-ie--"	gmt = time (NULL);	strftime (rfc1123, 64, "%a, %d %b %Y %H:%M:%S GMT", gmtime (&gmt));		if (!cn->url) {		e_wrong_url (cn);		return;	}	if (strncmp (cn->url, "/image", 6) != 0) {		if (strncmp (cn->url, "/help", 5) == 0)			e_help (cn);		else			e_wrong_url (cn);		return;	}	if (strstr (cn->url, "stream")) {		stream = 1;	}	if (cn->img->state == ST_ERROR) {		e_error (cn);		return;	}	http_status (cn->fd, HTTP_OK);	http_header (cn->fd, HTTP_SERVER, SERVER_NAME);	if (stream) {		http_header (cn->fd, HTTP_CONTENT_TYPE,				"multipart/x-mixed-replace;boundary="BOUNDARY);	} else {		http_header (cn->fd, HTTP_CONTENT_TYPE, "image/jpeg");	}	http_header (cn->fd, HTTP_EXPIRES, rfc1123);	http_header (cn->fd, HTTP_HEADER_END, NULL);	forever () {		pthread_cond_wait (&cn->img->img_cond, &cn->img->img_lock);		log_print ("process_url() state=%d\n", cn->img->state);		if (cn->img->state == ST_READY) {			/* pthread_mutex_lock (&cn->img->img_lock); */			if (stream) {				sprintf (buf, "\n%s\n", BOUNDARY);				write (cn->fd, buf, strlen(buf));				sprintf (buf, "Content-Type: image/jpeg\n\n");				write (cn->fd, buf, strlen(buf));			}			if (!write_jpeg (cn->img, cn->fd, cn->quality))				return;			/* pthread_mutex_unlock (&cn->img->img_lock); */			if (!stream)				break;		}	}}/* * child which handles an incoming connection */void *server_thread (void *data){#define MAX_BUF	1024#define MAX_ALL	4096	conn_t *cn = (conn_t *) data;	int len, inlen = 0;	char buf  [MAX_BUF+1];	char inbuf[MAX_ALL+1];	char **args, *val;	buf  [MAX_BUF] = '\0';	inbuf[MAX_BUF] = '\0';	if (cn->verbose)		printf ("server_thread() state=%d\n", cn->img->state);	forever () {		len = read (cn->fd, buf, MAX_BUF);		if (len <= 0) {			/* client closed connection */			goto CLIENT_END;			return (NULL);		}		buf[len] = '\0';		if (inlen + len > MAX_ALL) {			log_print ("input overrun\n");			break;		}		memcpy (inbuf+inlen, buf, len);		inlen += len;		if (strstr (inbuf, "\n\n")		||			strstr (inbuf, "\r\n\r\n")	||			strstr (inbuf, "\r\r")		)			break;	}	inbuf[inlen] = '\0';	cn->url = http_parse (inbuf, &args);	if (cn->verbose > 1)		log_print ("getting url=%s\n", cn->url);	if (args) {		val = http_arg_val (args, "refresh");		if (val)	/* not used until now */			cn->refresh = atof (val);		val = http_arg_val (args, "quality");		if (val)			cn->quality = atoi (val);	}	if (cn->verbose > 2) {		printf ("  quality=%d\n", cn->quality);		printf ("  refresh=%f\n", cn->refresh);	}	process_url (cn);	close (cn->fd);	cn->img->childs--;	if (args) {		http_free_args (args);	}	free (cn->url);	if (cn->verbose) {		printf ("connection closed\n");	}CLIENT_END:	pthread_detach (cn->thread);	free (cn);	return (NULL);}/* */static voidon_sig_pipe (int signum){	log_print ("** signal pipe received\n");}static voidon_signal (int signum){	log_print ("%d received signal %d\n", getpid(), signum);	exit (1);}/* * let's start up */intmain (int argc, char *argv[]){	int c, sd, cd, fps = 25, input = -1;	int verbose = 0, max_connections = 10;	int width = 240, height = 180;	int port = CAM_PORT;	char *host = "localhost";	/* default host to run on */	conn_t *cn;	image_t *img;	pthread_t ithread;	camera_t cam;	cam.dev = "/dev/video0";	/* parse arguments	 */	while ((c = getopt (argc, argv, "vp:h:i:s:f:m:d:")) != EOF) {		switch (c) {			case 'd':				cam.dev = optarg;				break;			case 'f':				fps = atoi(optarg);				break;			case 'h':				host = optarg;				break;			case 'i':				input = atoi(optarg);				break;			case 'm':				max_connections = atoi(optarg);				break;			case 'p':				port = atoi (optarg);				break;			case 's':				sscanf (optarg, "%dx%d", &width, &height);				break;			case 'v':				verbose++;				break;			default:				usage (argv[0]);				break;		}	}	if (verbose)		log_print ("main thread pid = %d\n", getpid());	img = malloc (sizeof (image_t) + 3 * MAX_WIDTH * MAX_HEIGHT);	if (!img)		exit (1);	img->img = (unsigned char *)(img + 1);	img->childs = 0;	img->width = width;	img->height= height;	img->state = ST_NONE;	img->input = input;	cam.img = img;	signal (SIGPIPE, on_sig_pipe);	signal (SIGSEGV, on_signal);	pthread_mutex_init (&img->childs_lock, NULL);	pthread_mutex_init (&img->img_lock, NULL);	pthread_cond_init  (&img->childs_cond, NULL);	pthread_cond_init  (&img->img_cond, NULL);	sd = bind_port (host, port);	if (verbose)		printf ("bind %s:%d to file descriptor %d\n", host, port, sd);	if (sd < 0) {		return (-1);	}	pthread_create (&ithread, NULL, image_thread, (void *)&cam);	forever () {		cd = accept_con (sd);		if (cd < 0) {			printf ("oops!? accept_con() returned < 0\n");			continue;		}		if (verbose)			printf ("incoming connection..\n");		if ((img->childs+1) > max_connections) {			if (verbose)				printf ("too much connections!\n");			continue;		}		pthread_mutex_lock (&img->childs_lock);		img->childs++;		pthread_cond_broadcast (&img->childs_cond);		pthread_mutex_unlock (&img->childs_lock);		cn = malloc (sizeof (conn_t));		if (!cn)			exit (2);		cn->fd = cd;		cn->img = img;		cn->verbose = verbose;		cn->quality = 75;		if (verbose)			printf ("serving connection, (childs=%d)\n", cn->img->childs);		/* child */		pthread_create (&cn->thread, NULL, server_thread, cn);	}	return (0);}

⌨️ 快捷键说明

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