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