]> err.no Git - linux-2.6/commitdiff
V4L/DVB (8197): gspca: pac207 frames no more decoded in the subdriver.
authorHans de Goede <j.w.r.degoede@hhs.nl>
Fri, 4 Jul 2008 21:29:32 +0000 (18:29 -0300)
committerMauro Carvalho Chehab <mchehab@infradead.org>
Sun, 20 Jul 2008 10:17:02 +0000 (07:17 -0300)
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>
drivers/media/video/gspca/gspca.c
drivers/media/video/gspca/gspca.h
drivers/media/video/gspca/pac207.c
include/linux/videodev2.h

index f6d216316b11a990035d1d50871ecd759caf35be..708270a46e1ff27c4c542b16d2ae3f63c2a0d90c 100644 (file)
@@ -321,6 +321,7 @@ static int gspca_is_compressed(__u32 format)
        case V4L2_PIX_FMT_MJPEG:
        case V4L2_PIX_FMT_JPEG:
        case V4L2_PIX_FMT_SPCA561:
+       case V4L2_PIX_FMT_PAC207:
                return 1;
        }
        return 0;
@@ -380,7 +381,8 @@ static __u32 get_v4l2_depth(__u32 pixfmt)
        case V4L2_PIX_FMT_JPEG:
        case V4L2_PIX_FMT_SBGGR8:       /* 'BA81' Bayer */
        case V4L2_PIX_FMT_SN9C10X:      /* 'S910' SN9C10x compression */
