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

📄 webcam_server.c

📁 此代码为嵌入式图片服务器
💻 C
📖 第 1 页 / 共 2 页
字号:
/*********************************************************************
 * webcam_server                                                     *
 *                                                                   *
 * (c) 2007 Jason totti guojunjie@jinyaco.com.cn                     *
 *                                                                   *
 * code used from Gerd Knorr's xawtv (libng)                         *
 * - and -                                                           *
 * Cory Lueninghoener's gqcam                                        *
 *                                                                   *
 *    waits for connections from a viewer and sends                  *
 *    jpeg encoded captures as a live video feed                     *
 *                                                                   *
 *********************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <pthread.h>
#include <linux/videodev.h>
#include <semaphore.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <fcntl.h>

#include "webcam_server.h"
#include "filters.h"
#include "jdatabuf.h"


/*-----------------------------------------------------------
  default options
  -----------------------------------------------------------*/
#define DEF_PORT		8888
#define DEF_QUALITY		60
#define DEF_CAMDEVFILE		"/dev/video0"
//#define DEF_LOGFILE		"/var/log/webcam_server.log"
//#define DEF_CAPTION		"%Y-%m-%d %H:%M:%S" /* strftime */
#define DEF_WIDTH		176
#define DEF_HEIGHT	144
//#define DEF_RETRYINIT		0
//#define DEF_DAEMON		0
#define DEF_SWAPRGB		0
#define DEF_TESTFPS		0
#define DEF_FLIP_HORIZ		0
#define DEF_FLIP_VERT		0
#define DEF_GAMMA		0
#define DEF_TEXT_FG		{0,0,0}
#define DEF_TEXT_BG		{255,255,255}
#define DEF_TRANS		{128,0,128}
#define DEF_TEXT_XPOS		0	
#define DEF_TEXT_YPOS		0
#define DEF_ROTATE		0
//#define DEF_FORCE_READ		0
//#define DEF_ALLOW_HTTP		1
//#define DEF_ALLOW_STREAM	1
//#define DEF_MAX_STREAM_BYTES	0
//#define DEF_MAX_STREAM_SECONDS	0
//#define DEF_MAX_STREAM_FRAMES	0
/* currently not implemented
#define DEF_ALLOW_ADMIN		0
#define DEF_ADMIN_PW		"\0"
*/
#define DEF_PALETTE		VIDEO_PALETTE_RGB24

#define MAX_BAD_GRABS		10	/* max bad image captures before exit */
#define CAPTURE_PAUSE		75000	/*  pause for 75ms between captures */

char *str_replace(const char *str, const char *find, const char *replace)
{
	char *ptr,*ret =NULL;
	int found=0;
	ptr = (char*)str;

	while((ptr=strstr(ptr, find)))
	{
		char *start,*end;
		int slen,elen,rlen,flen;

		rlen = strlen(replace);
		flen = strlen(find);
		slen = ptr - str;
		elen = strlen(ptr)-flen;

		start = (char*)malloc(slen+1);
		strncpy(start, str, slen);
		start[slen]=0;
		
		end = (char*)malloc(elen+1);
		strncpy(end, ptr+flen, elen);
		end[elen]=0;

		ret = (char*)malloc(slen+elen+rlen+1);
		sprintf(ret, "%s%s%s", start, replace, end);

		free(start);
		free(end);

		ptr = ret;

		found=1;
	}

	if(!found)
	{
		ret = (char*)malloc(strlen(str)+1);
		strcpy(ret, str);
	}

	return ret;
}

/*-----------------------------------------------------------
  create_and_listen
  - creates a server socket and listens
  - its a seperate function to clean up main
  -----------------------------------------------------------*/
int create_and_listen(int port)
{
	int sockfd, yes=1;
	struct sockaddr_in addr;
	
	if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
	{
		printf("creat socket error\n");
		return -1;
	}
	
	memset(&addr, 0, sizeof(addr));
	
	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	addr.sin_addr.s_addr = htonl(INADDR_ANY);
	
	if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) < 0)
	{
		printf("setsockopt is set error\n");
		return -1;
	}
	
	if(bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr)) < 0)
	{
		printf("bind is error\n");
		return -1;
	}
	
	if(listen(sockfd, 8) < 0)
	{
		printf("listen is error\n");
		return -1;
	}
	
	return sockfd;
}

