From 7b44ca8bda03a8ddfebb565be7a9554646538436 Mon Sep 17 00:00:00 2001 From: Gerd Knorr <kraxel@bytesex.org> Date: Tue, 7 Jan 2003 18:11:06 -0800 Subject: [PATCH] [PATCH] video-buf.c update This updates the video-buf helper module. It changes the field handling a bit and adds code do deal better with alternating field capture (= capture even and odd fields to separate video buffers). --- drivers/media/video/video-buf.c | 44 ++++++++++++++++++++++++++++++--- drivers/media/video/video-buf.h | 8 ++++-- 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c index 2f51c2a9fa2f..1083cac45da4 100644 --- a/drivers/media/video/video-buf.c +++ b/drivers/media/video/video-buf.c @@ -339,6 +339,7 @@ videobuf_queue_init(struct videobuf_queue *q, struct pci_dev *pci, spinlock_t *irqlock, enum v4l2_buf_type type, + enum v4l2_field field, int msize) { memset(q,0,sizeof(*q)); @@ -346,6 +347,7 @@ videobuf_queue_init(struct videobuf_queue *q, q->irqlock = irqlock; q->pci = pci; q->type = type; + q->field = field; q->msize = msize; q->ops = ops; @@ -406,6 +408,25 @@ videobuf_queue_cancel(struct file *file, struct videobuf_queue *q) /* --------------------------------------------------------------------- */ +enum v4l2_field +videobuf_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_TOP; + q->last = V4L2_FIELD_TOP; + } else { + field = V4L2_FIELD_BOTTOM; + q->last = V4L2_FIELD_BOTTOM; + } + } + return field; +} + void videobuf_status(struct v4l2_buffer *b, struct videobuf_buffer *vb, enum v4l2_buf_type type) @@ -486,6 +507,7 @@ videobuf_qbuf(struct file *file, struct videobuf_queue *q, struct v4l2_buffer *b) { struct videobuf_buffer *buf; + enum v4l2_field field; unsigned long flags; int retval; @@ -507,7 +529,8 @@ videobuf_qbuf(struct file *file, struct videobuf_queue *q, buf->state == STATE_ACTIVE) goto done; - retval = q->ops->buf_prepare(file,buf); + field = videobuf_next_field(q); + retval = q->ops->buf_prepare(file,buf,field); if (0 != retval) goto done; @@ -613,6 +636,8 @@ static ssize_t videobuf_read_zerocopy(struct file *file, struct videobuf_queue *q, char *data, size_t count, loff_t *ppos) { + enum v4l2_field field; + unsigned long flags; int retval; /* setup stuff */ @@ -623,12 +648,15 @@ videobuf_read_zerocopy(struct file *file, struct videobuf_queue *q, q->read_buf->baddr = (unsigned long)data; q->read_buf->bsize = count; - retval = q->ops->buf_prepare(file,q->read_buf); + field = videobuf_next_field(q); + retval = q->ops->buf_prepare(file,q->read_buf,field); if (0 != retval) goto done; /* start capture & wait */ + spin_lock_irqsave(q->irqlock,flags); q->ops->buf_queue(file,q->read_buf); + spin_unlock_irqrestore(q->irqlock,flags); retval = videobuf_waiton(q->read_buf,0,0); if (0 == retval) { videobuf_dma_pci_sync(q->pci,&q->read_buf->dma); @@ -646,6 +674,8 @@ videobuf_read_zerocopy(struct file *file, struct videobuf_queue *q, ssize_t videobuf_read_one(struct file *file, struct videobuf_queue *q, char *data, size_t count, loff_t *ppos) { + enum v4l2_field field; + unsigned long flags; int retval, bytes, size, nbufs; down(&q->lock); @@ -668,10 +698,13 @@ ssize_t videobuf_read_one(struct file *file, struct videobuf_queue *q, q->read_buf = videobuf_alloc(q->msize); if (NULL == q->read_buf) goto done; - retval = q->ops->buf_prepare(file,q->read_buf); + field = videobuf_next_field(q); + retval = q->ops->buf_prepare(file,q->read_buf,field); if (0 != retval) goto done; + spin_lock_irqsave(q->irqlock,flags); q->ops->buf_queue(file,q->read_buf); + spin_unlock_irqrestore(q->irqlock,flags); q->read_off = 0; } @@ -705,6 +738,7 @@ ssize_t videobuf_read_one(struct file *file, struct videobuf_queue *q, int videobuf_read_start(struct file *file, struct videobuf_queue *q) { + enum v4l2_field field; unsigned long flags; int count = 0, size = 0; int err, i; @@ -720,7 +754,8 @@ int videobuf_read_start(struct file *file, struct videobuf_queue *q) if (err) return err; for (i = 0; i < count; i++) { - err = q->ops->buf_prepare(file,q->bufs[i]); + field = videobuf_next_field(q); + err = q->ops->buf_prepare(file,q->bufs[i],field); if (err) return err; list_add_tail(&q->bufs[i]->stream, &q->stream); @@ -793,6 +828,7 @@ ssize_t videobuf_read_stream(struct file *file, struct videobuf_queue *q, fc = (unsigned int*)q->read_buf->dma.vmalloc; fc += (q->read_buf->size>>2) -1; *fc = q->read_buf->field_count >> 1; + dprintk(1,"vbihack: %d\n",*fc); } /* copy stuff */ diff --git a/drivers/media/video/video-buf.h b/drivers/media/video/video-buf.h index 76549c05462f..d4b03b3570d8 100644 --- a/drivers/media/video/video-buf.h +++ b/drivers/media/video/video-buf.h @@ -154,7 +154,8 @@ struct videobuf_buffer { struct videobuf_queue_ops { int (*buf_setup)(struct file *file, int *count, int *size); - int (*buf_prepare)(struct file *file,struct videobuf_buffer *vb); + int (*buf_prepare)(struct file *file,struct videobuf_buffer *vb, + enum v4l2_field field); void (*buf_queue)(struct file *file,struct videobuf_buffer *vb); void (*buf_release)(struct file *file,struct videobuf_buffer *vb); }; @@ -166,6 +167,8 @@ struct videobuf_queue { enum v4l2_buf_type type; int msize; + enum v4l2_field field; + enum v4l2_field last; /* for field=V4L2_FIELD_ALTERNATE */ struct videobuf_buffer *bufs[VIDEO_MAX_FRAME]; struct videobuf_queue_ops *ops; @@ -186,7 +189,8 @@ int videobuf_iolock(struct pci_dev *pci, struct videobuf_buffer *vb); void videobuf_queue_init(struct videobuf_queue *q, struct videobuf_queue_ops *ops, struct pci_dev *pci, spinlock_t *irqlock, - enum v4l2_buf_type type, int msize); + enum v4l2_buf_type type, + enum v4l2_field field, int msize); int videobuf_queue_is_busy(struct videobuf_queue *q); void videobuf_queue_cancel(struct file *file, struct videobuf_queue *q); -- 2.30.9