-       case V4L2_PIX_FMT_SPCA561:      /* 'S561' compressed BGGR bayer */
+       case V4L2_PIX_FMT_SPCA561:      /* 'S561' compressed GBRG bayer */
+       case V4L2_PIX_FMT_PAC207:       /* 'P207' compressed BGGR bayer */
                return 8;
        }
        PDEBUG(D_ERR|D_CONF, "Unknown pixel format %c%c%c%c",
@@ -395,6 +397,9 @@ static int gspca_get_buff_size(struct gspca_dev *gspca_dev, int mode)
 {
        unsigned int size;
 
+       if (gspca_dev->sd_desc->get_buff_size)
+               return gspca_dev->sd_desc->get_buff_size(gspca_dev, mode);
+
        size =  gspca_dev->cam.cam_mode[mode].width *
                gspca_dev->cam.cam_mode[mode].height *
                get_v4l2_depth(gspca_dev->cam.cam_mode[mode].pixfmt) / 8;
index 0d23e0a90c7796089a1f08e41b42c7fd04b9e16a..05e8ee06071b240f9aed9ad4a02bf9950c108f18 100644 (file)
@@ -80,6 +80,7 @@ typedef void (*cam_pkt_op) (struct gspca_dev *gspca_dev,
                                struct gspca_frame *frame,
                                __u8 *data,
                                int len);
+typedef int (*cam_get_buff_size_op) (struct gspca_dev *gspca_dev, int mode);
 
 struct ctrl {
        struct v4l2_queryctrl qctrl;
@@ -106,6 +107,7 @@ struct sd_desc {
        cam_jpg_op get_jcomp;
        cam_jpg_op set_jcomp;
        cam_qmnu_op querymenu;
+       cam_get_buff_size_op get_buff_size; /* optional */
 };
 
 /* packet types when moving from iso buf to frame buf */
index 7e067456e62b672db536161aaf16513ccfe3867e..0135ba599e81cb8890d23fd857469a5c27e25502 100644 (file)
@@ -58,34 +58,10 @@ MODULE_LICENSE("GPL");
    before doing any other adjustments */
 #define PAC207_AUTOGAIN_IGNORE_FRAMES  3
 
-enum pac207_line_state {
-       LINE_HEADER1,
-       LINE_HEADER2,
-       LINE_UNCOMPRESSED,
-       LINE_COMPRESSED,
-};
-
-struct pac207_decoder_state {
-       /* generic state */
-       u16 line_read;
-       u16 line_marker;
-       u8 line_state;
-       u8 header_read;
-       /* compression state */
-       u16 processed_bytes;
-       u8 remaining_bits;
-       s8 no_remaining_bits;
-       u8 get_abs;
-       u8 discard_byte;
-       u8 line_decode_buf[352];
-};
-
 /* specific webcam descriptor */
 struct sd {
        struct gspca_dev gspca_dev;             /* !! must be the first item */
 
-       struct pac207_decoder_state decoder_state;
-
        u8 mode;
 
        u8 brightness;
@@ -94,6 +70,7 @@ struct sd {
        u8 gain;
 
        u8 sof_read;
+       u8 header_read;
        u8 autogain_ignore_frames;
 
        atomic_t avg_lum;
@@ -173,8 +150,8 @@ static struct ctrl sd_ctrls[] = {
 };
 
 static struct cam_mode sif_mode[] = {
-       {V4L2_PIX_FMT_SBGGR8, 176, 144, 1},
-       {V4L2_PIX_FMT_SBGGR8, 352, 288, 0},
+       {V4L2_PIX_FMT_PAC207, 176, 144, 1},
+       {V4L2_PIX_FMT_PAC207, 352, 288, 0},
 };
 
 static const __u8 pac207_sensor_init[][8] = {
@@ -361,68 +338,17 @@ static void sd_close(struct gspca_dev *gspca_dev)
 {
 }
 
-/* -- convert pixart frames to Bayer -- */
-/* Sonix decompressor struct B.S.(2004) */
-static struct {
-       u8 is_abs;
-       u8 len;
-       s8 val;
-} table[256];
-
-void init_pixart_decoder(void)
+static int sd_get_buff_size_op(struct gspca_dev *gspca_dev, int mode)
 {
-       int i, is_abs, val, len;
-
-       for (i = 0; i < 256; i++) {
-               is_abs = 0;
-               val = 0;
-               len = 0;
-               if ((i & 0xC0) == 0) {
-                       /* code 00 */
-                       val = 0;
-                       len = 2;
-               } else if ((i & 0xC0) == 0x40) {
-                       /* code 01 */
-                       val = -5;
-                       len = 2;
-               } else if ((i & 0xC0) == 0x80) {
-                       /* code 10 */
-                       val = 5;
-                       len = 2;
-               } else if ((i & 0xF0) == 0xC0) {
-                       /* code 1100 */
-                       val = -10;
-                       len = 4;
-               } else if ((i & 0xF0) == 0xD0) {
-                       /* code 1101 */
-                       val = 10;
-                       len = 4;
-               } else if ((i & 0xF8) == 0xE0) {
-                       /* code 11100 */
-                       val = -15;
-                       len = 5;
-               } else if ((i & 0xF8) == 0xE8) {
-                       /* code 11101 */
-                       val = 15;
-                       len = 5;
-               } else if ((i & 0xFC) == 0xF0) {
-                       /* code 111100 */
-                       val = -20;
-                       len = 6;
-               } else if ((i & 0xFC) == 0xF4) {
-                       /* code 111101 */
-                       val = 20;
-                       len = 6;
-               } else if ((i & 0xF8) == 0xF8) {
-                       /* code 11111xxxxxx */
-                       is_abs = 1;
-                       val = 0;
-                       len = 5;
-               }
-               table[i].is_abs = is_abs;
-               table[i].val = val;
-               table[i].len = len;
+       switch (gspca_dev->cam.cam_mode[mode].width) {
+       case 176: /* 176x144 */
+               /* uncompressed, add 2 bytes / line for line header */
+               return (176 + 2) * 144;
+       case 352: /* 352x288 */
+               /* compressed */
+               return 352 * 288 / 2;
        }
+       return -EIO; /* should never happen */
 }
 
 /* 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,
        return NULL;
 }
 
-static int pac207_decompress_row(struct gspca_dev *gspca_dev,
-                               struct gspca_frame *f,
-                               __u8 *cdata,
-                               int len)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct pac207_decoder_state *decoder_state = &sd->decoder_state;
-       unsigned char *outp = decoder_state->line_decode_buf +
-                               decoder_state->line_read;
-       int val, bitlen, bitpos = -decoder_state->no_remaining_bits;
-       u8 code;
-
-       /* first two pixels are stored as raw 8-bit */
-       while (decoder_state->line_read < 2) {
-               *outp++ = *cdata++;
-               decoder_state->line_read++;
-               len--;
-               if (len == 0)
-                       return 0;
-       }
-
-       while (decoder_state->line_read < gspca_dev->width) {
-               if (bitpos < 0) {
-                       code = decoder_state->remaining_bits << (8 + bitpos) |
-                               cdata[0] >> -bitpos;
-               } else {
-                       u8 *addr = cdata + bitpos / 8;
-                       code = addr[0] << (bitpos & 7) |
-                               addr[1] >> (8 - (bitpos & 7));
-               }
-
-               bitlen = decoder_state->get_abs ?
-                               6 : table[code].len;
-
-               /* Stop decompressing if we're out of input data */
-               if ((bitpos + bitlen) > (len * 8))
-                       break;
-
-               if (decoder_state->get_abs) {
-                       *outp++ = code & 0xFC;
-                       decoder_state->line_read++;
-                       decoder_state->get_abs = 0;
-               } else {
-                       if (table[code].is_abs) {
-                               decoder_state->get_abs = 1;
-                       } else {
-                               /* relative to left pixel */
-                               val = outp[-2] +
-                                       table[code].val;
-                               if (val > 0xff)
-                                       val = 0xff;
-                               else if (val < 0)
-                                       val = 0;
-                               *outp++ = val;
-                               decoder_state->line_read++;
-                       }
-               }
-               bitpos += bitlen;
-       }
-
-       if (decoder_state->line_read == gspca_dev->width) {
-               int compressed_line_len;
-
-               gspca_frame_add(gspca_dev, INTER_PACKET, f,
-                               decoder_state->line_decode_buf,
-                               gspca_dev->width);
-
-               /* completely decompressed line, round pos to nearest word */
-               compressed_line_len = ((decoder_state->processed_bytes * 8 +
-                       bitpos + 15) / 16) * 2;
-
-               len -= compressed_line_len - decoder_state->processed_bytes;
-               if (len < 0) {
-                       decoder_state->discard_byte = 1;
-                       len = 0;
-               }
-       } else {
-               decoder_state->processed_bytes += len;
-               decoder_state->remaining_bits = cdata[bitpos/8];
-               decoder_state->no_remaining_bits = (8 - bitpos) & 7;
-               len = 0;
-       }
-
-       return len;
-}
-
-static void pac207_decode_line_init(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct pac207_decoder_state *decoder_state = &sd->decoder_state;
-
-       decoder_state->line_read = 0;
-       decoder_state->line_state = LINE_HEADER1;
-       decoder_state->processed_bytes = 0;
-       decoder_state->no_remaining_bits = 0;
-       decoder_state->get_abs = 0;
-}
-
-static void pac207_decode_frame_init(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct pac207_decoder_state *decoder_state = &sd->decoder_state;
-
-       decoder_state->header_read = 0;
-       decoder_state->discard_byte = 0;
-
-       pac207_decode_line_init(gspca_dev);
-}
-
-static int pac207_decode_frame_data(struct gspca_dev *gspca_dev,
-       struct gspca_frame *f, unsigned char *data, int len)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct pac207_decoder_state *decoder_state = &sd->decoder_state;
-       int needed = 0;
-
-       /* first 11 bytes after sof marker: frame header */
-       if (decoder_state->header_read < 11) {
-               /* get average lumination from frame header (byte 5) */
-               if (decoder_state->header_read < 5) {
-                       needed = 5 - decoder_state->header_read;
-                       if (len >= needed)
-                               atomic_set(&sd->avg_lum, data[needed-1]);
-               }
-               /* skip the rest of the header */
-               needed = 11 - decoder_state->header_read;
-               if (len <= needed) {
-                       decoder_state->header_read += len;
-                       return 0;
-               }
-               data += needed;
-               len -= needed;
-               decoder_state->header_read = 11;
-       }
-
-       while (len) {
-               if (decoder_state->discard_byte) {
-                       data++;
-                       len--;
-                       decoder_state->discard_byte = 0;
-                       continue;
-               }
-
-               switch (decoder_state->line_state) {
-               case LINE_HEADER1:
-                       decoder_state->line_marker = data[0] << 8;
-                       decoder_state->line_state = LINE_HEADER2;
-                       needed = 1;
-                       break;
-               case LINE_HEADER2:
-                       decoder_state->line_marker |= data[0];
-                       switch (decoder_state->line_marker) {
-                       case 0x0ff0:
-                               decoder_state->line_state = LINE_UNCOMPRESSED;
-                               break;
-                       case 0x1ee1:
-                               decoder_state->line_state = LINE_COMPRESSED;
-                               break;
-                       default:
-                               PDEBUG(D_STREAM,
-                                       "Error unknown line-header %04X",
-                                       (int) decoder_state->line_marker);
-                               gspca_dev->last_packet_type = DISCARD_PACKET;
-                               return 0;
-                       }
-                       needed = 1;
-                       break;
-               case LINE_UNCOMPRESSED:
-                       needed = gspca_dev->width - decoder_state->line_read;
-                       if (needed > len)
-                               needed = len;
-                       gspca_frame_add(gspca_dev, INTER_PACKET, f, data,
-                               needed);
-                       decoder_state->line_read += needed;
-                       break;
-               case LINE_COMPRESSED:
-                       needed = len -
-                               pac207_decompress_row(gspca_dev, f, data, len);
-                       break;
-               }
-
-               data += needed;
-               len -= needed;
-
-               if (decoder_state->line_read == gspca_dev->width) {
-                       if ((f->data_end - f->data) ==
-                               (gspca_dev->width * gspca_dev->height)) {
-                               /* eureka we've got a frame */
-                               return 1;
-                       }
-                       pac207_decode_line_init(gspca_dev);
-               }
-       }
-
-       return 0;
-}
-
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
                        struct gspca_frame *frame,
                        __u8 *data,
                        int len)
 {
+       struct sd *sd = (struct sd *) gspca_dev;
        unsigned char *sof;
-       int n;
 
        sof = pac207_find_sof(gspca_dev, data, len);
-
        if (sof) {
+               int n;
+
                /* finish decoding current frame */
-               if (gspca_dev->last_packet_type == INTER_PACKET) {
-                       n = sof - data;
-                       if (n > sizeof(pac207_sof_marker))
-                               n -= sizeof(pac207_sof_marker);
-                       else
-                               n = 0;
-                       n = pac207_decode_frame_data(gspca_dev, frame,
-                                                       data, n);
-                       if (n)
-                               frame = gspca_frame_add(gspca_dev,
-                                               LAST_PACKET,
-                                               frame,
-                                               NULL,
-                                               0);
-                       else
-                               PDEBUG(D_STREAM, "Incomplete frame");
-               }
-               pac207_decode_frame_init(gspca_dev);
+               n = sof - data;
+               if (n > sizeof pac207_sof_marker)
+                       n -= sizeof pac207_sof_marker;
+               else
+                       n = 0;
+               frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
+                                       data, n);
+               sd->header_read = 0;
                gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL, 0);
                len -= sof - data;
                data = sof;
        }
+       if (sd->header_read < 11) {
+               int needed;
 
-       if (gspca_dev->last_packet_type == DISCARD_PACKET)
-               return;
+               /* get average lumination from frame header (byte 5) */
+               if (sd->header_read < 5) {
+                       needed = 5 - sd->header_read;
+                       if (len >= needed)
+                               atomic_set(&sd->avg_lum, data[needed - 1]);
+               }
+               /* skip the rest of the header */
+               needed = 11 - sd->header_read;
+               if (len <= needed) {
+                       sd->header_read += len;
+                       return;
+               }
+               data += needed;
+               len -= needed;
+               sd->header_read = 11;
+       }
 
-       n = pac207_decode_frame_data(gspca_dev, frame, data, len);
-       if (n)
-               gspca_frame_add(gspca_dev, LAST_PACKET,
-                               frame, NULL, 0);
+       gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
 }
 
 static void setbrightness(struct gspca_dev *gspca_dev)
@@ -891,6 +624,7 @@ static const struct sd_desc sd_desc = {
        .close = sd_close,
        .dq_callback = pac207_do_auto_gain,
        .pkt_scan = sd_pkt_scan,
+       .get_buff_size = sd_get_buff_size_op,
 };
 
 /* -- module initialisation -- */
@@ -927,7 +661,6 @@ static struct usb_driver sd_driver = {
 /* -- module insert / remove -- */
 static int __init sd_mod_init(void)
 {
-       init_pixart_decoder();
        if (usb_register(&sd_driver) < 0)
                return -1;
        PDEBUG(D_PROBE, "v%s registered", version);
index 577f15634791f55ff9f182f3a80241bbf7dada78..2e66a95e8d32f5e19ee073891b0b103765cc865d 100644 (file)
@@ -326,7 +326,8 @@ struct v4l2_pix_format
 #define V4L2_PIX_FMT_PWC2     v4l2_fourcc('P','W','C','2') /* pwc newer webcam */
 #define V4L2_PIX_FMT_ET61X251 v4l2_fourcc('E','6','2','5') /* ET61X251 compression */
 #define V4L2_PIX_FMT_SPCA501  v4l2_fourcc('S','5','0','1') /* YUYV per line */
-#define V4L2_PIX_FMT_SPCA561  v4l2_fourcc('S','5','6','1') /* compressed BGGR bayer */
+#define V4L2_PIX_FMT_SPCA561  v4l2_fourcc('S','5','6','1') /* compressed GBRG bayer */
+#define V4L2_PIX_FMT_PAC207   v4l2_fourcc('P','2','0','7') /* compressed BGGR bayer */
 
 /*
  *     F O R M A T   E N U M E R A T I O N