/*---------------------------------------------------------------------
	     Get the video device struct information
	     struct video_window vid_win
	     struct video_picture vid_pic
	     struct video_capability vid_caps
	     struct video_mbuf vid_mbuf
  ---------------------------------------------------------------------*/
void get_cam_info(struct caminfo *cam)
{
	if(ioctl(cam->dev, VIDIOCGCAP, &cam->vid_caps) != 0)
	{
		printf("error ioctl (VIDIOCGCAP)");
		return;
	}
	if(ioctl(cam->dev, VIDIOCGWIN, &cam->vid_win) != 0)
	{
		printf("error ioctl (VIDIOCGCAP)");
		return;
	}
	if(ioctl(cam->dev, VIDIOCGPICT, &cam->vid_pic) != 0)
	{
		printf("error ioctl (VIDIOCGCAP)");
		return;
	}
	if(ioctl(cam->dev, VIDIOCGMBUF, &cam->vid_mbuf) == 0)
	{
		if(!cam->mmap)
			cam->mmap = mmap(0, cam->vid_mbuf.size, PROT_READ, MAP_SHARED, cam->dev, 0);
		if(cam->mmap == NULL)
			printf("error cam mmap");
	}
}

/*---------------------------------------------------------------------
	    Set the video device struct information
	    struct video_window vid_win
	    struct video_picture vid_pic
  ---------------------------------------------------------------------*/
int set_cam_info(struct caminfo *cam)
{
	if (ioctl (cam->dev, VIDIOCSPICT, &cam->vid_pic) == -1) {
		printf ("error ioctl (VIDIOCSPICT)");
		return -1;
	}
	if (ioctl (cam->dev, VIDIOCSWIN, &cam->vid_win) == -1) {
		printf ("error ioctl (VIDIOCSWIN)");
		return -1;
	}
	return 0;
}

/*---------------------------------------------------------------------
	        Get the image from video device
  ---------------------------------------------------------------------*/
struct image *get_cam_image(struct caminfo *cam)
{
	static struct image *img = NULL;
	int res;
	img = (struct image*)malloc(sizeof(struct image));
	img->width = cam->o.width;
	img->height = cam->o.height;
	img->bufsize = img->width * img->height * 3;
	img->buf = NULL;
	
	/* Set the mmap information */	
	cam->vid_v4lmmap.format = cam->o.palette;
	cam->vid_v4lmmap.frame = 0;
	cam->vid_v4lmmap.width = cam->o.width;
	cam->vid_v4lmmap.height = cam->o.height;
		
	/* read an image from camera */
	res = ioctl(cam->dev, VIDIOCMCAPTURE, &cam->vid_v4lmmap);
	if(res != 0)
		return NULL;

	res = ioctl(cam->dev, VIDIOCSYNC, &cam->vid_v4lmmap);
	if(res != 0)
		return NULL;

	img->buf = cam->mmap;
	return img;
}

/* --------------------------------------------------------------
                 Open the camera device 
 ----------------------------------------------------------------*/ 
int open_cam(struct caminfo *cam, char *devfile)
{
	if(!devfile)
		return -1;
	/* initialize and open camera */
	cam->dev = open(devfile, O_RDONLY);
	if(cam->dev < 0)
	{
		printf("The dev is open error\n");
		return -1;
	}
	return cam->dev;
}

/* --------------------------------------------------------------
                Close the camera device 
 ----------------------------------------------------------------*/ 
int close_cam(struct caminfo *cam)
{
	return close(cam->dev);
}

/*----------------------------------------------------------------------
	              Malloc the new image memeory
  ----------------------------------------------------------------------*/
struct image *image_new(int width, int height)
{
	struct image *img = (struct image*)malloc(sizeof(struct image));
	if(img)
	{
		img->width = width;
		img->height = height;
		img->bufsize = width*height*3;
		img->buf = (char *)malloc(img->bufsize);
		if(!img->bufsize)
		{
			free(img);
			img = NULL;
		}
	}
	
	return img;
}

