/* * MR97310A decoder * * Copyright (C) 2004 Theodore Kilgore * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #include "libv4lconvert-priv.h" #define CLIP(x) ((x)<0?0:((x)>0xff)?0xff:(x)) /* FIXME not threadsafe */ static int decoder_initialized = 0; static struct { unsigned char is_abs; unsigned char len; signed char val; } table[256]; static void init_mr97310a_decoder(void) { int i; int is_abs, val, len; for (i = 0; i < 256; ++i) { is_abs = 0; val = 0; len = 0; if ((i & 0x80) == 0) { /* code 0 */ val = 0; len = 1; } else if ((i & 0xe0) == 0xc0) { /* code 110 */ val = -3; len = 3; } else if ((i & 0xe0) == 0xa0) { /* code 101 */ val = +3; len = 3; } else if ((i & 0xf0) == 0x80) { /* code 1000 */ val = +7; len = 4; } else if ((i & 0xf0) == 0x90) { /* code 1001 */ val = -7; len = 4; } else if ((i & 0xf0) == 0xf0) { /* code 1111 */ val = -15; len = 4; } else if ((i & 0xf8) == 0xe0) { /* code 11100 */ val = +15; len = 5; } else if ((i & 0xf8) == 0xe8) { /* code 11101xxxxx */ is_abs = 1; val = 0; /* value is calculated later */ len = 5; } table[i].is_abs = is_abs; table[i].val = val; table[i].len = len; } decoder_initialized = 1; } static inline unsigned char get_byte(const unsigned char *inp, unsigned int bitpos) { const unsigned char *addr; addr = inp + (bitpos >> 3); return (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7))); } void v4lconvert_decode_mr97310a(const unsigned char *inp, unsigned char *outp, int width, int height) { int row, col; int val; int bitpos; unsigned char code; unsigned char lp, tp, tlp, trp; if (!decoder_initialized) init_mr97310a_decoder(); /* remove the header */ inp += 12; bitpos = 0; /* main decoding loop */ for (row = 0; row < height; ++row) { col = 0; /* first two pixels in first two rows are stored as raw 8-bit */ if (row < 2) { code = get_byte(inp, bitpos); bitpos += 8; *outp++ = code; code = get_byte(inp, bitpos); bitpos += 8; *outp++ = code; col += 2; } while (col < width) { /* get bitcode */ code = get_byte(inp, bitpos); /* update bit position */ bitpos += table[code].len; /* calculate pixel value */ if (table[code].is_abs) { /* get 5 more bits and use them as absolute value */ code = get_byte(inp, bitpos); val = (code & 0xf8); bitpos += 5; } else { /* value is relative to top or left pixel */ val = table[code].val; lp = outp[-2]; if (row > 1) { tlp = outp[-2*width-2]; tp = outp[-2*width]; trp = outp[-2*width+2]; } if (row < 2) { /* top row: relative to left pixel */ val += lp; } else if (col < 2) { /* left column: relative to top pixel */ /* initial estimate */ val += (2*tp + 2*trp + 1)/4; } else if (col > width - 3) { /* left column: relative to top pixel */ val += (2*tp + 2*tlp + 1)/4; /* main area: average of left and top pixel */ } else { /* initial estimate for predictor */ val += (2*lp + tp + trp + 1)/4; } } /* store pixel */ *outp++ = CLIP(val); ++col; } } return; }