aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean-Francois Moine <moinejf@free.fr>2008-09-03 15:47:35 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-09-03 17:36:39 -0400
commitf75c4950bb6e677e89479192b2ecfbec0beab14e (patch)
tree880fb7d751199d5a2e4bafbec7215e553754d729
parent6ab0b174d22b448d66058c9de0114fdfac5b7ccf (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>
-rw-r--r--drivers/media/video/gspca/pac7311.c200
-rw-r--r--include/linux/videodev2.h1
2 files changed, 10 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
26MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li"); 27MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
27MODULE_DESCRIPTION("Pixart PAC7311"); 28MODULE_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
123static struct v4l2_pix_format vga_mode[] = { 123static 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
143static 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 */
214static const __u8 probe_7302[] = { 142static 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 */
703static 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 */
731static void sd_pkt_scan(struct gspca_dev *gspca_dev, 630static 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 }
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index e65a6bed4e3e..6c73516b74c4 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -334,6 +334,7 @@ struct v4l2_pix_format {
334#define V4L2_PIX_FMT_SPCA508 v4l2_fourcc('S', '5', '0', '8') /* YUVY per line */ 334#define V4L2_PIX_FMT_SPCA508 v4l2_fourcc('S', '5', '0', '8') /* YUVY per line */
335#define V4L2_PIX_FMT_SPCA561 v4l2_fourcc('S', '5', '6', '1') /* compressed GBRG bayer */ 335#define V4L2_PIX_FMT_SPCA561 v4l2_fourcc('S', '5', '6', '1') /* compressed GBRG bayer */
336#define V4L2_PIX_FMT_PAC207 v4l2_fourcc('P', '2', '0', '7') /* compressed BGGR bayer */ 336#define V4L2_PIX_FMT_PAC207 v4l2_fourcc('P', '2', '0', '7') /* compressed BGGR bayer */
337#define V4L2_PIX_FMT_PJPG v4l2_fourcc('P', 'J', 'P', 'G') /* Pixart 73xx JPEG */
337 338
338/* 339/*
339 * F O R M A T E N U M E R A T I O N 340 * F O R M A T E N U M E R A T I O N