Luc Saillard | 2b455db | 2006-04-24 10:29:46 -0300 | [diff] [blame] | 1 | /* Linux driver for Philips webcam |
| 2 | Decompression for chipset version 2 et 3 |
| 3 | (C) 2004-2006 Luc Saillard (luc@saillard.org) |
| 4 | |
| 5 | NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx |
| 6 | driver and thus may have bugs that are not present in the original version. |
| 7 | Please send bug reports and support requests to <luc@saillard.org>. |
| 8 | The decompression routines have been implemented by reverse-engineering the |
| 9 | Nemosoft binary pwcx module. Caveat emptor. |
| 10 | |
| 11 | This program is free software; you can redistribute it and/or modify |
| 12 | it under the terms of the GNU General Public License as published by |
| 13 | the Free Software Foundation; either version 2 of the License, or |
| 14 | (at your option) any later version. |
| 15 | |
| 16 | This program is distributed in the hope that it will be useful, |
| 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 19 | GNU General Public License for more details. |
| 20 | |
| 21 | You should have received a copy of the GNU General Public License |
| 22 | along with this program; if not, write to the Free Software |
| 23 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 24 | |
| 25 | */ |
| 26 | |
| 27 | #include "pwc-timon.h" |
| 28 | #include "pwc-kiara.h" |
| 29 | #include "pwc-dec23.h" |
| 30 | #include <media/pwc-ioctl.h> |
| 31 | |
| 32 | #include <linux/string.h> |
Tejun Heo | 5a0e3ad | 2010-03-24 17:04:11 +0900 | [diff] [blame] | 33 | #include <linux/slab.h> |
Luc Saillard | 2b455db | 2006-04-24 10:29:46 -0300 | [diff] [blame] | 34 | |
| 35 | /* |
| 36 | * USE_LOOKUP_TABLE_TO_CLAMP |
| 37 | * 0: use a C version of this tests: { a<0?0:(a>255?255:a) } |
| 38 | * 1: use a faster lookup table for cpu with a big cache (intel) |
| 39 | */ |
| 40 | #define USE_LOOKUP_TABLE_TO_CLAMP 1 |
| 41 | /* |
| 42 | * UNROLL_LOOP_FOR_COPYING_BLOCK |
| 43 | * 0: use a loop for a smaller code (but little slower) |
| 44 | * 1: when unrolling the loop, gcc produces some faster code (perhaps only |
| 45 | * valid for intel processor class). Activating this option, automaticaly |
| 46 | * activate USE_LOOKUP_TABLE_TO_CLAMP |
| 47 | */ |
| 48 | #define UNROLL_LOOP_FOR_COPY 1 |
| 49 | #if UNROLL_LOOP_FOR_COPY |
| 50 | # undef USE_LOOKUP_TABLE_TO_CLAMP |
| 51 | # define USE_LOOKUP_TABLE_TO_CLAMP 1 |
| 52 | #endif |
| 53 | |
| 54 | /* |
| 55 | * ENABLE_BAYER_DECODER |
| 56 | * 0: bayer decoder is not build (save some space) |
| 57 | * 1: bayer decoder is build and can be used |
| 58 | */ |
| 59 | #define ENABLE_BAYER_DECODER 0 |
| 60 | |
| 61 | static void build_subblock_pattern(struct pwc_dec23_private *pdec) |
| 62 | { |
| 63 | static const unsigned int initial_values[12] = { |
| 64 | -0x526500, -0x221200, 0x221200, 0x526500, |
| 65 | -0x3de200, 0x3de200, |
| 66 | -0x6db480, -0x2d5d00, 0x2d5d00, 0x6db480, |
| 67 | -0x12c200, 0x12c200 |
| 68 | |
| 69 | }; |
| 70 | static const unsigned int values_derivated[12] = { |
| 71 | 0xa4ca, 0x4424, -0x4424, -0xa4ca, |
| 72 | 0x7bc4, -0x7bc4, |
| 73 | 0xdb69, 0x5aba, -0x5aba, -0xdb69, |
| 74 | 0x2584, -0x2584 |
| 75 | }; |
| 76 | unsigned int temp_values[12]; |
| 77 | int i, j; |
| 78 | |
| 79 | memcpy(temp_values, initial_values, sizeof(initial_values)); |
| 80 | for (i = 0; i < 256; i++) { |
| 81 | for (j = 0; j < 12; j++) { |
| 82 | pdec->table_subblock[i][j] = temp_values[j]; |
| 83 | temp_values[j] += values_derivated[j]; |
| 84 | } |
| 85 | } |
| 86 | } |
| 87 | |
| 88 | static void build_bit_powermask_table(struct pwc_dec23_private *pdec) |
| 89 | { |
| 90 | unsigned char *p; |
| 91 | unsigned int bit, byte, mask, val; |
| 92 | unsigned int bitpower = 1; |
| 93 | |
| 94 | for (bit = 0; bit < 8; bit++) { |
| 95 | mask = bitpower - 1; |
| 96 | p = pdec->table_bitpowermask[bit]; |
| 97 | for (byte = 0; byte < 256; byte++) { |
| 98 | val = (byte & mask); |
| 99 | if (byte & bitpower) |
| 100 | val = -val; |
| 101 | *p++ = val; |
| 102 | } |
| 103 | bitpower<<=1; |
| 104 | } |
| 105 | } |
| 106 | |
| 107 | |
| 108 | static void build_table_color(const unsigned int romtable[16][8], |
Trent Piepho | 657de3c | 2006-06-20 00:30:57 -0300 | [diff] [blame] | 109 | unsigned char p0004[16][1024], |
Luc Saillard | 2b455db | 2006-04-24 10:29:46 -0300 | [diff] [blame] | 110 | unsigned char p8004[16][256]) |
| 111 | { |
| 112 | int compression_mode, j, k, bit, pw; |
| 113 | unsigned char *p0, *p8; |
| 114 | const unsigned int *r; |
| 115 | |
| 116 | /* We have 16 compressions tables */ |
| 117 | for (compression_mode = 0; compression_mode < 16; compression_mode++) { |
| 118 | p0 = p0004[compression_mode]; |
| 119 | p8 = p8004[compression_mode]; |
| 120 | r = romtable[compression_mode]; |
| 121 | |
| 122 | for (j = 0; j < 8; j++, r++, p0 += 128) { |
| 123 | |
| 124 | for (k = 0; k < 16; k++) { |
| 125 | if (k == 0) |
| 126 | bit = 1; |
| 127 | else if (k >= 1 && k < 3) |
| 128 | bit = (r[0] >> 15) & 7; |
| 129 | else if (k >= 3 && k < 6) |
| 130 | bit = (r[0] >> 12) & 7; |
| 131 | else if (k >= 6 && k < 10) |
| 132 | bit = (r[0] >> 9) & 7; |
| 133 | else if (k >= 10 && k < 13) |
| 134 | bit = (r[0] >> 6) & 7; |
| 135 | else if (k >= 13 && k < 15) |
| 136 | bit = (r[0] >> 3) & 7; |
| 137 | else |
| 138 | bit = (r[0]) & 7; |
| 139 | if (k == 0) |
| 140 | *p8++ = 8; |
| 141 | else |
| 142 | *p8++ = j - bit; |
| 143 | *p8++ = bit; |
| 144 | |
| 145 | pw = 1 << bit; |
| 146 | p0[k + 0x00] = (1 * pw) + 0x80; |
| 147 | p0[k + 0x10] = (2 * pw) + 0x80; |
| 148 | p0[k + 0x20] = (3 * pw) + 0x80; |
| 149 | p0[k + 0x30] = (4 * pw) + 0x80; |
| 150 | p0[k + 0x40] = (-1 * pw) + 0x80; |
| 151 | p0[k + 0x50] = (-2 * pw) + 0x80; |
| 152 | p0[k + 0x60] = (-3 * pw) + 0x80; |
| 153 | p0[k + 0x70] = (-4 * pw) + 0x80; |
| 154 | } /* end of for (k=0; k<16; k++, p8++) */ |
| 155 | } /* end of for (j=0; j<8; j++ , table++) */ |
| 156 | } /* end of foreach compression_mode */ |
| 157 | } |
| 158 | |
| 159 | /* |
| 160 | * |
| 161 | */ |
| 162 | static void fill_table_dc00_d800(struct pwc_dec23_private *pdec) |
| 163 | { |
| 164 | #define SCALEBITS 15 |
| 165 | #define ONE_HALF (1UL << (SCALEBITS - 1)) |
| 166 | int i; |
| 167 | unsigned int offset1 = ONE_HALF; |
| 168 | unsigned int offset2 = 0x0000; |
| 169 | |
| 170 | for (i=0; i<256; i++) { |
| 171 | pdec->table_dc00[i] = offset1 & ~(ONE_HALF); |
| 172 | pdec->table_d800[i] = offset2; |
| 173 | |
| 174 | offset1 += 0x7bc4; |
| 175 | offset2 += 0x7bc4; |
| 176 | } |
| 177 | } |
| 178 | |
| 179 | /* |
| 180 | * To decode the stream: |
| 181 | * if look_bits(2) == 0: # op == 2 in the lookup table |
| 182 | * skip_bits(2) |
| 183 | * end of the stream |
| 184 | * elif look_bits(3) == 7: # op == 1 in the lookup table |
| 185 | * skip_bits(3) |
| 186 | * yyyy = get_bits(4) |
| 187 | * xxxx = get_bits(8) |
| 188 | * else: # op == 0 in the lookup table |
| 189 | * skip_bits(x) |
| 190 | * |
| 191 | * For speedup processing, we build a lookup table and we takes the first 6 bits. |
| 192 | * |
| 193 | * struct { |
| 194 | * unsigned char op; // operation to execute |
| 195 | * unsigned char bits; // bits use to perform operation |
| 196 | * unsigned char offset1; // offset to add to access in the table_0004 % 16 |
| 197 | * unsigned char offset2; // offset to add to access in the table_0004 |
| 198 | * } |
| 199 | * |
| 200 | * How to build this table ? |
| 201 | * op == 2 when (i%4)==0 |
| 202 | * op == 1 when (i%8)==7 |
| 203 | * op == 0 otherwise |
| 204 | * |
| 205 | */ |
| 206 | static const unsigned char hash_table_ops[64*4] = { |
| 207 | 0x02, 0x00, 0x00, 0x00, |
| 208 | 0x00, 0x03, 0x01, 0x00, |
| 209 | 0x00, 0x04, 0x01, 0x10, |
| 210 | 0x00, 0x06, 0x01, 0x30, |
| 211 | 0x02, 0x00, 0x00, 0x00, |
| 212 | 0x00, 0x03, 0x01, 0x40, |
| 213 | 0x00, 0x05, 0x01, 0x20, |
| 214 | 0x01, 0x00, 0x00, 0x00, |
| 215 | 0x02, 0x00, 0x00, 0x00, |
| 216 | 0x00, 0x03, 0x01, 0x00, |
| 217 | 0x00, 0x04, 0x01, 0x50, |
| 218 | 0x00, 0x05, 0x02, 0x00, |
| 219 | 0x02, 0x00, 0x00, 0x00, |
| 220 | 0x00, 0x03, 0x01, 0x40, |
| 221 | 0x00, 0x05, 0x03, 0x00, |
| 222 | 0x01, 0x00, 0x00, 0x00, |
| 223 | 0x02, 0x00, 0x00, 0x00, |
| 224 | 0x00, 0x03, 0x01, 0x00, |
| 225 | 0x00, 0x04, 0x01, 0x10, |
| 226 | 0x00, 0x06, 0x02, 0x10, |
| 227 | 0x02, 0x00, 0x00, 0x00, |
| 228 | 0x00, 0x03, 0x01, 0x40, |
| 229 | 0x00, 0x05, 0x01, 0x60, |
| 230 | 0x01, 0x00, 0x00, 0x00, |
| 231 | 0x02, 0x00, 0x00, 0x00, |
| 232 | 0x00, 0x03, 0x01, 0x00, |
| 233 | 0x00, 0x04, 0x01, 0x50, |
| 234 | 0x00, 0x05, 0x02, 0x40, |
| 235 | 0x02, 0x00, 0x00, 0x00, |
| 236 | 0x00, 0x03, 0x01, 0x40, |
| 237 | 0x00, 0x05, 0x03, 0x40, |
| 238 | 0x01, 0x00, 0x00, 0x00, |
| 239 | 0x02, 0x00, 0x00, 0x00, |
| 240 | 0x00, 0x03, 0x01, 0x00, |
| 241 | 0x00, 0x04, 0x01, 0x10, |
| 242 | 0x00, 0x06, 0x01, 0x70, |
| 243 | 0x02, 0x00, 0x00, 0x00, |
| 244 | 0x00, 0x03, 0x01, 0x40, |
| 245 | 0x00, 0x05, 0x01, 0x20, |
| 246 | 0x01, 0x00, 0x00, 0x00, |
| 247 | 0x02, 0x00, 0x00, 0x00, |
| 248 | 0x00, 0x03, 0x01, 0x00, |
| 249 | 0x00, 0x04, 0x01, 0x50, |
| 250 | 0x00, 0x05, 0x02, 0x00, |
| 251 | 0x02, 0x00, 0x00, 0x00, |
| 252 | 0x00, 0x03, 0x01, 0x40, |
| 253 | 0x00, 0x05, 0x03, 0x00, |
| 254 | 0x01, 0x00, 0x00, 0x00, |
| 255 | 0x02, 0x00, 0x00, 0x00, |
| 256 | 0x00, 0x03, 0x01, 0x00, |
| 257 | 0x00, 0x04, 0x01, 0x10, |
| 258 | 0x00, 0x06, 0x02, 0x50, |
| 259 | 0x02, 0x00, 0x00, 0x00, |
| 260 | 0x00, 0x03, 0x01, 0x40, |
| 261 | 0x00, 0x05, 0x01, 0x60, |
| 262 | 0x01, 0x00, 0x00, 0x00, |
| 263 | 0x02, 0x00, 0x00, 0x00, |
| 264 | 0x00, 0x03, 0x01, 0x00, |
| 265 | 0x00, 0x04, 0x01, 0x50, |
| 266 | 0x00, 0x05, 0x02, 0x40, |
| 267 | 0x02, 0x00, 0x00, 0x00, |
| 268 | 0x00, 0x03, 0x01, 0x40, |
| 269 | 0x00, 0x05, 0x03, 0x40, |
| 270 | 0x01, 0x00, 0x00, 0x00 |
| 271 | }; |
| 272 | |
| 273 | /* |
| 274 | * |
| 275 | */ |
| 276 | static const unsigned int MulIdx[16][16] = { |
| 277 | {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, |
| 278 | {0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,}, |
| 279 | {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,}, |
| 280 | {4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4,}, |
| 281 | {6, 7, 8, 9, 7, 10, 11, 8, 8, 11, 10, 7, 9, 8, 7, 6,}, |
| 282 | {4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4,}, |
| 283 | {1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2,}, |
| 284 | {0, 3, 3, 0, 1, 2, 2, 1, 2, 1, 1, 2, 3, 0, 0, 3,}, |
| 285 | {0, 1, 2, 3, 3, 2, 1, 0, 3, 2, 1, 0, 0, 1, 2, 3,}, |
| 286 | {1, 1, 1, 1, 3, 3, 3, 3, 0, 0, 0, 0, 2, 2, 2, 2,}, |
| 287 | {7, 10, 11, 8, 9, 8, 7, 6, 6, 7, 8, 9, 8, 11, 10, 7,}, |
| 288 | {4, 5, 5, 4, 5, 4, 4, 5, 5, 4, 4, 5, 4, 5, 5, 4,}, |
| 289 | {7, 9, 6, 8, 10, 8, 7, 11, 11, 7, 8, 10, 8, 6, 9, 7,}, |
| 290 | {1, 3, 0, 2, 2, 0, 3, 1, 2, 0, 3, 1, 1, 3, 0, 2,}, |
| 291 | {1, 2, 2, 1, 3, 0, 0, 3, 0, 3, 3, 0, 2, 1, 1, 2,}, |
| 292 | {10, 8, 7, 11, 8, 6, 9, 7, 7, 9, 6, 8, 11, 7, 8, 10} |
| 293 | }; |
| 294 | |
| 295 | #if USE_LOOKUP_TABLE_TO_CLAMP |
| 296 | #define MAX_OUTER_CROP_VALUE (512) |
| 297 | static unsigned char pwc_crop_table[256 + 2*MAX_OUTER_CROP_VALUE]; |
| 298 | #define CLAMP(x) (pwc_crop_table[MAX_OUTER_CROP_VALUE+(x)]) |
| 299 | #else |
| 300 | #define CLAMP(x) ((x)>255?255:((x)<0?0:x)) |
| 301 | #endif |
| 302 | |
| 303 | |
| 304 | /* If the type or the command change, we rebuild the lookup table */ |
| 305 | int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd) |
| 306 | { |
| 307 | int flags, version, shift, i; |
| 308 | struct pwc_dec23_private *pdec; |
| 309 | |
| 310 | if (pwc->decompress_data == NULL) { |
| 311 | pdec = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL); |
| 312 | if (pdec == NULL) |
| 313 | return -ENOMEM; |
| 314 | pwc->decompress_data = pdec; |
| 315 | } |
| 316 | pdec = pwc->decompress_data; |
| 317 | |
| 318 | if (DEVICE_USE_CODEC3(type)) { |
| 319 | flags = cmd[2] & 0x18; |
| 320 | if (flags == 8) |
| 321 | pdec->nbits = 7; /* More bits, mean more bits to encode the stream, but better quality */ |
| 322 | else if (flags == 0x10) |
| 323 | pdec->nbits = 8; |
| 324 | else |
| 325 | pdec->nbits = 6; |
| 326 | |
| 327 | version = cmd[2] >> 5; |
| 328 | build_table_color(KiaraRomTable[version][0], pdec->table_0004_pass1, pdec->table_8004_pass1); |
| 329 | build_table_color(KiaraRomTable[version][1], pdec->table_0004_pass2, pdec->table_8004_pass2); |
| 330 | |
| 331 | } else { |
| 332 | |
| 333 | flags = cmd[2] & 6; |
| 334 | if (flags == 2) |
| 335 | pdec->nbits = 7; |
| 336 | else if (flags == 4) |
| 337 | pdec->nbits = 8; |
| 338 | else |
| 339 | pdec->nbits = 6; |
| 340 | |
| 341 | version = cmd[2] >> 3; |
| 342 | build_table_color(TimonRomTable[version][0], pdec->table_0004_pass1, pdec->table_8004_pass1); |
| 343 | build_table_color(TimonRomTable[version][1], pdec->table_0004_pass2, pdec->table_8004_pass2); |
| 344 | } |
| 345 | |
| 346 | /* Informations can be coded on a variable number of bits but never less than 8 */ |
| 347 | shift = 8 - pdec->nbits; |
| 348 | pdec->scalebits = SCALEBITS - shift; |
| 349 | pdec->nbitsmask = 0xFF >> shift; |
| 350 | |
| 351 | fill_table_dc00_d800(pdec); |
| 352 | build_subblock_pattern(pdec); |
| 353 | build_bit_powermask_table(pdec); |
| 354 | |
| 355 | #if USE_LOOKUP_TABLE_TO_CLAMP |
| 356 | /* Build the static table to clamp value [0-255] */ |
| 357 | for (i=0;i<MAX_OUTER_CROP_VALUE;i++) |
| 358 | pwc_crop_table[i] = 0; |
| 359 | for (i=0; i<256; i++) |
| 360 | pwc_crop_table[MAX_OUTER_CROP_VALUE+i] = i; |
| 361 | for (i=0; i<MAX_OUTER_CROP_VALUE; i++) |
| 362 | pwc_crop_table[MAX_OUTER_CROP_VALUE+256+i] = 255; |
| 363 | #endif |
| 364 | |
| 365 | return 0; |
| 366 | } |
| 367 | |
| 368 | /* |
| 369 | * Copy the 4x4 image block to Y plane buffer |
| 370 | */ |
| 371 | static void copy_image_block_Y(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits) |
| 372 | { |
| 373 | #if UNROLL_LOOP_FOR_COPY |
| 374 | const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE; |
| 375 | const int *c = src; |
| 376 | unsigned char *d = dst; |
| 377 | |
| 378 | *d++ = cm[c[0] >> scalebits]; |
| 379 | *d++ = cm[c[1] >> scalebits]; |
| 380 | *d++ = cm[c[2] >> scalebits]; |
| 381 | *d++ = cm[c[3] >> scalebits]; |
| 382 | |
| 383 | d = dst + bytes_per_line; |
| 384 | *d++ = cm[c[4] >> scalebits]; |
| 385 | *d++ = cm[c[5] >> scalebits]; |
| 386 | *d++ = cm[c[6] >> scalebits]; |
| 387 | *d++ = cm[c[7] >> scalebits]; |
| 388 | |
| 389 | d = dst + bytes_per_line*2; |
| 390 | *d++ = cm[c[8] >> scalebits]; |
| 391 | *d++ = cm[c[9] >> scalebits]; |
| 392 | *d++ = cm[c[10] >> scalebits]; |
| 393 | *d++ = cm[c[11] >> scalebits]; |
| 394 | |
| 395 | d = dst + bytes_per_line*3; |
| 396 | *d++ = cm[c[12] >> scalebits]; |
| 397 | *d++ = cm[c[13] >> scalebits]; |
| 398 | *d++ = cm[c[14] >> scalebits]; |
| 399 | *d++ = cm[c[15] >> scalebits]; |
| 400 | #else |
| 401 | int i; |
| 402 | const int *c = src; |
| 403 | unsigned char *d = dst; |
| 404 | for (i = 0; i < 4; i++, c++) |
| 405 | *d++ = CLAMP((*c) >> scalebits); |
| 406 | |
| 407 | d = dst + bytes_per_line; |
| 408 | for (i = 0; i < 4; i++, c++) |
| 409 | *d++ = CLAMP((*c) >> scalebits); |
| 410 | |
| 411 | d = dst + bytes_per_line*2; |
| 412 | for (i = 0; i < 4; i++, c++) |
| 413 | *d++ = CLAMP((*c) >> scalebits); |
| 414 | |
| 415 | d = dst + bytes_per_line*3; |
| 416 | for (i = 0; i < 4; i++, c++) |
| 417 | *d++ = CLAMP((*c) >> scalebits); |
| 418 | #endif |
| 419 | } |
| 420 | |
| 421 | /* |
| 422 | * Copy the 4x4 image block to a CrCb plane buffer |
| 423 | * |
| 424 | */ |
| 425 | static void copy_image_block_CrCb(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits) |
| 426 | { |
| 427 | #if UNROLL_LOOP_FOR_COPY |
| 428 | /* Unroll all loops */ |
| 429 | const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE; |
| 430 | const int *c = src; |
| 431 | unsigned char *d = dst; |
| 432 | |
| 433 | *d++ = cm[c[0] >> scalebits]; |
| 434 | *d++ = cm[c[4] >> scalebits]; |
| 435 | *d++ = cm[c[1] >> scalebits]; |
| 436 | *d++ = cm[c[5] >> scalebits]; |
| 437 | *d++ = cm[c[2] >> scalebits]; |
| 438 | *d++ = cm[c[6] >> scalebits]; |
| 439 | *d++ = cm[c[3] >> scalebits]; |
| 440 | *d++ = cm[c[7] >> scalebits]; |
| 441 | |
| 442 | d = dst + bytes_per_line; |
| 443 | *d++ = cm[c[12] >> scalebits]; |
| 444 | *d++ = cm[c[8] >> scalebits]; |
| 445 | *d++ = cm[c[13] >> scalebits]; |
| 446 | *d++ = cm[c[9] >> scalebits]; |
| 447 | *d++ = cm[c[14] >> scalebits]; |
| 448 | *d++ = cm[c[10] >> scalebits]; |
| 449 | *d++ = cm[c[15] >> scalebits]; |
| 450 | *d++ = cm[c[11] >> scalebits]; |
| 451 | #else |
| 452 | int i; |
| 453 | const int *c1 = src; |
| 454 | const int *c2 = src + 4; |
| 455 | unsigned char *d = dst; |
| 456 | |
| 457 | for (i = 0; i < 4; i++, c1++, c2++) { |
| 458 | *d++ = CLAMP((*c1) >> scalebits); |
| 459 | *d++ = CLAMP((*c2) >> scalebits); |
| 460 | } |
| 461 | c1 = src + 12; |
| 462 | d = dst + bytes_per_line; |
| 463 | for (i = 0; i < 4; i++, c1++, c2++) { |
| 464 | *d++ = CLAMP((*c1) >> scalebits); |
| 465 | *d++ = CLAMP((*c2) >> scalebits); |
| 466 | } |
| 467 | #endif |
| 468 | } |
| 469 | |
| 470 | #if ENABLE_BAYER_DECODER |
| 471 | /* |
| 472 | * Format: 8x2 pixels |
| 473 | * . G . G . G . G . G . G . G |
| 474 | * . . . . . . . . . . . . . . |
| 475 | * . G . G . G . G . G . G . G |
| 476 | * . . . . . . . . . . . . . . |
| 477 | * or |
| 478 | * . . . . . . . . . . . . . . |
| 479 | * G . G . G . G . G . G . G . |
| 480 | * . . . . . . . . . . . . . . |
| 481 | * G . G . G . G . G . G . G . |
| 482 | */ |
| 483 | static void copy_image_block_Green(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits) |
| 484 | { |
| 485 | #if UNROLL_LOOP_FOR_COPY |
| 486 | /* Unroll all loops */ |
| 487 | const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE; |
| 488 | unsigned char *d = dst; |
| 489 | const int *c = src; |
| 490 | |
| 491 | d[0] = cm[c[0] >> scalebits]; |
| 492 | d[2] = cm[c[1] >> scalebits]; |
| 493 | d[4] = cm[c[2] >> scalebits]; |
| 494 | d[6] = cm[c[3] >> scalebits]; |
| 495 | d[8] = cm[c[4] >> scalebits]; |
| 496 | d[10] = cm[c[5] >> scalebits]; |
| 497 | d[12] = cm[c[6] >> scalebits]; |
| 498 | d[14] = cm[c[7] >> scalebits]; |
| 499 | |
| 500 | d = dst + bytes_per_line; |
| 501 | d[0] = cm[c[8] >> scalebits]; |
| 502 | d[2] = cm[c[9] >> scalebits]; |
| 503 | d[4] = cm[c[10] >> scalebits]; |
| 504 | d[6] = cm[c[11] >> scalebits]; |
| 505 | d[8] = cm[c[12] >> scalebits]; |
| 506 | d[10] = cm[c[13] >> scalebits]; |
| 507 | d[12] = cm[c[14] >> scalebits]; |
| 508 | d[14] = cm[c[15] >> scalebits]; |
| 509 | #else |
| 510 | int i; |
| 511 | unsigned char *d; |
| 512 | const int *c = src; |
| 513 | |
| 514 | d = dst; |
| 515 | for (i = 0; i < 8; i++, c++) |
| 516 | d[i*2] = CLAMP((*c) >> scalebits); |
| 517 | |
| 518 | d = dst + bytes_per_line; |
| 519 | for (i = 0; i < 8; i++, c++) |
| 520 | d[i*2] = CLAMP((*c) >> scalebits); |
| 521 | #endif |
| 522 | } |
| 523 | #endif |
| 524 | |
| 525 | #if ENABLE_BAYER_DECODER |
| 526 | /* |
| 527 | * Format: 4x4 pixels |
| 528 | * R . R . R . R |
| 529 | * . B . B . B . |
| 530 | * R . R . R . R |
| 531 | * . B . B . B . |
| 532 | */ |
| 533 | static void copy_image_block_RedBlue(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits) |
| 534 | { |
| 535 | #if UNROLL_LOOP_FOR_COPY |
| 536 | /* Unroll all loops */ |
| 537 | const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE; |
| 538 | unsigned char *d = dst; |
| 539 | const int *c = src; |
| 540 | |
| 541 | d[0] = cm[c[0] >> scalebits]; |
| 542 | d[2] = cm[c[1] >> scalebits]; |
| 543 | d[4] = cm[c[2] >> scalebits]; |
| 544 | d[6] = cm[c[3] >> scalebits]; |
| 545 | |
| 546 | d = dst + bytes_per_line; |
| 547 | d[1] = cm[c[4] >> scalebits]; |
| 548 | d[3] = cm[c[5] >> scalebits]; |
| 549 | d[5] = cm[c[6] >> scalebits]; |
| 550 | d[7] = cm[c[7] >> scalebits]; |
| 551 | |
| 552 | d = dst + bytes_per_line*2; |
| 553 | d[0] = cm[c[8] >> scalebits]; |
| 554 | d[2] = cm[c[9] >> scalebits]; |
| 555 | d[4] = cm[c[10] >> scalebits]; |
| 556 | d[6] = cm[c[11] >> scalebits]; |
| 557 | |
| 558 | d = dst + bytes_per_line*3; |
| 559 | d[1] = cm[c[12] >> scalebits]; |
| 560 | d[3] = cm[c[13] >> scalebits]; |
| 561 | d[5] = cm[c[14] >> scalebits]; |
| 562 | d[7] = cm[c[15] >> scalebits]; |
| 563 | #else |
| 564 | int i; |
| 565 | unsigned char *d; |
| 566 | const int *c = src; |
| 567 | |
| 568 | d = dst; |
| 569 | for (i = 0; i < 4; i++, c++) |
| 570 | d[i*2] = CLAMP((*c) >> scalebits); |
| 571 | |
| 572 | d = dst + bytes_per_line; |
| 573 | for (i = 0; i < 4; i++, c++) |
| 574 | d[i*2+1] = CLAMP((*c) >> scalebits); |
| 575 | |
| 576 | d = dst + bytes_per_line*2; |
| 577 | for (i = 0; i < 4; i++, c++) |
| 578 | d[i*2] = CLAMP((*c) >> scalebits); |
| 579 | |
| 580 | d = dst + bytes_per_line*3; |
| 581 | for (i = 0; i < 4; i++, c++) |
| 582 | d[i*2+1] = CLAMP((*c) >> scalebits); |
| 583 | #endif |
| 584 | } |
| 585 | #endif |
| 586 | |
| 587 | /* |
| 588 | * To manage the stream, we keep bits in a 32 bits register. |
| 589 | * fill_nbits(n): fill the reservoir with at least n bits |
| 590 | * skip_bits(n): discard n bits from the reservoir |
| 591 | * get_bits(n): fill the reservoir, returns the first n bits and discard the |
| 592 | * bits from the reservoir. |
| 593 | * __get_nbits(n): faster version of get_bits(n), but asumes that the reservoir |
| 594 | * contains at least n bits. bits returned is discarded. |
| 595 | */ |
| 596 | #define fill_nbits(pdec, nbits_wanted) do { \ |
| 597 | while (pdec->nbits_in_reservoir<(nbits_wanted)) \ |
| 598 | { \ |
| 599 | pdec->reservoir |= (*(pdec->stream)++) << (pdec->nbits_in_reservoir); \ |
| 600 | pdec->nbits_in_reservoir += 8; \ |
| 601 | } \ |
| 602 | } while(0); |
| 603 | |
| 604 | #define skip_nbits(pdec, nbits_to_skip) do { \ |
| 605 | pdec->reservoir >>= (nbits_to_skip); \ |
| 606 | pdec->nbits_in_reservoir -= (nbits_to_skip); \ |
| 607 | } while(0); |
| 608 | |
| 609 | #define get_nbits(pdec, nbits_wanted, result) do { \ |
| 610 | fill_nbits(pdec, nbits_wanted); \ |
| 611 | result = (pdec->reservoir) & ((1U<<(nbits_wanted))-1); \ |
| 612 | skip_nbits(pdec, nbits_wanted); \ |
| 613 | } while(0); |
| 614 | |
| 615 | #define __get_nbits(pdec, nbits_wanted, result) do { \ |
| 616 | result = (pdec->reservoir) & ((1U<<(nbits_wanted))-1); \ |
| 617 | skip_nbits(pdec, nbits_wanted); \ |
| 618 | } while(0); |
| 619 | |
| 620 | #define look_nbits(pdec, nbits_wanted) \ |
| 621 | ((pdec->reservoir) & ((1U<<(nbits_wanted))-1)) |
| 622 | |
| 623 | /* |
| 624 | * Decode a 4x4 pixel block |
| 625 | */ |
| 626 | static void decode_block(struct pwc_dec23_private *pdec, |
| 627 | const unsigned char *ptable0004, |
| 628 | const unsigned char *ptable8004) |
| 629 | { |
| 630 | unsigned int primary_color; |
| 631 | unsigned int channel_v, offset1, op; |
| 632 | int i; |
| 633 | |
| 634 | fill_nbits(pdec, 16); |
| 635 | __get_nbits(pdec, pdec->nbits, primary_color); |
| 636 | |
| 637 | if (look_nbits(pdec,2) == 0) { |
| 638 | skip_nbits(pdec, 2); |
| 639 | /* Very simple, the color is the same for all pixels of the square */ |
| 640 | for (i = 0; i < 16; i++) |
| 641 | pdec->temp_colors[i] = pdec->table_dc00[primary_color]; |
| 642 | |
| 643 | return; |
| 644 | } |
| 645 | |
| 646 | /* This block is encoded with small pattern */ |
| 647 | for (i = 0; i < 16; i++) |
| 648 | pdec->temp_colors[i] = pdec->table_d800[primary_color]; |
| 649 | |
| 650 | __get_nbits(pdec, 3, channel_v); |
| 651 | channel_v = ((channel_v & 1) << 2) | (channel_v & 2) | ((channel_v & 4) >> 2); |
| 652 | |
| 653 | ptable0004 += (channel_v * 128); |
| 654 | ptable8004 += (channel_v * 32); |
| 655 | |
| 656 | offset1 = 0; |
| 657 | do |
| 658 | { |
| 659 | unsigned int htable_idx, rows = 0; |
| 660 | const unsigned int *block; |
| 661 | |
| 662 | /* [ zzzz y x x ] |
| 663 | * xx == 00 :=> end of the block def, remove the two bits from the stream |
| 664 | * yxx == 111 |
| 665 | * yxx == any other value |
| 666 | * |
| 667 | */ |
| 668 | fill_nbits(pdec, 16); |
| 669 | htable_idx = look_nbits(pdec, 6); |
| 670 | op = hash_table_ops[htable_idx * 4]; |
| 671 | |
| 672 | if (op == 2) { |
| 673 | skip_nbits(pdec, 2); |
| 674 | |
| 675 | } else if (op == 1) { |
| 676 | /* 15bits [ xxxx xxxx yyyy 111 ] |
| 677 | * yyy => offset in the table8004 |
| 678 | * xxx => offset in the tabled004 (tree) |
| 679 | */ |
| 680 | unsigned int mask, shift; |
| 681 | unsigned int nbits, col1; |
| 682 | unsigned int yyyy; |
| 683 | |
| 684 | skip_nbits(pdec, 3); |
| 685 | /* offset1 += yyyy */ |
| 686 | __get_nbits(pdec, 4, yyyy); |
| 687 | offset1 += 1 + yyyy; |
| 688 | offset1 &= 0x0F; |
| 689 | nbits = ptable8004[offset1 * 2]; |
| 690 | |
| 691 | /* col1 = xxxx xxxx */ |
| 692 | __get_nbits(pdec, nbits+1, col1); |
| 693 | |
| 694 | /* Bit mask table */ |
| 695 | mask = pdec->table_bitpowermask[nbits][col1]; |
| 696 | shift = ptable8004[offset1 * 2 + 1]; |
| 697 | rows = ((mask << shift) + 0x80) & 0xFF; |
| 698 | |
| 699 | block = pdec->table_subblock[rows]; |
| 700 | for (i = 0; i < 16; i++) |
| 701 | pdec->temp_colors[i] += block[MulIdx[offset1][i]]; |
| 702 | |
| 703 | } else { |
| 704 | /* op == 0 |
| 705 | * offset1 is coded on 3 bits |
| 706 | */ |
| 707 | unsigned int shift; |
| 708 | |
| 709 | offset1 += hash_table_ops [htable_idx * 4 + 2]; |
| 710 | offset1 &= 0x0F; |
| 711 | |
| 712 | rows = ptable0004[offset1 + hash_table_ops [htable_idx * 4 + 3]]; |
| 713 | block = pdec->table_subblock[rows]; |
| 714 | for (i = 0; i < 16; i++) |
| 715 | pdec->temp_colors[i] += block[MulIdx[offset1][i]]; |
| 716 | |
| 717 | shift = hash_table_ops[htable_idx * 4 + 1]; |
| 718 | skip_nbits(pdec, shift); |
| 719 | } |
| 720 | |
| 721 | } while (op != 2); |
| 722 | |
| 723 | } |
| 724 | |
| 725 | static void DecompressBand23(struct pwc_dec23_private *pdec, |
| 726 | const unsigned char *rawyuv, |
| 727 | unsigned char *planar_y, |
| 728 | unsigned char *planar_u, |
| 729 | unsigned char *planar_v, |
| 730 | unsigned int compressed_image_width, |
| 731 | unsigned int real_image_width) |
| 732 | { |
| 733 | int compression_index, nblocks; |
| 734 | const unsigned char *ptable0004; |
| 735 | const unsigned char *ptable8004; |
| 736 | |
| 737 | pdec->reservoir = 0; |
| 738 | pdec->nbits_in_reservoir = 0; |
| 739 | pdec->stream = rawyuv + 1; /* The first byte of the stream is skipped */ |
| 740 | |
| 741 | get_nbits(pdec, 4, compression_index); |
| 742 | |
| 743 | /* pass 1: uncompress Y component */ |
| 744 | nblocks = compressed_image_width / 4; |
| 745 | |
| 746 | ptable0004 = pdec->table_0004_pass1[compression_index]; |
| 747 | ptable8004 = pdec->table_8004_pass1[compression_index]; |
| 748 | |
| 749 | /* Each block decode a square of 4x4 */ |
| 750 | while (nblocks) { |
| 751 | decode_block(pdec, ptable0004, ptable8004); |
| 752 | copy_image_block_Y(pdec->temp_colors, planar_y, real_image_width, pdec->scalebits); |
| 753 | planar_y += 4; |
| 754 | nblocks--; |
| 755 | } |
| 756 | |
| 757 | /* pass 2: uncompress UV component */ |
| 758 | nblocks = compressed_image_width / 8; |
| 759 | |
| 760 | ptable0004 = pdec->table_0004_pass2[compression_index]; |
| 761 | ptable8004 = pdec->table_8004_pass2[compression_index]; |
| 762 | |
| 763 | /* Each block decode a square of 4x4 */ |
| 764 | while (nblocks) { |
| 765 | decode_block(pdec, ptable0004, ptable8004); |
| 766 | copy_image_block_CrCb(pdec->temp_colors, planar_u, real_image_width/2, pdec->scalebits); |
| 767 | |
| 768 | decode_block(pdec, ptable0004, ptable8004); |
| 769 | copy_image_block_CrCb(pdec->temp_colors, planar_v, real_image_width/2, pdec->scalebits); |
| 770 | |
| 771 | planar_v += 8; |
| 772 | planar_u += 8; |
| 773 | nblocks -= 2; |
| 774 | } |
| 775 | |
| 776 | } |
| 777 | |
| 778 | #if ENABLE_BAYER_DECODER |
| 779 | /* |
| 780 | * Size need to be a multiple of 8 in width |
| 781 | * |
| 782 | * Return a block of four line encoded like this: |
| 783 | * |
| 784 | * G R G R G R G R G R G R G R G R |
| 785 | * B G B G B G B G B G B G B G B G |
| 786 | * G R G R G R G R G R G R G R G R |
| 787 | * B G B G B G B G B G B G B G B G |
| 788 | * |
| 789 | */ |
| 790 | static void DecompressBandBayer(struct pwc_dec23_private *pdec, |
Trent Piepho | 657de3c | 2006-06-20 00:30:57 -0300 | [diff] [blame] | 791 | const unsigned char *rawyuv, |
Luc Saillard | 2b455db | 2006-04-24 10:29:46 -0300 | [diff] [blame] | 792 | unsigned char *rgbbayer, |
| 793 | unsigned int compressed_image_width, |
| 794 | unsigned int real_image_width) |
| 795 | { |
| 796 | int compression_index, nblocks; |
| 797 | const unsigned char *ptable0004; |
| 798 | const unsigned char *ptable8004; |
| 799 | unsigned char *dest; |
| 800 | |
| 801 | pdec->reservoir = 0; |
| 802 | pdec->nbits_in_reservoir = 0; |
| 803 | pdec->stream = rawyuv + 1; /* The first byte of the stream is skipped */ |
| 804 | |
| 805 | get_nbits(pdec, 4, compression_index); |
| 806 | |
| 807 | /* pass 1: uncompress RB component */ |
| 808 | nblocks = compressed_image_width / 4; |
| 809 | |
| 810 | ptable0004 = pdec->table_0004_pass1[compression_index]; |
| 811 | ptable8004 = pdec->table_8004_pass1[compression_index]; |
| 812 | dest = rgbbayer; |
| 813 | |
| 814 | /* Each block decode a square of 4x4 */ |
| 815 | while (nblocks) { |
| 816 | decode_block(pdec, ptable0004, ptable8004); |
| 817 | copy_image_block_RedBlue(pdec->temp_colors, rgbbayer, real_image_width, pdec->scalebits); |
| 818 | dest += 8; |
| 819 | nblocks--; |
| 820 | } |
| 821 | |
| 822 | /* pass 2: uncompress G component */ |
| 823 | nblocks = compressed_image_width / 8; |
| 824 | |
| 825 | ptable0004 = pdec->table_0004_pass2[compression_index]; |
| 826 | ptable8004 = pdec->table_8004_pass2[compression_index]; |
| 827 | |
| 828 | /* Each block decode a square of 4x4 */ |
| 829 | while (nblocks) { |
| 830 | decode_block(pdec, ptable0004, ptable8004); |
| 831 | copy_image_block_Green(pdec->temp_colors, rgbbayer+1, real_image_width, pdec->scalebits); |
| 832 | |
| 833 | decode_block(pdec, ptable0004, ptable8004); |
| 834 | copy_image_block_Green(pdec->temp_colors, rgbbayer+real_image_width, real_image_width, pdec->scalebits); |
| 835 | |
| 836 | rgbbayer += 16; |
| 837 | nblocks -= 2; |
| 838 | } |
| 839 | } |
| 840 | #endif |
| 841 | |
| 842 | |
| 843 | /** |
| 844 | * |
| 845 | * Uncompress a pwc23 buffer. |
| 846 | * |
| 847 | * pwc.view: size of the image wanted |
| 848 | * pwc.image: size of the image returned by the camera |
| 849 | * pwc.offset: (x,y) to displayer image in the view |
| 850 | * |
| 851 | * src: raw data |
| 852 | * dst: image output |
| 853 | * flags: PWCX_FLAG_PLANAR or PWCX_FLAG_BAYER |
| 854 | */ |
| 855 | void pwc_dec23_decompress(const struct pwc_device *pwc, |
| 856 | const void *src, |
| 857 | void *dst, |
| 858 | int flags) |
| 859 | { |
| 860 | int bandlines_left, stride, bytes_per_block; |
| 861 | |
| 862 | bandlines_left = pwc->image.y / 4; |
| 863 | bytes_per_block = pwc->view.x * 4; |
| 864 | |
| 865 | if (flags & PWCX_FLAG_BAYER) { |
| 866 | #if ENABLE_BAYER_DECODER |
| 867 | /* RGB Bayer format */ |
| 868 | unsigned char *rgbout; |
| 869 | |
| 870 | stride = pwc->view.x * pwc->offset.y; |
| 871 | rgbout = dst + stride + pwc->offset.x; |
| 872 | |
| 873 | |
| 874 | while (bandlines_left--) { |
| 875 | |
| 876 | DecompressBandBayer(pwc->decompress_data, |
| 877 | src, |
| 878 | rgbout, |
| 879 | pwc->image.x, pwc->view.x); |
| 880 | |
| 881 | src += pwc->vbandlength; |
| 882 | rgbout += bytes_per_block; |
| 883 | |
| 884 | } |
| 885 | #else |
akpm@osdl.org | 7923dee | 2006-05-22 10:31:49 -0300 | [diff] [blame] | 886 | memset(dst, 0, pwc->view.x * pwc->view.y); |
Luc Saillard | 2b455db | 2006-04-24 10:29:46 -0300 | [diff] [blame] | 887 | #endif |
| 888 | |
| 889 | } else { |
| 890 | /* YUV420P image format */ |
| 891 | unsigned char *pout_planar_y; |
| 892 | unsigned char *pout_planar_u; |
| 893 | unsigned char *pout_planar_v; |
| 894 | unsigned int plane_size; |
| 895 | |
| 896 | plane_size = pwc->view.x * pwc->view.y; |
| 897 | |
| 898 | /* offset in Y plane */ |
| 899 | stride = pwc->view.x * pwc->offset.y; |
| 900 | pout_planar_y = dst + stride + pwc->offset.x; |
| 901 | |
| 902 | /* offsets in U/V planes */ |
| 903 | stride = (pwc->view.x * pwc->offset.y) / 4 + pwc->offset.x / 2; |
| 904 | pout_planar_u = dst + plane_size + stride; |
| 905 | pout_planar_v = dst + plane_size + plane_size / 4 + stride; |
| 906 | |
| 907 | while (bandlines_left--) { |
| 908 | |
| 909 | DecompressBand23(pwc->decompress_data, |
| 910 | src, |
| 911 | pout_planar_y, pout_planar_u, pout_planar_v, |
| 912 | pwc->image.x, pwc->view.x); |
| 913 | src += pwc->vbandlength; |
| 914 | pout_planar_y += bytes_per_block; |
| 915 | pout_planar_u += pwc->view.x; |
| 916 | pout_planar_v += pwc->view.x; |
| 917 | |
| 918 | } |
| 919 | |
| 920 | } |
| 921 | |
| 922 | } |
| 923 | |
| 924 | void pwc_dec23_exit(void) |
| 925 | { |
| 926 | /* Do nothing */ |
| 927 | |
| 928 | } |
| 929 | |
| 930 | /** |
| 931 | * Allocate a private structure used by lookup table. |
| 932 | * You must call kfree() to free the memory allocated. |
| 933 | */ |
| 934 | int pwc_dec23_alloc(struct pwc_device *pwc) |
| 935 | { |
| 936 | pwc->decompress_data = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL); |
| 937 | if (pwc->decompress_data == NULL) |
| 938 | return -ENOMEM; |
| 939 | return 0; |
| 940 | } |
| 941 | |
| 942 | /* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */ |