欢迎来到虫虫下载站 | 资源下载 资源专辑 关于我们
虫虫下载站

video-buf.c

LINUX 2.6.17.4的源码
C
第 1 页 / 共 3 页
字号:
			dprintk(1,"busy: buffer #%d queued\n",i);			return 1;		}		if (q->bufs[i]->state == STATE_ACTIVE) {			dprintk(1,"busy: buffer #%d avtive\n",i);			return 1;		}	}	return 0;}voidvideobuf_queue_cancel(struct videobuf_queue *q){	unsigned long flags=0;	int i;	/* remove queued buffers from list */	if (q->irqlock)		spin_lock_irqsave(q->irqlock,flags);	for (i = 0; i < VIDEO_MAX_FRAME; i++) {		if (NULL == q->bufs[i])			continue;		if (q->bufs[i]->state == STATE_QUEUED) {			list_del(&q->bufs[i]->queue);			q->bufs[i]->state = STATE_ERROR;		}	}	if (q->irqlock)		spin_unlock_irqrestore(q->irqlock,flags);	/* free all buffers + clear queue */	for (i = 0; i < VIDEO_MAX_FRAME; i++) {		if (NULL == q->bufs[i])			continue;		q->ops->buf_release(q,q->bufs[i]);	}	INIT_LIST_HEAD(&q->stream);}/* --------------------------------------------------------------------- */enum v4l2_fieldvideobuf_next_field(struct videobuf_queue *q){	enum v4l2_field field = q->field;	BUG_ON(V4L2_FIELD_ANY == field);	if (V4L2_FIELD_ALTERNATE == field) {		if (V4L2_FIELD_TOP == q->last) {			field   = V4L2_FIELD_BOTTOM;			q->last = V4L2_FIELD_BOTTOM;		} else {			field   = V4L2_FIELD_TOP;			q->last = V4L2_FIELD_TOP;		}	}	return field;}voidvideobuf_status(struct v4l2_buffer *b, struct videobuf_buffer *vb,		enum v4l2_buf_type type){	MAGIC_CHECK(vb->magic,MAGIC_BUFFER);	b->index    = vb->i;	b->type     = type;	b->memory   = vb->memory;	switch (b->memory) {	case V4L2_MEMORY_MMAP:		b->m.offset  = vb->boff;		b->length    = vb->bsize;		break;	case V4L2_MEMORY_USERPTR:		b->m.userptr = vb->baddr;		b->length    = vb->bsize;		break;	case V4L2_MEMORY_OVERLAY:		b->m.offset  = vb->boff;		break;	}	b->flags    = 0;	if (vb->map)		b->flags |= V4L2_BUF_FLAG_MAPPED;	switch (vb->state) {	case STATE_PREPARED:	case STATE_QUEUED:	case STATE_ACTIVE:		b->flags |= V4L2_BUF_FLAG_QUEUED;		break;	case STATE_DONE:	case STATE_ERROR:		b->flags |= V4L2_BUF_FLAG_DONE;		break;	case STATE_NEEDS_INIT:	case STATE_IDLE:		/* nothing */		break;	}	if (vb->input != UNSET) {		b->flags |= V4L2_BUF_FLAG_INPUT;		b->input  = vb->input;	}	b->field     = vb->field;	b->timestamp = vb->ts;	b->bytesused = vb->size;	b->sequence  = vb->field_count >> 1;}intvideobuf_reqbufs(struct videobuf_queue *q,		 struct v4l2_requestbuffers *req){	unsigned int size,count;	int retval;	if (req->type != q->type) {		dprintk(1,"reqbufs: queue type invalid\n");		return -EINVAL;	}	if (req->count < 1) {		dprintk(1,"reqbufs: count invalid (%d)\n",req->count);		return -EINVAL;	}	if (req->memory != V4L2_MEMORY_MMAP     &&	    req->memory != V4L2_MEMORY_USERPTR  &&	    req->memory != V4L2_MEMORY_OVERLAY) {		dprintk(1,"reqbufs: memory type invalid\n");		return -EINVAL;	}	if (q->streaming) {		dprintk(1,"reqbufs: streaming already exists\n");		return -EBUSY;	}	if (!list_empty(&q->stream)) {		dprintk(1,"reqbufs: stream running\n");		return -EBUSY;	}	mutex_lock(&q->lock);	count = req->count;	if (count > VIDEO_MAX_FRAME)		count = VIDEO_MAX_FRAME;	size = 0;	q->ops->buf_setup(q,&count,&size);	size = PAGE_ALIGN(size);	dprintk(1,"reqbufs: bufs=%d, size=0x%x [%d pages total]\n",		count, size, (count*size)>>PAGE_SHIFT);	retval = videobuf_mmap_setup(q,count,size,req->memory);	if (retval < 0) {		dprintk(1,"reqbufs: mmap setup returned %d\n",retval);		goto done;	}	req->count = count; done:	mutex_unlock(&q->lock);	return retval;}intvideobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b){	if (unlikely(b->type != q->type)) {		dprintk(1,"querybuf: Wrong type.\n");		return -EINVAL;	}	if (unlikely(b->index < 0 || b->index >= VIDEO_MAX_FRAME)) {		dprintk(1,"querybuf: index out of range.\n");		return -EINVAL;	}	if (unlikely(NULL == q->bufs[b->index])) {		dprintk(1,"querybuf: buffer is null.\n");		return -EINVAL;	}	videobuf_status(b,q->bufs[b->index],q->type);	return 0;}intvideobuf_qbuf(struct videobuf_queue *q,	      struct v4l2_buffer *b){	struct videobuf_buffer *buf;	enum v4l2_field field;	unsigned long flags=0;	int retval;	mutex_lock(&q->lock);	retval = -EBUSY;	if (q->reading) {		dprintk(1,"qbuf: Reading running...\n");		goto done;	}	retval = -EINVAL;	if (b->type != q->type) {		dprintk(1,"qbuf: Wrong type.\n");		goto done;	}	if (b->index < 0 || b->index >= VIDEO_MAX_FRAME) {		dprintk(1,"qbuf: index out of range.\n");		goto done;	}	buf = q->bufs[b->index];	if (NULL == buf) {		dprintk(1,"qbuf: buffer is null.\n");		goto done;	}	MAGIC_CHECK(buf->magic,MAGIC_BUFFER);	if (buf->memory != b->memory) {		dprintk(1,"qbuf: memory type is wrong.\n");		goto done;	}	if (buf->state == STATE_QUEUED ||	    buf->state == STATE_ACTIVE) {		dprintk(1,"qbuf: buffer is already queued or active.\n");		goto done;	}	if (b->flags & V4L2_BUF_FLAG_INPUT) {		if (b->input >= q->inputs) {			dprintk(1,"qbuf: wrong input.\n");			goto done;		}		buf->input = b->input;	} else {		buf->input = UNSET;	}	switch (b->memory) {	case V4L2_MEMORY_MMAP:		if (0 == buf->baddr) {			dprintk(1,"qbuf: mmap requested but buffer addr is zero!\n");			goto done;		}		break;	case V4L2_MEMORY_USERPTR:		if (b->length < buf->bsize) {			dprintk(1,"qbuf: buffer length is not enough\n");			goto done;		}		if (STATE_NEEDS_INIT != buf->state && buf->baddr != b->m.userptr)			q->ops->buf_release(q,buf);		buf->baddr = b->m.userptr;		break;	case V4L2_MEMORY_OVERLAY:		buf->boff = b->m.offset;		break;	default:		dprintk(1,"qbuf: wrong memory type\n");		goto done;	}	dprintk(1,"qbuf: requesting next field\n");	field = videobuf_next_field(q);	retval = q->ops->buf_prepare(q,buf,field);	if (0 != retval) {		dprintk(1,"qbuf: buffer_prepare returned %d\n",retval);		goto done;	}	list_add_tail(&buf->stream,&q->stream);	if (q->streaming) {		if (q->irqlock)			spin_lock_irqsave(q->irqlock,flags);		q->ops->buf_queue(q,buf);		if (q->irqlock)			spin_unlock_irqrestore(q->irqlock,flags);	}	dprintk(1,"qbuf: succeded\n");	retval = 0; done:	mutex_unlock(&q->lock);	return retval;}intvideobuf_dqbuf(struct videobuf_queue *q,	       struct v4l2_buffer *b, int nonblocking){	struct videobuf_buffer *buf;	int retval;	mutex_lock(&q->lock);	retval = -EBUSY;	if (q->reading) {		dprintk(1,"dqbuf: Reading running...\n");		goto done;	}	retval = -EINVAL;	if (b->type != q->type) {		dprintk(1,"dqbuf: Wrong type.\n");		goto done;	}	if (list_empty(&q->stream)) {		dprintk(1,"dqbuf: stream running\n");		goto done;	}	buf = list_entry(q->stream.next, struct videobuf_buffer, stream);	retval = videobuf_waiton(buf, nonblocking, 1);	if (retval < 0) {		dprintk(1,"dqbuf: waiton returned %d\n",retval);		goto done;	}	switch (buf->state) {	case STATE_ERROR:		dprintk(1,"dqbuf: state is error\n");		retval = -EIO;		videobuf_dma_sync(q,&buf->dma);		buf->state = STATE_IDLE;		break;	case STATE_DONE:		dprintk(1,"dqbuf: state is done\n");		videobuf_dma_sync(q,&buf->dma);		buf->state = STATE_IDLE;		break;	default:		dprintk(1,"dqbuf: state invalid\n");		retval = -EINVAL;		goto done;	}	list_del(&buf->stream);	memset(b,0,sizeof(*b));	videobuf_status(b,buf,q->type); done:	mutex_unlock(&q->lock);	return retval;}int videobuf_streamon(struct videobuf_queue *q){	struct videobuf_buffer *buf;	struct list_head *list;	unsigned long flags=0;	int retval;	mutex_lock(&q->lock);	retval = -EBUSY;	if (q->reading)		goto done;	retval = 0;	if (q->streaming)		goto done;	q->streaming = 1;	if (q->irqlock)		spin_lock_irqsave(q->irqlock,flags);	list_for_each(list,&q->stream) {		buf = list_entry(list, struct videobuf_buffer, stream);		if (buf->state == STATE_PREPARED)			q->ops->buf_queue(q,buf);	}	if (q->irqlock)		spin_unlock_irqrestore(q->irqlock,flags); done:	mutex_unlock(&q->lock);	return retval;}int videobuf_streamoff(struct videobuf_queue *q){	int retval = -EINVAL;	mutex_lock(&q->lock);	if (!q->streaming)		goto done;	videobuf_queue_cancel(q);	q->streaming = 0;	retval = 0; done:	mutex_unlock(&q->lock);	return retval;}static ssize_tvideobuf_read_zerocopy(struct videobuf_queue *q, char __user *data,		       size_t count, loff_t *ppos){	enum v4l2_field field;	unsigned long flags=0;	int retval;	/* setup stuff */	q->read_buf = videobuf_alloc(q->msize);	if (NULL == q->read_buf)		return -ENOMEM;	q->read_buf->memory = V4L2_MEMORY_USERPTR;	q->read_buf->baddr  = (unsigned long)data;	q->read_buf->bsize  = count;	field = videobuf_next_field(q);	retval = q->ops->buf_prepare(q,q->read_buf,field);	if (0 != retval)		goto done;	/* start capture & wait */	if (q->irqlock)		spin_lock_irqsave(q->irqlock,flags);	q->ops->buf_queue(q,q->read_buf);	if (q->irqlock)		spin_unlock_irqrestore(q->irqlock,flags);	retval = videobuf_waiton(q->read_buf,0,0);	if (0 == retval) {		videobuf_dma_sync(q,&q->read_buf->dma);		if (STATE_ERROR == q->read_buf->state)			retval = -EIO;		else			retval = q->read_buf->size;	} done:	/* cleanup */	q->ops->buf_release(q,q->read_buf);	kfree(q->read_buf);	q->read_buf = NULL;	return retval;}ssize_t videobuf_read_one(struct videobuf_queue *q,			  char __user *data, size_t count, loff_t *ppos,			  int nonblocking){	enum v4l2_field field;	unsigned long flags=0;	unsigned size, nbufs, bytes;	int retval;	mutex_lock(&q->lock);	nbufs = 1; size = 0;	q->ops->buf_setup(q,&nbufs,&size);	if (NULL == q->read_buf  &&	    count >= size        &&	    !nonblocking) {		retval = videobuf_read_zerocopy(q,data,count,ppos);		if (retval >= 0  ||  retval == -EIO)			/* ok, all done */			goto done;		/* fallback to kernel bounce buffer on failures */	}	if (NULL == q->read_buf) {		/* need to capture a new frame */		retval = -ENOMEM;		q->read_buf = videobuf_alloc(q->msize);		dprintk(1,"video alloc=0x%p\n", q->read_buf);		if (NULL == q->read_buf)			goto done;		q->read_buf->memory = V4L2_MEMORY_USERPTR;		q->read_buf->bsize = count; /* preferred size */		field = videobuf_next_field(q);		retval = q->ops->buf_prepare(q,q->read_buf,field);		if (0 != retval) {			kfree (q->read_buf);			q->read_buf = NULL;			goto done;		}		if (q->irqlock)			spin_lock_irqsave(q->irqlock,flags);		q->ops->buf_queue(q,q->read_buf);

⌨️ 快捷键说明

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