diff options
author | Devin Heitmueller <dheitmueller@kernellabs.com> | 2010-01-22 00:34:32 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-05-17 23:50:14 -0400 |
commit | 5fee334039550bdd5efed9e69af7860a66a9de37 (patch) | |
tree | 8d73d74d6bbd0f50fae8fe32738909b54953d1dc /drivers | |
parent | 1744feab9a2241f2adf03be5ef8ecbd279f5944b (diff) |
V4L/DVB: em28xx: rework buffer pointer tracking for offset to start of video
Rework the logic for tracking the amount of data copied to the VBI buffer, to
address problem found where the video lines are several bytes shifted to the
right (and the leading pixels in the first line rendered are garbage). This
would occur because the copy function would advance the pointer when detecting
headers, but the caller would not adjust the length actually copied.
This work was sponsored by EyeMagnet Limited.
Signed-off-by: Devin Heitmueller <dheitmueller@kernellabs.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/video/em28xx/em28xx-video.c | 61 |
1 files changed, 39 insertions, 22 deletions
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 0fe20110bfd6..b6ac99de97d2 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
@@ -203,12 +203,6 @@ static void em28xx_copy_video(struct em28xx *dev, | |||
203 | if (dma_q->pos + len > buf->vb.size) | 203 | if (dma_q->pos + len > buf->vb.size) |
204 | len = buf->vb.size - dma_q->pos; | 204 | len = buf->vb.size - dma_q->pos; |
205 | 205 | ||
206 | if (p[0] != 0x88 && p[0] != 0x22) { | ||
207 | em28xx_isocdbg("frame is not complete\n"); | ||
208 | len += 4; | ||
209 | } else | ||
210 | p += 4; | ||
211 | |||
212 | startread = p; | 206 | startread = p; |
213 | remain = len; | 207 | remain = len; |
214 | 208 | ||
@@ -309,14 +303,6 @@ static void em28xx_copy_vbi(struct em28xx *dev, | |||
309 | if (dma_q->pos + len > buf->vb.size) | 303 | if (dma_q->pos + len > buf->vb.size) |
310 | len = buf->vb.size - dma_q->pos; | 304 | len = buf->vb.size - dma_q->pos; |
311 | 305 | ||
312 | if ((p[0] == 0x33 && p[1] == 0x95) || | ||
313 | (p[0] == 0x88 && p[1] == 0x88)) { | ||
314 | /* Header field, advance past it */ | ||
315 | p += 4; | ||
316 | } else { | ||
317 | len += 4; | ||
318 | } | ||
319 | |||
320 | startread = p; | 306 | startread = p; |
321 | 307 | ||
322 | startwrite = outp + dma_q->pos; | 308 | startwrite = outp + dma_q->pos; |
@@ -507,8 +493,15 @@ static inline int em28xx_isoc_copy(struct em28xx *dev, struct urb *urb) | |||
507 | 493 | ||
508 | dma_q->pos = 0; | 494 | dma_q->pos = 0; |
509 | } | 495 | } |
510 | if (buf != NULL) | 496 | if (buf != NULL) { |
497 | if (p[0] != 0x88 && p[0] != 0x22) { | ||
498 | em28xx_isocdbg("frame is not complete\n"); | ||
499 | len += 4; | ||
500 | } else { | ||
501 | p += 4; | ||
502 | } | ||
511 | em28xx_copy_video(dev, dma_q, buf, p, outp, len); | 503 | em28xx_copy_video(dev, dma_q, buf, p, outp, len); |
504 | } | ||
512 | } | 505 | } |
513 | return rc; | 506 | return rc; |
514 | } | 507 | } |
@@ -555,8 +548,7 @@ static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb) | |||
555 | continue; | 548 | continue; |
556 | } | 549 | } |
557 | 550 | ||
558 | len = urb->iso_frame_desc[i].actual_length - 4; | 551 | len = urb->iso_frame_desc[i].actual_length; |
559 | |||
560 | if (urb->iso_frame_desc[i].actual_length <= 0) { | 552 | if (urb->iso_frame_desc[i].actual_length <= 0) { |
561 | /* em28xx_isocdbg("packet %d is empty",i); - spammy */ | 553 | /* em28xx_isocdbg("packet %d is empty",i); - spammy */ |
562 | continue; | 554 | continue; |
@@ -577,6 +569,17 @@ static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb) | |||
577 | dev->vbi_read = 0; | 569 | dev->vbi_read = 0; |
578 | em28xx_isocdbg("VBI START HEADER!!!\n"); | 570 | em28xx_isocdbg("VBI START HEADER!!!\n"); |
579 | dev->cur_field = p[2]; | 571 | dev->cur_field = p[2]; |
572 | p += 4; | ||
573 | len -= 4; | ||
574 | } else if (p[0] == 0x88 && p[1] == 0x88 && | ||
575 | p[2] == 0x88 && p[3] == 0x88) { | ||
576 | /* continuation */ | ||
577 | p += 4; | ||
578 | len -= 4; | ||
579 | } else if (p[0] == 0x22 && p[1] == 0x5a) { | ||
580 | /* start video */ | ||
581 | p += 4; | ||
582 | len -= 4; | ||
580 | } | 583 | } |
581 | 584 | ||
582 | vbi_size = dev->vbi_width * dev->vbi_height; | 585 | vbi_size = dev->vbi_width * dev->vbi_height; |
@@ -631,9 +634,6 @@ static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb) | |||
631 | 634 | ||
632 | if (dev->capture_type == 1) { | 635 | if (dev->capture_type == 1) { |
633 | dev->capture_type = 2; | 636 | dev->capture_type = 2; |
634 | em28xx_isocdbg("Video frame %d, length=%i, %s\n", p[2], | ||
635 | len, (p[2] & 1) ? "odd" : "even"); | ||
636 | |||
637 | if (dev->progressive || !(dev->cur_field & 1)) { | 637 | if (dev->progressive || !(dev->cur_field & 1)) { |
638 | if (buf != NULL) | 638 | if (buf != NULL) |
639 | buffer_filled(dev, dma_q, buf); | 639 | buffer_filled(dev, dma_q, buf); |
@@ -652,8 +652,25 @@ static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb) | |||
652 | 652 | ||
653 | dma_q->pos = 0; | 653 | dma_q->pos = 0; |
654 | } | 654 | } |
655 | if (buf != NULL && dev->capture_type == 2) | 655 | |
656 | em28xx_copy_video(dev, dma_q, buf, p, outp, len); | 656 | if (buf != NULL && dev->capture_type == 2) { |
657 | if (len > 4 && p[0] == 0x88 && p[1] == 0x88 && | ||
658 | p[2] == 0x88 && p[3] == 0x88) { | ||
659 | p += 4; | ||
660 | len -= 4; | ||
661 | } | ||
662 | if (len > 4 && p[0] == 0x22 && p[1] == 0x5a) { | ||
663 | em28xx_isocdbg("Video frame %d, len=%i, %s\n", | ||
664 | p[2], len, (p[2] & 1) ? | ||
665 | "odd" : "even"); | ||
666 | p += 4; | ||
667 | len -= 4; | ||
668 | } | ||
669 | |||
670 | if (len > 0) | ||
671 | em28xx_copy_video(dev, dma_q, buf, p, outp, | ||
672 | len); | ||
673 | } | ||
657 | } | 674 | } |
658 | return rc; | 675 | return rc; |
659 | } | 676 | } |