aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2009-08-08 02:14:55 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-08-13 19:39:09 -0400
commitc2a6b54a9cf08d4ffeb75d70603c4a5d03ac97ad (patch)
tree3f263afdb14fb8226b0d0f60b026f8e3fc29bf85 /drivers/media
parentd594317bdc716ccd8c8cf711e3827f9b6e0b766b (diff)
V4L/DVB (12406): em28xx: fix: don't do image interlacing on webcams
Due to historical reasons, em28xx driver gets two consecutive frames and fold them into an unique framing, doing interlacing. While this works fine for TV images, this produces two bad effects with webcams: 1) webcam images are progressive. Merging two consecutive images produce interlacing artifacts on the image; 2) since the driver needs to get two frames, it reduces the maximum frame rate by two. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/em28xx/em28xx-cards.c4
-rw-r--r--drivers/media/video/em28xx/em28xx-core.c5
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c40
-rw-r--r--drivers/media/video/em28xx/em28xx.h3
4 files changed, 42 insertions, 10 deletions
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
index c9e420e8a614..9011a498e5b3 100644
--- a/drivers/media/video/em28xx/em28xx-cards.c
+++ b/drivers/media/video/em28xx/em28xx-cards.c
@@ -2502,6 +2502,10 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
2502 if (em28xx_hint_sensor(dev) < 0) 2502 if (em28xx_hint_sensor(dev) < 0)
2503 dev->board.is_webcam = 0; 2503 dev->board.is_webcam = 0;
2504 2504
2505 /* It makes no sense to use de-interlacing mode on webcams */
2506 if (dev->board.is_webcam)
2507 dev->progressive = 1;
2508
2505 /* Do board specific init and eeprom reading */ 2509 /* Do board specific init and eeprom reading */
2506 em28xx_card_setup(dev); 2510 em28xx_card_setup(dev);
2507 2511
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
index 5b78e199abd1..339fffdf6bce 100644
--- a/drivers/media/video/em28xx/em28xx-core.c
+++ b/drivers/media/video/em28xx/em28xx-core.c
@@ -720,7 +720,10 @@ int em28xx_resolution_set(struct em28xx *dev)
720{ 720{
721 int width, height; 721 int width, height;
722 width = norm_maxw(dev); 722 width = norm_maxw(dev);
723 height = norm_maxh(dev) >> 1; 723 height = norm_maxh(dev);
724
725 if (!dev->progressive)
726 height >>= norm_maxh(dev);
724 727
725 em28xx_set_outfmt(dev); 728 em28xx_set_outfmt(dev);
726 729
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 92ee9c644328..ab079d9256c4 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -194,15 +194,24 @@ static void em28xx_copy_video(struct em28xx *dev,
194 startread = p; 194 startread = p;
195 remain = len; 195 remain = len;
196 196
197 /* Interlaces frame */ 197 if (dev->progressive)
198 if (buf->top_field)
199 fieldstart = outp; 198 fieldstart = outp;
200 else 199 else {
201 fieldstart = outp + bytesperline; 200 /* Interlaces two half frames */
201 if (buf->top_field)
202 fieldstart = outp;
203 else
204 fieldstart = outp + bytesperline;
205 }
202 206
203 linesdone = dma_q->pos / bytesperline; 207 linesdone = dma_q->pos / bytesperline;
204 currlinedone = dma_q->pos % bytesperline; 208 currlinedone = dma_q->pos % bytesperline;
205 offset = linesdone * bytesperline * 2 + currlinedone; 209
210 if (dev->progressive)
211 offset = linesdone * bytesperline + currlinedone;
212 else
213 offset = linesdone * bytesperline * 2 + currlinedone;
214
206 startwrite = fieldstart + offset; 215 startwrite = fieldstart + offset;
207 lencopy = bytesperline - currlinedone; 216 lencopy = bytesperline - currlinedone;
208 lencopy = lencopy > remain ? remain : lencopy; 217 lencopy = lencopy > remain ? remain : lencopy;
@@ -376,7 +385,7 @@ static inline int em28xx_isoc_copy(struct em28xx *dev, struct urb *urb)
376 em28xx_isocdbg("Video frame %d, length=%i, %s\n", p[2], 385 em28xx_isocdbg("Video frame %d, length=%i, %s\n", p[2],
377 len, (p[2] & 1) ? "odd" : "even"); 386 len, (p[2] & 1) ? "odd" : "even");
378 387
379 if (!(p[2] & 1)) { 388 if (dev->progressive || !(p[2] & 1)) {
380 if (buf != NULL) 389 if (buf != NULL)
381 buffer_filled(dev, dma_q, buf); 390 buffer_filled(dev, dma_q, buf);
382 get_next_buf(dma_q, &buf); 391 get_next_buf(dma_q, &buf);
@@ -689,7 +698,10 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
689 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; 698 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
690 699
691 /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */ 700 /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */
692 f->fmt.pix.field = dev->interlaced ? 701 if (dev->progressive)
702 f->fmt.pix.field = V4L2_FIELD_NONE;
703 else
704 f->fmt.pix.field = dev->interlaced ?
693 V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; 705 V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
694 706
695 mutex_unlock(&dev->lock); 707 mutex_unlock(&dev->lock);
@@ -753,7 +765,11 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
753 f->fmt.pix.bytesperline = (dev->width * fmt->depth + 7) >> 3; 765 f->fmt.pix.bytesperline = (dev->width * fmt->depth + 7) >> 3;
754 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height; 766 f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height;
755 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; 767 f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
756 f->fmt.pix.field = V4L2_FIELD_INTERLACED; 768 if (dev->progressive)
769 f->fmt.pix.field = V4L2_FIELD_NONE;
770 else
771 f->fmt.pix.field = dev->interlaced ?
772 V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
757 773
758 return 0; 774 return 0;
759} 775}
@@ -1659,6 +1675,7 @@ static int em28xx_v4l2_open(struct file *filp)
1659 struct em28xx *dev; 1675 struct em28xx *dev;
1660 enum v4l2_buf_type fh_type; 1676 enum v4l2_buf_type fh_type;
1661 struct em28xx_fh *fh; 1677 struct em28xx_fh *fh;
1678 enum v4l2_field field;
1662 1679
1663 dev = em28xx_get_device(minor, &fh_type, &radio); 1680 dev = em28xx_get_device(minor, &fh_type, &radio);
1664 1681
@@ -1700,8 +1717,13 @@ static int em28xx_v4l2_open(struct file *filp)
1700 1717
1701 dev->users++; 1718 dev->users++;
1702 1719
1720 if (dev->progressive)
1721 field = V4L2_FIELD_NONE;
1722 else
1723 field = V4L2_FIELD_INTERLACED;
1724
1703 videobuf_queue_vmalloc_init(&fh->vb_vidq, &em28xx_video_qops, 1725 videobuf_queue_vmalloc_init(&fh->vb_vidq, &em28xx_video_qops,
1704 NULL, &dev->slock, fh->type, V4L2_FIELD_INTERLACED, 1726 NULL, &dev->slock, fh->type, field,
1705 sizeof(struct em28xx_buffer), fh); 1727 sizeof(struct em28xx_buffer), fh);
1706 1728
1707 mutex_unlock(&dev->lock); 1729 mutex_unlock(&dev->lock);
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
index 45bd513f62dc..8c2dc38bca9f 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -484,6 +484,9 @@ struct em28xx {
484 int sensor_xres, sensor_yres; 484 int sensor_xres, sensor_yres;
485 int sensor_xtal; 485 int sensor_xtal;
486 486
487 /* Allows progressive (e. g. non-interlaced) mode */
488 int progressive;
489
487 /* Vinmode/Vinctl used at the driver */ 490 /* Vinmode/Vinctl used at the driver */
488 int vinmode, vinctl; 491 int vinmode, vinctl;
489 492