// SPDX-License-Identifier: GPL-2.0-or-later
/* Linux driver for Philips webcam
Decompression for chipset version 2 et 3
(C) 2004-2006 Luc Saillard (luc@saillard.org)
NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
driver and thus may have bugs that are not present in the original version.
Please send bug reports and support requests to <luc@saillard.org>.
The decompression routines have been implemented by reverse-engineering the
Nemosoft binary pwcx module. Caveat emptor.
*/
#include "pwc-timon.h"
#include "pwc-kiara.h"
#include "pwc-dec23.h"
#include <linux/string.h>
#include <linux/slab.h>
/*
* USE_LOOKUP_TABLE_TO_CLAMP
* 0: use a C version of this tests: { a<0?0:(a>255?255:a) }
* 1: use a faster lookup table for cpu with a big cache (intel)
*/
#define USE_LOOKUP_TABLE_TO_CLAMP 1
/*
* UNROLL_LOOP_FOR_COPYING_BLOCK
* 0: use a loop for a smaller code (but little slower)
* 1: when unrolling the loop, gcc produces some faster code (perhaps only
* valid for intel processor class). Activating this option, automatically
* activate USE_LOOKUP_TABLE_TO_CLAMP
*/
#define UNROLL_LOOP_FOR_COPY 1
#if UNROLL_LOOP_FOR_COPY
# undef USE_LOOKUP_TABLE_TO_CLAMP
# define USE_LOOKUP_TABLE_TO_CLAMP 1
#endif
static void build_subblock_pattern(struct pwc_dec23_private *pdec)
{
static const unsigned int initial_values[12 ] = {
-0 x526500, -0 x221200, 0 x221200, 0 x526500,
-0 x3de200, 0 x3de200,
-0 x6db480, -0 x2d5d00, 0 x2d5d00, 0 x6db480,
-0 x12c200, 0 x12c200
};
static const unsigned int values_derivated[12 ] = {
0 xa4ca, 0 x4424, -0 x4424, -0 xa4ca,
0 x7bc4, -0 x7bc4,
0 xdb69, 0 x5aba, -0 x5aba, -0 xdb69,
0 x2584, -0 x2584
};
unsigned int temp_values[12 ];
int i, j;
memcpy(temp_values, initial_values, sizeof (initial_values));
for (i = 0 ; i < 256 ; i++) {
for (j = 0 ; j < 12 ; j++) {
pdec->table_subblock[i][j] = temp_values[j];
temp_values[j] += values_derivated[j];
}
}
}
static void build_bit_powermask_table(struct pwc_dec23_private *pdec)
{
unsigned char *p;
unsigned int bit, byte, mask, val;
unsigned int bitpower = 1 ;
for (bit = 0 ; bit < 8 ; bit++) {
mask = bitpower - 1 ;
p = pdec->table_bitpowermask[bit];
for (byte = 0 ; byte < 256 ; byte++) {
val = (byte & mask);
if (byte & bitpower)
val = -val;
*p++ = val;
}
bitpower<<=1 ;
}
}
static void build_table_color(const unsigned int romtable[16 ][8 ],
unsigned char p0004[16 ][1024 ],
unsigned char p8004[16 ][256 ])
{
int compression_mode, j, k, bit, pw;
unsigned char *p0, *p8;
const unsigned int *r;
/* We have 16 compressions tables */
for (compression_mode = 0 ; compression_mode < 16 ; compression_mode++) {
p0 = p0004[compression_mode];
p8 = p8004[compression_mode];
r = romtable[compression_mode];
for (j = 0 ; j < 8 ; j++, r++, p0 += 128 ) {
for (k = 0 ; k < 16 ; k++) {
if (k == 0 )
bit = 1 ;
else if (k >= 1 && k < 3 )
bit = (r[0 ] >> 15 ) & 7 ;
else if (k >= 3 && k < 6 )
bit = (r[0 ] >> 12 ) & 7 ;
else if (k >= 6 && k < 10 )
bit = (r[0 ] >> 9 ) & 7 ;
else if (k >= 10 && k < 13 )
bit = (r[0 ] >> 6 ) & 7 ;
else if (k >= 13 && k < 15 )
bit = (r[0 ] >> 3 ) & 7 ;
else
bit = (r[0 ]) & 7 ;
if (k == 0 )
*p8++ = 8 ;
else
*p8++ = j - bit;
*p8++ = bit;
pw = 1 << bit;
p0[k + 0 x00] = (1 * pw) + 0 x80;
p0[k + 0 x10] = (2 * pw) + 0 x80;
p0[k + 0 x20] = (3 * pw) + 0 x80;
p0[k + 0 x30] = (4 * pw) + 0 x80;
p0[k + 0 x40] = (-1 * pw) + 0 x80;
p0[k + 0 x50] = (-2 * pw) + 0 x80;
p0[k + 0 x60] = (-3 * pw) + 0 x80;
p0[k + 0 x70] = (-4 * pw) + 0 x80;
} /* end of for (k=0; k<16; k++, p8++) */
} /* end of for (j=0; j<8; j++ , table++) */
} /* end of foreach compression_mode */
}
/*
*
*/
static void fill_table_dc00_d800(struct pwc_dec23_private *pdec)
{
#define SCALEBITS 15
#define ONE_HALF (1 UL << (SCALEBITS - 1 ))
int i;
unsigned int offset1 = ONE_HALF;
unsigned int offset2 = 0 x0000;
for (i=0 ; i<256 ; i++) {
pdec->table_dc00[i] = offset1 & ~(ONE_HALF);
pdec->table_d800[i] = offset2;
offset1 += 0 x7bc4;
offset2 += 0 x7bc4;
}
}
/*
* To decode the stream:
* if look_bits(2) == 0: # op == 2 in the lookup table
* skip_bits(2)
* end of the stream
* elif look_bits(3) == 7: # op == 1 in the lookup table
* skip_bits(3)
* yyyy = get_bits(4)
* xxxx = get_bits(8)
* else: # op == 0 in the lookup table
* skip_bits(x)
*
* For speedup processing, we build a lookup table and we takes the first 6 bits.
*
* struct {
* unsigned char op; // operation to execute
* unsigned char bits; // bits use to perform operation
* unsigned char offset1; // offset to add to access in the table_0004 % 16
* unsigned char offset2; // offset to add to access in the table_0004
* }
*
* How to build this table ?
* op == 2 when (i%4)==0
* op == 1 when (i%8)==7
* op == 0 otherwise
*
*/
static const unsigned char hash_table_ops[64 *4 ] = {
0 x02, 0 x00, 0 x00, 0 x00,
0 x00, 0 x03, 0 x01, 0 x00,
0 x00, 0 x04, 0 x01, 0 x10,
0 x00, 0 x06, 0 x01, 0 x30,
0 x02, 0 x00, 0 x00, 0 x00,
0 x00, 0 x03, 0 x01, 0 x40,
0 x00, 0 x05, 0 x01, 0 x20,
0 x01, 0 x00, 0 x00, 0 x00,
0 x02, 0 x00, 0 x00, 0 x00,
0 x00, 0 x03, 0 x01, 0 x00,
0 x00, 0 x04, 0 x01, 0 x50,
0 x00, 0 x05, 0 x02, 0 x00,
0 x02, 0 x00, 0 x00, 0 x00,
0 x00, 0 x03, 0 x01, 0 x40,
0 x00, 0 x05, 0 x03, 0 x00,
0 x01, 0 x00, 0 x00, 0 x00,
0 x02, 0 x00, 0 x00, 0 x00,
0 x00, 0 x03, 0 x01, 0 x00,
0 x00, 0 x04, 0 x01, 0 x10,
0 x00, 0 x06, 0 x02, 0 x10,
0 x02, 0 x00, 0 x00, 0 x00,
0 x00, 0 x03, 0 x01, 0 x40,
0 x00, 0 x05, 0 x01, 0 x60,
0 x01, 0 x00, 0 x00, 0 x00,
0 x02, 0 x00, 0 x00, 0 x00,
0 x00, 0 x03, 0 x01, 0 x00,
0 x00, 0 x04, 0 x01, 0 x50,
0 x00, 0 x05, 0 x02, 0 x40,
0 x02, 0 x00, 0 x00, 0 x00,
0 x00, 0 x03, 0 x01, 0 x40,
0 x00, 0 x05, 0 x03, 0 x40,
0 x01, 0 x00, 0 x00, 0 x00,
0 x02, 0 x00, 0 x00, 0 x00,
0 x00, 0 x03, 0 x01, 0 x00,
0 x00, 0 x04, 0 x01, 0 x10,
0 x00, 0 x06, 0 x01, 0 x70,
0 x02, 0 x00, 0 x00, 0 x00,
0 x00, 0 x03, 0 x01, 0 x40,
0 x00, 0 x05, 0 x01, 0 x20,
0 x01, 0 x00, 0 x00, 0 x00,
0 x02, 0 x00, 0 x00, 0 x00,
0 x00, 0 x03, 0 x01, 0 x00,
0 x00, 0 x04, 0 x01, 0 x50,
0 x00, 0 x05, 0 x02, 0 x00,
0 x02, 0 x00, 0 x00, 0 x00,
0 x00, 0 x03, 0 x01, 0 x40,
0 x00, 0 x05, 0 x03, 0 x00,
0 x01, 0 x00, 0 x00, 0 x00,
0 x02, 0 x00, 0 x00, 0 x00,
0 x00, 0 x03, 0 x01, 0 x00,
0 x00, 0 x04, 0 x01, 0 x10,
0 x00, 0 x06, 0 x02, 0 x50,
0 x02, 0 x00, 0 x00, 0 x00,
0 x00, 0 x03, 0 x01, 0 x40,
0 x00, 0 x05, 0 x01, 0 x60,
0 x01, 0 x00, 0 x00, 0 x00,
0 x02, 0 x00, 0 x00, 0 x00,
0 x00, 0 x03, 0 x01, 0 x00,
0 x00, 0 x04, 0 x01, 0 x50,
0 x00, 0 x05, 0 x02, 0 x40,
0 x02, 0 x00, 0 x00, 0 x00,
0 x00, 0 x03, 0 x01, 0 x40,
0 x00, 0 x05, 0 x03, 0 x40,
0 x01, 0 x00, 0 x00, 0 x00
};
/*
*
*/
static const unsigned int MulIdx[16 ][16 ] = {
{0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,},
{0 , 1 , 2 , 3 , 0 , 1 , 2 , 3 , 0 , 1 , 2 , 3 , 0 , 1 , 2 , 3 ,},
{0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 2 , 2 , 2 , 2 , 3 , 3 , 3 , 3 ,},
{4 , 4 , 4 , 4 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 4 , 4 , 4 , 4 ,},
{6 , 7 , 8 , 9 , 7 , 10 , 11 , 8 , 8 , 11 , 10 , 7 , 9 , 8 , 7 , 6 ,},
{4 , 5 , 5 , 4 , 4 , 5 , 5 , 4 , 4 , 5 , 5 , 4 , 4 , 5 , 5 , 4 ,},
{1 , 3 , 0 , 2 , 1 , 3 , 0 , 2 , 1 , 3 , 0 , 2 , 1 , 3 , 0 , 2 ,},
{0 , 3 , 3 , 0 , 1 , 2 , 2 , 1 , 2 , 1 , 1 , 2 , 3 , 0 , 0 , 3 ,},
{0 , 1 , 2 , 3 , 3 , 2 , 1 , 0 , 3 , 2 , 1 , 0 , 0 , 1 , 2 , 3 ,},
{1 , 1 , 1 , 1 , 3 , 3 , 3 , 3 , 0 , 0 , 0 , 0 , 2 , 2 , 2 , 2 ,},
{7 , 10 , 11 , 8 , 9 , 8 , 7 , 6 , 6 , 7 , 8 , 9 , 8 , 11 , 10 , 7 ,},
{4 , 5 , 5 , 4 , 5 , 4 , 4 , 5 , 5 , 4 , 4 , 5 , 4 , 5 , 5 , 4 ,},
{7 , 9 , 6 , 8 , 10 , 8 , 7 , 11 , 11 , 7 , 8 , 10 , 8 , 6 , 9 , 7 ,},
{1 , 3 , 0 , 2 , 2 , 0 , 3 , 1 , 2 , 0 , 3 , 1 , 1 , 3 , 0 , 2 ,},
{1 , 2 , 2 , 1 , 3 , 0 , 0 , 3 , 0 , 3 , 3 , 0 , 2 , 1 , 1 , 2 ,},
{10 , 8 , 7 , 11 , 8 , 6 , 9 , 7 , 7 , 9 , 6 , 8 , 11 , 7 , 8 , 10 }
};
#if USE_LOOKUP_TABLE_TO_CLAMP
#define MAX_OUTER_CROP_VALUE (512 )
static unsigned char pwc_crop_table[256 + 2 *MAX_OUTER_CROP_VALUE];
#define CLAMP(x) (pwc_crop_table[MAX_OUTER_CROP_VALUE+(x)])
#else
#define CLAMP(x) ((x)>255 ?255 :((x)<0 ?0 :x))
#endif
/* If the type or the command change, we rebuild the lookup table */
void pwc_dec23_init(struct pwc_device *pdev, const unsigned char *cmd)
{
int flags, version, shift, i;
struct pwc_dec23_private *pdec = &pdev->dec23;
mutex_init(&pdec->lock);
if (pdec->last_cmd_valid && pdec->last_cmd == cmd[2 ])
return ;
if (DEVICE_USE_CODEC3(pdev->type)) {
flags = cmd[2 ] & 0 x18;
if (flags == 8 )
pdec->nbits = 7 ; /* More bits, mean more bits to encode the stream, but better quality */
else if (flags == 0 x10)
pdec->nbits = 8 ;
else
pdec->nbits = 6 ;
version = cmd[2 ] >> 5 ;
build_table_color(KiaraRomTable[version][0 ], pdec->table_0004_pass1, pdec->table_8004_pass1);
build_table_color(KiaraRomTable[version][1 ], pdec->table_0004_pass2, pdec->table_8004_pass2);
} else {
flags = cmd[2 ] & 6 ;
if (flags == 2 )
pdec->nbits = 7 ;
else if (flags == 4 )
pdec->nbits = 8 ;
else
pdec->nbits = 6 ;
version = cmd[2 ] >> 3 ;
build_table_color(TimonRomTable[version][0 ], pdec->table_0004_pass1, pdec->table_8004_pass1);
build_table_color(TimonRomTable[version][1 ], pdec->table_0004_pass2, pdec->table_8004_pass2);
}
/* Information can be coded on a variable number of bits but never less than 8 */
shift = 8 - pdec->nbits;
pdec->scalebits = SCALEBITS - shift;
pdec->nbitsmask = 0 xFF >> shift;
fill_table_dc00_d800(pdec);
build_subblock_pattern(pdec);
build_bit_powermask_table(pdec);
#if USE_LOOKUP_TABLE_TO_CLAMP
/* Build the static table to clamp value [0-255] */
for (i=0 ;i<MAX_OUTER_CROP_VALUE;i++)
pwc_crop_table[i] = 0 ;
for (i=0 ; i<256 ; i++)
pwc_crop_table[MAX_OUTER_CROP_VALUE+i] = i;
for (i=0 ; i<MAX_OUTER_CROP_VALUE; i++)
pwc_crop_table[MAX_OUTER_CROP_VALUE+256 +i] = 255 ;
#endif
pdec->last_cmd = cmd[2 ];
pdec->last_cmd_valid = 1 ;
}
/*
* Copy the 4x4 image block to Y plane buffer
*/
static void copy_image_block_Y(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits)
{
#if UNROLL_LOOP_FOR_COPY
const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;
const int *c = src;
unsigned char *d = dst;
*d++ = cm[c[0 ] >> scalebits];
*d++ = cm[c[1 ] >> scalebits];
*d++ = cm[c[2 ] >> scalebits];
*d++ = cm[c[3 ] >> scalebits];
d = dst + bytes_per_line;
*d++ = cm[c[4 ] >> scalebits];
*d++ = cm[c[5 ] >> scalebits];
*d++ = cm[c[6 ] >> scalebits];
*d++ = cm[c[7 ] >> scalebits];
d = dst + bytes_per_line*2 ;
*d++ = cm[c[8 ] >> scalebits];
*d++ = cm[c[9 ] >> scalebits];
*d++ = cm[c[10 ] >> scalebits];
*d++ = cm[c[11 ] >> scalebits];
d = dst + bytes_per_line*3 ;
*d++ = cm[c[12 ] >> scalebits];
*d++ = cm[c[13 ] >> scalebits];
*d++ = cm[c[14 ] >> scalebits];
*d++ = cm[c[15 ] >> scalebits];
#else
int i;
const int *c = src;
unsigned char *d = dst;
for (i = 0 ; i < 4 ; i++, c++)
*d++ = CLAMP((*c) >> scalebits);
d = dst + bytes_per_line;
for (i = 0 ; i < 4 ; i++, c++)
*d++ = CLAMP((*c) >> scalebits);
d = dst + bytes_per_line*2 ;
for (i = 0 ; i < 4 ; i++, c++)
*d++ = CLAMP((*c) >> scalebits);
d = dst + bytes_per_line*3 ;
for (i = 0 ; i < 4 ; i++, c++)
*d++ = CLAMP((*c) >> scalebits);
#endif
}
/*
* Copy the 4x4 image block to a CrCb plane buffer
*
*/
static void copy_image_block_CrCb(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits)
{
#if UNROLL_LOOP_FOR_COPY
/* Unroll all loops */
const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;
const int *c = src;
unsigned char *d = dst;
*d++ = cm[c[0 ] >> scalebits];
*d++ = cm[c[4 ] >> scalebits];
*d++ = cm[c[1 ] >> scalebits];
*d++ = cm[c[5 ] >> scalebits];
*d++ = cm[c[2 ] >> scalebits];
*d++ = cm[c[6 ] >> scalebits];
*d++ = cm[c[3 ] >> scalebits];
*d++ = cm[c[7 ] >> scalebits];
d = dst + bytes_per_line;
*d++ = cm[c[12 ] >> scalebits];
*d++ = cm[c[8 ] >> scalebits];
*d++ = cm[c[13 ] >> scalebits];
*d++ = cm[c[9 ] >> scalebits];
*d++ = cm[c[14 ] >> scalebits];
*d++ = cm[c[10 ] >> scalebits];
*d++ = cm[c[15 ] >> scalebits];
*d++ = cm[c[11 ] >> scalebits];
#else
int i;
const int *c1 = src;
const int *c2 = src + 4 ;
unsigned char *d = dst;
for (i = 0 ; i < 4 ; i++, c1++, c2++) {
*d++ = CLAMP((*c1) >> scalebits);
*d++ = CLAMP((*c2) >> scalebits);
}
c1 = src + 12 ;
d = dst + bytes_per_line;
for (i = 0 ; i < 4 ; i++, c1++, c2++) {
*d++ = CLAMP((*c1) >> scalebits);
*d++ = CLAMP((*c2) >> scalebits);
}
#endif
}
/*
* To manage the stream, we keep bits in a 32 bits register.
* fill_nbits(n): fill the reservoir with at least n bits
* skip_bits(n): discard n bits from the reservoir
* get_bits(n): fill the reservoir, returns the first n bits and discard the
* bits from the reservoir.
* __get_nbits(n): faster version of get_bits(n), but asumes that the reservoir
* contains at least n bits. bits returned is discarded.
*/
#define fill_nbits(pdec, nbits_wanted) do { \
while (pdec->nbits_in_reservoir<(nbits_wanted)) \
{ \
pdec->reservoir |= (*(pdec->stream)++) << (pdec->nbits_in_reservoir); \
pdec->nbits_in_reservoir += 8 ; \
} \
} while (0 );
#define skip_nbits(pdec, nbits_to_skip) do { \
pdec->reservoir >>= (nbits_to_skip); \
pdec->nbits_in_reservoir -= (nbits_to_skip); \
} while (0 );
#define get_nbits(pdec, nbits_wanted, result) do { \
fill_nbits(pdec, nbits_wanted); \
result = (pdec->reservoir) & ((1 U<<(nbits_wanted))-1 ); \
skip_nbits(pdec, nbits_wanted); \
} while (0 );
#define __get_nbits(pdec, nbits_wanted, result) do { \
result = (pdec->reservoir) & ((1 U<<(nbits_wanted))-1 ); \
skip_nbits(pdec, nbits_wanted); \
} while (0 );
#define look_nbits(pdec, nbits_wanted) \
((pdec->reservoir) & ((1 U<<(nbits_wanted))-1 ))
/*
* Decode a 4x4 pixel block
*/
static void decode_block(struct pwc_dec23_private *pdec,
const unsigned char *ptable0004,
const unsigned char *ptable8004)
{
unsigned int primary_color;
unsigned int channel_v, offset1, op;
int i;
fill_nbits(pdec, 16 );
__get_nbits(pdec, pdec->nbits, primary_color);
if (look_nbits(pdec,2 ) == 0 ) {
skip_nbits(pdec, 2 );
/* Very simple, the color is the same for all pixels of the square */
for (i = 0 ; i < 16 ; i++)
pdec->temp_colors[i] = pdec->table_dc00[primary_color];
return ;
}
/* This block is encoded with small pattern */
for (i = 0 ; i < 16 ; i++)
pdec->temp_colors[i] = pdec->table_d800[primary_color];
__get_nbits(pdec, 3 , channel_v);
channel_v = ((channel_v & 1 ) << 2 ) | (channel_v & 2 ) | ((channel_v & 4 ) >> 2 );
ptable0004 += (channel_v * 128 );
ptable8004 += (channel_v * 32 );
offset1 = 0 ;
do
{
unsigned int htable_idx, rows = 0 ;
const unsigned int *block;
/* [ zzzz y x x ]
* xx == 00 :=> end of the block def, remove the two bits from the stream
* yxx == 111
* yxx == any other value
*
*/
fill_nbits(pdec, 16 );
htable_idx = look_nbits(pdec, 6 );
op = hash_table_ops[htable_idx * 4 ];
if (op == 2 ) {
skip_nbits(pdec, 2 );
} else if (op == 1 ) {
/* 15bits [ xxxx xxxx yyyy 111 ]
* yyy => offset in the table8004
* xxx => offset in the tabled004 (tree)
*/
unsigned int mask, shift;
unsigned int nbits, col1;
unsigned int yyyy;
skip_nbits(pdec, 3 );
/* offset1 += yyyy */
__get_nbits(pdec, 4 , yyyy);
offset1 += 1 + yyyy;
offset1 &= 0 x0F;
nbits = ptable8004[offset1 * 2 ];
/* col1 = xxxx xxxx */
__get_nbits(pdec, nbits+1 , col1);
/* Bit mask table */
mask = pdec->table_bitpowermask[nbits][col1];
shift = ptable8004[offset1 * 2 + 1 ];
rows = ((mask << shift) + 0 x80) & 0 xFF;
block = pdec->table_subblock[rows];
for (i = 0 ; i < 16 ; i++)
pdec->temp_colors[i] += block[MulIdx[offset1][i]];
} else {
/* op == 0
* offset1 is coded on 3 bits
*/
unsigned int shift;
offset1 += hash_table_ops [htable_idx * 4 + 2 ];
offset1 &= 0 x0F;
rows = ptable0004[offset1 + hash_table_ops [htable_idx * 4 + 3 ]];
block = pdec->table_subblock[rows];
for (i = 0 ; i < 16 ; i++)
pdec->temp_colors[i] += block[MulIdx[offset1][i]];
shift = hash_table_ops[htable_idx * 4 + 1 ];
skip_nbits(pdec, shift);
}
} while (op != 2 );
}
static void DecompressBand23(struct pwc_dec23_private *pdec,
const unsigned char *rawyuv,
unsigned char *planar_y,
unsigned char *planar_u,
unsigned char *planar_v,
unsigned int compressed_image_width,
unsigned int real_image_width)
{
int compression_index, nblocks;
const unsigned char *ptable0004;
const unsigned char *ptable8004;
pdec->reservoir = 0 ;
pdec->nbits_in_reservoir = 0 ;
pdec->stream = rawyuv + 1 ; /* The first byte of the stream is skipped */
get_nbits(pdec, 4 , compression_index);
/* pass 1: uncompress Y component */
nblocks = compressed_image_width / 4 ;
ptable0004 = pdec->table_0004_pass1[compression_index];
ptable8004 = pdec->table_8004_pass1[compression_index];
/* Each block decode a square of 4x4 */
while (nblocks) {
decode_block(pdec, ptable0004, ptable8004);
copy_image_block_Y(pdec->temp_colors, planar_y, real_image_width, pdec->scalebits);
planar_y += 4 ;
nblocks--;
}
/* pass 2: uncompress UV component */
nblocks = compressed_image_width / 8 ;
ptable0004 = pdec->table_0004_pass2[compression_index];
ptable8004 = pdec->table_8004_pass2[compression_index];
/* Each block decode a square of 4x4 */
while (nblocks) {
decode_block(pdec, ptable0004, ptable8004);
copy_image_block_CrCb(pdec->temp_colors, planar_u, real_image_width/2 , pdec->scalebits);
decode_block(pdec, ptable0004, ptable8004);
copy_image_block_CrCb(pdec->temp_colors, planar_v, real_image_width/2 , pdec->scalebits);
planar_v += 8 ;
planar_u += 8 ;
nblocks -= 2 ;
}
}
/**
* pwc_dec23_decompress - Uncompress a pwc23 buffer.
* @pdev: pointer to pwc device's internal struct
* @src: raw data
* @dst: image output
*/
void pwc_dec23_decompress(struct pwc_device *pdev,
const void *src,
void *dst)
{
int bandlines_left, bytes_per_block;
struct pwc_dec23_private *pdec = &pdev->dec23;
/* YUV420P image format */
unsigned char *pout_planar_y;
unsigned char *pout_planar_u;
unsigned char *pout_planar_v;
unsigned int plane_size;
mutex_lock(&pdec->lock);
bandlines_left = pdev->height / 4 ;
bytes_per_block = pdev->width * 4 ;
plane_size = pdev->height * pdev->width;
pout_planar_y = dst;
pout_planar_u = dst + plane_size;
pout_planar_v = dst + plane_size + plane_size / 4 ;
while (bandlines_left--) {
DecompressBand23(pdec, src,
pout_planar_y, pout_planar_u, pout_planar_v,
pdev->width, pdev->width);
src += pdev->vbandlength;
pout_planar_y += bytes_per_block;
pout_planar_u += pdev->width;
pout_planar_v += pdev->width;
}
mutex_unlock(&pdec->lock);
}
Messung V0.5 in Prozent C=95 H=91 G=92
¤ Dauer der Verarbeitung: 0.17 Sekunden
(vorverarbeitet am 2026-06-08)
¤
*© Formatika GbR, Deutschland