📄 pwc-dec23.c
字号:
* . G . G . G . G . G . G . G * . . . . . . . . . . . . . . * . G . G . G . G . G . G . G * . . . . . . . . . . . . . . * or * . . . . . . . . . . . . . . * G . G . G . G . G . G . G . * . . . . . . . . . . . . . . * G . G . G . G . G . G . G .*/static void copy_image_block_Green(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; unsigned char *d = dst; const int *c = src; d[0] = cm[c[0] >> scalebits]; d[2] = cm[c[1] >> scalebits]; d[4] = cm[c[2] >> scalebits]; d[6] = cm[c[3] >> scalebits]; d[8] = cm[c[4] >> scalebits]; d[10] = cm[c[5] >> scalebits]; d[12] = cm[c[6] >> scalebits]; d[14] = cm[c[7] >> scalebits]; d = dst + bytes_per_line; d[0] = cm[c[8] >> scalebits]; d[2] = cm[c[9] >> scalebits]; d[4] = cm[c[10] >> scalebits]; d[6] = cm[c[11] >> scalebits]; d[8] = cm[c[12] >> scalebits]; d[10] = cm[c[13] >> scalebits]; d[12] = cm[c[14] >> scalebits]; d[14] = cm[c[15] >> scalebits];#else int i; unsigned char *d; const int *c = src; d = dst; for (i = 0; i < 8; i++, c++) d[i*2] = CLAMP((*c) >> scalebits); d = dst + bytes_per_line; for (i = 0; i < 8; i++, c++) d[i*2] = CLAMP((*c) >> scalebits);#endif}#endif#if ENABLE_BAYER_DECODER/* * Format: 4x4 pixels * R . R . R . R * . B . B . B . * R . R . R . R * . B . B . B . */static void copy_image_block_RedBlue(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; unsigned char *d = dst; const int *c = src; d[0] = cm[c[0] >> scalebits]; d[2] = cm[c[1] >> scalebits]; d[4] = cm[c[2] >> scalebits]; d[6] = cm[c[3] >> scalebits]; d = dst + bytes_per_line; d[1] = cm[c[4] >> scalebits]; d[3] = cm[c[5] >> scalebits]; d[5] = cm[c[6] >> scalebits]; d[7] = cm[c[7] >> scalebits]; d = dst + bytes_per_line*2; d[0] = cm[c[8] >> scalebits]; d[2] = cm[c[9] >> scalebits]; d[4] = cm[c[10] >> scalebits]; d[6] = cm[c[11] >> scalebits]; d = dst + bytes_per_line*3; d[1] = cm[c[12] >> scalebits]; d[3] = cm[c[13] >> scalebits]; d[5] = cm[c[14] >> scalebits]; d[7] = cm[c[15] >> scalebits];#else int i; unsigned char *d; const int *c = src; d = dst; for (i = 0; i < 4; i++, c++) d[i*2] = CLAMP((*c) >> scalebits); d = dst + bytes_per_line; for (i = 0; i < 4; i++, c++) d[i*2+1] = CLAMP((*c) >> scalebits); d = dst + bytes_per_line*2; for (i = 0; i < 4; i++, c++) d[i*2] = CLAMP((*c) >> scalebits); d = dst + bytes_per_line*3; for (i = 0; i < 4; i++, c++) d[i*2+1] = CLAMP((*c) >> scalebits);#endif}#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) & ((1U<<(nbits_wanted))-1); \ skip_nbits(pdec, nbits_wanted); \} while(0);#define __get_nbits(pdec, nbits_wanted, result) do { \ result = (pdec->reservoir) & ((1U<<(nbits_wanted))-1); \ skip_nbits(pdec, nbits_wanted); \} while(0);#define look_nbits(pdec, nbits_wanted) \ ((pdec->reservoir) & ((1U<<(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 &= 0x0F; 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) + 0x80) & 0xFF; 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 &= 0x0F; 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; }}#if ENABLE_BAYER_DECODER/* * Size need to be a multiple of 8 in width * * Return a block of four line encoded like this: * * G R G R G R G R G R G R G R G R * B G B G B G B G B G B G B G B G * G R G R G R G R G R G R G R G R * B G B G B G B G B G B G B G B G * */static void DecompressBandBayer(struct pwc_dec23_private *pdec, const unsigned char *rawyuv, unsigned char *rgbbayer, unsigned int compressed_image_width, unsigned int real_image_width){ int compression_index, nblocks; const unsigned char *ptable0004; const unsigned char *ptable8004; unsigned char *dest; 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 RB component */ nblocks = compressed_image_width / 4; ptable0004 = pdec->table_0004_pass1[compression_index]; ptable8004 = pdec->table_8004_pass1[compression_index]; dest = rgbbayer; /* Each block decode a square of 4x4 */ while (nblocks) { decode_block(pdec, ptable0004, ptable8004); copy_image_block_RedBlue(pdec->temp_colors, rgbbayer, real_image_width, pdec->scalebits); dest += 8; nblocks--; } /* pass 2: uncompress G 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_Green(pdec->temp_colors, rgbbayer+1, real_image_width, pdec->scalebits); decode_block(pdec, ptable0004, ptable8004); copy_image_block_Green(pdec->temp_colors, rgbbayer+real_image_width, real_image_width, pdec->scalebits); rgbbayer += 16; nblocks -= 2; }}#endif/** * * Uncompress a pwc23 buffer. * * pwc.view: size of the image wanted * pwc.image: size of the image returned by the camera * pwc.offset: (x,y) to displayer image in the view * * src: raw data * dst: image output * flags: PWCX_FLAG_PLANAR or PWCX_FLAG_BAYER */void pwc_dec23_decompress(const struct pwc_device *pwc, const void *src, void *dst, int flags){ int bandlines_left, stride, bytes_per_block; bandlines_left = pwc->image.y / 4; bytes_per_block = pwc->view.x * 4; if (flags & PWCX_FLAG_BAYER) {#if ENABLE_BAYER_DECODER /* RGB Bayer format */ unsigned char *rgbout; stride = pwc->view.x * pwc->offset.y; rgbout = dst + stride + pwc->offset.x; while (bandlines_left--) { DecompressBandBayer(pwc->decompress_data, src, rgbout, pwc->image.x, pwc->view.x); src += pwc->vbandlength; rgbout += bytes_per_block; } #else memcpy(dst, 0, pwc->view.x * pwc->view.y);#endif } else { /* YUV420P image format */ unsigned char *pout_planar_y; unsigned char *pout_planar_u; unsigned char *pout_planar_v; unsigned int plane_size; plane_size = pwc->view.x * pwc->view.y; /* offset in Y plane */ stride = pwc->view.x * pwc->offset.y; pout_planar_y = dst + stride + pwc->offset.x; /* offsets in U/V planes */ stride = (pwc->view.x * pwc->offset.y) / 4 + pwc->offset.x / 2; pout_planar_u = dst + plane_size + stride; pout_planar_v = dst + plane_size + plane_size / 4 + stride; while (bandlines_left--) { DecompressBand23(pwc->decompress_data, src, pout_planar_y, pout_planar_u, pout_planar_v, pwc->image.x, pwc->view.x); src += pwc->vbandlength; pout_planar_y += bytes_per_block; pout_planar_u += pwc->view.x; pout_planar_v += pwc->view.x; } }}void pwc_dec23_exit(void){ /* Do nothing */}/** * Allocate a private structure used by lookup table. * You must call kfree() to free the memory allocated. */int pwc_dec23_alloc(struct pwc_device *pwc){ pwc->decompress_data = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL); if (pwc->decompress_data == NULL) return -ENOMEM; return 0;}/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -