diff options
author | Jean-Francois Moine <moinejf@free.fr> | 2008-09-03 15:47:35 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-09-03 17:36:39 -0400 |
commit | f75c4950bb6e677e89479192b2ecfbec0beab14e (patch) | |
tree | 880fb7d751199d5a2e4bafbec7215e553754d729 /drivers/media | |
parent | 6ab0b174d22b448d66058c9de0114fdfac5b7ccf (diff) |
V4L/DVB (8675): gspca: Pixmap PJPG (Pixart 73xx JPEG) added, generated by pac7311.
The JPEG frames generated by the Pixart 73xx have:
- special markers 'ff ff ff xx' every 1024/512 bytes,
- unused 8 bits at end of JPEG blocks,
and then ask for a new pixel format.
Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/gspca/pac7311.c | 200 |
1 files changed, 9 insertions, 191 deletions
diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index 85d9ddbc5b7f..3c9f2b14ca8c 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #define MODULE_NAME "pac7311" | 22 | #define MODULE_NAME "pac7311" |
23 | 23 | ||
24 | #include "gspca.h" | 24 | #include "gspca.h" |
25 | #include "jpeg.h" | ||
25 | 26 | ||
26 | MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li"); | 27 | MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li"); |
27 | MODULE_DESCRIPTION("Pixart PAC7311"); | 28 | MODULE_DESCRIPTION("Pixart PAC7311"); |
@@ -40,7 +41,6 @@ struct sd { | |||
40 | unsigned char colors; | 41 | unsigned char colors; |
41 | unsigned char autogain; | 42 | unsigned char autogain; |
42 | 43 | ||
43 | char ffnb; /* number of 'ff' in the previous frame */ | ||
44 | char tosof; /* number of bytes before next start of frame */ | 44 | char tosof; /* number of bytes before next start of frame */ |
45 | signed char ag_cnt; | 45 | signed char ag_cnt; |
46 | #define AG_CNT_START 13 | 46 | #define AG_CNT_START 13 |
@@ -121,95 +121,23 @@ static struct ctrl sd_ctrls[] = { | |||
121 | }; | 121 | }; |
122 | 122 | ||
123 | static struct v4l2_pix_format vga_mode[] = { | 123 | static struct v4l2_pix_format vga_mode[] = { |
124 | {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | 124 | {160, 120, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE, |
125 | .bytesperline = 160, | 125 | .bytesperline = 160, |
126 | .sizeimage = 160 * 120 * 3 / 8 + 590, | 126 | .sizeimage = 160 * 120 * 3 / 8 + 590, |
127 | .colorspace = V4L2_COLORSPACE_JPEG, | 127 | .colorspace = V4L2_COLORSPACE_JPEG, |
128 | .priv = 2}, | 128 | .priv = 2}, |
129 | {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | 129 | {320, 240, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE, |
130 | .bytesperline = 320, | 130 | .bytesperline = 320, |
131 | .sizeimage = 320 * 240 * 3 / 8 + 590, | 131 | .sizeimage = 320 * 240 * 3 / 8 + 590, |
132 | .colorspace = V4L2_COLORSPACE_JPEG, | 132 | .colorspace = V4L2_COLORSPACE_JPEG, |
133 | .priv = 1}, | 133 | .priv = 1}, |
134 | {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | 134 | {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE, |
135 | .bytesperline = 640, | 135 | .bytesperline = 640, |
136 | .sizeimage = 640 * 480 * 3 / 8 + 590, | 136 | .sizeimage = 640 * 480 * 3 / 8 + 590, |
137 | .colorspace = V4L2_COLORSPACE_JPEG, | 137 | .colorspace = V4L2_COLORSPACE_JPEG, |
138 | .priv = 0}, | 138 | .priv = 0}, |
139 | }; | 139 | }; |
140 | 140 | ||
141 | #define PAC7311_JPEG_HEADER_SIZE (sizeof pac7311_jpeg_header) /* (594) */ | ||
142 | |||
143 | static const __u8 pac7311_jpeg_header[] = { | ||
144 | 0xff, 0xd8, | ||
145 | 0xff, 0xe0, 0x00, 0x03, 0x20, | ||
146 | 0xff, 0xc0, 0x00, 0x11, 0x08, | ||
147 | 0x01, 0xe0, /* 12: height */ | ||
148 | 0x02, 0x80, /* 14: width */ | ||
149 | 0x03, /* 16 */ | ||
150 | 0x01, 0x21, 0x00, | ||
151 | 0x02, 0x11, 0x01, | ||
152 | 0x03, 0x11, 0x01, | ||
153 | 0xff, 0xdb, 0x00, 0x84, | ||
154 | 0x00, 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d, | ||
155 | 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a, 0x18, 0x16, | ||
156 | 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d, 0x28, 0x3a, 0x33, 0x3d, | ||
157 | 0x3c, 0x39, 0x33, 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, | ||
158 | 0x44, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57, 0x5f, | ||
159 | 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, 0x79, 0x70, 0x64, | ||
160 | 0x78, 0x5c, 0x65, 0x67, 0x63, 0x01, 0x11, 0x12, 0x12, 0x18, | ||
161 | 0x15, 0x18, 0x2f, 0x1a, 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, | ||
162 | 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, | ||
163 | 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, | ||
164 | 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, | ||
165 | 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, | ||
166 | 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, | ||
167 | 0xff, 0xc4, 0x01, 0xa2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, | ||
168 | 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
169 | 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, | ||
170 | 0x09, 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, | ||
171 | 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d, | ||
172 | 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, | ||
173 | 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, | ||
174 | 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, | ||
175 | 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, | ||
176 | 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, | ||
177 | 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, | ||
178 | 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, | ||
179 | 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, | ||
180 | 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, | ||
181 | 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, | ||
182 | 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, | ||
183 | 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, | ||
184 | 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, | ||
185 | 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, | ||
186 | 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, | ||
187 | 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, | ||
188 | 0xf9, 0xfa, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, | ||
189 | 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
190 | 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, | ||
191 | 0x0b, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, | ||
192 | 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, | ||
193 | 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, | ||
194 | 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, | ||
195 | 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, | ||
196 | 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, | ||
197 | 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, | ||
198 | 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, | ||
199 | 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, | ||
200 | 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, | ||
201 | 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, | ||
202 | 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, | ||
203 | 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, | ||
204 | 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, | ||
205 | 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, | ||
206 | 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, | ||
207 | 0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, | ||
208 | 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, | ||
209 | 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, | ||
210 | 0x11, 0x00, 0x3f, 0x00 | ||
211 | }; | ||
212 | |||
213 | /* pac 7302 */ | 141 | /* pac 7302 */ |
214 | static const __u8 probe_7302[] = { | 142 | static const __u8 probe_7302[] = { |
215 | /* index,value */ | 143 | /* index,value */ |
@@ -566,7 +494,6 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
566 | { | 494 | { |
567 | struct sd *sd = (struct sd *) gspca_dev; | 495 | struct sd *sd = (struct sd *) gspca_dev; |
568 | 496 | ||
569 | sd->ffnb = 0; | ||
570 | sd->tosof = 0; | 497 | sd->tosof = 0; |
571 | 498 | ||
572 | if (sd->sensor == SENSOR_PAC7302) | 499 | if (sd->sensor == SENSOR_PAC7302) |
@@ -699,34 +626,6 @@ static void do_autogain(struct gspca_dev *gspca_dev) | |||
699 | } | 626 | } |
700 | } | 627 | } |
701 | 628 | ||
702 | /* output the jpeg header */ | ||
703 | static void put_jpeg_head(struct gspca_dev *gspca_dev, | ||
704 | struct gspca_frame *frame) | ||
705 | { | ||
706 | struct sd *sd = (struct sd *) gspca_dev; | ||
707 | unsigned char tmpbuf[4]; | ||
708 | |||
709 | if (sd->ag_cnt >= 0) { | ||
710 | if (--sd->ag_cnt < 0) { | ||
711 | sd->ag_cnt = AG_CNT_START; | ||
712 | atomic_set(&sd->avg_lum, sd->lum_sum / AG_CNT_START); | ||
713 | atomic_set(&sd->do_gain, 1); | ||
714 | } | ||
715 | } | ||
716 | gspca_frame_add(gspca_dev, FIRST_PACKET, frame, | ||
717 | (__u8 *) pac7311_jpeg_header, | ||
718 | 12); | ||
719 | tmpbuf[0] = gspca_dev->height >> 8; | ||
720 | tmpbuf[1] = gspca_dev->height & 0xff; | ||
721 | tmpbuf[2] = gspca_dev->width >> 8; | ||
722 | tmpbuf[3] = gspca_dev->width & 0xff; | ||
723 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, | ||
724 | tmpbuf, 4); | ||
725 | gspca_frame_add(gspca_dev, INTER_PACKET, frame, | ||
726 | (__u8 *) &pac7311_jpeg_header[16], | ||
727 | PAC7311_JPEG_HEADER_SIZE - 16); | ||
728 | } | ||
729 | |||
730 | /* this function is run at interrupt level */ | 629 | /* this function is run at interrupt level */ |
731 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 630 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
732 | struct gspca_frame *frame, /* target */ | 631 | struct gspca_frame *frame, /* target */ |
@@ -739,24 +638,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
739 | #define INTER_FRAME 0x53 /* eof + inter frame + sof */ | 638 | #define INTER_FRAME 0x53 /* eof + inter frame + sof */ |
740 | #define LUM_OFFSET 0x1e /* reverse offset / start of frame */ | 639 | #define LUM_OFFSET 0x1e /* reverse offset / start of frame */ |
741 | 640 | ||
742 | /*fixme:test+*/ | ||
743 | /* dump the packet */ | ||
744 | if (gspca_debug & 0x200) { | ||
745 | static char tmp[50]; | ||
746 | |||
747 | PDEBUG(0x200, "pkt_scan"); | ||
748 | tmp[0] = 0; | ||
749 | for (i = 0; i < len; i++) { | ||
750 | if (i % 16 == 0 && i != 0) { | ||
751 | PDEBUG(0x200, "%s", tmp); | ||
752 | tmp[0] = 0; | ||
753 | } | ||
754 | sprintf(&tmp[(i % 16) * 3], "%02x ", data[i]); | ||
755 | } | ||
756 | if (tmp[0] != 0) | ||
757 | PDEBUG(0x200, "%s", tmp); | ||
758 | } | ||
759 | /*fixme:test-*/ | ||
760 | /* | 641 | /* |
761 | * inside a frame, there may be: | 642 | * inside a frame, there may be: |
762 | * escaped ff ('ff 00') | 643 | * escaped ff ('ff 00') |
@@ -767,47 +648,10 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
767 | * 0x33 bytes | 648 | * 0x33 bytes |
768 | * one byte luminosity | 649 | * one byte luminosity |
769 | * 0x16 bytes | 650 | * 0x16 bytes |
770 | * ff ff 00 ff 96 62 44 start of frame header | 651 | * ff ff 00 ff 96 62 44 start of frame |
771 | */ | 652 | */ |
772 | 653 | ||
773 | if (sd->tosof == 0) { /* if inside a frame */ | 654 | if (sd->tosof != 0) { /* if outside a frame */ |
774 | |||
775 | /* check for 'ff ff ff xx' at start and at end of packet */ | ||
776 | /* (len is always >= 3 and xx never ff) */ | ||
777 | switch (sd->ffnb) { | ||
778 | case 1: | ||
779 | if (data[0] != 0xff) { /* can be '00' only */ | ||
780 | __u8 ff; | ||
781 | |||
782 | sd->ffnb = 0; | ||
783 | ff = 0xff; | ||
784 | gspca_frame_add(gspca_dev, INTER_PACKET, | ||
785 | frame, &ff, 1); | ||
786 | break; /* keep 'ff 00' */ | ||
787 | } | ||
788 | /* fall thru */ | ||
789 | case 2: | ||
790 | case 3: | ||
791 | data += 4 - sd->ffnb; | ||
792 | len -= 4 - sd->ffnb; | ||
793 | sd->ffnb = 0; | ||
794 | break; | ||
795 | } | ||
796 | if (data[len - 1] == 0xff) { | ||
797 | if (data[len - 2] == 0xff) { | ||
798 | if (data[len - 3] == 0xff) { | ||
799 | sd->ffnb = 3; | ||
800 | len -= 3; | ||
801 | } else { | ||
802 | sd->ffnb = 2; | ||
803 | len -= 2; | ||
804 | } | ||
805 | } else { | ||
806 | sd->ffnb = 1; | ||
807 | len--; | ||
808 | } | ||
809 | } | ||
810 | } else { /* outside a frame */ | ||
811 | 655 | ||
812 | /* get the luminosity and go to the start of frame */ | 656 | /* get the luminosity and go to the start of frame */ |
813 | data += sd->tosof; | 657 | data += sd->tosof; |
@@ -815,14 +659,14 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
815 | if (sd->tosof > LUM_OFFSET) | 659 | if (sd->tosof > LUM_OFFSET) |
816 | sd->lum_sum += data[-LUM_OFFSET]; | 660 | sd->lum_sum += data[-LUM_OFFSET]; |
817 | sd->tosof = 0; | 661 | sd->tosof = 0; |
818 | put_jpeg_head(gspca_dev, frame); | 662 | jpeg_put_header(gspca_dev, frame, 1, 0x21); |
819 | } | 663 | } |
820 | 664 | ||
821 | for (i = 0; i < len; i++) { | 665 | for (i = 0; i < len; i++) { |
822 | if (data[i] != 0xff) | 666 | if (data[i] != 0xff) |
823 | continue; | 667 | continue; |
824 | switch (data[i + 1]) { | 668 | switch (data[i + 1]) { |
825 | case 0xd9: /* end of frame */ | 669 | case 0xd9: /* 'ff d9' end of frame */ |
826 | frame = gspca_frame_add(gspca_dev, | 670 | frame = gspca_frame_add(gspca_dev, |
827 | LAST_PACKET, | 671 | LAST_PACKET, |
828 | frame, data, i + 2); | 672 | frame, data, i + 2); |
@@ -835,33 +679,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
835 | sd->tosof = -len; | 679 | sd->tosof = -len; |
836 | break; | 680 | break; |
837 | } | 681 | } |
838 | put_jpeg_head(gspca_dev, frame); | 682 | jpeg_put_header(gspca_dev, frame, 1, 0x21); |
839 | break; | ||
840 | case 0xff: /* 'ff ff ff xx' */ | ||
841 | /*fixme:test+*/ | ||
842 | /* is there a start of frame ? */ | ||
843 | if (data[i + 2] == 0x00) { | ||
844 | static __u8 ffd9[2] = {0xff, 0xd9}; | ||
845 | |||
846 | gspca_frame_add(gspca_dev, | ||
847 | INTER_PACKET, | ||
848 | frame, data, | ||
849 | i + 7 - INTER_FRAME); | ||
850 | frame = gspca_frame_add(gspca_dev, | ||
851 | LAST_PACKET, | ||
852 | frame, ffd9, 2); | ||
853 | data += i + 7; | ||
854 | len -= i + 7; | ||
855 | i = 0; | ||
856 | put_jpeg_head(gspca_dev, frame); | ||
857 | break; | ||
858 | } | ||
859 | /*fixme:test-*/ | ||
860 | gspca_frame_add(gspca_dev, INTER_PACKET, | ||
861 | frame, data, i); | ||
862 | data += i + 4; | ||
863 | len -= i + 4; | ||
864 | i = 0; | ||
865 | break; | 683 | break; |
866 | } | 684 | } |
867 | } | 685 | } |