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

📄 ov511.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		for (l = 0; l < 8; l++) {			*pOut1 = *(pOut1 + w) = *pIn++;			pOut1++;		}		pOut += iWidth;	}	pIn = pIn0 + 64;	pOut = pOut0 + iOutUV + a + a/2;	for (k = 0; k < 8; k++) {		pOut1 = pOut;		for (l = 0; l < 8; l++) {			*pOut1 = *(pOut1 + w) = *pIn++;			pOut1++;		}		pOut += iWidth;	}	pIn = pIn0 + 128;	pOut = pOut0 + iOutY;	for (k = 0; k < 4; k++) {		pOut1 = pOut;		for (l = 0; l < 8; l++) {			for (m = 0; m < 8; m++)				*pOut1++ =*pIn++;			pOut1 += iWidth - 8;		}		pOut += 8;	}}/* * For 640x480 RAW BW images, data shows up in 1200 256 byte segments. * The segments represent 4 squares of 8x8 pixels as follows: * *      0  1 ...  7    64  65 ...  71   ...  192 193 ... 199 *      8  9 ... 15    72  73 ...  79        200 201 ... 207 *           ...              ...                    ... *     56 57 ... 63   120 121 ... 127        248 249 ... 255 * */ static voidov511_parse_data_grey(unsigned char *pIn0, unsigned char *pOut0,		      int iOutY, int iWidth)		    {	int k, l, m;	unsigned char *pIn;	unsigned char *pOut, *pOut1;	pIn = pIn0;	pOut = pOut0 + iOutY;	for (k = 0; k < 4; k++) {		pOut1 = pOut;		for (l = 0; l < 8; l++) {			for (m = 0; m < 8; m++) {				*pOut1++ = *pIn++;			}			pOut1 += iWidth - 8;		}		pOut += 8;	}}/* * fixFrameRGBoffset-- * My camera seems to return the red channel about 1 pixel * low, and the blue channel about 1 pixel high. After YUV->RGB * conversion, we can correct this easily. OSL 2/24/2000. */static void fixFrameRGBoffset(struct ov511_frame *frame){	int x, y;	int rowBytes = frame->width*3, w = frame->width;	unsigned char *rgb = frame->data;	const int shift = 1;  /* Distance to shift pixels by, vertically */	/* Don't bother with little images */	if (frame->width < 400) 		return;	/* Shift red channel up */	for (y = shift; y < frame->height; y++)	{		int lp = (y-shift)*rowBytes;     /* Previous line offset */		int lc = y*rowBytes;             /* Current line offset */		for (x = 0; x < w; x++)			rgb[lp+x*3+2] = rgb[lc+x*3+2]; /* Shift red up */	}	/* Shift blue channel down */	for (y = frame->height-shift-1; y >= 0; y--) {		int ln = (y + shift) * rowBytes;  /* Next line offset */		int lc = y * rowBytes;            /* Current line offset */		for (x = 0; x < w; x++)			rgb[ln+x*3+0] = rgb[lc+x*3+0]; /* Shift blue down */	}}/********************************************************************** * * OV511 data transfer, IRQ handler * **********************************************************************/static int ov511_move_data(struct usb_ov511 *ov511, urb_t *urb){	unsigned char *cdata;	int i, totlen = 0;	int aPackNum[10];	struct ov511_frame *frame;	unsigned char *pData;	int iPix;	PDEBUG (4, "Moving %d packets", urb->number_of_packets);	for (i = 0; i < urb->number_of_packets; i++) {		int n = urb->iso_frame_desc[i].actual_length;		int st = urb->iso_frame_desc[i].status;		urb->iso_frame_desc[i].actual_length = 0;		urb->iso_frame_desc[i].status = 0;		cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset;		aPackNum[i] = n ? cdata[ov511->packet_size - 1] : -1;		if (!n || ov511->curframe == -1)			continue;		if (st)			PDEBUG(2, "data error: [%d] len=%d, status=%d", i, n, st);		frame = &ov511->frame[ov511->curframe];				/* SOF/EOF packets have 1st to 8th bytes zeroed and the 9th		 * byte non-zero. The EOF packet has image width/height in the		 * 10th and 11th packets. The 9th bit is given as follows:		 *		 * bit 7: EOF		 *     6: compression enabled		 *     5: 422/420/400 modes		 *     4: 422/420/400 modes		 *     3: 1		 *     2: snapshot bottom on		 *     1: snapshot frame		 *     0: even/odd field		 */		/* Check for SOF/EOF packet */		if ((cdata[0] | cdata[1] | cdata[2] | cdata[3] | 		     cdata[4] | cdata[5] | cdata[6] | cdata[7]) ||		     (~cdata[8] & 0x08))			goto check_middle;		/* Frame end */		if (cdata[8] & 0x80) {			struct timeval *ts;			ts = (struct timeval *)(frame->data + MAX_FRAME_SIZE);			do_gettimeofday (ts);		 	PDEBUG(4, "Frame end, curframe = %d, packnum=%d, hw=%d, vw=%d",				ov511->curframe, (int)(cdata[ov511->packet_size - 1]),				(int)(cdata[9]), (int)(cdata[10]));			if (frame->scanstate == STATE_LINES) {		    		int iFrameNext;				if (fix_rgb_offset)					fixFrameRGBoffset(frame);				frame->grabstate = FRAME_DONE;				if (waitqueue_active(&frame->wq)) {					frame->grabstate = FRAME_DONE;					wake_up_interruptible(&frame->wq);				}				/* If next frame is ready or grabbing,                                 * point to it */				iFrameNext = (ov511->curframe + 1) % OV511_NUMFRAMES;				if (ov511->frame[iFrameNext].grabstate == FRAME_READY				    || ov511->frame[iFrameNext].grabstate == FRAME_GRABBING) {					ov511->curframe = iFrameNext;					ov511->frame[iFrameNext].scanstate = STATE_SCANNING;				} else {					if (frame->grabstate == FRAME_DONE) {						PDEBUG(4, "Frame done! congratulations");					} else {						PDEBUG(4, "Frame not ready? state = %d",							ov511->frame[iFrameNext].grabstate);					}					ov511->curframe = -1;				}			}			/* Image corruption caused by misplaced frame->segment = 0			 * fixed by carlosf@conectiva.com.br			 */		} else {			/* Frame start */			PDEBUG(4, "Frame start, framenum = %d", ov511->curframe);#if 0			/* Make sure no previous data carries over; necessary			 * for compression experimentation */			memset(frame->data, 0, MAX_DATA_SIZE);#endif			output_offset = 0;			/* Check to see if it's a snapshot frame */			/* FIXME?? Should the snapshot reset go here? Performance? */			if (cdata[8] & 0x02) {				frame->snapshot = 1;				PDEBUG(3, "snapshot detected");			}			frame->scanstate = STATE_LINES;			frame->segment = 0;		}check_middle:		/* Are we in a frame? */		if (frame->scanstate != STATE_LINES)			continue;		/* Deal with leftover from last segment, if any */		if (frame->segment) {			pData = ov511->scratch;			iPix = -ov511->scratchlen;			memmove(pData + ov511->scratchlen, cdata,				iPix+frame->segsize);		} else {			pData = &cdata[iPix = 9];	 	}		/* Parse the segments */		while (iPix <= (ov511->packet_size - 1) - frame->segsize &&		    frame->segment < frame->width * frame->height / 256) {			int iSegY, iSegUV;			int iY, jY, iUV, jUV;			int iOutY, iOutYP, iOutUV, iOutUVP;			unsigned char *pOut;			iSegY = iSegUV = frame->segment;			pOut = frame->data;			frame->segment++;			iPix += frame->segsize;			/* Handle subwindow */			if (frame->sub_flag) {				int iSeg1;				iSeg1 = iSegY / (ov511->subw / 32);				iSeg1 *= frame->width / 32;				iSegY = iSeg1 + (iSegY % (ov511->subw / 32));				if (iSegY >= frame->width * ov511->subh / 256)					break;				iSeg1 = iSegUV / (ov511->subw / 16);				iSeg1 *= frame->width / 16;				iSegUV = iSeg1 + (iSegUV % (ov511->subw / 16));				pOut += (ov511->subx + ov511->suby * frame->width) *					(frame->depth >> 3);			}			/* 			 * i counts segment lines			 * j counts segment columns			 * iOut is the offset (in bytes) of the upper left corner			 */			iY = iSegY / (frame->width / WDIV);			jY = iSegY - iY * (frame->width / WDIV);			iOutYP = iY*HDIV*frame->width + jY*WDIV;			iOutY = iOutYP * (frame->depth >> 3);			iUV = iSegUV / (frame->width / WDIV * 2);			jUV = iSegUV - iUV * (frame->width / WDIV * 2);			iOutUVP = iUV*HDIV*2*frame->width + jUV*WDIV/2;			iOutUV = iOutUVP * (frame->depth >> 3);			switch (frame->format) {			case VIDEO_PALETTE_GREY:				ov511_parse_data_grey (pData, pOut, iOutY, frame->width);				break;			case VIDEO_PALETTE_RGB24:				if (dumppix)					ov511_dumppix(pData, pOut, iOutY, iOutUV,						iY & 1, frame->width);				else if (sensor_gbr)					ov511_parse_gbr422_to_rgb24(pData, pOut, iOutY, iOutUV,						iY & 1, frame->width);				else					ov511_parse_yuv420_to_rgb(pData, pOut, iOutY, iOutUV,						iY & 1, frame->width, 24);				break;			case VIDEO_PALETTE_RGB565:				ov511_parse_yuv420_to_rgb(pData, pOut, iOutY, iOutUV,					iY & 1, frame->width, 16);				break;			case VIDEO_PALETTE_YUV422:			case VIDEO_PALETTE_YUYV:				ov511_parse_data_yuv422(pData, pOut, iOutY, iOutUV, frame->width);				break;			case VIDEO_PALETTE_YUV420:				ov511_parse_data_yuv420 (pData, pOut, iOutYP, iUV*HDIV*frame->width/2 + jUV*WDIV/4,					frame->width, frame->height);				break;			case VIDEO_PALETTE_YUV422P:				ov511_parse_data_yuv422p (pData, pOut, iOutYP, iOutUVP/2,					frame->width, frame->height);				break;			default:				err("Unsupported format: %d", frame->format);			}			pData = &cdata[iPix];		}		/* Save extra data for next time */		if (frame->segment < frame->width * frame->height / 256) {			ov511->scratchlen = (ov511->packet_size - 1) - iPix;			if (ov511->scratchlen < frame->segsize)				memmove(ov511->scratch, pData, ov511->scratchlen);			else				ov511->scratchlen = 0;		}	}	PDEBUG(5, "pn: %d %d %d %d %d %d %d %d %d %d",	       aPackNum[0], aPackNum[1], aPackNum[2], aPackNum[3], aPackNum[4],	       aPackNum[5],aPackNum[6], aPackNum[7], aPackNum[8], aPackNum[9]);	return totlen;}static void ov511_isoc_irq(struct urb *urb){	int len;	struct usb_ov511 *ov511;	struct ov511_sbuf *sbuf;	if (!urb->context) {		PDEBUG(4, "no context");		return;	}	ov511 = (struct usb_ov511 *) urb->context;	if (!ov511->dev || !ov511->user) {		PDEBUG(4, "no device, or not open");		return;	}	if (!ov511->streaming) {		PDEBUG(4, "hmmm... not streaming, but got interrupt");		return;	}		sbuf = &ov511->sbuf[ov511->cursbuf];	/* Copy the data received into our scratch buffer */	if (ov511->curframe >= 0) {		len = ov511_move_data(ov511, urb);	} else if (waitqueue_active(&ov511->wq)) {		wake_up_interruptible(&ov511->wq);	}	/* Move to the next sbuf */	ov511->cursbuf = (ov511->cursbuf + 1) % OV511_NUMSBUF;	urb->dev = ov511->dev;	return;}static int ov511_init_isoc(struct usb_ov511 *ov511){	urb_t *urb;	int fx, err, n, size;	PDEBUG(3, "*** Initializing capture ***");	ov511->compress = 0;	ov511->curframe = -1;	ov511->cursbuf = 0;	ov511->scratchlen = 0;	if (ov511->bridge == BRG_OV511)		if (cams == 1)			 size = 993;		else if (cams == 2)		 size = 513;		else if (cams == 3 || cams == 4) size = 257;		else {			err("\"cams\" parameter too high!");			return -1;		}	else if (ov511->bridge == BRG_OV511PLUS)		if (cams == 1)                      size = 961;		else if (cams == 2)                 size = 513;		else if (cams == 3 || cams == 4) size = 257;		else if (cams >= 5 && cams <= 8)    size = 129;		else if (cams >= 9 && cams <= 31)   size = 33;		else {			err("\"cams\" parameter too high!");			return -1;		}	else {		err("invalid bridge type");		return -1;	}	ov511_set_packet_size(ov511, size);	for (n = 0; n < OV511_NUMSBUF; n++) {		urb = usb_alloc_urb(FRAMES_PER_DESC);			if (!urb) {			err("init isoc: usb_alloc_urb ret. NULL");			return -ENOMEM;		}		ov511->sbuf[n].urb = urb;		urb->dev = ov511->dev;		urb->context = ov511;		urb->pipe = usb_rcvisocpipe(ov511->dev, OV511_ENDPOINT_ADDRESS);		urb->transfer_flags = USB_ISO_ASAP;		urb->transfer_buffer = ov511->sbuf[n].data;		urb->complete = ov511_isoc_irq;		urb->number_of_packets = FRAMES_PER_DESC;		urb->transfer_buffer_length = ov511->packet_size * FRAMES_PER_DESC;		for (fx = 0; fx < FRAMES_PER_DESC; fx++) {			urb->iso_frame_desc[fx].offset = ov511->packet_size * fx;			urb->iso_frame_desc[fx].length = ov511->packet_size;		}	}	ov511->sbuf[OV511_NUMSBUF - 1].urb->next = ov511->sbuf[0].urb;	for (n = 0; n < OV511_NUMSBUF - 1; n++)		ov511->sbuf[n].urb->next = ov511->sbuf[n+1].urb;	for (n = 0; n < OV511_NUMSBUF; n++) {		ov511->sbuf[n].urb->dev = ov511->dev;		err = usb_submit_urb(ov511->sbuf[n].urb);		if (err)			err("init isoc: usb_submit_urb(%d) ret %d", n, err);	}	ov511->streaming = 1;	return 0;}static void ov511_stop_isoc(struct usb_ov511 *ov511){	int n;	if (!ov511->streaming || !ov511->dev)		return;	PDEBUG (3, "*** Stopping capture ***");	ov511_set_packet_size(ov511, 0);	ov511->streaming = 0;	/* Unschedule all of the iso td's */	for (n = OV511_NUMSBUF - 1; n >= 0; n--) {		if (ov511->sbuf[n].urb) {			ov511->sbuf[n].urb->next = NULL;			usb_unlink_urb(ov511->sbuf[n].urb);			usb_free_urb(ov511->sbuf[n].urb);			ov511->sbuf[n].urb = NULL;		}	}}static int ov511_new_frame(struct usb_ov511 *ov511, int framenum){	struct ov511_frame *frame;	PDEBUG(4, "ov511->curframe = %d, framenum = %d", ov511->curframe,		framenum);	if (!ov511->dev)		return -1;	/* If we're not grabbing a frame right now and the other frame is */	/* ready to be grabbed into, then use it instead */	if (ov511->curframe == -1) {		if (ov511->frame[(framenum - 1 + OV511_NUMFRAMES) % OV511_NUMFRAMES].grabstate == FRAME_READY)			framenum = (framenum - 1 + OV511_NUMFRAMES) % OV511_NUMFRAMES;	} else		return 0;	frame = &ov511->frame[framenum];	PDEBUG (4, "framenum = %d, width = %d, height = %d", framenum, 		frame->width, frame->height);	frame->grabstate = FRAME_GRABBING;	frame->scanstate = STATE_SCANNING;	frame->scanlength = 0;		/* accumulated in ov511_parse_data() */	frame->snapshot = 0;	ov511->curframe = framenum;	/* Make sure it's not too big */	if (frame->width > ov511->maxwidth)		frame->width = ov511->maxwidth;

⌨️ 快捷键说明

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