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

📄 ibmcam.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 5 页
字号:
		case HDRSIG_MODEL1_128x96:			scanLength = 128;			scanHeight = 96;			order_uv = 1;	/* U Y V Y ... */			break;		case HDRSIG_MODEL1_176x144:			scanLength = 176;			scanHeight = 144;			order_uv = 1;	/* U Y V Y ... */			break;		case HDRSIG_MODEL1_352x288:			scanLength = 352;			scanHeight = 288;			order_uv = 0;	/* Y V Y V ... */			break;		default:			err("Unknown header signature 00 FF 00 %02lX", frame->header);			return scan_NextFrame;		}		/* order_yc: true=Yc false=cY ('c'=either U or V) */		order_yc = (IBMCAM_T(uvd)->camera_model == IBMCAM_MODEL_2);	}	len = scanLength * 3;	assert(len <= sizeof(lineBuffer));	/*	 * Lines are organized this way:	 *	 * I420:	 * ~~~~	 * <scanLength->	 * ___________________________________	 * |-----Y-----|---UVUVUV...UVUV-----| \	 * |-----------+---------------------|  \	 * |<-- 176 -->|<------ 176*2 ------>|  Total 72. lines (interlaced)	 * |...	   ... |        ...          |  /	 * |<-- 352 -->|<------ 352*2 ------>|  Total 144. lines (interlaced)	 * |___________|_____________________| /	 *  \           \	 *   lumaLine    chromaLine	 */	/* Make sure there's enough data for the entire line */	if (RingQueue_GetLength(&uvd->dp) < len)		return scan_Out;	/* Suck one line out of the ring queue */	RingQueue_Dequeue(&uvd->dp, lineBuffer, len);	/*	 * Make sure that our writing into output buffer	 * will not exceed the buffer. Mind that we may write	 * not into current output scanline but in several after	 * it as well (if we enlarge image vertically.)	 */	if ((frame->curline + 2) >= VIDEOSIZE_Y(frame->request))		return scan_NextFrame;	/*	 * Now we are sure that entire line (representing all 'scanLength'	 * pixels from the camera) is available in the buffer. We	 * start copying the line left-aligned to the V4L buffer.	 * If the camera line is shorter then we should pad the V4L	 * buffer with something (black) to complete the line.	 */	assert(frame->data != NULL);	f = frame->data + (v4l_linesize * frame->curline);	/*	 * To obtain chrominance data from the 'chromaLine' use this:	 *   v = chromaLine[0]; // 0-1:[0], 2-3:[4], 4-5:[8]...	 *   u = chromaLine[2]; // 0-1:[2], 2-3:[6], 4-5:[10]...	 *	 * Indices must be calculated this way:	 * v_index = (i >> 1) << 2;	 * u_index = (i >> 1) << 2 + 2;	 *	 * where 'i' is the column number [0..VIDEOSIZE_X(frame->request)-1]	 */	lumaLine = lineBuffer;	chromaLine = lineBuffer + scanLength;	for (i = 0; i < VIDEOSIZE_X(frame->request); i++)	{		unsigned char rv, gv, bv;	/* RGB components */		/* Check for various visual debugging hints (colorized pixels) */		if ((flags & FLAGS_DISPLAY_HINTS) && (icam->has_hdr)) {			/*			 * This is bad and should not happen. This means that			 * we somehow overshoot the line and encountered new			 * frame! Obviously our camera/V4L frame size is out			 * of whack. This cyan dot will help you to figure			 * out where exactly the new frame arrived.			 */			if (icam->has_hdr == 1) {				bv = 0; /* Yellow marker */				gv = 0xFF;				rv = 0xFF;			} else {				bv = 0xFF; /* Cyan marker */				gv = 0xFF;				rv = 0;			}			icam->has_hdr = 0;			goto make_pixel;		}		/*		 * Check if we are still in range. We may be out of range if our		 * V4L canvas is wider or taller than the camera "native" image.		 * Then we quickly fill the remainder of the line with zeros to		 * make black color and quit the horizontal scanning loop.		 */		if (((frame->curline + 2) >= scanHeight) || (i >= scanLength)) {			const int j = i * V4L_BYTES_PER_PIXEL;#if USES_IBMCAM_PUTPIXEL			/* Refresh 'f' because we don't use it much with PUTPIXEL */			f = frame->data + (v4l_linesize * frame->curline) + j;#endif			memset(f, 0, v4l_linesize - j);			break;		}		y = lumaLine[i];		if (flags & FLAGS_MONOCHROME) /* Use monochrome for debugging */			rv = gv = bv = y;		else {			int off_0, off_2;			off_0 = (i >> 1) << 2;			off_2 = off_0 + 2;			if (order_yc) {				off_0++;				off_2++;			}			if (!order_uv) {				off_0 += 2;				off_2 -= 2;			}			u = chromaLine[off_0] + hue_corr;			v = chromaLine[off_2] + hue2_corr;			/* Apply color correction */			if (color_corr != 0) {				/* Magnify up to 2 times, reduce down to zero saturation */				u = 128 + ((ccm + color_corr) * (u - 128)) / ccm;				v = 128 + ((ccm + color_corr) * (v - 128)) / ccm;			}			YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv);		}	make_pixel:		/*		 * The purpose of creating the pixel here, in one,		 * dedicated place is that we may need to make the		 * pixel wider and taller than it actually is. This		 * may be used if camera generates small frames for		 * sake of frame rate (or any other reason.)		 *		 * The output data consists of B, G, R bytes		 * (in this order).		 */#if USES_IBMCAM_PUTPIXEL		RGB24_PUTPIXEL(frame, i, frame->curline, rv, gv, bv);#else		*f++ = bv;		*f++ = gv;		*f++ = rv;#endif		/*		 * Typically we do not decide within a legitimate frame		 * that we want to end the frame. However debugging code		 * may detect marker of new frame within the data. Then		 * this condition activates. The 'data' pointer is already		 * pointing at the new marker, so we'd better leave it as is.		 */		if (frame_done)			break;	/* End scanning of lines */	}	/*	 * Account for number of bytes that we wrote into output V4L frame.	 * We do it here, after we are done with the scanline, because we	 * may fill more than one output scanline if we do vertical	 * enlargement.	 */	frame->curline += 2;	if (pcopylen != NULL)		*pcopylen += 2 * v4l_linesize;	frame->deinterlace = Deinterlace_FillOddLines;	if (frame_done || (frame->curline >= VIDEOSIZE_Y(frame->request)))		return scan_NextFrame;	else		return scan_Continue;}/* * ibmcam_model2_320x240_parse_lines() * * This procedure deals with a weird RGB format that is produced by IBM * camera model 2 in modes 320x240 and above; 'x' below is 159 or 175, * depending on horizontal size of the picture: * * <--- 160 or 176 pairs of RA,RB bytes -----> * *-----------------------------------------* \ * | RA0 | RB0 | RA1 | RB1 | ... | RAx | RBx |  \   This is pair of horizontal lines, * |-----+-----+-----+-----+ ... +-----+-----|   *- or one interlaced line, total * | B0  | G0  | B1  | G1  | ... | Bx  | Gx  |  /   120 or 144 such pairs which yield * |=====+=====+=====+=====+ ... +=====+=====| /    240 or 288 lines after deinterlacing. * * Each group of FOUR bytes (RAi, RBi, Bi, Gi) where i=0..frame_width/2-1 * defines ONE pixel. Therefore this format yields 176x144 "decoded" * resolution at best. I do not know why camera sends such format - the * previous model (1) just used interlaced I420 and everyone was happy. * * I do not know what is the difference between RAi and RBi bytes. Both * seemingly represent R component, but slightly vary in value (so that * the picture looks a bit colored if one or another is used). I use * them both as R component in attempt to at least partially recover the * lost resolution. */static enum ParseState ibmcam_model2_320x240_parse_lines(	struct uvd *uvd,	struct usbvideo_frame *frame,	long *pcopylen){	unsigned char *f, *la, *lb;	unsigned int len;	int v4l_linesize; /* V4L line offset */	int i, j, frame_done=0, color_corr;	int scanLength, scanHeight;	static unsigned char lineBuffer[352*2];	switch (uvd->videosize) {	case VIDEOSIZE_320x240:	case VIDEOSIZE_352x240:	case VIDEOSIZE_352x288:		scanLength = VIDEOSIZE_X(uvd->videosize);		scanHeight = VIDEOSIZE_Y(uvd->videosize);		break;	default:		err("ibmcam_model2_320x240_parse_lines: Wrong mode.");		return scan_Out;	}	color_corr = (uvd->vpic.colour) >> 8; /* 0..+255 */	v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;	len = scanLength * 2; /* See explanation above */	assert(len <= sizeof(lineBuffer));	/* Make sure there's enough data for the entire line */	if (RingQueue_GetLength(&uvd->dp) < len)		return scan_Out;	/* Suck one line out of the ring queue */	RingQueue_Dequeue(&uvd->dp, lineBuffer, len);	/*	 * Make sure that our writing into output buffer	 * will not exceed the buffer. Mind that we may write	 * not into current output scanline but in several after	 * it as well (if we enlarge image vertically.)	 */	if ((frame->curline + 2) >= VIDEOSIZE_Y(frame->request))		return scan_NextFrame;	la = lineBuffer;	lb = lineBuffer + scanLength;	/*	 * Now we are sure that entire line (representing all	 *         VIDEOSIZE_X(frame->request)	 * pixels from the camera) is available in the scratch buffer. We	 * start copying the line left-aligned to the V4L buffer (which	 * might be larger - not smaller, hopefully). If the camera	 * line is shorter then we should pad the V4L buffer with something	 * (black in this case) to complete the line.	 */	f = frame->data + (v4l_linesize * frame->curline);	/* Fill the 2-line strip */	for (i = 0; i < VIDEOSIZE_X(frame->request); i++) {		int y, rv, gv, bv;	/* RGB components */		j = i & (~1);		/* Check for various visual debugging hints (colorized pixels) */		if ((flags & FLAGS_DISPLAY_HINTS) && (IBMCAM_T(uvd)->has_hdr)) {			if (IBMCAM_T(uvd)->has_hdr == 1) {				bv = 0; /* Yellow marker */				gv = 0xFF;				rv = 0xFF;			} else {				bv = 0xFF; /* Cyan marker */				gv = 0xFF;				rv = 0;			}			IBMCAM_T(uvd)->has_hdr = 0;			goto make_pixel;		}		/*		 * Check if we are still in range. We may be out of range if our		 * V4L canvas is wider or taller than the camera "native" image.		 * Then we quickly fill the remainder of the line with zeros to		 * make black color and quit the horizontal scanning loop.		 */		if (((frame->curline + 2) >= scanHeight) || (i >= scanLength)) {			const int j = i * V4L_BYTES_PER_PIXEL;#if USES_IBMCAM_PUTPIXEL			/* Refresh 'f' because we don't use it much with PUTPIXEL */			f = frame->data + (v4l_linesize * frame->curline) + j;#endif			memset(f, 0, v4l_linesize - j);			break;		}		/*		 * Here I use RA and RB components, one per physical pixel.		 * This causes fine vertical grid on the picture but may improve		 * horizontal resolution. If you prefer replicating, use this:		 *   rv = la[j + 0];   ... or ... rv = la[j + 1];		 * then the pixel will be replicated.		 */		rv = la[i];		gv = lb[j + 1];		bv = lb[j + 0];		y = (rv + gv + bv) / 3; /* Brightness (badly calculated) */		if (flags & FLAGS_MONOCHROME) /* Use monochrome for debugging */			rv = gv = bv = y;		else if (color_corr != 128) {			/* Calculate difference between color and brightness */			rv -= y;			gv -= y;			bv -= y;			/* Scale differences */			rv = (rv * color_corr) / 128;			gv = (gv * color_corr) / 128;			bv = (bv * color_corr) / 128;			/* Reapply brightness */			rv += y;			gv += y;			bv += y;			/* Watch for overflows */			RESTRICT_TO_RANGE(rv, 0, 255);			RESTRICT_TO_RANGE(gv, 0, 255);			RESTRICT_TO_RANGE(bv, 0, 255);		}	make_pixel:		RGB24_PUTPIXEL(frame, i, frame->curline, rv, gv, bv);	}	/*	 * Account for number of bytes that we wrote into output V4L frame.	 * We do it here, after we are done with the scanline, because we	 * may fill more than one output scanline if we do vertical	 * enlargement.	 */	frame->curline += 2;	*pcopylen += v4l_linesize * 2;	frame->deinterlace = Deinterlace_FillOddLines;	if (frame_done || (frame->curline >= VIDEOSIZE_Y(frame->request)))		return scan_NextFrame;	else		return scan_Continue;}static enum ParseState ibmcam_model3_parse_lines(	struct uvd *uvd,	struct usbvideo_frame *frame,	long *pcopylen){	unsigned char *data;	const unsigned char *color;	unsigned int len;	int v4l_linesize; /* V4L line offset */	const int hue_corr  = (uvd->vpic.hue - 0x8000) >> 10;	/* -32..+31 */	const int hue2_corr = (hue_correction - 128) / 4;		/* -32..+31 */	const int ccm = 128; /* Color correction median - see below */	int i, u, v, rw, data_w=0, data_h=0, color_corr;	static unsigned char lineBuffer[640*3];	color_corr = (uvd->vpic.colour - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/	RESTRICT_TO_RANGE(color_corr, -ccm, ccm+1);	v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;	/* The header tells us what sort of data is in this frame */	switch (frame->header) {		/*		 * Uncompressed modes (that are easy to decode).		 */	case 0x0308:		data_w = 640;		data_h = 480;		break;	case 0x0208:		data_w = 320;		data_h = 240;		break;	case 0x020A:		data_w = 160;		data_h = 120;		break;		/*		 * Compressed modes (ViCE - that I don't know how to decode).		 */	case 0x0328:	/* 640x480, best quality compression */	case 0x0368:	/* 640x480, best frame rate compression */	case 0x0228:	/* 320x240, best quality compression */	case 0x0268:	/* 320x240, best frame rate compression */	case 0x02CA:	/* 160x120, best quality compression */	case 0x02EA:	/* 160x120, best frame rate compression */		/* Do nothing with this - not supported */		err("Unsupported mode $%04lx", frame->header);		return scan_NextFrame;	default:		/* Catch unknown headers, may help in learning new headers */

⌨️ 快捷键说明

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