diff options
author | Hans de Goede <j.w.r.degoede@hhs.nl> | 2008-07-04 17:29:32 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-07-20 06:17:02 -0400 |
commit | ab8f12cf8e3d33adec382585f9f60f8686a372c3 (patch) | |
tree | 5e788581199b1a8ddeaba222d958a8a77ba84a02 /drivers/media/video/gspca/pac207.c | |
parent | 24c530b4abb979f9e79298f0b4c4e83781a0e4c3 (diff) |
V4L/DVB (8197): gspca: pac207 frames no more decoded in the subdriver.
videodev2: New pixfmt
pac207: Remove the specific decoding.
main: get_buff_size operation added for the subdriver.
Signed-off-by: Hans de Goede <j.w.r.degoede@hhs.nl>
Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/gspca/pac207.c')
-rw-r--r-- | drivers/media/video/gspca/pac207.c | 353 |
1 files changed, 43 insertions, 310 deletions
diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c index 7e067456e62b..0135ba599e81 100644 --- a/drivers/media/video/gspca/pac207.c +++ b/drivers/media/video/gspca/pac207.c | |||
@@ -58,34 +58,10 @@ MODULE_LICENSE("GPL"); | |||
58 | before doing any other adjustments */ | 58 | before doing any other adjustments */ |
59 | #define PAC207_AUTOGAIN_IGNORE_FRAMES 3 | 59 | #define PAC207_AUTOGAIN_IGNORE_FRAMES 3 |
60 | 60 | ||
61 | enum pac207_line_state { | ||
62 | LINE_HEADER1, | ||
63 | LINE_HEADER2, | ||
64 | LINE_UNCOMPRESSED, | ||
65 | LINE_COMPRESSED, | ||
66 | }; | ||
67 | |||
68 | struct pac207_decoder_state { | ||
69 | /* generic state */ | ||
70 | u16 line_read; | ||
71 | u16 line_marker; | ||
72 | u8 line_state; | ||
73 | u8 header_read; | ||
74 | /* compression state */ | ||
75 | u16 processed_bytes; | ||
76 | u8 remaining_bits; | ||
77 | s8 no_remaining_bits; | ||
78 | u8 get_abs; | ||
79 | u8 discard_byte; | ||
80 | u8 line_decode_buf[352]; | ||
81 | }; | ||
82 | |||
83 | /* specific webcam descriptor */ | 61 | /* specific webcam descriptor */ |
84 | struct sd { | 62 | struct sd { |
85 | struct gspca_dev gspca_dev; /* !! must be the first item */ | 63 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
86 | 64 | ||
87 | struct pac207_decoder_state decoder_state; | ||
88 | |||
89 | u8 mode; | 65 | u8 mode; |
90 | 66 | ||
91 | u8 brightness; | 67 | u8 brightness; |
@@ -94,6 +70,7 @@ struct sd { | |||
94 | u8 gain; | 70 | u8 gain; |
95 | 71 | ||
96 | u8 sof_read; | 72 | u8 sof_read; |
73 | u8 header_read; | ||
97 | u8 autogain_ignore_frames; | 74 | u8 autogain_ignore_frames; |
98 | 75 | ||
99 | atomic_t avg_lum; | 76 | atomic_t avg_lum; |
@@ -173,8 +150,8 @@ static struct ctrl sd_ctrls[] = { | |||
173 | }; | 150 | }; |
174 | 151 | ||
175 | static struct cam_mode sif_mode[] = { | 152 | static struct cam_mode sif_mode[] = { |
176 | {V4L2_PIX_FMT_SBGGR8, 176, 144, 1}, | 153 | {V4L2_PIX_FMT_PAC207, 176, 144, 1}, |
177 | {V4L2_PIX_FMT_SBGGR8, 352, 288, 0}, | 154 | {V4L2_PIX_FMT_PAC207, 352, 288, 0}, |
178 | }; | 155 | }; |
179 | 156 | ||
180 | static const __u8 pac207_sensor_init[][8] = { | 157 | static const __u8 pac207_sensor_init[][8] = { |
@@ -361,68 +338,17 @@ static void sd_close(struct gspca_dev *gspca_dev) | |||
361 | { | 338 | { |
362 | } | 339 | } |
363 | 340 | ||
364 | /* -- convert pixart frames to Bayer -- */ | 341 | static int sd_get_buff_size_op(struct gspca_dev *gspca_dev, int mode) |
365 | /* Sonix decompressor struct B.S.(2004) */ | ||
366 | static struct { | ||
367 | u8 is_abs; | ||
368 | u8 len; | ||
369 | s8 val; | ||
370 | } table[256]; | ||
371 | |||
372 | void init_pixart_decoder(void) | ||
373 | { | 342 | { |
374 | int i, is_abs, val, len; | 343 | switch (gspca_dev->cam.cam_mode[mode].width) { |
375 | 344 | case 176: /* 176x144 */ | |
376 | for (i = 0; i < 256; i++) { | 345 | /* uncompressed, add 2 bytes / line for line header */ |
377 | is_abs = 0; | 346 | return (176 + 2) * 144; |
378 | val = 0; | 347 | case 352: /* 352x288 */ |
379 | len = 0; | 348 | /* compressed */ |
380 | if ((i & 0xC0) == 0) { | 349 | return 352 * 288 / 2; |
381 | /* code 00 */ | ||
382 | val = 0; | ||
383 | len = 2; | ||
384 | } else if ((i & 0xC0) == 0x40) { | ||
385 | /* code 01 */ | ||
386 | val = -5; | ||
387 | len = 2; | ||
388 | } else if ((i & 0xC0) == 0x80) { | ||
389 | /* code 10 */ | ||
390 | val = 5; | ||
391 | len = 2; | ||
392 | } else if ((i & 0xF0) == 0xC0) { | ||
393 | /* code 1100 */ | ||
394 | val = -10; | ||
395 | len = 4; | ||
396 | } else if ((i & 0xF0) == 0xD0) { | ||
397 | /* code 1101 */ | ||
398 | val = 10; | ||
399 | len = 4; | ||
400 | } else if ((i & 0xF8) == 0xE0) { | ||
401 | /* code 11100 */ | ||
402 | val = -15; | ||
403 | len = 5; | ||
404 | } else if ((i & 0xF8) == 0xE8) { | ||
405 | /* code 11101 */ | ||
406 | val = 15; | ||
407 | len = 5; | ||
408 | } else if ((i & 0xFC) == 0xF0) { | ||
409 | /* code 111100 */ | ||
410 | val = -20; | ||
411 | len = 6; | ||
412 | } else if ((i & 0xFC) == 0xF4) { | ||
413 | /* code 111101 */ | ||
414 | val = 20; | ||
415 | len = 6; | ||
416 | } else if ((i & 0xF8) == 0xF8) { | ||
417 | /* code 11111xxxxxx */ | ||
418 | is_abs = 1; | ||
419 | val = 0; | ||
420 | len = 5; | ||
421 | } | ||
422 | table[i].is_abs = is_abs; | ||
423 | table[i].val = val; | ||
424 | table[i].len = len; | ||
425 | } | 350 | } |
351 | return -EIO; /* should never happen */ | ||
426 | } | 352 | } |
427 | 353 | ||
428 | /* auto gain and exposure algorithm based on the knee algorithm described here: | 354 | /* auto gain and exposure algorithm based on the knee algorithm described here: |
@@ -517,245 +443,52 @@ static unsigned char *pac207_find_sof(struct gspca_dev *gspca_dev, | |||
517 | return NULL; | 443 | return NULL; |
518 | } | 444 | } |
519 | 445 | ||
520 | static int pac207_decompress_row(struct gspca_dev *gspca_dev, | ||
521 | struct gspca_frame *f, | ||
522 | __u8 *cdata, | ||
523 | int len) | ||
524 | { | ||
525 | struct sd *sd = (struct sd *) gspca_dev; | ||
526 | struct pac207_decoder_state *decoder_state = &sd->decoder_state; | ||
527 | unsigned char *outp = decoder_state->line_decode_buf + | ||
528 | decoder_state->line_read; | ||
529 | int val, bitlen, bitpos = -decoder_state->no_remaining_bits; | ||
530 | u8 code; | ||
531 | |||
532 | /* first two pixels are stored as raw 8-bit */ | ||
533 | while (decoder_state->line_read < 2) { | ||
534 | *outp++ = *cdata++; | ||
535 | decoder_state->line_read++; | ||
536 | len--; | ||
537 | if (len == 0) | ||
538 | return 0; | ||
539 | } | ||
540 | |||
541 | while (decoder_state->line_read < gspca_dev->width) { | ||
542 | if (bitpos < 0) { | ||
543 | code = decoder_state->remaining_bits << (8 + bitpos) | | ||
544 | cdata[0] >> -bitpos; | ||
545 | } else { | ||
546 | u8 *addr = cdata + bitpos / 8; | ||
547 | code = addr[0] << (bitpos & 7) | | ||
548 | addr[1] >> (8 - (bitpos & 7)); | ||
549 | } | ||
550 | |||
551 | bitlen = decoder_state->get_abs ? | ||
552 | 6 : table[code].len; | ||
553 | |||
554 | /* Stop decompressing if we're out of input data */ | ||
555 | if ((bitpos + bitlen) > (len * 8)) | ||
556 | break; | ||
557 | |||
558 | if (decoder_state->get_abs) { | ||
559 | *outp++ = code & 0xFC; | ||
560 | decoder_state->line_read++; | ||
561 | decoder_state->get_abs = 0; | ||
562 | } else { | ||
563 | if (table[code].is_abs) { | ||
564 | decoder_state->get_abs = 1; | ||
565 | } else { | ||
566 | /* relative to left pixel */ | ||
567 | val = outp[-2] + | ||
568 | table[code].val; | ||
569 | if (val > 0xff) | ||
570 | val = 0xff; | ||
571 | else if (val < 0) | ||
572 | val = 0; | ||
573 | *outp++ = val; | ||
574 | decoder_state->line_read++; | ||
575 | } | ||
576 | } | ||
577 | bitpos += bitlen; | ||
578 | } | ||
579 | |||
580 | if (decoder_state->line_read == gspca_dev->width) { | ||
581 | int compressed_line_len; | ||
582 | |||
583 | gspca_frame_add(gspca_dev, INTER_PACKET, f, | ||
584 | decoder_state->line_decode_buf, | ||
585 | gspca_dev->width); | ||
586 | |||
587 | /* completely decompressed line, round pos to nearest word */ | ||
588 | compressed_line_len = ((decoder_state->processed_bytes * 8 + | ||
589 | bitpos + 15) / 16) * 2; | ||
590 | |||
591 | len -= compressed_line_len - decoder_state->processed_bytes; | ||
592 | if (len < 0) { | ||
593 | decoder_state->discard_byte = 1; | ||
594 | len = 0; | ||
595 | } | ||
596 | } else { | ||
597 | decoder_state->processed_bytes += len; | ||
598 | decoder_state->remaining_bits = cdata[bitpos/8]; | ||
599 | decoder_state->no_remaining_bits = (8 - bitpos) & 7; | ||
600 | len = 0; | ||
601 | } | ||
602 | |||
603 | return len; | ||
604 | } | ||
605 | |||
606 | static void pac207_decode_line_init(struct gspca_dev *gspca_dev) | ||
607 | { | ||
608 | struct sd *sd = (struct sd *) gspca_dev; | ||
609 | struct pac207_decoder_state *decoder_state = &sd->decoder_state; | ||
610 | |||
611 | decoder_state->line_read = 0; | ||
612 | decoder_state->line_state = LINE_HEADER1; | ||
613 | decoder_state->processed_bytes = 0; | ||
614 | decoder_state->no_remaining_bits = 0; | ||
615 | decoder_state->get_abs = 0; | ||
616 | } | ||
617 | |||
618 | static void pac207_decode_frame_init(struct gspca_dev *gspca_dev) | ||
619 | { | ||
620 | struct sd *sd = (struct sd *) gspca_dev; | ||
621 | struct pac207_decoder_state *decoder_state = &sd->decoder_state; | ||
622 | |||
623 | decoder_state->header_read = 0; | ||
624 | decoder_state->discard_byte = 0; | ||
625 | |||
626 | pac207_decode_line_init(gspca_dev); | ||
627 | } | ||
628 | |||
629 | static int pac207_decode_frame_data(struct gspca_dev *gspca_dev, | ||
630 | struct gspca_frame *f, unsigned char *data, int len) | ||
631 | { | ||
632 | struct sd *sd = (struct sd *) gspca_dev; | ||
633 | struct pac207_decoder_state *decoder_state = &sd->decoder_state; | ||
634 | int needed = 0; | ||
635 | |||
636 | /* first 11 bytes after sof marker: frame header */ | ||
637 | if (decoder_state->header_read < 11) { | ||
638 | /* get average lumination from frame header (byte 5) */ | ||
639 | if (decoder_state->header_read < 5) { | ||
640 | needed = 5 - decoder_state->header_read; | ||
641 | if (len >= needed) | ||
642 | atomic_set(&sd->avg_lum, data[needed-1]); | ||
643 | } | ||
644 | /* skip the rest of the header */ | ||
645 | needed = 11 - decoder_state->header_read; | ||
646 | if (len <= needed) { | ||
647 | decoder_state->header_read += len; | ||
648 | return 0; | ||
649 | } | ||
650 | data += needed; | ||
651 | len -= needed; | ||
652 | decoder_state->header_read = 11; | ||
653 | } | ||
654 | |||
655 | while (len) { | ||
656 | if (decoder_state->discard_byte) { | ||
657 | data++; | ||
658 | len--; | ||
659 | decoder_state->discard_byte = 0; | ||
660 | continue; | ||
661 | } | ||
662 | |||
663 | switch (decoder_state->line_state) { | ||
664 | case LINE_HEADER1: | ||
665 | decoder_state->line_marker = data[0] << 8; | ||
666 | decoder_state->line_state = LINE_HEADER2; | ||
667 | needed = 1; | ||
668 | break; | ||
669 | case LINE_HEADER2: | ||
670 | decoder_state->line_marker |= data[0]; | ||
671 | switch (decoder_state->line_marker) { | ||
672 | case 0x0ff0: | ||
673 | decoder_state->line_state = LINE_UNCOMPRESSED; | ||
674 | break; | ||
675 | case 0x1ee1: | ||
676 | decoder_state->line_state = LINE_COMPRESSED; | ||
677 | break; | ||
678 | default: | ||
679 | PDEBUG(D_STREAM, | ||
680 | "Error unknown line-header %04X", | ||
681 | (int) decoder_state->line_marker); | ||
682 | gspca_dev->last_packet_type = DISCARD_PACKET; | ||
683 | return 0; | ||
684 | } | ||
685 | needed = 1; | ||
686 | break; | ||
687 | case LINE_UNCOMPRESSED: | ||
688 | needed = gspca_dev->width - decoder_state->line_read; | ||
689 | if (needed > len) | ||
690 | needed = len; | ||
691 | gspca_frame_add(gspca_dev, INTER_PACKET, f, data, | ||
692 | needed); | ||
693 | decoder_state->line_read += needed; | ||
694 | break; | ||
695 | case LINE_COMPRESSED: | ||
696 | needed = len - | ||
697 | pac207_decompress_row(gspca_dev, f, data, len); | ||
698 | break; | ||
699 | } | ||
700 | |||
701 | data += needed; | ||
702 | len -= needed; | ||
703 | |||
704 | if (decoder_state->line_read == gspca_dev->width) { | ||
705 | if ((f->data_end - f->data) == | ||
706 | (gspca_dev->width * gspca_dev->height)) { | ||
707 | /* eureka we've got a frame */ | ||
708 | return 1; | ||
709 | } | ||
710 | pac207_decode_line_init(gspca_dev); | ||
711 | } | ||
712 | } | ||
713 | |||
714 | return 0; | ||
715 | } | ||
716 | |||
717 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 446 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
718 | struct gspca_frame *frame, | 447 | struct gspca_frame *frame, |
719 | __u8 *data, | 448 | __u8 *data, |
720 | int len) | 449 | int len) |
721 | { | 450 | { |
451 | struct sd *sd = (struct sd *) gspca_dev; | ||
722 | unsigned char *sof; | 452 | unsigned char *sof; |
723 | int n; | ||
724 | 453 | ||
725 | sof = pac207_find_sof(gspca_dev, data, len); | 454 | sof = pac207_find_sof(gspca_dev, data, len); |
726 | |||
727 | if (sof) { | 455 | if (sof) { |
456 | int n; | ||
457 | |||
728 | /* finish decoding current frame */ | 458 | /* finish decoding current frame */ |
729 | if (gspca_dev->last_packet_type == INTER_PACKET) { | 459 | n = sof - data; |
730 | n = sof - data; | 460 | if (n > sizeof pac207_sof_marker) |
731 | if (n > sizeof(pac207_sof_marker)) | 461 | n -= sizeof pac207_sof_marker; |
732 | n -= sizeof(pac207_sof_marker); | 462 | else |
733 | else | 463 | n = 0; |
734 | n = 0; | 464 | frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, |
735 | n = pac207_decode_frame_data(gspca_dev, frame, | 465 | data, n); |
736 | data, n); | 466 | sd->header_read = 0; |
737 | if (n) | ||
738 | frame = gspca_frame_add(gspca_dev, | ||
739 | LAST_PACKET, | ||
740 | frame, | ||
741 | NULL, | ||
742 | 0); | ||
743 | else | ||
744 | PDEBUG(D_STREAM, "Incomplete frame"); | ||
745 | } | ||
746 | pac207_decode_frame_init(gspca_dev); | ||
747 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL, 0); | 467 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL, 0); |
748 | len -= sof - data; | 468 | len -= sof - data; |
749 | data = sof; | 469 | data = sof; |
750 | } | 470 | } |
471 | if (sd->header_read < 11) { | ||
472 | int needed; | ||
751 | 473 | ||
752 | if (gspca_dev->last_packet_type == DISCARD_PACKET) | 474 | /* get average lumination from frame header (byte 5) */ |
753 | return; | 475 | if (sd->header_read < 5) { |
476 | needed = 5 - sd->header_read; | ||
477 | if (len >= needed) | ||
478 | atomic_set(&sd->avg_lum, data[needed - 1]); | ||
479 | } | ||
480 | /* skip the rest of the header */ | ||
481 | needed = 11 - sd->header_read; | ||
482 | if (len <= needed) { | ||
483 | sd->header_read += len; | ||
484 | return; | ||
485 | } | ||
486 | data += needed; | ||
487 | len -= needed; | ||
488 | sd->header_read = 11; | ||
489 | } | ||
754 | 490 | ||
755 | n = pac207_decode_frame_data(gspca_dev, frame, data, len); | 491 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); |
756 | if (n) | ||
757 | gspca_frame_add(gspca_dev, LAST_PACKET, | ||
758 | frame, NULL, 0); | ||
759 | } | 492 | } |
760 | 493 | ||
761 | static void setbrightness(struct gspca_dev *gspca_dev) | 494 | static void setbrightness(struct gspca_dev *gspca_dev) |
@@ -891,6 +624,7 @@ static const struct sd_desc sd_desc = { | |||
891 | .close = sd_close, | 624 | .close = sd_close, |
892 | .dq_callback = pac207_do_auto_gain, | 625 | .dq_callback = pac207_do_auto_gain, |
893 | .pkt_scan = sd_pkt_scan, | 626 | .pkt_scan = sd_pkt_scan, |
627 | .get_buff_size = sd_get_buff_size_op, | ||
894 | }; | 628 | }; |
895 | 629 | ||
896 | /* -- module initialisation -- */ | 630 | /* -- module initialisation -- */ |
@@ -927,7 +661,6 @@ static struct usb_driver sd_driver = { | |||
927 | /* -- module insert / remove -- */ | 661 | /* -- module insert / remove -- */ |
928 | static int __init sd_mod_init(void) | 662 | static int __init sd_mod_init(void) |
929 | { | 663 | { |
930 | init_pixart_decoder(); | ||
931 | if (usb_register(&sd_driver) < 0) | 664 | if (usb_register(&sd_driver) < 0) |
932 | return -1; | 665 | return -1; |
933 | PDEBUG(D_PROBE, "v%s registered", version); | 666 | PDEBUG(D_PROBE, "v%s registered", version); |