Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame^] | 1 | /* Linux driver for Philips webcam |
| 2 | Decompression for chipset version 2 et 3 |
| 3 | (C) 2004 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 | #include "pwc-timon.h" |
| 27 | #include "pwc-kiara.h" |
| 28 | #include "pwc-dec23.h" |
| 29 | #include "pwc-ioctl.h" |
| 30 | |
| 31 | #include <linux/string.h> |
| 32 | |
| 33 | /**** |
| 34 | * |
| 35 | * |
| 36 | * |
| 37 | */ |
| 38 | |
| 39 | |
| 40 | static void fill_table_a000(unsigned int *p) |
| 41 | { |
| 42 | static unsigned int initial_values[12] = { |
| 43 | 0xFFAD9B00, 0xFFDDEE00, 0x00221200, 0x00526500, |
| 44 | 0xFFC21E00, 0x003DE200, 0xFF924B80, 0xFFD2A300, |
| 45 | 0x002D5D00, 0x006DB480, 0xFFED3E00, 0x0012C200 |
| 46 | }; |
| 47 | static unsigned int values_derivated[12] = { |
| 48 | 0x0000A4CA, 0x00004424, 0xFFFFBBDC, 0xFFFF5B36, |
| 49 | 0x00007BC4, 0xFFFF843C, 0x0000DB69, 0x00005ABA, |
| 50 | 0xFFFFA546, 0xFFFF2497, 0x00002584, 0xFFFFDA7C |
| 51 | }; |
| 52 | unsigned int temp_values[12]; |
| 53 | int i,j; |
| 54 | |
| 55 | memcpy(temp_values,initial_values,sizeof(initial_values)); |
| 56 | for (i=0;i<256;i++) |
| 57 | { |
| 58 | for (j=0;j<12;j++) |
| 59 | { |
| 60 | *p++ = temp_values[j]; |
| 61 | temp_values[j] += values_derivated[j]; |
| 62 | } |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | static void fill_table_d000(unsigned char *p) |
| 67 | { |
| 68 | int bit,byte; |
| 69 | |
| 70 | for (bit=0; bit<8; bit++) |
| 71 | { |
| 72 | unsigned char bitpower = 1<<bit; |
| 73 | unsigned char mask = bitpower-1; |
| 74 | for (byte=0; byte<256; byte++) |
| 75 | { |
| 76 | if (byte & bitpower) |
| 77 | *p++ = -(byte & mask); |
| 78 | else |
| 79 | *p++ = (byte & mask); |
| 80 | } |
| 81 | } |
| 82 | } |
| 83 | |
| 84 | /* |
| 85 | * |
| 86 | * Kiara: 0 <= ver <= 7 |
| 87 | * Timon: 0 <= ver <= 15 |
| 88 | * |
| 89 | */ |
| 90 | static void fill_table_color(unsigned int version, const unsigned int *romtable, |
| 91 | unsigned char *p0004, |
| 92 | unsigned char *p8004) |
| 93 | { |
| 94 | const unsigned int *table; |
| 95 | unsigned char *p0, *p8; |
| 96 | int i,j,k; |
| 97 | int dl,bit,pw; |
| 98 | |
| 99 | romtable += version*256; |
| 100 | |
| 101 | for (i=0; i<2; i++) |
| 102 | { |
| 103 | table = romtable + i*128; |
| 104 | |
| 105 | for (dl=0; dl<16; dl++) |
| 106 | { |
| 107 | p0 = p0004 + (i<<14) + (dl<<10); |
| 108 | p8 = p8004 + (i<<12) + (dl<<8); |
| 109 | |
| 110 | for (j=0; j<8; j++ , table++, p0+=128) |
| 111 | { |
| 112 | for (k=0; k<16; k++) |
| 113 | { |
| 114 | if (k==0) |
| 115 | bit=1; |
| 116 | else if (k>=1 && k<3) |
| 117 | bit=(table[0]>>15)&7; |
| 118 | else if (k>=3 && k<6) |
| 119 | bit=(table[0]>>12)&7; |
| 120 | else if (k>=6 && k<10) |
| 121 | bit=(table[0]>>9)&7; |
| 122 | else if (k>=10 && k<13) |
| 123 | bit=(table[0]>>6)&7; |
| 124 | else if (k>=13 && k<15) |
| 125 | bit=(table[0]>>3)&7; |
| 126 | else |
| 127 | bit=(table[0])&7; |
| 128 | if (k == 0) |
| 129 | *(unsigned char *)p8++ = 8; |
| 130 | else |
| 131 | *(unsigned char *)p8++ = j - bit; |
| 132 | *(unsigned char *)p8++ = bit; |
| 133 | |
| 134 | pw = 1<<bit; |
| 135 | p0[k+0x00] = (1*pw) + 0x80; |
| 136 | p0[k+0x10] = (2*pw) + 0x80; |
| 137 | p0[k+0x20] = (3*pw) + 0x80; |
| 138 | p0[k+0x30] = (4*pw) + 0x80; |
| 139 | p0[k+0x40] = (-pw) + 0x80; |
| 140 | p0[k+0x50] = (2*-pw) + 0x80; |
| 141 | p0[k+0x60] = (3*-pw) + 0x80; |
| 142 | p0[k+0x70] = (4*-pw) + 0x80; |
| 143 | } /* end of for (k=0; k<16; k++, p8++) */ |
| 144 | } /* end of for (j=0; j<8; j++ , table++) */ |
| 145 | } /* end of for (dl=0; dl<16; dl++) */ |
| 146 | } /* end of for (i=0; i<2; i++) */ |
| 147 | } |
| 148 | |
| 149 | /* |
| 150 | * precision = (pdev->xx + pdev->yy) |
| 151 | * |
| 152 | */ |
| 153 | static void fill_table_dc00_d800(unsigned int precision, unsigned int *pdc00, unsigned int *pd800) |
| 154 | { |
| 155 | int i; |
| 156 | unsigned int offset1, offset2; |
| 157 | |
| 158 | for(i=0,offset1=0x4000, offset2=0; i<256 ; i++,offset1+=0x7BC4, offset2+=0x7BC4) |
| 159 | { |
| 160 | unsigned int msb = offset1 >> 15; |
| 161 | |
| 162 | if ( msb > 255) |
| 163 | { |
| 164 | if (msb) |
| 165 | msb=0; |
| 166 | else |
| 167 | msb=255; |
| 168 | } |
| 169 | |
| 170 | *pdc00++ = msb << precision; |
| 171 | *pd800++ = offset2; |
| 172 | } |
| 173 | |
| 174 | } |
| 175 | |
| 176 | /* |
| 177 | * struct { |
| 178 | * unsigned char op; // operation to execute |
| 179 | * unsigned char bits; // bits use to perform operation |
| 180 | * unsigned char offset1; // offset to add to access in the table_0004 % 16 |
| 181 | * unsigned char offset2; // offset to add to access in the table_0004 |
| 182 | * } |
| 183 | * |
| 184 | */ |
| 185 | static unsigned int table_ops[] = { |
| 186 | 0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x10, 0x00,0x06,0x01,0x30, |
| 187 | 0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x01,0x20, 0x01,0x00,0x00,0x00, |
| 188 | 0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x50, 0x00,0x05,0x02,0x00, |
| 189 | 0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x03,0x00, 0x01,0x00,0x00,0x00, |
| 190 | 0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x10, 0x00,0x06,0x02,0x10, |
| 191 | 0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x01,0x60, 0x01,0x00,0x00,0x00, |
| 192 | 0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x50, 0x00,0x05,0x02,0x40, |
| 193 | 0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x03,0x40, 0x01,0x00,0x00,0x00, |
| 194 | 0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x10, 0x00,0x06,0x01,0x70, |
| 195 | 0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x01,0x20, 0x01,0x00,0x00,0x00, |
| 196 | 0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x50, 0x00,0x05,0x02,0x00, |
| 197 | 0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x03,0x00, 0x01,0x00,0x00,0x00, |
| 198 | 0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x10, 0x00,0x06,0x02,0x50, |
| 199 | 0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x01,0x60, 0x01,0x00,0x00,0x00, |
| 200 | 0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x50, 0x00,0x05,0x02,0x40, |
| 201 | 0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x03,0x40, 0x01,0x00,0x00,0x00 |
| 202 | }; |
| 203 | |
| 204 | /* |
| 205 | * TODO: multiply by 4 all values |
| 206 | * |
| 207 | */ |
| 208 | static unsigned int MulIdx[256] = { |
| 209 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 210 | 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, |
| 211 | 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, |
| 212 | 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, |
| 213 | 6, 7, 8, 9, 7,10,11, 8, 8,11,10, 7, 9, 8, 7, 6, |
| 214 | 4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4, |
| 215 | 1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2, |
| 216 | 0, 3, 3, 0, 1, 2, 2, 1, 2, 1, 1, 2, 3, 0, 0, 3, |
| 217 | 0, 1, 2, 3, 3, 2, 1, 0, 3, 2, 1, 0, 0, 1, 2, 3, |
| 218 | 1, 1, 1, 1, 3, 3, 3, 3, 0, 0, 0, 0, 2, 2, 2, 2, |
| 219 | 7,10,11, 8, 9, 8, 7, 6, 6, 7, 8, 9, 8,11,10, 7, |
| 220 | 4, 5, 5, 4, 5, 4, 4, 5, 5, 4, 4, 5, 4, 5, 5, 4, |
| 221 | 7, 9, 6, 8,10, 8, 7,11,11, 7, 8,10, 8, 6, 9, 7, |
| 222 | 1, 3, 0, 2, 2, 0, 3, 1, 2, 0, 3, 1, 1, 3, 0, 2, |
| 223 | 1, 2, 2, 1, 3, 0, 0, 3, 0, 3, 3, 0, 2, 1, 1, 2, |
| 224 | 10, 8, 7,11, 8, 6, 9, 7, 7, 9, 6, 8,11, 7, 8,10 |
| 225 | }; |
| 226 | |
| 227 | |
| 228 | |
| 229 | void pwc_dec23_init(int type, int release, unsigned char *mode, void *data) |
| 230 | { |
| 231 | int flags; |
| 232 | struct pwc_dec23_private *pdev = data; |
| 233 | release = release; |
| 234 | |
| 235 | switch (type) |
| 236 | { |
| 237 | case 720: |
| 238 | case 730: |
| 239 | case 740: |
| 240 | case 750: |
| 241 | flags = mode[2]&0x18; /* our: flags = 8, mode[2]==e8 */ |
| 242 | if (flags==8) |
| 243 | pdev->zz = 7; |
| 244 | else if (flags==0x10) |
| 245 | pdev->zz = 8; |
| 246 | else |
| 247 | pdev->zz = 6; |
| 248 | flags = mode[2]>>5; /* our: 7 */ |
| 249 | |
| 250 | fill_table_color(flags, (unsigned int *)KiaraRomTable, pdev->table_0004, pdev->table_8004); |
| 251 | break; |
| 252 | |
| 253 | |
| 254 | case 675: |
| 255 | case 680: |
| 256 | case 690: |
| 257 | flags = mode[2]&6; |
| 258 | if (flags==2) |
| 259 | pdev->zz = 7; |
| 260 | else if (flags==4) |
| 261 | pdev->zz = 8; |
| 262 | else |
| 263 | pdev->zz = 6; |
| 264 | flags = mode[2]>>3; |
| 265 | |
| 266 | fill_table_color(flags, (unsigned int *)TimonRomTable, pdev->table_0004, pdev->table_8004); |
| 267 | break; |
| 268 | |
| 269 | default: |
| 270 | /* Not supported */ |
| 271 | return; |
| 272 | } |
| 273 | |
| 274 | /* * * * ** */ |
| 275 | pdev->xx = 8 - pdev->zz; |
| 276 | pdev->yy = 15 - pdev->xx; |
| 277 | pdev->zzmask = 0xFF>>pdev->xx; |
| 278 | //pdev->zzmask = (1U<<pdev->zz)-1; |
| 279 | |
| 280 | |
| 281 | fill_table_dc00_d800(pdev->xx + pdev->yy, pdev->table_dc00, pdev->table_d800); |
| 282 | fill_table_a000(pdev->table_a004); |
| 283 | fill_table_d000(pdev->table_d004); |
| 284 | } |
| 285 | |
| 286 | |
| 287 | /* |
| 288 | * To manage the stream, we keep in a 32 bits variables, |
| 289 | * the next bits in the stream. fill_reservoir() add to |
| 290 | * the reservoir at least wanted nbits. |
| 291 | * |
| 292 | * |
| 293 | */ |
| 294 | #define fill_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted) do { \ |
| 295 | while (nbits_in_reservoir<nbits_wanted) \ |
| 296 | { \ |
| 297 | reservoir |= (*(stream)++) << nbits_in_reservoir; \ |
| 298 | nbits_in_reservoir+=8; \ |
| 299 | } \ |
| 300 | } while(0); |
| 301 | |
| 302 | #define get_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted,result) do { \ |
| 303 | fill_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted); \ |
| 304 | result = (reservoir) & ((1U<<nbits_wanted)-1); \ |
| 305 | reservoir >>= nbits_wanted; \ |
| 306 | nbits_in_reservoir -= nbits_wanted; \ |
| 307 | } while(0); |
| 308 | |
| 309 | |
| 310 | |
| 311 | static void DecompressBand23(const struct pwc_dec23_private *pdev, |
| 312 | const unsigned char *rawyuv, |
| 313 | unsigned char *planar_y, |
| 314 | unsigned char *planar_u, |
| 315 | unsigned char *planar_v, |
| 316 | unsigned int image_x, /* aka number of pixels wanted ??? */ |
| 317 | unsigned int pixels_per_line, /* aka number of pixels per line */ |
| 318 | int flags) |
| 319 | { |
| 320 | |
| 321 | |
| 322 | unsigned int reservoir, nbits_in_reservoir; |
| 323 | int first_4_bits; |
| 324 | unsigned int bytes_per_channel; |
| 325 | int line_size; /* size of the line (4Y+U+V) */ |
| 326 | int passes; |
| 327 | const unsigned char *ptable0004, *ptable8004; |
| 328 | |
| 329 | int even_line; |
| 330 | unsigned int temp_colors[16]; |
| 331 | int nblocks; |
| 332 | |
| 333 | const unsigned char *stream; |
| 334 | unsigned char *dest_y, *dest_u=NULL, *dest_v=NULL; |
| 335 | unsigned int offset_to_plane_u, offset_to_plane_v; |
| 336 | |
| 337 | int i; |
| 338 | |
| 339 | |
| 340 | reservoir = 0; |
| 341 | nbits_in_reservoir = 0; |
| 342 | stream = rawyuv+1; /* The first byte of the stream is skipped */ |
| 343 | even_line = 1; |
| 344 | |
| 345 | get_nbits(reservoir,nbits_in_reservoir,stream,4,first_4_bits); |
| 346 | |
| 347 | line_size = pixels_per_line*3; |
| 348 | |
| 349 | for (passes=0;passes<2;passes++) |
| 350 | { |
| 351 | if (passes==0) |
| 352 | { |
| 353 | bytes_per_channel = pixels_per_line; |
| 354 | dest_y = planar_y; |
| 355 | nblocks = image_x/4; |
| 356 | } |
| 357 | else |
| 358 | { |
| 359 | /* Format planar: All Y, then all U, then all V */ |
| 360 | bytes_per_channel = pixels_per_line/2; |
| 361 | dest_u = planar_u; |
| 362 | dest_v = planar_v; |
| 363 | dest_y = dest_u; |
| 364 | nblocks = image_x/8; |
| 365 | } |
| 366 | |
| 367 | offset_to_plane_u = bytes_per_channel*2; |
| 368 | offset_to_plane_v = bytes_per_channel*3; |
| 369 | /* |
| 370 | printf("bytes_per_channel = %d\n",bytes_per_channel); |
| 371 | printf("offset_to_plane_u = %d\n",offset_to_plane_u); |
| 372 | printf("offset_to_plane_v = %d\n",offset_to_plane_v); |
| 373 | */ |
| 374 | |
| 375 | while (nblocks-->0) |
| 376 | { |
| 377 | unsigned int gray_index; |
| 378 | |
| 379 | fill_nbits(reservoir,nbits_in_reservoir,stream,16); |
| 380 | gray_index = reservoir & pdev->zzmask; |
| 381 | reservoir >>= pdev->zz; |
| 382 | nbits_in_reservoir -= pdev->zz; |
| 383 | |
| 384 | fill_nbits(reservoir,nbits_in_reservoir,stream,2); |
| 385 | |
| 386 | if ( (reservoir & 3) == 0) |
| 387 | { |
| 388 | reservoir>>=2; |
| 389 | nbits_in_reservoir-=2; |
| 390 | for (i=0;i<16;i++) |
| 391 | temp_colors[i] = pdev->table_dc00[gray_index]; |
| 392 | |
| 393 | } |
| 394 | else |
| 395 | { |
| 396 | unsigned int channel_v, offset1; |
| 397 | |
| 398 | /* swap bit 0 and 2 of offset_OR */ |
| 399 | channel_v = ((reservoir & 1) << 2) | (reservoir & 2) | ((reservoir & 4)>>2); |
| 400 | reservoir>>=3; |
| 401 | nbits_in_reservoir-=3; |
| 402 | |
| 403 | for (i=0;i<16;i++) |
| 404 | temp_colors[i] = pdev->table_d800[gray_index]; |
| 405 | |
| 406 | ptable0004 = pdev->table_0004 + (passes*16384) + (first_4_bits*1024) + (channel_v*128); |
| 407 | ptable8004 = pdev->table_8004 + (passes*4096) + (first_4_bits*256) + (channel_v*32); |
| 408 | |
| 409 | offset1 = 0; |
| 410 | while(1) |
| 411 | { |
| 412 | unsigned int index_in_table_ops, op, rows=0; |
| 413 | fill_nbits(reservoir,nbits_in_reservoir,stream,16); |
| 414 | |
| 415 | /* mode is 0,1 or 2 */ |
| 416 | index_in_table_ops = (reservoir&0x3F); |
| 417 | op = table_ops[ index_in_table_ops*4 ]; |
| 418 | if (op == 2) |
| 419 | { |
| 420 | reservoir >>= 2; |
| 421 | nbits_in_reservoir -= 2; |
| 422 | break; /* exit the while(1) */ |
| 423 | } |
| 424 | if (op == 0) |
| 425 | { |
| 426 | unsigned int shift; |
| 427 | |
| 428 | offset1 = (offset1 + table_ops[index_in_table_ops*4+2]) & 0x0F; |
| 429 | shift = table_ops[ index_in_table_ops*4+1 ]; |
| 430 | reservoir >>= shift; |
| 431 | nbits_in_reservoir -= shift; |
| 432 | rows = ptable0004[ offset1 + table_ops[index_in_table_ops*4+3] ]; |
| 433 | } |
| 434 | if (op == 1) |
| 435 | { |
| 436 | /* 10bits [ xxxx xxxx yyyy 000 ] |
| 437 | * yyy => offset in the table8004 |
| 438 | * xxx => offset in the tabled004 |
| 439 | */ |
| 440 | unsigned int mask, shift; |
| 441 | unsigned int col1, row1, total_bits; |
| 442 | |
| 443 | offset1 = (offset1 + ((reservoir>>3)&0x0F)+1) & 0x0F; |
| 444 | |
| 445 | col1 = (reservoir>>7) & 0xFF; |
| 446 | row1 = ptable8004 [ offset1*2 ]; |
| 447 | |
| 448 | /* Bit mask table */ |
| 449 | mask = pdev->table_d004[ (row1<<8) + col1 ]; |
| 450 | shift = ptable8004 [ offset1*2 + 1]; |
| 451 | rows = ((mask << shift) + 0x80) & 0xFF; |
| 452 | |
| 453 | total_bits = row1 + 8; |
| 454 | reservoir >>= total_bits; |
| 455 | nbits_in_reservoir -= total_bits; |
| 456 | } |
| 457 | { |
| 458 | const unsigned int *table_a004 = pdev->table_a004 + rows*12; |
| 459 | unsigned int *poffset = MulIdx + offset1*16; /* 64/4 (int) */ |
| 460 | for (i=0;i<16;i++) |
| 461 | { |
| 462 | temp_colors[i] += table_a004[ *poffset ]; |
| 463 | poffset++; |
| 464 | } |
| 465 | } |
| 466 | } |
| 467 | } |
| 468 | #define USE_SIGNED_INT_FOR_COLOR |
| 469 | #ifdef USE_SIGNED_INT_FOR_COLOR |
| 470 | # define CLAMP(x) ((x)>255?255:((x)<0?0:x)) |
| 471 | #else |
| 472 | # define CLAMP(x) ((x)>255?255:x) |
| 473 | #endif |
| 474 | |
| 475 | if (passes == 0) |
| 476 | { |
| 477 | #ifdef USE_SIGNED_INT_FOR_COLOR |
| 478 | const int *c = temp_colors; |
| 479 | #else |
| 480 | const unsigned int *c = temp_colors; |
| 481 | #endif |
| 482 | unsigned char *d; |
| 483 | |
| 484 | d = dest_y; |
| 485 | for (i=0;i<4;i++,c++) |
| 486 | *d++ = CLAMP((*c) >> pdev->yy); |
| 487 | |
| 488 | d = dest_y + bytes_per_channel; |
| 489 | for (i=0;i<4;i++,c++) |
| 490 | *d++ = CLAMP((*c) >> pdev->yy); |
| 491 | |
| 492 | d = dest_y + offset_to_plane_u; |
| 493 | for (i=0;i<4;i++,c++) |
| 494 | *d++ = CLAMP((*c) >> pdev->yy); |
| 495 | |
| 496 | d = dest_y + offset_to_plane_v; |
| 497 | for (i=0;i<4;i++,c++) |
| 498 | *d++ = CLAMP((*c) >> pdev->yy); |
| 499 | |
| 500 | dest_y += 4; |
| 501 | } |
| 502 | else if (passes == 1) |
| 503 | { |
| 504 | #ifdef USE_SIGNED_INT_FOR_COLOR |
| 505 | int *c1 = temp_colors; |
| 506 | int *c2 = temp_colors+4; |
| 507 | #else |
| 508 | unsigned int *c1 = temp_colors; |
| 509 | unsigned int *c2 = temp_colors+4; |
| 510 | #endif |
| 511 | unsigned char *d; |
| 512 | |
| 513 | d = dest_y; |
| 514 | for (i=0;i<4;i++,c1++,c2++) |
| 515 | { |
| 516 | *d++ = CLAMP((*c1) >> pdev->yy); |
| 517 | *d++ = CLAMP((*c2) >> pdev->yy); |
| 518 | } |
| 519 | c1 = temp_colors+12; |
| 520 | //c2 = temp_colors+8; |
| 521 | d = dest_y + bytes_per_channel; |
| 522 | for (i=0;i<4;i++,c1++,c2++) |
| 523 | { |
| 524 | *d++ = CLAMP((*c1) >> pdev->yy); |
| 525 | *d++ = CLAMP((*c2) >> pdev->yy); |
| 526 | } |
| 527 | |
| 528 | if (even_line) /* Each line, swap u/v */ |
| 529 | { |
| 530 | even_line=0; |
| 531 | dest_y = dest_v; |
| 532 | dest_u += 8; |
| 533 | } |
| 534 | else |
| 535 | { |
| 536 | even_line=1; |
| 537 | dest_y = dest_u; |
| 538 | dest_v += 8; |
| 539 | } |
| 540 | } |
| 541 | |
| 542 | } /* end of while (nblocks-->0) */ |
| 543 | |
| 544 | } /* end of for (passes=0;passes<2;passes++) */ |
| 545 | |
| 546 | } |
| 547 | |
| 548 | |
| 549 | /** |
| 550 | * |
| 551 | * image: size of the image wanted |
| 552 | * view : size of the image returned by the camera |
| 553 | * offset: (x,y) to displayer image in the view |
| 554 | * |
| 555 | * src: raw data |
| 556 | * dst: image output |
| 557 | * flags: PWCX_FLAG_PLANAR |
| 558 | * pdev: private buffer |
| 559 | * bandlength: |
| 560 | * |
| 561 | */ |
| 562 | void pwc_dec23_decompress(const struct pwc_coord *image, |
| 563 | const struct pwc_coord *view, |
| 564 | const struct pwc_coord *offset, |
| 565 | const void *src, |
| 566 | void *dst, |
| 567 | int flags, |
| 568 | const void *data, |
| 569 | int bandlength) |
| 570 | { |
| 571 | const struct pwc_dec23_private *pdev = data; |
| 572 | unsigned char *pout, *pout_planar_y=NULL, *pout_planar_u=NULL, *pout_planar_v=NULL; |
| 573 | int i,n,stride,pixel_size; |
| 574 | |
| 575 | |
| 576 | if (flags & PWCX_FLAG_BAYER) |
| 577 | { |
| 578 | pout = dst + (view->x * offset->y) + offset->x; |
| 579 | pixel_size = view->x * 4; |
| 580 | } |
| 581 | else |
| 582 | { |
| 583 | n = view->x * view->y; |
| 584 | |
| 585 | /* offset in Y plane */ |
| 586 | stride = view->x * offset->y; |
| 587 | pout_planar_y = dst + stride + offset->x; |
| 588 | |
| 589 | /* offsets in U/V planes */ |
| 590 | stride = (view->x * offset->y)/4 + offset->x/2; |
| 591 | pout_planar_u = dst + n + + stride; |
| 592 | pout_planar_v = dst + n + n/4 + stride; |
| 593 | |
| 594 | pixel_size = view->x * 4; |
| 595 | } |
| 596 | |
| 597 | |
| 598 | for (i=0;i<image->y;i+=4) |
| 599 | { |
| 600 | if (flags & PWCX_FLAG_BAYER) |
| 601 | { |
| 602 | //TODO: |
| 603 | //DecompressBandBayer(pdev,src,pout,image.x,view->x,flags); |
| 604 | src += bandlength; |
| 605 | pout += pixel_size; |
| 606 | } |
| 607 | else |
| 608 | { |
| 609 | DecompressBand23(pdev,src,pout_planar_y,pout_planar_u,pout_planar_v,image->x,view->x,flags); |
| 610 | src += bandlength; |
| 611 | pout_planar_y += pixel_size; |
| 612 | pout_planar_u += view->x; |
| 613 | pout_planar_v += view->x; |
| 614 | } |
| 615 | } |
| 616 | } |
| 617 | |
| 618 | void pwc_dec23_exit(void) |
| 619 | { |
| 620 | /* Do nothing */ |
| 621 | |
| 622 | } |
| 623 | |