/*----------------------------------------------------------------------
	              free the image memeory
  ----------------------------------------------------------------------*/
void image_delete(struct image *img)
{
	free(img->buf);
}

/*----------------------------------------------------------------------
	             format the palette 
  ----------------------------------------------------------------------*/
static void unpalette_bgr24(struct image *dst, unsigned char *src)
{
	unsigned char *dstbuf, *dstend;
	
	dstbuf = dst->buf;
	dstend = dstbuf + dst->bufsize; 
	while (dstbuf < dstend)
	{
		dstbuf[0] = src[2];
		dstbuf[1] = src[1];
		dstbuf[2] = src[0];
		dstbuf += 3;
		src += 3;
	}
}

/*-----------------------------------------------------------------------
		  Get the data to the Imagedata struct
  -----------------------------------------------------------------------*/
struct imagedata *peek(struct caminfo *cam)
{
	struct imagedata *ptr;
	//获取jpeg图像数据
	ptr = (struct imagedata*)malloc(sizeof(struct imagedata));
	ptr = cam->data;	
	return ptr;
}

/*-----------------------------------------------------------
  grab_thread
  - runs only when clients are connected or when test mode
    enabled
  - captures an image, converts it to jpeg, pushes it on 
    queue, loops
  -----------------------------------------------------------*/
int grab_thread(struct caminfo *cam)
{
	char *jpeg_data = NULL;
	int jpeg_len = 0;
	struct imagedata *new;
	struct image *img = NULL, *tmp = NULL;

	while(1)
	{
		/*if(!cam->o.test_fps)
		{
			// wait for a connection
			sem_wait(&cam->sem_con);
			sem_post(&cam->sem_con);
		}*/

		/* fetch an image */
		img = get_cam_image(cam);
		if(img == NULL)
		{

			printf("Bad image grab\n");
			usleep(100000);
			continue;
		}
		
		/* convert to rgb24 */
		tmp = image_new(img->width, img->height);
		unpalette_bgr24(tmp, img->buf);
		img = tmp;

		/* swap rgb? */
		if(cam->o.swap_rgb)
			swap_rgb24(img);
		
		/* adjust gamma? */
		if(cam->o.gamma)
			adjust_gamma(img, cam->o.gamma);

		/* flip horiz/vert */
		if(cam->o.flip_horiz)
			fliph(img);
		if(cam->o.flip_vert)
			flipv(img);

		/* rotate image? */
		if(cam->o.rotate > 0)
			rotate_image(img, cam->o.rotate);

		/* add the caption? */
		/*if(cam->o.caption && strlen(cam->o.caption) > 0)
		{
			char *text,*tmp;
			char viewers[16], frames[16], version[16];
			int x,y;
			snprintf(viewers, 15, "%d", cam->s.num_users);
			snprintf(frames, 15, "%d", cam->s.id_newest_img);
			snprintf(version, 15, "%s", get_version());
			
			tmp = str_replace(cam->o.caption, "%%v", viewers);
			text = str_replace(tmp, "%%f", frames);
			free(tmp);
			tmp = str_replace(text, "%%V", version);
			free(text);
			text = tmp;

			x = 50;
			y = 20;
			add_text(img, text, cam->o.text_fg, cam->o.text_bg, cam->o.trans, cam->o.text_xpos, cam->o.text_ypos);
			free(text);
		}*/
		
		/* allocate some storage for the new image */
		new = (struct imagedata *)malloc(sizeof(struct imagedata));
		if(!new)
		{
			printf("imagedata malloc is error\n");
			free(new);
			continue;
		}
		
		/* compress the image in jpeg format */
		jpeg_len = image2jpeg(img, &jpeg_data, cam->o.jpeg_quality);
		
		image_delete(tmp);
		free(tmp);
		
		/* set fields */
		new->len = jpeg_len;
		new->jpeg_data = jpeg_data;
		cam->data = new ;
		//printf("The image length is =====%d\n", jpeg_len);
		//free(new);
		//image_delete(img);
		//free(img);
	}
	printf("grab thread exiting...\n");
	munmap(cam->mmap, cam->vid_mbuf.size);
	return 0;
}

⌨️ 快捷键说明

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