On Thu, 3 Jun 2004 11:48:20 -0400
Alan Cox <[EMAIL PROTECTED]> wrote:
> Why not do it in user space ?
>
> Also are you thinking of JPEG to RGB or JPEG to YUV420 or YUYV or
> YV12 etc - each of which is the right answer depending on which
> video card or further processing isbeing done.
> I've consistently resisted people putting decoder features into
> kernel space - you can't do it well in kernel space (mmx), you
> can't tile it in kernel space for performance. Take a look at
> how alsa has attacked the problem for audio - once you have
> libraries that do the conversions you can keep it all out of
> unswappable kernel memory.
V4L1 lacks the proper interface for decompression to be done in user
space, and none will (re-)write a V4L2 driver or patch the existing
V4L1 applications with new libraries, since a V4L1 driver
(with optional decoder in kernel space) already exists.
That said, it's true that a module in kernel space is not the
_best_ solution, but is actually a _possible_ solution for providing
full support for the features of the chips. Also, given that it would
be optional, why not let the users decide (we can disable it by default)?
The decompressor is (sort of) JPEG to YUV420/YUV422 decoding, but faster,
since frame headers have not to be parsed.
Below is the code (no mmx as you can see)...
Thanks for your opinion.
/***************************************************************************
* Video decoder for the W996[87]CF driver for Linux. *
* *
* Copyright (C) 2003 2004 by Luca Risolia <[EMAIL PROTECTED]> *
* *
* - The IDCT function has been initially taken from the *
* "Small JPEG Decoder Library" v0.93b by Rich Geldreich *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
***************************************************************************/
#include <linux/string.h>
#include <linux/errno.h>
#include <asm/semaphore.h>
#include "w9968cf_decoder.h"
static const unsigned char* datap, * src;
static unsigned char* dest;
static int err;
static unsigned long size;
static DECLARE_MUTEX(w9968cf_decoder_lock);
enum w9968cf_marker {
M_SOF0 = 0xc0,
M_SOI = 0xd8,
M_EOI = 0xd9,
M_SOS = 0xda,
MARKER = 0xff,
NO_MARKER = 0x00
};
static const unsigned char Y_DC_BITS[16] = {
0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static const unsigned char Y_DC_HUFFVAL[12] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b
};
static const unsigned char Y_AC_BITS[16] = {
0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d
};
static const unsigned char Y_AC_HUFFVAL[162] = {
0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
0xf9, 0xfa
};
static const unsigned char UV_DC_BITS[16] = {
0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
};
static const unsigned char UV_DC_HUFFVAL[12] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b
};
static const unsigned char UV_AC_BITS[16] = {
0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77
};
static const unsigned char UV_AC_HUFFVAL[162] = {
0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
0xf9, 0xfa
};
static unsigned char y_dc_huffsize[13],
y_ac_huffsize[163],
uv_dc_huffsize[13],
uv_ac_huffsize[163];
static unsigned int y_dc_huffcode[13],
y_ac_huffcode[163],
uv_dc_huffcode[13],
uv_ac_huffcode[163];
static struct decoder_tables {
int mincode[16],
maxcode[16];
unsigned char valptr[16];
} y_dc_dec_tables, y_ac_dec_tables, uv_dc_dec_tables, uv_ac_dec_tables;
static unsigned char b, cnt;
static int pred, zz[64], dct[64];
static unsigned char de_zz[64] = {
0, 1, 5, 6, 14, 15, 27, 28,
2, 4, 7, 13, 16, 26, 29, 42,
3, 8, 12, 17, 25, 30, 41, 43,
9, 11, 18, 24, 31, 40, 44, 53,
10, 19, 23, 32, 39, 45, 52, 54,
20, 22, 33, 38, 46, 51, 55, 60,
21, 34, 37, 47, 50, 56, 59, 61,
35, 36, 48, 49, 57, 58, 62, 63
};
/****************************************************************************/
static inline unsigned char pop_byte(void)
{
return *datap++;
}
static inline void push_byte(void)
{
datap--;
}
static inline unsigned int pop_word(void)
{
unsigned int* w = (unsigned int*)datap;
datap += 2;
return *w;
}
static inline void skip_bytes(unsigned int n)
{
datap += n;
}
static enum w9968cf_marker get_marker(void)
{
enum w9968cf_marker m = pop_byte();
if (m != MARKER)
return NO_MARKER;
m = pop_byte();
if (m == 0xff) {
push_byte();
return NO_MARKER;
}
return m;
}
static enum w9968cf_marker goto_marker(enum w9968cf_marker marker)
{
enum w9968cf_marker m;
do {
m = get_marker();
if ((datap - src) > size)
return NO_MARKER;
} while (m != marker && m != M_EOI);
return marker;
}
/****************************************************************************/
static void
generate_size_table(const unsigned char BITS[], unsigned char huffsize[])
{
unsigned int i, k = 0, j;
for (i = 1; i <= 16; i++)
for (j = 1; j <= BITS[i-1]; j++)
huffsize[k++] = i;
huffsize[k] = 0;
}
static void
generate_code_table(const unsigned char HUFFSIZE[], unsigned int huffcode[])
{
unsigned int k = 0, si = HUFFSIZE[0];
unsigned int code = 0;
while (HUFFSIZE[k]) {
while (HUFFSIZE[k] == si) {
huffcode[k++] = code;
code++;
}
code <<= 1;
si++;
}
}
static void
generate_decoder_tables(struct decoder_tables* tbls,
const unsigned char BITS[],
const unsigned int HUFFCODE[])
{
unsigned int i, j = 0;
for (i = 0; i < 16; i++)
if (BITS[i] == 0)
tbls->maxcode[i] = ~0;
else {
tbls->valptr[i] = j;
tbls->mincode[i] = HUFFCODE[j];
j += (BITS[i] - 1);
tbls->maxcode[i] = HUFFCODE[j];
j++;
}
}
/****************************************************************************/
static inline unsigned char nextbyte(void)
{
if ((datap - src) > size) {
err = W9968CF_DEC_ERR_BUF_OVERFLOW;
return 0;
}
return *datap++;
}
static unsigned char nextbit(void)
{
unsigned int bit;
if (cnt == 0) {
b = nextbyte();
cnt = 8;
if (b == 0xff)
if (nextbyte() != 0x00) {
err = W9968CF_DEC_ERR_CORRUPTED_DATA;
return 0;
}
}
bit = b >> 7;
cnt--;
b <<= 1;
return bit;
}
static unsigned char
decode(struct decoder_tables* tbls, const unsigned char HUFFVAL[])
{
unsigned int i = 0, j;
int code;
for (code = nextbit(); code > tbls->maxcode[i];
code = (code << 1) + nextbit())
if (i++ == 15) {
err = W9968CF_DEC_ERR_CORRUPTED_DATA;
return 0;
}
j = tbls->valptr[i] + code - tbls->mincode[i];
return HUFFVAL[j];
}
static unsigned int receive(const unsigned char SSSS)
{
unsigned int i = 0, v = 0;
while (i++ != SSSS)
v = (v << 1) + nextbit();
return v;
}
static inline unsigned int extend(const unsigned int V, const unsigned char T)
{
unsigned int vt = (T == 1) ? 1 : 1 << (T - 1);
return (V < vt) ? V + ((-1) << T) + 1 : V;
}
static void
decode_dc_coefficient(struct decoder_tables* tbls,
const unsigned char HUFFVAL[])
{
unsigned char t;
unsigned int diff = 0;
if ((t = decode(tbls, HUFFVAL)) != 0) {
diff = receive(t);
diff = extend(diff, t);
}
zz[0] = (pred += diff);
}
static void
decode_ac_coefficients(struct decoder_tables* tbls,
const unsigned char HUFFVAL[])
{
unsigned int k;
unsigned char rs, ssss, rrrr, r;
memset(&zz[1], 0, 63*sizeof(int));
for (k = 1; k <= 63; k++) {
restart:
rs = decode(tbls, HUFFVAL);
ssss = rs % 16;
rrrr = rs >> 4;
r = rrrr;
if (ssss == 0) {
if (r == 15) {
if ((k += 16) > 63) {
err = W9968CF_DEC_ERR_CORRUPTED_DATA;
return;
}
goto restart;
} else
return;
}
if ((k += r) > 63) {
err = W9968CF_DEC_ERR_CORRUPTED_DATA;
return;
}
zz[k] = receive(ssss);
zz[k] = extend(zz[k], ssss);
}
}
static inline void dezigzag_dequantize(const unsigned char QUANTABLE[])
{
unsigned int i;
for (i = 0; i < 64; i++)
dct[i] = zz[de_zz[i]] * QUANTABLE[i];
}
static void idct(unsigned char* Pout, const unsigned STRIDE)
{
int* Pin;
long tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13,
z1, z2, z3, z4, z5;
int row, dcval, i;
#define DESCALE(x,n) (((x) + ((1L) << ((n)-1))) >> n)
#define CLAMP(i) if ((i) & 0xFF00) (i) = (((~(i)) >> 15) & 0xFF);
for (row = 7, Pin = dct; row >= 0; row--, Pin += 8) {
if ((Pin[1] | Pin[2] | Pin[3] | Pin[4] |
Pin[5] | Pin[6] | Pin[7]) == 0) {
dcval = Pin[0] << 2;
Pin[0] = dcval;
Pin[1] = dcval;
Pin[2] = dcval;
Pin[3] = dcval;
Pin[4] = dcval;
Pin[5] = dcval;
Pin[6] = dcval;
Pin[7] = dcval;
continue;
}
z2 = (long)Pin[2];
z3 = (long)Pin[6];
z1 = (z2 + z3) * 4433L;
tmp2 = z1 + z3 * -15137L;
tmp3 = z1 + z2 * 6270L;
tmp0 = ((long)Pin[0] + (long)Pin[4]) << 13;
tmp1 = ((long)Pin[0] - (long)Pin[4]) << 13;
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
tmp0 = (long)Pin[7];
tmp1 = (long)Pin[5];
tmp2 = (long)Pin[3];
tmp3 = (long)Pin[1];
z1 = tmp0 + tmp3;
z2 = tmp1 + tmp2;
z3 = tmp0 + tmp2;
z4 = tmp1 + tmp3;
z5 = (z3 + z4) * 9633L;
tmp0 = tmp0 * 2446L;
tmp1 = tmp1 * 16819L;
tmp2 = tmp2 * 25172L;
tmp3 = tmp3 * 12299L;
z1 = z1 * -7373L;
z2 = z2 * -20995L;
z3 = z3 * -16069L;
z4 = z4 * -3196L;
z3 += z5;
z4 += z5;
tmp0 += z1 + z3;
tmp1 += z2 + z4;
tmp2 += z2 + z3;
tmp3 += z1 + z4;
Pin[0] = (int)DESCALE(tmp10 + tmp3, 11);
Pin[7] = (int)DESCALE(tmp10 - tmp3, 11);
Pin[1] = (int)DESCALE(tmp11 + tmp2, 11);
Pin[6] = (int)DESCALE(tmp11 - tmp2, 11);
Pin[2] = (int)DESCALE(tmp12 + tmp1, 11);
Pin[5] = (int)DESCALE(tmp12 - tmp1, 11);
Pin[3] = (int)DESCALE(tmp13 + tmp0, 11);
Pin[4] = (int)DESCALE(tmp13 - tmp0, 11);
}
for (row = 7, Pin = dct; row >= 0; row--, Pin++, Pout++) {
if ((Pin[8*1] | Pin[8*2] | Pin[8*3] |
Pin[8*4] | Pin[8*5] | Pin[8*6] | Pin[8*7]) == 0) {
dcval = (int)DESCALE((long)Pin[0], 5);
if ((dcval += 128) < 0)
dcval = 0;
else if (dcval > 255)
dcval = 255;
Pout[STRIDE*0] = (unsigned char)dcval;
Pout[STRIDE*1] = (unsigned char)dcval;
Pout[STRIDE*2] = (unsigned char)dcval;
Pout[STRIDE*3] = (unsigned char)dcval;
Pout[STRIDE*4] = (unsigned char)dcval;
Pout[STRIDE*5] = (unsigned char)dcval;
Pout[STRIDE*6] = (unsigned char)dcval;
Pout[STRIDE*7] = (unsigned char)dcval;
continue;
}
z2 = (long)Pin[8*2];
z3 = (long)Pin[8*6];
z1 = (z2 + z3) * 4433L;
tmp2 = z1 + z3 * -15137L;
tmp3 = z1 + z2 * 6270L;
tmp0 = ((long)Pin[8*0] + (long)Pin[8*4]) << 13;
tmp1 = ((long)Pin[8*0] - (long)Pin[8*4]) << 13;
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
tmp0 = (long)Pin[8*7];
tmp1 = (long)Pin[8*5];
tmp2 = (long)Pin[8*3];
tmp3 = (long)Pin[8*1];
z1 = tmp0 + tmp3;
z2 = tmp1 + tmp2;
z3 = tmp0 + tmp2;
z4 = tmp1 + tmp3;
z5 = (z3 + z4) * 9633L;
tmp0 = tmp0 * 2446L;
tmp1 = tmp1 * 16819L;
tmp2 = tmp2 * 25172L;
tmp3 = tmp3 * 12299L;
z1 = z1 * -7373L;
z2 = z2 * -20995L;
z3 = z3 * -16069L;
z4 = z4 * -3196L;
z3 += z5;
z4 += z5;
tmp0 += z1 + z3;
tmp1 += z2 + z4;
tmp2 += z2 + z3;
tmp3 += z1 + z4;
i = (int)DESCALE(tmp10 + tmp3, 18) + 128;
CLAMP(i)
Pout[STRIDE*0] = (unsigned char)i;
i = (int)DESCALE(tmp10 - tmp3, 18) + 128;
CLAMP(i)
Pout[STRIDE*7] = (unsigned char)i;
i = (int)DESCALE(tmp11 + tmp2, 18) + 128;
CLAMP(i)
Pout[STRIDE*1] = (unsigned char)i;
i = (int)DESCALE(tmp11 - tmp2, 18) + 128;
CLAMP(i)
Pout[STRIDE*6] = (unsigned char)i;
i = (int)DESCALE(tmp12 + tmp1, 18) + 128;
CLAMP(i)
Pout[STRIDE*2] = (unsigned char)i;
i = (int)DESCALE(tmp12 - tmp1, 18) + 128;
CLAMP(i)
Pout[STRIDE*5] = (unsigned char)i;
i = (int)DESCALE(tmp13 + tmp0, 18) + 128;
CLAMP(i)
Pout[STRIDE*3] = (unsigned char)i;
i = (int)DESCALE(tmp13 - tmp0, 18) + 128;
CLAMP(i)
Pout[STRIDE*4] = (unsigned char)i;
}
}
/****************************************************************************/
static void
decode_scan(const unsigned MCUSX, const unsigned MCUSY,
struct decoder_tables* DC_TBLS, struct decoder_tables* AC_TBLS,
const unsigned char DC_HUFFVAL[], const unsigned char AC_HUFFVAL[],
const unsigned char QUANTABLE[])
{
unsigned int i, j;
unsigned char* base;
pred = 0;
cnt = 0;
base = dest;
for (i = 0; i < MCUSY; i++)
for (j = 0; j < MCUSX; j++) {
if (err)
return;
decode_dc_coefficient(DC_TBLS, DC_HUFFVAL);
decode_ac_coefficients(AC_TBLS, AC_HUFFVAL);
dezigzag_dequantize(QUANTABLE);
idct(base + 8*j + 64*MCUSX*i, 8*MCUSX);
dest += 64;
}
}
/****************************************************************************/
void w9968cf_init_decoder(void)
{
generate_size_table(Y_DC_BITS, y_dc_huffsize);
generate_size_table(Y_AC_BITS, y_ac_huffsize);
generate_size_table(UV_DC_BITS, uv_dc_huffsize);
generate_size_table(UV_AC_BITS, uv_ac_huffsize);
generate_code_table(y_dc_huffsize, y_dc_huffcode);
generate_code_table(y_ac_huffsize, y_ac_huffcode);
generate_code_table(uv_dc_huffsize, uv_dc_huffcode);
generate_code_table(uv_ac_huffsize, uv_ac_huffcode);
generate_decoder_tables(&y_dc_dec_tables, Y_DC_BITS, y_dc_huffcode);
generate_decoder_tables(&y_ac_dec_tables, Y_AC_BITS, y_ac_huffcode);
generate_decoder_tables(&uv_dc_dec_tables, UV_DC_BITS, uv_dc_huffcode);
generate_decoder_tables(&uv_ac_dec_tables, UV_AC_BITS, uv_ac_huffcode);
}
int w9968cf_check_headers(const unsigned char* Pin,
const unsigned long BUF_SIZE)
{
const unsigned char* base = Pin;
unsigned int i = 0;
Pin++;
if (*Pin++ != M_SOI)
return W9968CF_DEC_ERR_NO_SOI;
Pin++;
if (*Pin++ != M_SOF0)
return W9968CF_DEC_ERR_NO_SOF0;
Pin += 24;
if (*Pin++ != M_SOS)
return W9968CF_DEC_ERR_NO_SOS;
Pin += 8;
do {
if ((Pin - base) >= BUF_SIZE - 1)
return W9968CF_DEC_ERR_NO_SOS;
else if (*Pin++ == MARKER)
if (*Pin == M_SOS)
i++;
} while (i != 2);
for (;;)
if ((Pin - base) >= BUF_SIZE - 1)
return W9968CF_DEC_ERR_NO_EOI;
else if (*Pin++ == MARKER)
if (*Pin == M_EOI)
break;
return 0;
}
int w9968cf_decode(const char* Pin, const unsigned long BUF_SIZE,
const unsigned WIDTH, const unsigned HEIGHT, char* Pout)
{
unsigned char v;
if (down_interruptible(&w9968cf_decoder_lock))
return -ERESTARTSYS;
datap = Pin;
src = datap;
dest = Pout;
size = BUF_SIZE;
err = 0;
skip_bytes(13);
v = pop_byte() & 0x0f;
skip_bytes(14);
if (pop_byte() != M_SOS) {
up(&w9968cf_decoder_lock);
return W9968CF_DEC_ERR_NO_SOS;
}
skip_bytes(8);
decode_scan(WIDTH/8, HEIGHT/8, &y_dc_dec_tables, &y_ac_dec_tables,
Y_DC_HUFFVAL, Y_AC_HUFFVAL, Y_QUANTABLE);
if (goto_marker(M_SOS) == NO_MARKER) {
up(&w9968cf_decoder_lock);
return W9968CF_DEC_ERR_NO_SOS;
}
skip_bytes(8);
decode_scan(WIDTH/16, HEIGHT/8/v, &uv_dc_dec_tables, &uv_ac_dec_tables,
UV_DC_HUFFVAL, UV_AC_HUFFVAL, UV_QUANTABLE);
if (goto_marker(M_SOS) == NO_MARKER) {
up(&w9968cf_decoder_lock);
return W9968CF_DEC_ERR_NO_SOS;
}
skip_bytes(8);
decode_scan(WIDTH/16, HEIGHT/8/v, &uv_dc_dec_tables, &uv_ac_dec_tables,
UV_DC_HUFFVAL, UV_AC_HUFFVAL, UV_QUANTABLE);
up(&w9968cf_decoder_lock);
return err;
}
-------------------------------------------------------
This SF.Net email is sponsored by the new InstallShield X.
>From Windows to Linux, servers to mobile, InstallShield X is the one
installation-authoring solution that does it all. Learn more and
evaluate today! http://www.installshield.com/Dev2Dev/0504
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel