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

📄 video_common.c

📁 motion motion
💻 C
📖 第 1 页 / 共 2 页
字号:
/*      video_common.c * *      Video stream functions for motion. *      Copyright 2000 by Jeroen Vreeken (pe1rxq@amsat.org) *      	  2006 by Krzysztof Blaszkowski (kb@sysmikro.com.pl)	 *      	  2007 by Angel Carpinteo (ack@telefonica.net) *      This software is distributed under the GNU public license version 2 *      See also the file 'COPYING'. * *///#include "motion.h"/* for rotation */#include "rotate.h"	/* already includes motion.h */#include "video.h"/* for rotation *///#include "rotate.h"#ifdef MJPEGT #include <mjpegtools/jpegutils.h>#include <mjpegtools/mjpeg_types.h>#endiftypedef unsigned char uint8_t;typedef unsigned short int uint16_t;typedef unsigned int uint32_t;#define CLAMP(x)        ((x)<0?0:((x)>255)?255:(x))typedef struct {	int is_abs;	int len;	int val;} code_table_t;/* *   sonix_decompress_init *   ===================== *   pre-calculates a locally stored table for efficient huffman-decoding. * *   Each entry at index x in the table represents the codeword *   present at the MSB of byte x. * */static void sonix_decompress_init(code_table_t * table){	int i;	int is_abs, val, len;	for (i = 0; i < 256; i++) {		is_abs = 0;		val = 0;		len = 0;		if ((i & 0x80) == 0) {			/* code 0 */			val = 0;			len = 1;		} else if ((i & 0xE0) == 0x80) {			/* code 100 */			val = +4;			len = 3;		} else if ((i & 0xE0) == 0xA0) {			/* code 101 */			val = -4;			len = 3;		} else if ((i & 0xF0) == 0xD0) {			/* code 1101 */			val = +11;			len = 4;		} else if ((i & 0xF0) == 0xF0) {			/* code 1111 */			val = -11;			len = 4;		} else if ((i & 0xF8) == 0xC8) {			/* code 11001 */			val = +20;			len = 5;		} else if ((i & 0xFC) == 0xC0) {			/* code 110000 */			val = -20;			len = 6;		} else if ((i & 0xFC) == 0xC4) {			/* code 110001xx: unknown */			val = 0;			len = 8;		} else if ((i & 0xF0) == 0xE0) {			/* code 1110xxxx */			is_abs = 1;			val = (i & 0x0F) << 4;			len = 8;		}		table[i].is_abs = is_abs;		table[i].val = val;		table[i].len = len;	}}/* *   sonix_decompress *   ================ *   decompresses an image encoded by a SN9C101 camera controller chip. * *   IN    width *         height *         inp     pointer to compressed frame (with header already stripped) *   OUT   outp    pointer to decompressed frame * *         Returns 0 if the operation was successful. *         Returns <0 if operation failed. * */int sonix_decompress(unsigned char *outp, unsigned char *inp, int width, int height){	int row, col;	int val;	int bitpos;	unsigned char code;	unsigned char *addr;	/* local storage */	static code_table_t table[256];	static int init_done = 0;	if (!init_done) {		init_done = 1;		sonix_decompress_init(table);		/* do sonix_decompress_init first! */		//return -1; // so it has been done and now fall through	}	bitpos = 0;	for (row = 0; row < height; row++) {		col = 0;		/* first two pixels in first two rows are stored as raw 8-bit */		if (row < 2) {			addr = inp + (bitpos >> 3);			code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7)));			bitpos += 8;			*outp++ = code;			addr = inp + (bitpos >> 3);			code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7)));			bitpos += 8;			*outp++ = code;			col += 2;		}		while (col < width) {			/* get bitcode from bitstream */			addr = inp + (bitpos >> 3);			code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7)));			/* update bit position */			bitpos += table[code].len;			/* calculate pixel value */			val = table[code].val;			if (!table[code].is_abs) {				/* value is relative to top and left pixel */				if (col < 2) {					/* left column: relative to top pixel */					val += outp[-2 * width];				} else if (row < 2) {					/* top row: relative to left pixel */					val += outp[-2];				} else {					/* main area: average of left pixel and top pixel */					val += (outp[-2] + outp[-2 * width]) / 2;				}			}			/* store pixel */			*outp++ = CLAMP(val);			col++;		}	}	return 0;}/* * BAYER2RGB24 ROUTINE TAKEN FROM: * * Sonix SN9C10x based webcam basic I/F routines * Takafumi Mizuno <taka-qce@ls-a.jp> * */void bayer2rgb24(unsigned char *dst, unsigned char *src, long int width, long int height){	long int i;	unsigned char *rawpt, *scanpt;	long int size;	rawpt = src;	scanpt = dst;	size = width * height;	for (i = 0; i < size; i++) {		if (((i / width) & 1) == 0) {	// %2 changed to & 1			if ((i & 1) == 0) {				/* B */				if ((i > width) && ((i % width) > 0)) {					*scanpt++ = *rawpt;     /* B */					*scanpt++ = (*(rawpt - 1) + *(rawpt + 1) + *(rawpt + width) + *(rawpt - width)) / 4;	/* G */					*scanpt++ = (*(rawpt - width - 1) + *(rawpt - width + 1) + *(rawpt + width - 1) + *(rawpt + width + 1)) / 4;    /* R */				} else {					/* first line or left column */					*scanpt++ = *rawpt;     /* B */					*scanpt++ = (*(rawpt + 1) + *(rawpt + width)) / 2;	/* G */					*scanpt++ = *(rawpt + width + 1);       /* R */				}			} else {				/* (B)G */				if ((i > width) && ((i % width) < (width - 1))) {					*scanpt++ = (*(rawpt - 1) + *(rawpt + 1)) / 2;  /* B */					*scanpt++ = *rawpt;	/* G */					*scanpt++ = (*(rawpt + width) + *(rawpt - width)) / 2;  /* R */				} else {					/* first line or right column */					*scanpt++ = *(rawpt - 1);       /* B */					*scanpt++ = *rawpt;	/* G */					*scanpt++ = *(rawpt + width);   /* R */				}			}		} else {			if ((i & 1) == 0) {				/* G(R) */				if ((i < (width * (height - 1))) && ((i % width) > 0)) {					*scanpt++ = (*(rawpt + width) + *(rawpt - width)) / 2;  /* B */					*scanpt++ = *rawpt;	/* G */					*scanpt++ = (*(rawpt - 1) + *(rawpt + 1)) / 2;  /* R */				} else {					/* bottom line or left column */					*scanpt++ = *(rawpt - width);   /* B */					*scanpt++ = *rawpt;	/* G */					*scanpt++ = *(rawpt + 1);       /* R */				}			} else {				/* R */				if (i < (width * (height - 1)) && ((i % width) < (width - 1))) {					*scanpt++ = (*(rawpt - width - 1) + *(rawpt - width + 1) + *(rawpt + width - 1) + *(rawpt + width + 1)) / 4;    /* B */					*scanpt++ = (*(rawpt - 1) + *(rawpt + 1) + *(rawpt - width) + *(rawpt + width)) / 4;	/* G */					*scanpt++ = *rawpt;     /* R */				} else {					/* bottom line or right column */					*scanpt++ = *(rawpt - width - 1);       /* B */					*scanpt++ = (*(rawpt - 1) + *(rawpt - width)) / 2;	/* G */					*scanpt++ = *rawpt;     /* R */				}			}		}		rawpt++;	}}void conv_yuv422to420p(unsigned char *map, unsigned char *cap_map, int width, int height){	unsigned char *src, *dest, *src2, *dest2;	int i, j;	/* Create the Y plane */	src = cap_map;	dest = map;	for (i = width * height; i > 0; i--) {		*dest++ = *src;		src += 2;	}	/* Create U and V planes */	src = cap_map + 1;	src2 = cap_map + width * 2 + 1;	dest = map + width * height;	dest2 = dest + (width * height) / 4;	for (i = height / 2; i > 0; i--) {		for (j = width / 2; j > 0; j--) {			*dest = ((int) *src + (int) *src2) / 2;			src += 2;			src2 += 2;			dest++;			*dest2 = ((int) *src + (int) *src2) / 2;			src += 2;			src2 += 2;			dest2++;		}		src += width * 2;		src2 += width * 2;	}}void conv_uyvyto420p(unsigned char *map, unsigned char *cap_map, unsigned int width, unsigned int height){	uint8_t *pY = map;	uint8_t *pU = pY + (width * height);	uint8_t *pV = pU + (width * height)/4;	uint32_t uv_offset = width * 4 * sizeof(uint8_t);	uint32_t ix, jx;	for (ix = 0; ix < height; ix++) {		for (jx = 0; jx < width; jx += 2) {			uint16_t calc;			if ((ix&1) == 0) {				calc = *cap_map;				calc += *(cap_map + uv_offset);				calc /= 2;				*pU++ = (uint8_t) calc;			}			cap_map++;			*pY++ = *cap_map++;			if ((ix&1) == 0) {				calc = *cap_map;				calc += *(cap_map + uv_offset);				calc /= 2;				*pV++ = (uint8_t) calc;			}			cap_map++;			*pY++ = *cap_map++;		}	}}void conv_rgb24toyuv420p(unsigned char *map, unsigned char *cap_map, int width, int height){	unsigned char *y, *u, *v;	unsigned char *r, *g, *b;	int i, loop;	b = cap_map;	g = b + 1;	r = g + 1;	y = map;	u = y + width * height;	v = u + (width * height) / 4;	memset(u, 0, width * height / 4);	memset(v, 0, width * height / 4);	for (loop = 0; loop < height; loop++) {		for (i = 0; i < width; i += 2) {			*y++ = (9796 ** r + 19235 ** g + 3736 ** b) >> 15;			*u += ((-4784 ** r - 9437 ** g + 14221 ** b) >> 17) + 32;			*v += ((20218 ** r - 16941 ** g - 3277 ** b) >> 17) + 32;			r += 3;			g += 3;			b += 3;			*y++ = (9796 ** r + 19235 ** g + 3736 ** b) >> 15;			*u += ((-4784 ** r - 9437 ** g + 14221 ** b) >> 17) + 32;			*v += ((20218 ** r - 16941 ** g - 3277 ** b) >> 17) + 32;			r += 3;			g += 3;			b += 3;			u++;			v++;		}		if ((loop & 1) == 0) {			u -= width / 2;			v -= width / 2;		}	}}int conv_jpeg2yuv420(struct context *cnt, unsigned char *dst, netcam_buff * buff, int width, int height){	netcam_context netcam;	if (!buff || !dst)		return 3;	if (!buff->ptr)		return 2;	/* Error decoding MJPEG frame */	memset(&netcam, 0, sizeof(netcam));	netcam.imgcnt_last = 1;	netcam.latest = buff;	netcam.width = width;	netcam.height = height;	netcam.cnt = cnt;	pthread_mutex_init(&netcam.mutex, NULL);	pthread_cond_init(&netcam.cap_cond, NULL);	pthread_cond_init(&netcam.pic_ready, NULL);	pthread_cond_init(&netcam.exiting, NULL);	if (setjmp(netcam.setjmp_buffer)) {		return NETCAM_GENERAL_ERROR | NETCAM_JPEG_CONV_ERROR;	}	return netcam_proc_jpeg(&netcam, dst);}#ifdef MJPEGT void mjpegtoyuv420p(unsigned char *map, unsigned char *cap_map, int width, int height, unsigned int size){	uint8_t *yuv[3];	unsigned char *y, *u, *v;	int loop;	yuv[0] = malloc(width * height * sizeof(yuv[0][0]));	yuv[1] = malloc(width * height / 4 * sizeof(yuv[1][0]));	yuv[2] = malloc(width * height / 4 * sizeof(yuv[2][0]));	decode_jpeg_raw(cap_map, size, 0, 420, width, height, yuv[0], yuv[1], yuv[2]);	y=map;	u=y+width*height;	v=u+(width*height)/4;	memset(y, 0, width*height);	memset(u, 0, width*height/4);	memset(v, 0, width*height/4);	for(loop=0; loop<width*height; loop++) {		*map++=yuv[0][loop];	}	for(loop=0; loop<width*height/4; loop++) {		*map++=yuv[1][loop];	}	for(loop=0; loop<width*height/4; loop++) {		*map++=yuv[2][loop];	}	free(yuv[0]);	free(yuv[1]);	free(yuv[2]);}#endif#define MAX2(x, y) ((x) > (y) ? (x) : (y))#define MIN2(x, y) ((x) < (y) ? (x) : (y))/* Constants used by auto brightness feature * Defined as constant to make it easier for people to tweak code for a * difficult camera. * The experience gained from people could help improving the feature without * adding too many new options. * AUTOBRIGHT_HYSTERESIS sets the minimum the light intensity must change before * we adjust brigtness. * AUTOBRIGHTS_DAMPER damps the speed with which we adjust the brightness * When the brightness changes a lot we step in large steps and as we approach the * target value we slow down to avoid overshoot and oscillations. If the camera * adjusts too slowly decrease the DAMPER value. If the camera oscillates try * increasing the DAMPER value. DAMPER must be minimum 1. * MAX and MIN are the max and min values of brightness setting we will send to * the camera device. */#define AUTOBRIGHT_HYSTERESIS 10#define AUTOBRIGHT_DAMPER 5#define AUTOBRIGHT_MAX 255#define AUTOBRIGHT_MIN 0int vid_do_autobright(struct context *cnt, struct video_dev *viddev){	int brightness_window_high;	int brightness_window_low;	int brightness_target;	int i, j = 0, avg = 0, step = 0;	unsigned char *image = cnt->imgs.image_virgin; /* Or cnt->current_image ? */	int make_change = 0;	if (cnt->conf.brightness)		brightness_target = cnt->conf.brightness;	else		brightness_target = 128;	brightness_window_high = MIN2(brightness_target + AUTOBRIGHT_HYSTERESIS, 255);	brightness_window_low = MAX2(brightness_target - AUTOBRIGHT_HYSTERESIS, 1);	for (i = 0; i < cnt->imgs.motionsize; i += 101) {		avg += image[i];

⌨️ 快捷键说明

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