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

📄 gspca_core.c

📁 Linux下面摄像头最新源代码:支持200多中摄像头
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Can we find a frame start */		if (sequenceNumber == 0) {			PDEBUG(3, "spca50x: Found Frame Start!, framenum = %d",			       spca50x->curframe);// Start of frame is implicit end of previous frame// Check for a previous frame and finish it off if one exists			if (frame->scanstate == STATE_LINES) {				if (frame->format != VIDEO_PALETTE_RAW_JPEG) {/* overflow ? */					ms_times_now = spca5xx_gettimes();					if (ms_times_now < spca50x->last_times)						spca50x->last_times = 0;					spin_lock(&spca50x->v4l_lock);					ms_times_before =					    spca50x->last_times +					    spca50x->dtimes;					spin_unlock(&spca50x->v4l_lock);					if (ms_times_now >= ms_times_before) {						PDEBUG(2,						       "Decode frame last %d",						       (int) (ms_times_now -							      spca50x->							      last_times));						spca50x->last_times =						    ms_times_now;/* Decode the frame one at a times or drop*/						if(!atomic_read(&spca50x->in_use)){						atomic_set(&spca50x->in_use,1);						spca50x->spca5xx_tasklet.data = (unsigned long) frame;						tasklet_schedule(&spca50x->								 spca5xx_tasklet);						} else							frame->grabstate = FRAME_ERROR;					} else						frame->grabstate = FRAME_ERROR;				} else {/* RAW DATA stream */					frame->grabstate = FRAME_DONE;					if (waitqueue_active(&frame->wq))						wake_up_interruptible(&frame->								      wq);				}// If someone decided to wait for ANY frame - wake him up 				if (waitqueue_active(&spca50x->wq))					wake_up_interruptible(&spca50x->wq);				frame = spca50x_next_frame(spca50x, cdata);			} else				frame->scanstate = STATE_LINES;		}/* Are we in a frame? */		if (frame == NULL || frame->scanstate != STATE_LINES)			continue;		frame->last_packet = sequenceNumber;		pData = cdata + iPix;	// Skip packet header (1 or 10 bytes)// Consume data		PDEBUG(5, "Processing packet seq  %d,length %d,totlength %d",		       frame->last_packet, datalength, frame->totlength);/* this copy consume input data from the isoc stream */		if ((datalength > 0)) {			memcpy(frame->highwater, pData, datalength);			frame->highwater += datalength;			frame->totlength += datalength;		}	}	return 0;}/****************************************************************************** Buffer management****************************************************************************/static intspca50x_alloc(struct usb_spca50x *spca50x){	int i;	PDEBUG(4, "entered");	down(&spca50x->buf_lock);	if (spca50x->buf_state == BUF_ALLOCATED)		goto out;	spca50x->tmpBuffer = rvmalloc(MAX_FRAME_SIZE);	if (!spca50x->tmpBuffer)		goto error;	spca50x->fbuf = rvmalloc(SPCA50X_NUMFRAMES * MAX_DATA_SIZE);	if (!spca50x->fbuf)		goto error;	for (i = 0; i < SPCA50X_NUMFRAMES; i++) {		spca50x->frame[i].tmpbuffer = spca50x->tmpBuffer;		spca50x->frame[i].decoder = &spca50x->maindecode;	//connect each frame to the main data decoding spca50x->frame[i].spca50x_dev = spca50x;	//refind the whole structure 		spca50x->frame[i].grabstate = FRAME_UNUSED;		spca50x->frame[i].scanstate = STATE_SCANNING;		spca50x->frame[i].data = spca50x->fbuf + i * MAX_DATA_SIZE;		spca50x->frame[i].highwater = spca50x->frame[i].data;		memset(&spca50x->frame[i].pictsetting, 0,		       sizeof (struct pictparam));		PDEBUG(4, "frame[%d] @ %p", i, spca50x->frame[i].data);	}	spca50x->buf_state = BUF_ALLOCATED;      out:	up(&spca50x->buf_lock);	PDEBUG(4, "leaving");	return 0;      error:	if (spca50x->fbuf) {		rvfree(spca50x->fbuf, SPCA50X_NUMFRAMES * MAX_DATA_SIZE);		spca50x->fbuf = NULL;	}	if (spca50x->tmpBuffer) {		rvfree(spca50x->tmpBuffer, MAX_FRAME_SIZE);		spca50x->tmpBuffer = NULL;	}	spca50x->buf_state = BUF_NOT_ALLOCATED;	up(&spca50x->buf_lock);	PDEBUG(1, "errored");	return -ENOMEM;}static voidspca5xx_dealloc(struct usb_spca50x *spca50x){	int i;	PDEBUG(2, "entered dealloc");	down(&spca50x->buf_lock);	if (spca50x->fbuf) {		rvfree(spca50x->fbuf, SPCA50X_NUMFRAMES * MAX_DATA_SIZE);		spca50x->fbuf = NULL;		for (i = 0; i < SPCA50X_NUMFRAMES; i++)			spca50x->frame[i].data = NULL;	}	if (spca50x->tmpBuffer) {		rvfree(spca50x->tmpBuffer, MAX_FRAME_SIZE);		spca50x->tmpBuffer = NULL;	}	PDEBUG(2, "buffer memory deallocated");	spca50x->buf_state = BUF_NOT_ALLOCATED;	up(&spca50x->buf_lock);	PDEBUG(2, "leaving dealloc");}/*** Reset the camera and send the correct initialization sequence for the* currently selected source*/static intspca50x_init_source(struct usb_spca50x *spca50x){	int err_code;	if ((err_code = spca50x->funct.initialize(spca50x)) < 0)		return -EINVAL;	spca50x->norme = 0;	spca50x->channel = 0;	spca50x->light_freq = lightfreq;	if ((err_code =	     spca5xx_setMode(spca50x, spca50x->width, spca50x->height,			     VIDEO_PALETTE_RGB24)) < 0)		return -EINVAL;	spca5xx_set_light_freq(spca50x, lightfreq); 	return 0;}/****************************************************************************** V4L API****************************************************************************/static inline voidspca5xx_setFrameDecoder(struct usb_spca50x *spca50x){	int i;/* configure the frame detector with default parameters */	memset(&spca50x->pictsetting, 0, sizeof (struct pictparam));	spca50x->pictsetting.change = 0x01;	spca50x->pictsetting.force_rgb = force_rgb;	spca50x->pictsetting.gamma = gamma;	spca50x->pictsetting.OffRed = OffRed;	spca50x->pictsetting.OffBlue = OffBlue;	spca50x->pictsetting.OffGreen = OffGreen;	spca50x->pictsetting.GRed = GRed;	spca50x->pictsetting.GBlue = GBlue;	spca50x->pictsetting.GGreen = GGreen;/* Set default sizes in case IOCTL (VIDIOCMCAPTURE) is not used* (using read() instead). */	for (i = 0; i < SPCA50X_NUMFRAMES; i++) {		spca50x->frame[i].width = spca50x->width;		spca50x->frame[i].height = spca50x->height;		spca50x->frame[i].cameratype = spca50x->cameratype;		spca50x->frame[i].scanlength = spca50x->width * spca50x->height * 3 / 2;	// assumes 4:2:0 data		spca50x->frame[i].depth = 24;/* Note: format reflects format of data as returned to* a process, not as read from camera hardware.* This might be a good idea for dumb programs always* assuming the following settings.*/		spca50x->frame[i].format = VIDEO_PALETTE_RGB24;	}	spca50x->format = VIDEO_PALETTE_RGB24;}static intspca5xx_isjpeg(struct usb_spca50x *spca50x){	if (spca50x->cameratype == JPGH	    || spca50x->cameratype == JPGC	    || spca50x->cameratype == JPGS	    || spca50x->cameratype == JPEG		|| spca50x->cameratype == JPGM		|| spca50x->cameratype == PJPG)		return 1;	return 0;}static voidspca5xx_initDecoder(struct usb_spca50x *spca50x){	if (spca5xx_isjpeg(spca50x))		init_jpeg_decoder(spca50x);	if (spca50x->bridge == BRIDGE_SONIX)		init_sonix_decoder(spca50x);	if (spca50x->bridge == BRIDGE_PAC207)		init_pixart_decoder(spca50x);}static voidspca5xx_chgAuto(struct usb_spca50x *spca50x, __u8 autoval){	spca50x->autoexpo = (int) autoval;	spca50x->funct.set_autobright(spca50x);}static voidspca5xx_chgQtable(struct usb_spca50x *spca50x, __u8 qtable){	int intqtable = (int) qtable;/* one frame maybe corrupted  wait for the result */	if (spca5xx_isjpeg(spca50x) && (spca50x->qindex != intqtable)) {		if (spca50x->cameratype == JPGH) {/* only vimicro ATM */			spca50x->qindex = intqtable;			spca50x->funct.set_quality(spca50x);			init_jpeg_decoder(spca50x);		}	}}static inline voidspca5xx_chgDtimes(struct usb_spca50x *spca50x, __u16 dtimes){	unsigned long flags;	spin_lock_irqsave(&spca50x->v4l_lock, flags);	spca50x->dtimes = (unsigned int) dtimes;	spin_unlock_irqrestore(&spca50x->v4l_lock, flags);}/* Matches the sensor's internal frame rate to the lighting frequency. * Valid frequencies are: *	50 - 50Hz, for European and Asian lighting (default) *	60 - 60Hz, for American lighting *       0 - No Fliker (for outdoore usage) * Returns: 0 for success */static intspca5xx_set_light_freq(struct usb_spca50x *spca50x, int freq){	int freq_set;	if (freq == 50)		freq_set = freq_50HZ;	else if (freq == 60)		freq_set = freq_60HZ;	else if (freq == 0)		freq_set = NoFliker;	else {		PDEBUG(0,"Invalid light freq (%d Hz)", freq);		return -EINVAL;	}	switch (spca50x->sensor) {	case SENSOR_TAS5130C_VF0250:	case SENSOR_TAS5130CXX:	case SENSOR_PB0330:	case SENSOR_PAS106:	case SENSOR_ICM105A:	case SENSOR_HDCS2020b:	case SENSOR_CS2102:	case SENSOR_OV7660:	    break;	default:		PDEBUG(0,"Sensor currently not support light frequency banding filters.");		return -EINVAL;	}		if (freq_set == freq_50HZ) {          PDEBUG(1, "Light frequency banding filter set to 50HZ mode");	 if (spca50x->mode && spca50x->funct.set_50HZ) {            spca50x->funct.set_50HZ(spca50x);	 }  else if (spca50x->funct.set_50HZScale) {            spca50x->funct.set_50HZScale(spca50x); 	 }       	} else if (freq_set == freq_60HZ) {          PDEBUG(1, "Light frequency banding filter set to 60HZ mode");         if (spca50x->mode && spca50x->funct.set_60HZ) {            spca50x->funct.set_60HZ(spca50x);	 } else if (spca50x->funct.set_60HZScale) {	    spca50x->funct.set_60HZScale(spca50x);	 }        	} else if (freq_set == NoFliker) {          PDEBUG(1, "Light frequency banding filter set to NoFliker mode");         if (spca50x->mode && spca50x->funct.set_NoFliker) {            spca50x->funct.set_NoFliker(spca50x);	} else if (spca50x->funct.set_NoFlikerScale) {            spca50x->funct.set_NoFlikerScale(spca50x);	 }        	}	spca50x->light_freq = freq;	return 0;}static intspca5xx_open(struct inode *inode, struct file *file){	struct video_device *vdev = video_devdata(file);	struct usb_spca50x *spca50x = video_get_drvdata(vdev);	int err;	PDEBUG(2, "opening");	down(&spca50x->lock);/* sanity check disconnect, in use, no memory available */	err = -ENODEV;	if (!spca50x->present)		goto out;	err = -EBUSY;	if (spca50x->user)		goto out;	err = -ENOMEM;	if (spca50x_alloc(spca50x))		goto out;/* initialize sensor and decoding */	err = spca50x_init_source(spca50x);	if (err != 0) {		PDEBUG(0, "DEALLOC error on spca50x_init_source\n");		up(&spca50x->lock);		spca5xx_dealloc(spca50x);		goto out2;	}	spca5xx_initDecoder(spca50x);/* open always start in rgb24 a bug in gqcam did not select the palette nor the size  v4l spec need that the camera always start on the last setting */	spca5xx_setFrameDecoder(spca50x);	spca50x->user++;	file->private_data = vdev;	err = gspca_init_transfert(spca50x);	if (err) {		PDEBUG(0, " DEALLOC error on init_Isoc\n");		spca50x->user--;		gspca_kill_transfert(spca50x);		up(&spca50x->lock);		spca5xx_dealloc(spca50x);		file->private_data = NULL;		goto out2;	}/* Now, let's get brightness from the camera */	spca50x->brightness = spca50x->funct.get_bright(spca50x);	spca50x->whiteness = 0;      out:	up(&spca50x->lock);      out2:	if (err) {		PDEBUG(2, "Open failed");	} else {		PDEBUG(2, "Open done");	}	return err;}static void inlinespcaCameraShutDown(struct usb_spca50x *spca50x){	if (spca50x->dev) {		spca50x->funct.cam_shutdown(spca50x);	}}static intspca5xx_close(struct inode *inode, struct file *file){	struct video_device *vdev = file->private_data;	struct usb_spca50x *spca50x = video_get_drvdata(vdev);	int i;	PDEBUG(2, "spca50x_close");	down(&spca50x->lock);	spca50x->user--;	spca50x->curframe = -1;	if (spca50x->present) {		spca50x_stop_isoc(spca50x);		spcaCameraShutDown(spca50x);		for (i = 0; i < SPCA50X_NUMFRAMES; i++) {			if (waitqueue_active(&spca50x->frame[i].wq))				wake_up_interruptible(&spca50x->frame[i].wq);		}		if (waitqueue_active(&spca50x->wq))			wake_up_interruptible(&spca50x->wq);	}/* times to dealloc ressource */	up(&spca50x->lock);	spca5xx_dealloc(spca50x);	PD

⌨️ 快捷键说明

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