home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Geek 6
/
Geek-006.iso
/
linux
/
video
/
xmovie-1.5.3.tar.gz
/
xmovie-1.5.3.tar
/
xmovie-1.5.3
/
quicktime
/
fastjpg.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-11-29
|
48KB
|
1,800 lines
#include "fastjpg.h"
#include "fastjpgmacro.h"
/* JPEG decoder from XAnim which ended up 10% slower than libjpeg */
/* JPEG MARKERS */
#define M_SOF0 0xc0
#define M_SOF1 0xc1
#define M_SOF2 0xc2
#define M_SOF3 0xc3
#define M_SOF5 0xc5
#define M_SOF6 0xc6
#define M_SOF7 0xc7
#define M_JPG 0xc8
#define M_SOF9 0xc9
#define M_SOF10 0xca
#define M_SOF11 0xcb
#define M_SOF13 0xcd
#define M_SOF14 0xce
#define M_SOF15 0xcf
#define M_DHT 0xc4
#define M_DAC 0xcc
#define M_RST0 0xd0
#define M_RST1 0xd1
#define M_RST2 0xd2
#define M_RST3 0xd3
#define M_RST4 0xd4
#define M_RST5 0xd5
#define M_RST6 0xd6
#define M_RST7 0xd7
#define M_SOI 0xd8
#define M_EOI 0xd9
#define M_SOS 0xda
#define M_DQT 0xdb
#define M_DNL 0xdc
#define M_DRI 0xdd
#define M_DHP 0xde
#define M_EXP 0xdf
#define M_APP0 0xe0
#define M_APP1 0xe1
#define M_APP2 0xe2
#define M_APP3 0xe3
#define M_APP4 0xe4
#define M_APP5 0xe5
#define M_APP6 0xe6
#define M_APP7 0xe7
#define M_APP8 0xe8
#define M_APP9 0xe9
#define M_APP10 0xea
#define M_APP11 0xeb
#define M_APP12 0xec
#define M_APP13 0xed
#define M_APP14 0xee
#define M_APP15 0xef
#define M_JPG0 0xf0
#define M_JPG13 0xfd
#define M_COM 0xfe
#define M_TEM 0x01
#define M_ERROR 0x100
static long JJ_ZAG[DCTSIZE2 + 16] =
{
0, 1, 8, 16, 9, 2, 3, 10,
17, 24, 32, 25, 18, 11, 4, 5,
12, 19, 26, 33, 40, 48, 41, 34,
27, 20, 13, 6, 7, 14, 21, 28,
35, 42, 49, 56, 57, 50, 43, 36,
29, 22, 15, 23, 30, 37, 44, 51,
58, 59, 52, 45, 38, 31, 39, 46,
53, 60, 61, 54, 47, 55, 62, 63,
0, 0, 0, 0, 0, 0, 0, 0, /* extra entries in case k>63 below */
0, 0, 0, 0, 0, 0, 0, 0
};
static char std_luminance_quant_tbl[64] = {
16, 11, 12, 14, 12, 10, 16, 14,
13, 14, 18, 17, 16, 19, 24, 40,
26, 24, 22, 22, 24, 49, 35, 37,
29, 40, 58, 51, 61, 60, 57, 51,
56, 55, 64, 72, 92, 78, 64, 68,
87, 69, 55, 56, 80, 109, 81, 87,
95, 98, 103, 104, 103, 62, 77, 113,
121, 112, 100, 120, 92, 101, 103, 99
};
static char std_chrominance_quant_tbl[64] = {
17, 18, 18, 24, 21, 24, 47, 26,
26, 47, 99, 66, 56, 66, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99
};
int quicktime_fastjpg_skip(quicktime_jpeg_t *jpeg_info, long len)
{
if(len > jpeg_info->chunk_size)
jpeg_info->chunk += jpeg_info->chunk_size;
else
jpeg_info->chunk += len;
return 0;
}
int quicktime_fastjpg_readbyte(quicktime_jpeg_t *jpeg_info)
{
if(jpeg_info->chunk_size > 0)
{
jpeg_info->chunk_size--;
return *(jpeg_info->chunk++);
}
else
return 0;
}
int quicktime_fastjpg_readint16(quicktime_jpeg_t *jpeg_info)
{
if(jpeg_info->chunk_size > 1)
{
jpeg_info->chunk_size -= 2;
jpeg_info->chunk += 2;
return ((int)jpeg_info->chunk[-2] << 8) | (unsigned char)jpeg_info->chunk[-1];
}
else
return 0;
}
int quicktime_fastjpg_readint32(quicktime_jpeg_t *jpeg_info)
{
if(jpeg_info->chunk_size > 3)
{
jpeg_info->chunk_size -= 4;
return (((unsigned long)*(jpeg_info->chunk++) << 24) |
((unsigned long)*(jpeg_info->chunk++) << 16) |
((unsigned long)*(jpeg_info->chunk++) << 8) |
((unsigned long)*(jpeg_info->chunk++)));
}
else
return 0;
}
int quicktime_fastjpg_eof(quicktime_jpeg_t *jpeg_info)
{
if(jpeg_info->chunk_size > 0)
return 0;
else
return 1;
}
int quicktime_fastjpg_init_limittable(quicktime_jpeg_t *jpeg_info)
{
unsigned char *table;
int i;
jpeg_info->jpg_samp_limit = (unsigned char *)malloc((5 * (MAXJSAMPLE + 1) + CENTERJSAMPLE));
jpeg_info->byte_limit = jpeg_info->jpg_samp_limit + MAXJSAMPLE + 1;
/* create negative subscripts for simple table */
table = jpeg_info->jpg_samp_limit + MAXJSAMPLE + 1;
/* First segment of "simple" table: limit[x] = 0 for x < 0 */
memset(table - (MAXJSAMPLE + 1), 0, (MAXJSAMPLE + 1));
/* Main part of "simple" table: limit[x] = x */
for(i = 0; i <= MAXJSAMPLE; i++) table[i] = (unsigned char)i;
/* Point to where post-IDCT table starts */
table += CENTERJSAMPLE;
/* End of simple table, rest of first half of post-IDCT table */
for(i = CENTERJSAMPLE; i < 2 * (MAXJSAMPLE + 1); i++) table[i] = MAXJSAMPLE;
/* Second half of post-IDCT table */
memset(table + (2 * (MAXJSAMPLE + 1)), 0, (2 * (MAXJSAMPLE + 1) - CENTERJSAMPLE));
memcpy(table + (4 * (MAXJSAMPLE + 1) - CENTERJSAMPLE),
(char*)(jpeg_info->jpg_samp_limit + (MAXJSAMPLE + 1)), CENTERJSAMPLE);
}
int quicktime_fastjpg_init_yuv(quicktime_jpeg_t *jpeg_info)
{
long i;
float t_ub, t_vr, t_ug, t_vg;
float t2_ub, t2_vr, t2_ug, t2_vg;
jpeg_info->yuvtabs.YUV_Y_tab = (long*)malloc(256 * sizeof(long));
jpeg_info->yuvtabs.YUV_UB_tab = (long*)malloc(256 * sizeof(long));
jpeg_info->yuvtabs.YUV_VR_tab = (long*)malloc(256 * sizeof(long));
jpeg_info->yuvtabs.YUV_UG_tab = (long*)malloc(256 * sizeof(long));
jpeg_info->yuvtabs.YUV_VG_tab = (long*)malloc(256 * sizeof(long));
t_ub = (1.77200 / 2.0) * (float)(1 << 6) + 0.5;
t_vr = (1.40200 / 2.0) * (float)(1 << 6) + 0.5;
t_ug = (0.34414 / 2.0) * (float)(1 << 6) + 0.5;
t_vg = (0.71414 / 2.0) * (float)(1 << 6) + 0.5;
t2_ub = (1.4 * 1.77200 / 2.0) * (float)(1 << 6) + 0.5;
t2_vr = (1.4 * 1.40200 / 2.0) * (float)(1 << 6) + 0.5;
t2_ug = (1.4 * 0.34414 / 2.0) * (float)(1 << 6) + 0.5;
t2_vg = (1.4 * 0.71414 / 2.0) * (float)(1 << 6) + 0.5;
for(i = 0; i < 256; i++)
{
float x = (float)(2 * i - 255);
jpeg_info->yuvtabs.YUV_UB_tab[i] = (long)(( t_ub * x) + (1 << 5));
jpeg_info->yuvtabs.YUV_VR_tab[i] = (long)(( t_vr * x) + (1 << 5));
jpeg_info->yuvtabs.YUV_UG_tab[i] = (long)((-t_ug * x));
jpeg_info->yuvtabs.YUV_VG_tab[i] = (long)((-t_vg * x) + (1 << 5));
jpeg_info->yuvtabs.YUV_Y_tab[i] = (long)((i << 6) | (i >> 2));
}
return 0;
}
int quicktime_fastjpg_init(quicktime_jpeg_t *jpeg_info)
{
int i;
for(i = 0; i < TOTAL_QUANT_TBLS; i++) jpeg_info->quant_tables[i] = 0;
quicktime_fastjpg_init_limittable(jpeg_info);
jpeg_info->mjpg_kludge = 0;
jpeg_info->jpg_std_DHT_flag = 0;
jpeg_info->mjpa_info.valid = 0;
jpeg_info->yuvbufs.allocated = 0;
jpeg_info->yuvbufs.ybuf = 0;
jpeg_info->yuvbufs.ubuf = 0;
jpeg_info->yuvbufs.vbuf = 0;
quicktime_fastjpg_init_yuv(jpeg_info);
return 0;
}
int quicktime_fastjpg_deleteMCU(quicktime_jpeg_t *jpeg_info)
{
if(jpeg_info->yuvbufs.allocated)
{
free(jpeg_info->yuvbufs.ybuf);
free(jpeg_info->yuvbufs.ubuf);
free(jpeg_info->yuvbufs.vbuf);
}
jpeg_info->yuvbufs.ybuf = 0;
jpeg_info->yuvbufs.ubuf = 0;
jpeg_info->yuvbufs.vbuf = 0;
return 0;
}
int quicktime_fastjpg_delete(quicktime_jpeg_t *jpeg_info)
{
int i;
for(i = 0; i < TOTAL_QUANT_TBLS; i++)
if(jpeg_info->quant_tables[i])
{
free(jpeg_info->quant_tables[i]);
jpeg_info->quant_tables[i] = 0;
}
if(jpeg_info->jpg_samp_limit)
{
free(jpeg_info->jpg_samp_limit);
jpeg_info->jpg_samp_limit = 0;
}
quicktime_fastjpg_deleteMCU(jpeg_info);
free(jpeg_info->yuvtabs.YUV_Y_tab);
free(jpeg_info->yuvtabs.YUV_UB_tab);
free(jpeg_info->yuvtabs.YUV_VR_tab);
free(jpeg_info->yuvtabs.YUV_UG_tab);
free(jpeg_info->yuvtabs.YUV_VG_tab);
}
int quicktime_fastjpg_resethuffman(quicktime_jpeg_t *jpeg_info)
{
jpeg_info->jpg_comps[0].dc = 0;
jpeg_info->jpg_comps[1].dc = 0;
jpeg_info->jpg_comps[2].dc = 0;
jpeg_info->jpg_h_bbuf = 0; /* clear huffman bit buffer */
jpeg_info->jpg_h_bnum = 0;
}
int quicktime_fastjpg_buildhuffman(quicktime_jpeg_t *jpeg_info,
quicktime_jpeg_huffman *htable,
unsigned char *hbits,
unsigned char *hvals)
{
unsigned long clen, num_syms, p, i, si, code, lookbits;
unsigned long l, ctr;
unsigned char huffsize[257];
unsigned long huffcode[257];
/*** generate code lengths for each symbol */
num_syms = 0;
for(clen = 1; clen <= 16; clen++)
{
for(i = 1; i <= (unsigned long)(hbits[clen]); i++)
huffsize[num_syms++] = (unsigned char)(clen);
}
huffsize[num_syms] = 0;
/*** generate codes */
code = 0;
si = huffsize[0];
p = 0;
while(huffsize[p])
{
while(((unsigned long)huffsize[p]) == si)
{
huffcode[p++] = code;
code++;
}
code <<= 1;
si++;
}
/* Init mincode/maxcode/valptr arrays */
p = 0;
for(l = 1; l <= 16; l++)
{
if (htable->bits[l])
{
htable->valptr[l] = p; /* huffval[] index of 1st symbol of code length l */
htable->mincode[l] = huffcode[p]; /* minimum code of length l */
p += (unsigned long)(htable->bits[l]);
htable->maxcode[l] = huffcode[p-1]; /* maximum code of length l */
}
else
{
htable->valptr[l] = 0; /* not needed */
htable->mincode[l] = 0; /* not needed */
htable->maxcode[l] = 0; /* WAS -1; */ /* -1 if no codes of this length */
}
}
htable->maxcode[17] = 0xFFFFFL; /* ensures huff_DECODE terminates */
/* Init huffman cache */
memset((char *)htable->cache, 0, ((1 << HUFF_LOOKAHEAD) * sizeof(unsigned QUICKTIME_INT16)));
p = 0;
for (l = 1; l <= HUFF_LOOKAHEAD; l++)
{
for (i = 1; i <= (unsigned long) htable->bits[l]; i++, p++)
{
QUICKTIME_INT16 the_code = (unsigned QUICKTIME_INT16)((l << 8) | htable->vals[p]);
/* l = current code's length, p = its index in huffcode[] & huffval[]. */
/* Generate left-justified code followed by all possible bit sequences */
lookbits = huffcode[p] << (HUFF_LOOKAHEAD - l);
for(ctr = 1 << (HUFF_LOOKAHEAD - l); ctr > 0; ctr--)
{
htable->cache[lookbits] = the_code;
lookbits++;
}
}
}
}
int quicktime_fastjpg_buildstdhuffman(quicktime_jpeg_t *jpeg_info)
{
long ttt, len;
quicktime_jpeg_huffman *htable;
unsigned char *hbits, *Sbits;
unsigned char *hvals, *Svals;
static unsigned char dc_luminance_bits[] =
{ /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
static unsigned char dc_luminance_vals[] =
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
static unsigned char dc_chrominance_bits[] =
{ /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
static unsigned char dc_chrominance_vals[] =
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
static unsigned char ac_luminance_bits[] =
{ /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
static unsigned char ac_luminance_vals[] =
{ 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 unsigned char ac_chrominance_bits[] =
{ /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
static unsigned char ac_chrominance_vals[] =
{ 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 };
for(ttt = 0; ttt < 4; ttt++)
{
unsigned long index = ttt & 1;
unsigned long i, count;
if (ttt <= 1) /* DC tables */
{
htable = &(jpeg_info->jpg_dc_huff[index]);
hbits = jpeg_info->jpg_dc_huff[index].bits;
hvals = jpeg_info->jpg_dc_huff[index].vals;
if(index == 0)
{
Sbits = dc_luminance_bits;
Svals = dc_luminance_vals;
}
else
{
Sbits = dc_chrominance_bits;
Svals = dc_chrominance_vals;
}
}
else /* AC tables */
{
htable = &(jpeg_info->jpg_ac_huff[index]);
hbits = jpeg_info->jpg_ac_huff[index].bits;
hvals = jpeg_info->jpg_ac_huff[index].vals;
if(index == 0)
{
Sbits = ac_luminance_bits;
Svals = ac_luminance_vals;
}
else
{
Sbits = ac_chrominance_bits;
Svals = ac_chrominance_vals;
}
}
hbits[0] = 0;
count = 0;
for(i = 1; i <= 16; i++)
{
hbits[i] = Sbits[i];
count += hbits[i];
}
len -= 17;
if(count > 256)
{
printf("quicktime_fastjpg_buildstdhuffman: STD DHT bad count %d\n", count);
return 1;
}
for(i = 0; i < count; i++) hvals[i] = Svals[i];
len -= count;
quicktime_fastjpg_buildhuffman(jpeg_info,
htable,
hbits,
hvals);
}
jpeg_info->jpg_std_DHT_flag = 1;
return 0;
}
int quicktime_fastjpg_buildstdDQT(quicktime_jpeg_t *jpeg_info, long scale)
{
long i, tbl_num;
long *quant_table;
unsigned int *table;
unsigned int std_luminance_quant_tbl[DCTSIZE2] =
{
16, 11, 10, 16, 24, 40, 51, 61,
12, 12, 14, 19, 26, 58, 60, 55,
14, 13, 16, 24, 40, 57, 69, 56,
14, 17, 22, 29, 51, 87, 80, 62,
18, 22, 37, 56, 68, 109, 103, 77,
24, 35, 55, 64, 81, 104, 113, 92,
49, 64, 78, 87, 103, 121, 120, 101,
72, 92, 95, 98, 112, 100, 103, 99
};
unsigned int std_chrominance_quant_tbl[DCTSIZE2] =
{
17, 18, 24, 47, 99, 99, 99, 99,
18, 21, 26, 66, 99, 99, 99, 99,
24, 26, 56, 99, 99, 99, 99, 99,
47, 66, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99
};
tbl_num = 0;
for(tbl_num = 0; tbl_num <= 1; tbl_num++)
{
if(jpeg_info->quant_tables[tbl_num] == 0)
{
jpeg_info->quant_tables[tbl_num] = (long*)malloc(64 * sizeof(long));
}
if (tbl_num == 0)
table = std_luminance_quant_tbl;
else
table = std_chrominance_quant_tbl;
quant_table = jpeg_info->quant_tables[tbl_num];
for (i = 0; i < DCTSIZE2; i++)
{
long tmp;
tmp = ((long)table[i] * scale + 50L) / 100L;
if(tmp <= 0) tmp = 1;
if(tmp > 255) tmp = 255;
quant_table[i] = (long)tmp;
}
}
return 0;
}
int quicktime_fastjpg_get_marker(quicktime_jpeg_t *jpeg_info)
{
int c, done = 0; /* 1 - completion 2 - error */
while(!done)
{
c = quicktime_fastjpg_readbyte(jpeg_info);
/* look for FF */
while(c != 0xFF)
{
if(quicktime_fastjpg_eof(jpeg_info)) done = 2;
c = quicktime_fastjpg_readbyte(jpeg_info);
}
/* now we've got 1 0xFF, keep reading until not 0xFF */
do
{
if(quicktime_fastjpg_eof(jpeg_info)) done = 2;
c = quicktime_fastjpg_readbyte(jpeg_info);
}while (c == 0xFF);
/* not a 00 or FF */
if (c != 0) done = 1;
}
if(done == 1)
return c;
else
return 0;
}
int quicktime_fastjpg_skip_marker(quicktime_jpeg_t *jpeg_info)
{
long len, tmp;
len = quicktime_fastjpg_readint16(jpeg_info);
len -= 2;
if(len <= 0) return 1;
if(quicktime_fastjpg_eof(jpeg_info)) return 1;
while(len--) quicktime_fastjpg_readbyte(jpeg_info);
return 0;
}
int quicktime_fastjpg_check_for_marker(quicktime_jpeg_t *jpeg_info)
{
if(jpeg_info->marker) return(jpeg_info->marker);
if(jpeg_info->chunk_size < 2) return(0);
if((jpeg_info->chunk[0] == 0xff) && (jpeg_info->chunk[1] != 0x00))
{
jpeg_info->marker = jpeg_info->chunk[1];
{
if(jpeg_info->jpg_h_bnum)
{
printf("quicktime_fastjpg_check_for_marker: check marker positive - lost %d bits\n",
jpeg_info->jpg_h_bnum);
}
}
jpeg_info->jpg_h_bnum = 0;
jpeg_info->jpg_h_bbuf = 0;
jpeg_info->chunk += 2;
jpeg_info->chunk_size -= 2;
}
return(jpeg_info->marker);
}
int quicktime_fastjpg_readSOI(quicktime_jpeg_t *jpeg_info)
{
jpeg_info->jpg_rst_interval = 0;
return 0;
}
int quicktime_fastjpg_readSOF(quicktime_jpeg_t *jpeg_info)
{
int result = 0;
int len, i, c;
quicktime_jpeg_comp_header *comp;
len = quicktime_fastjpg_readint16(jpeg_info);
if(jpeg_info->mjpg_kludge)
len -= 6;
else
len -= 8;
jpeg_info->jpg_dprec = quicktime_fastjpg_readbyte(jpeg_info);
jpeg_info->jpg_height = quicktime_fastjpg_readint16(jpeg_info);
jpeg_info->jpg_width = quicktime_fastjpg_readint16(jpeg_info);
jpeg_info->jpg_num_comps = quicktime_fastjpg_readbyte(jpeg_info);
for(i = 0; i < jpeg_info->jpg_num_comps; i++)
{
if(i > MAX_COMPS)
comp = &(jpeg_info->jpg_comps[DUMMY_COMP]);
else
comp = &(jpeg_info->jpg_comps[i]);
comp->id = quicktime_fastjpg_readbyte(jpeg_info);
comp->hvsample = quicktime_fastjpg_readbyte(jpeg_info);
comp->qtbl_num = quicktime_fastjpg_readbyte(jpeg_info);
}
return(quicktime_fastjpg_eof(jpeg_info));
}
int quicktime_fastjpg_readSOS(quicktime_jpeg_t *jpeg_info)
{
int len, i, j;
int comp_id, htbl_num;
int jpg_Ss, jpg_Se, jpg_AhAl;
len = quicktime_fastjpg_readint16(jpeg_info);
jpeg_info->jpg_comps_in_scan = quicktime_fastjpg_readbyte(jpeg_info);
for(i = 0; i < jpeg_info->jpg_comps_in_scan; i++)
{
quicktime_jpeg_comp_header *comp = 0;
comp_id = quicktime_fastjpg_readbyte(jpeg_info);
for(j = 0; j < jpeg_info->jpg_num_comps; )
{
comp = &(jpeg_info->jpg_comps[j]);
if(comp->id == comp_id) break;
j++;
}
if (j > jpeg_info->jpg_num_comps)
{
printf("quicktime_fastjpg_readSOS: bad id %x", comp_id);
return 1;
}
htbl_num = quicktime_fastjpg_readbyte(jpeg_info);
comp->dc_htbl_num = (htbl_num >> 4) & 0x0f;
comp->ac_htbl_num = (htbl_num ) & 0x0f;
}
jpg_Ss = quicktime_fastjpg_readbyte(jpeg_info);
jpg_Se = quicktime_fastjpg_readbyte(jpeg_info);
jpg_AhAl = quicktime_fastjpg_readbyte(jpeg_info);
return(quicktime_fastjpg_eof(jpeg_info));
}
int quicktime_fastjpg_readDHT(quicktime_jpeg_t *jpeg_info)
{
int len, i, index, count;
unsigned long result = 1;
quicktime_jpeg_huffman *htable;
unsigned char *hbits;
unsigned char *hvals;
jpeg_info->jpg_std_DHT_flag = 0;
len = quicktime_fastjpg_readint16(jpeg_info);
if(jpeg_info->mjpg_kludge) len += 2;
len -= 2;
if(quicktime_fastjpg_eof(jpeg_info)) return 1;
while(len > 0)
{
index = quicktime_fastjpg_readbyte(jpeg_info);
len--;
/* Test indexes */
if (index & 0x10) /* AC Table */
{
index &= 0x0f;
if (index >= TOTAL_HUFF_TBLS) break;
htable = &(jpeg_info->jpg_ac_huff[index]);
hbits = jpeg_info->jpg_ac_huff[index].bits;
hvals = jpeg_info->jpg_ac_huff[index].vals;
}
else /* DC Table */
{
index &= 0x0f;
if (index >= TOTAL_HUFF_TBLS) break;
htable = &(jpeg_info->jpg_dc_huff[index]);
hbits = jpeg_info->jpg_dc_huff[index].bits;
hvals = jpeg_info->jpg_dc_huff[index].vals;
}
hbits[0] = 0;
count = 0;
if(len < 16) break;
for (i = 1; i <= 16; i++)
{
hbits[i] = quicktime_fastjpg_readbyte(jpeg_info);
count += hbits[i];
}
len -= 16;
if(count > 256)
{
printf("quicktime_fastjpg_readDHT: DHT bad count %d using default.\n", count);
break;
}
if(len < count)
{
printf("quicktime_fastjpg_readDHT: DHT count(%d) > len(%d).\n", count, len);
break;
}
for(i = 0; i < count; i++) hvals[i] = quicktime_fastjpg_readbyte(jpeg_info);
len -= count;
quicktime_fastjpg_buildhuffman(jpeg_info, htable, hbits, hvals);
result = 0;
}
if(result)
{
/* Something is roached, but what the heck, try default DHT instead */
while(len > 0)
{
len--;
quicktime_fastjpg_readbyte(jpeg_info);
}
quicktime_fastjpg_buildstdhuffman(jpeg_info);
result = 0;
}
return result;
}
int quicktime_fastjpg_readDQT(quicktime_jpeg_t *jpeg_info)
{
long len;
len = quicktime_fastjpg_readint16(jpeg_info);
if(!jpeg_info->mjpg_kludge) len -= 2;
while(len > 0)
{
long i, tbl_num, prec;
long *quant_table;
tbl_num = quicktime_fastjpg_readbyte(jpeg_info);
len -= 1;
prec = (tbl_num >> 4) & 0x0f;
prec = (prec)?(2 * DCTSIZE2) : (DCTSIZE2); /* 128 or 64 */
tbl_num &= 0x0f;
if (tbl_num > 4)
{
printf("quicktime_fastjpg_readDQT: bad DQT tnum %x\n", tbl_num);
return 1;
}
if(jpeg_info->quant_tables[tbl_num] == 0)
{
jpeg_info->quant_tables[tbl_num] = (long *)malloc(64 * sizeof(long));
}
len -= prec;
if(quicktime_fastjpg_eof(jpeg_info)) return 1;
quant_table = jpeg_info->quant_tables[tbl_num];
if(prec == 128)
{
unsigned long tmp;
for(i = 0; i < DCTSIZE2; i++)
{
tmp = quicktime_fastjpg_readint16(jpeg_info);
quant_table[JJ_ZAG[i]] = (long)tmp;
}
}
else
{
unsigned long tmp;
for(i = 0; i < DCTSIZE2; i++)
{
tmp = quicktime_fastjpg_readbyte(jpeg_info);
quant_table[JJ_ZAG[i]] = (long)tmp;
}
}
}
return 0;
}
int quicktime_fastjpg_readAPPX(quicktime_jpeg_t *jpeg_info)
{
long len;
len = quicktime_fastjpg_readint32(jpeg_info);
len -= 2;
if(len > 4)
{
unsigned long first;
first = quicktime_fastjpg_readint32(jpeg_info);
len -= 4;
/* if (first == 0x41564931) /* AVI1 */ */
/* { */
/* int interleave; */
/* interleave = quicktime_fastjpg_readbyte(jpeg_info); */
/* len--; */
/* avi_jpeg_info.valid = 1; */
/* avi_jpeg_info.ileave = interleave; */
/* } */
/* else */
if(len > (0x28 - 4)) /* Maybe APPLE MJPEG A */
{
unsigned long jid;
jid = quicktime_fastjpg_readint32(jpeg_info);
len -= 4;
if(jid == JPEG_APP1_MJPA)
{
jpeg_info->mjpa_info.valid = 1;
jpeg_info->mjpa_info.field_sz = quicktime_fastjpg_readint32(jpeg_info);
jpeg_info->mjpa_info.pad_field_sz = quicktime_fastjpg_readint32(jpeg_info);
jpeg_info->mjpa_info.next_off = quicktime_fastjpg_readint32(jpeg_info);
jpeg_info->mjpa_info.quant_off = quicktime_fastjpg_readint32(jpeg_info);
jpeg_info->mjpa_info.huff_off = quicktime_fastjpg_readint32(jpeg_info);
jpeg_info->mjpa_info.image_off = quicktime_fastjpg_readint32(jpeg_info);
jpeg_info->mjpa_info.scan_off = quicktime_fastjpg_readint32(jpeg_info);
jpeg_info->mjpa_info.data_off = quicktime_fastjpg_readint32(jpeg_info);
len -= 32;
}
}
}
if(len) quicktime_fastjpg_skip(jpeg_info, len);
return 0;
}
int quicktime_fastjpg_readDRI(quicktime_jpeg_t *jpeg_info)
{
long len;
len = quicktime_fastjpg_readint16(jpeg_info);
jpeg_info->jpg_rst_interval = quicktime_fastjpg_readint16(jpeg_info);
return 0;
}
int quicktime_fastjpg_readEOI(quicktime_jpeg_t *jpeg_info)
{
while(jpeg_info->marker = quicktime_fastjpg_get_marker(jpeg_info))
{
if(jpeg_info->marker == M_EOI)
{
jpeg_info->jpg_saw_EOI = 1;
return 1;
}
}
return 0;
}
int quicktime_fastjpg_read_markers(quicktime_jpeg_t *jpeg_info)
{
int done = 0; /* 1 = completion 2 = error */
while(!done)
{
if(!(jpeg_info->marker = quicktime_fastjpg_get_marker(jpeg_info)))
done = 2;
else
{
/*printf("quicktime_fastjpg_read_markers %x\n", jpeg_info->marker); */
switch(jpeg_info->marker)
{
case M_SOI:
if(quicktime_fastjpg_readSOI(jpeg_info)) done = 2;
else
jpeg_info->jpg_saw_SOI = 1;
break;
case M_SOF0:
case M_SOF1:
case M_SOF2:
if(quicktime_fastjpg_readSOF(jpeg_info)) done = 2;
else
jpeg_info->jpg_saw_SOF = 1;
break;
/* Not yet supported */
case M_SOF3:
case M_SOF5:
case M_SOF6:
case M_SOF7:
case M_SOF9:
case M_SOF10:
case M_SOF11:
case M_SOF13:
case M_SOF14:
case M_SOF15:
done = 2;
break;
case M_SOS:
if(quicktime_fastjpg_readSOS(jpeg_info)) done = 2;
else
{
jpeg_info->jpg_saw_SOS = 1;
jpeg_info->jpg_nxt_rst_num = 0;
done = 1;
}
break;
case M_DHT:
if(quicktime_fastjpg_readDHT(jpeg_info)) done = 2;
else
jpeg_info->jpg_saw_DHT = 1;
break;
case M_DQT:
if(quicktime_fastjpg_readDQT(jpeg_info)) done = 2;
else
jpeg_info->jpg_saw_DQT = 1;
break;
case M_DRI:
if(quicktime_fastjpg_readDRI(jpeg_info)) done = 2;
break;
case M_COM:
{
/* Comment */
int len;
len = quicktime_fastjpg_readint16(jpeg_info);
len -= 2;
while(len > 0)
{
quicktime_fastjpg_readbyte(jpeg_info); len--;
}
}
break;
case M_APP0:
case M_APP1:
if(quicktime_fastjpg_readAPPX(jpeg_info)) done = 2;
break;
case M_EOI:
printf("quicktime_fastjpg_read_markers: reached EOI without data\n");
done = 2;
break;
case M_RST0: /* these are all parameterless */
case M_RST1:
case M_RST2:
case M_RST3:
case M_RST4:
case M_RST5:
case M_RST6:
case M_RST7:
case M_TEM:
break;
default:
printf("quicktime_fastjpg_read_markers: unknown marker %x\n", jpeg_info->marker);
if(quicktime_fastjpg_skip_marker(jpeg_info)) done = 2;
break;
} /* end of switch */
}
}
if(done == 2) return 1; else return 0;
}
int quicktime_fastjpg_initMCU(quicktime_jpeg_t *jpeg_info,
int width,
int height,
int full_flag)
{
int twidth = (width + 15) / 16;
int theight = (height + 15) / 16;
if(theight & 1) theight++;
if(full_flag)
twidth *= (theight << 2);
else
twidth <<= 2; /* four dct's deep */
if(!jpeg_info->yuvbufs.allocated)
{
jpeg_info->yuvbufs.allocated = 1;
jpeg_info->yuvbufs.ybuf = (unsigned char*)malloc(twidth * DCTSIZE2);
jpeg_info->yuvbufs.ubuf = (unsigned char*)malloc(twidth * DCTSIZE2);
jpeg_info->yuvbufs.vbuf = (unsigned char*)malloc(twidth * DCTSIZE2);
}
}
int quicktime_fastjpg_skip_to_next_rst(quicktime_jpeg_t *jpeg_info)
{
unsigned long d, last_ff = 0;
jpeg_info->jpg_h_bnum = 0;
jpeg_info->jpg_h_bbuf = 0;
while(jpeg_info->chunk_size)
{
d = *(jpeg_info->chunk++);
jpeg_info->chunk_size--;
if(last_ff)
{
if((d != 0) && (d != 0xff)) return d;
}
last_ff = (d == 0xff) ? 1 : 0;
}
return M_EOI;
}
/* clears dctbuf to zeroes.
* fills from huffman encode stream
*/
int quicktime_fastjpg_huffparse(quicktime_jpeg_t *jpeg_info,
quicktime_jpeg_comp_header *comp,
QUICKTIME_INT16 *dct_buf,
unsigned long *qtab,
unsigned char *OBuf)
{
unsigned long tmp_, tmp__, hcode_, t1_, shift_, minbits_;
long i, dcval, level;
unsigned long size, run, tmp, coeff;
quicktime_jpeg_huffman *huff_hdr = &(jpeg_info->jpg_dc_huff[comp->dc_htbl_num]);
unsigned QUICKTIME_INT16 *huff_tbl = huff_hdr->cache;
unsigned char *rnglimit = jpeg_info->jpg_samp_limit + (CENTERJSAMPLE + MAXJSAMPLE + 1);
unsigned long c_cnt, pos = 0;
QUICKTIME_FASTJPG_HUFF_DECODE(huff_hdr, huff_tbl, jpeg_info->jpg_h_bnum, jpeg_info->jpg_h_bbuf, size);
if(size)
{
unsigned long bits;
QUICKTIME_FASTJPG_GET_BITS(size, jpeg_info->jpg_h_bnum, jpeg_info->jpg_h_bbuf, bits);
dcval = QUICKTIME_FASTJPG_HUFF_EXTEND(bits, size);
comp->dc += dcval;
}
dcval = comp->dc;
/* clear rest of dct buffer */
memset((char *)(dct_buf), 0, (DCTSIZE2 * sizeof(QUICKTIME_INT16)));
dcval *= (long)qtab[0];
dct_buf[0] = (QUICKTIME_INT16)dcval;
c_cnt = 0;
huff_hdr = &(jpeg_info->jpg_ac_huff[comp->ac_htbl_num]);
huff_tbl = huff_hdr->cache;
for(i = 1; i < 64; )
{
QUICKTIME_FASTJPG_HUFF_DECODE(huff_hdr, huff_tbl, jpeg_info->jpg_h_bnum, jpeg_info->jpg_h_bbuf, tmp);
size = tmp & 0x0f;
run = (tmp >> 4) & 0x0f; /* leading zeroes */
if(size)
{
i += run; /* skip zeroes */
QUICKTIME_FASTJPG_GET_BITS(size, jpeg_info->jpg_h_bnum, jpeg_info->jpg_h_bbuf, level);
coeff = (long)QUICKTIME_FASTJPG_HUFF_EXTEND(level, size);
pos = JJ_ZAG[i];
coeff *= (long)qtab[pos];
if(coeff)
{
c_cnt++;
dct_buf[pos] = (QUICKTIME_INT16)(coeff);
}
i++;
}
else
{
if(run != 15) break; /* EOB */
i += 16;
}
}
if(c_cnt) quicktime_rev_dct(dct_buf, OBuf, rnglimit);
else
{
register unsigned char *op = OBuf;
register int jj = 8;
QUICKTIME_INT16 v = *dct_buf;
register unsigned char dc;
v = (v < 0) ? ((v - 3) >> 3) : ((v + 4) >> 3);
dc = rnglimit[(int)(v & RANGE_MASK)];
while(jj--)
{
op[0] = op[1] = op[2] = op[3] = op[4] = op[5] = op[6] = op[7] = dc;
op += 8;
}
}
return 0;
}
int quicktime_fastjpg_MCU411111_to_RGB(QUICKTIME_MCU_ARGS)
{
QUICKTIME_MCU_VARS
QUICKTIME_MCU111111_MID_VARS
QUICKTIME_MCU_INNER_VARS
while(frame_height > 0)
{
yptr = ybuf;
uptr = ubuf;
vptr = vbuf;
for(yi = 0; yi < 8; yi++)
{
QUICKTIME_MCU111111_MID_DECL;
if(frame_height <= 0) return 0;
while(xi--)
{
QUICKTIME_MCU_INNER_INIT;
QUICKTIME_MCU_YUV_TO_RGB(YTab[*yp++], cr, cg, cb, ip);
QUICKTIME_MCU_YUV_TO_RGB(YTab[*yp++], cr, cg, cb, ip);
QUICKTIME_MCU_YUV_TO_RGB(YTab[*yp++], cr, cg, cb, ip);
QUICKTIME_MCU_YUV_TO_RGB(YTab[*yp++], cr, cg, cb, ip);
QUICKTIME_MCU4H_INNER_TAIL(56, 56);
}
yptr += 8;
uptr += 8;
vptr += 8;
frame_height--;
row_pointers += interlaced ? 2 : 1;
}
ybuf += mcu_row_size << 2;
ubuf += mcu_row_size;
vbuf += mcu_row_size;
}
}
int quicktime_fastjpg_decode_411111(quicktime_jpeg_t *jpeg_info,
unsigned char **output_rows,
int jpeg_width,
int jpeg_height,
int interlaced,
int row_offset,
int frame_width,
int frame_height)
{
long x, mcu_cols, mcu_rows;
long *qtab0, *qtab1, *qtab2;
unsigned char *Ybuf, *Ubuf, *Vbuf;
unsigned long rst_count;
unsigned long rst_skip = 0;
unsigned long orow_size = frame_width * 3 * (interlaced ? 2 : 1);
if(interlaced) frame_height >>= 1;
frame_width += 3;
frame_width >>= 2; /* 4h */
qtab0 = jpeg_info->quant_tables[jpeg_info->jpg_comps[0].qtbl_num];
qtab1 = jpeg_info->quant_tables[jpeg_info->jpg_comps[1].qtbl_num];
qtab2 = jpeg_info->quant_tables[jpeg_info->jpg_comps[2].qtbl_num];
mcu_cols = (jpeg_width + 31) / 32;
mcu_rows = (jpeg_height + 7) / 8;
jpeg_info->marker = 0x00;
rst_count = jpeg_info->jpg_rst_interval;
output_rows += row_offset;
while(mcu_rows--)
{
Ybuf = jpeg_info->yuvbufs.ybuf;
Ubuf = jpeg_info->yuvbufs.ubuf;
Vbuf = jpeg_info->yuvbufs.vbuf;
x = mcu_cols;
while(x--)
{
if(rst_skip)
{
rst_skip--;
memset(Ybuf, 0, (DCTSIZE2 << 2));
memset(Ubuf, 0x80, DCTSIZE2);
memset(Vbuf, 0x80, DCTSIZE2);
Ybuf += (DCTSIZE2 << 2);
Ubuf += DCTSIZE2;
Vbuf += DCTSIZE2;
}
else
{
QUICKTIME_FASTJPG_HANDLE_RST(jpeg_info->jpg_rst_interval, rst_count);
/* Y0 Y1 Y2 Y3 U V */
quicktime_fastjpg_huffparse(jpeg_info, &(jpeg_info->jpg_comps[0]), jpeg_info->jpg_dct_buf, qtab0, Ybuf); Ybuf += DCTSIZE2;
quicktime_fastjpg_huffparse(jpeg_info, &(jpeg_info->jpg_comps[0]), jpeg_info->jpg_dct_buf, qtab0, Ybuf); Ybuf += DCTSIZE2;
quicktime_fastjpg_huffparse(jpeg_info, &(jpeg_info->jpg_comps[0]), jpeg_info->jpg_dct_buf, qtab0, Ybuf); Ybuf += DCTSIZE2;
quicktime_fastjpg_huffparse(jpeg_info, &(jpeg_info->jpg_comps[0]), jpeg_info->jpg_dct_buf, qtab0, Ybuf); Ybuf += DCTSIZE2;
quicktime_fastjpg_huffparse(jpeg_info, &(jpeg_info->jpg_comps[1]), jpeg_info->jpg_dct_buf, qtab1, Ubuf); Ubuf += DCTSIZE2;
quicktime_fastjpg_huffparse(jpeg_info, &(jpeg_info->jpg_comps[2]), jpeg_info->jpg_dct_buf, qtab2, Vbuf); Vbuf += DCTSIZE2;
if(jpeg_info->marker == 0)
jpeg_info->marker = quicktime_fastjpg_check_for_marker(jpeg_info);
QUICKTIME_FASTJPG_TEST_MARKER;
}
} /* end of mcu_cols */
quicktime_fastjpg_MCU411111_to_RGB(jpeg_info,
output_rows,
frame_width,
(frame_height < 8 ? frame_height : 8),
(mcu_cols * DCTSIZE2),
orow_size,
&(jpeg_info->yuvbufs),
interlaced);
frame_height -= 8;
output_rows += interlaced ? 16 : 8;
} /* end of mcu_rows */
if(jpeg_info->marker)
{
jpeg_info->jpg_h_bbuf = 0;
jpeg_info->jpg_h_bnum = 0;
}
return 0;
}
int quicktime_fastjpg_MCU221111_to_RGB(QUICKTIME_MCU_ARGS)
{
QUICKTIME_MCU_VARS
QUICKTIME_MCU221111_MID_VARS
QUICKTIME_MCU_INNER_VARS
while(frame_height > 0)
{
yptr = ybuf;
uptr = ubuf;
vptr = vbuf;
for(yi = 0; yi < 8; yi++)
{
QUICKTIME_MCU221111_MID_DECL;
while(xi--)
{
QUICKTIME_MCU_INNER_INIT;
QUICKTIME_MCU_YUV_TO_RGB(YTab[yp[8]], cr, cg, cb, ip1);
QUICKTIME_MCU_YUV_TO_RGB(YTab[*yp++], cr, cg, cb, ip0);
QUICKTIME_MCU_YUV_TO_RGB(YTab[yp[8]], cr, cg, cb, ip1);
QUICKTIME_MCU_YUV_TO_RGB(YTab[*yp++], cr, cg, cb, ip0);
QUICKTIME_MCU2H_INNER_TAIL(56, 184);
}
yptr += 16;
uptr += 8;
vptr += 8;
frame_height -= 2;
}
ybuf += mcu_row_size << 2;
ubuf += mcu_row_size;
vbuf += mcu_row_size;
}
}
int quicktime_fastjpg_decode_221111(quicktime_jpeg_t *jpeg_info,
unsigned char **output_rows,
int jpeg_width,
int jpeg_height,
int interlaced,
int row_offset,
int frame_width,
int frame_height)
{
long x, mcu_cols, mcu_rows;
long *qtab0, *qtab1, *qtab2;
unsigned char *Ybuf, *Ubuf, *Vbuf;
unsigned long rst_count;
unsigned long rst_skip = 0;
unsigned long orow_size = frame_width * 3 * (interlaced ? 2 : 1);
if(interlaced) frame_height >>= 1;
frame_width += 1;
frame_width >>= 1; /* 2h */
qtab0 = jpeg_info->quant_tables[jpeg_info->jpg_comps[0].qtbl_num];
qtab1 = jpeg_info->quant_tables[jpeg_info->jpg_comps[1].qtbl_num];
qtab2 = jpeg_info->quant_tables[jpeg_info->jpg_comps[2].qtbl_num];
mcu_cols = (jpeg_width + 15) / 16;
mcu_rows = (jpeg_height + 15) / 16;
jpeg_info->marker = 0x00;
rst_count = jpeg_info->jpg_rst_interval;
output_rows += row_offset;
while(mcu_rows--)
{
Ybuf = jpeg_info->yuvbufs.ybuf;
Ubuf = jpeg_info->yuvbufs.ubuf;
Vbuf = jpeg_info->yuvbufs.vbuf;
x = mcu_cols;
while(x--)
{
if(rst_skip)
{
rst_skip--;
memset(Ybuf, 0, (DCTSIZE2 << 2));
memset(Ubuf, 0x80, DCTSIZE2);
memset(Vbuf, 0x80, DCTSIZE2);
Ybuf += (DCTSIZE2 << 2);
Ubuf += DCTSIZE2;
Vbuf += DCTSIZE2;
}
else
{
QUICKTIME_FASTJPG_HANDLE_RST(jpeg_info->jpg_rst_interval, rst_count);
/* Y0 Y1 Y2 Y3 U V */
quicktime_fastjpg_huffparse(jpeg_info, &(jpeg_info->jpg_comps[0]), jpeg_info->jpg_dct_buf, qtab0, Ybuf); Ybuf += DCTSIZE2;
quicktime_fastjpg_huffparse(jpeg_info, &(jpeg_info->jpg_comps[0]), jpeg_info->jpg_dct_buf, qtab0, Ybuf); Ybuf += DCTSIZE2;
quicktime_fastjpg_huffparse(jpeg_info, &(jpeg_info->jpg_comps[0]), jpeg_info->jpg_dct_buf, qtab0, Ybuf); Ybuf += DCTSIZE2;
quicktime_fastjpg_huffparse(jpeg_info, &(jpeg_info->jpg_comps[0]), jpeg_info->jpg_dct_buf, qtab0, Ybuf); Ybuf += DCTSIZE2;
quicktime_fastjpg_huffparse(jpeg_info, &(jpeg_info->jpg_comps[1]), jpeg_info->jpg_dct_buf, qtab1, Ubuf); Ubuf += DCTSIZE2;
quicktime_fastjpg_huffparse(jpeg_info, &(jpeg_info->jpg_comps[2]), jpeg_info->jpg_dct_buf, qtab2, Vbuf); Vbuf += DCTSIZE2;
if(jpeg_info->marker == 0)
jpeg_info->marker = quicktime_fastjpg_check_for_marker(jpeg_info);
QUICKTIME_FASTJPG_TEST_MARKER;
}
} /* end of mcu_cols */
quicktime_fastjpg_MCU221111_to_RGB(jpeg_info,
output_rows,
frame_width,
(frame_height < 16 ? frame_height : 16),
(mcu_cols * DCTSIZE2),
orow_size,
&(jpeg_info->yuvbufs),
interlaced);
frame_height -= 16;
output_rows += interlaced ? 32 : 16;
} /* end of mcu_rows */
if(jpeg_info->marker)
{
jpeg_info->jpg_h_bbuf = 0;
jpeg_info->jpg_h_bnum = 0;
}
return 0;
}
int quicktime_fastjpg_double_mcu(unsigned char *ptr, int mcus)
{
unsigned char *sblk, *dblk;
int blks = mcus * 8;
int flag = 0;
sblk = ptr + (blks * 8) - 8;
dblk = ptr + (blks * 16) - 8;
while(blks--)
{
dblk[7] = dblk[6] = sblk[7];
dblk[5] = dblk[4] = sblk[6];
dblk[3] = dblk[2] = sblk[5];
dblk[1] = dblk[0] = sblk[4];
dblk -= 64;
dblk[7] = dblk[6] = sblk[3];
dblk[5] = dblk[4] = sblk[2];
dblk[3] = dblk[2] = sblk[1];
dblk[1] = dblk[0] = sblk[0];
flag++;
if(flag >= 8)
{
flag = 0;
dblk -= 8;
}
else
{
dblk += 56;
}
sblk -= 8;
}
}
int quicktime_fastjpg_MCU211111_to_RGB(QUICKTIME_MCU_ARGS)
{
QUICKTIME_MCU_VARS
QUICKTIME_MCU111111_MID_VARS
QUICKTIME_MCU_INNER_VARS
while(frame_height > 0)
{
yptr = ybuf;
uptr = ubuf;
vptr = vbuf;
for(yi = 0; yi < 8; yi++)
{
QUICKTIME_MCU111111_MID_DECL;
if(frame_height <= 0) return;
while(xi--)
{
QUICKTIME_MCU_INNER_INIT;
QUICKTIME_MCU_YUV_TO_RGB(YTab[*yp++], cr, cg, cb, ip);
QUICKTIME_MCU_YUV_TO_RGB(YTab[*yp++], cr, cg, cb, ip);
QUICKTIME_MCU2H_INNER_TAIL(56, 56);
}
yptr += 8;
uptr += 8;
vptr += 8;
frame_height -= 2;
row_pointers += interlaced ? 2 : 1;
}
ybuf += mcu_row_size << 1;
ubuf += mcu_row_size;
vbuf += mcu_row_size;
}
}
int quicktime_fastjpg_decode_211111(quicktime_jpeg_t *jpeg_info,
unsigned char **output_rows,
int jpeg_width,
int jpeg_height,
int interlaced,
int row_offset,
int frame_width,
int frame_height)
{
long x, mcu_cols, mcu_rows;
long *qtab0, *qtab1, *qtab2;
unsigned char *Ybuf, *Ubuf, *Vbuf;
unsigned long rst_count;
unsigned long rst_skip = 0;
unsigned long orow_size = frame_width * 3 * (interlaced ? 2 : 1);
if(interlaced) frame_height >>= 1;
frame_width += 1;
frame_width >>= 1; /* 2h */
qtab0 = jpeg_info->quant_tables[jpeg_info->jpg_comps[0].qtbl_num];
qtab1 = jpeg_info->quant_tables[jpeg_info->jpg_comps[1].qtbl_num];
qtab2 = jpeg_info->quant_tables[jpeg_info->jpg_comps[2].qtbl_num];
mcu_cols = (jpeg_width + 15) / 16;
mcu_rows = (jpeg_height + 7) / 8;
jpeg_info->marker = 0x00;
rst_count = jpeg_info->jpg_rst_interval;
output_rows += row_offset;
while(mcu_rows--)
{
Ybuf = jpeg_info->yuvbufs.ybuf;
Ubuf = jpeg_info->yuvbufs.ubuf;
Vbuf = jpeg_info->yuvbufs.vbuf;
x = mcu_cols;
while(x--)
{
if(rst_skip)
{
rst_skip--;
memset(Ybuf, 0, (DCTSIZE2 << 1));
memset(Ubuf, 0x80, DCTSIZE2);
memset(Vbuf, 0x80, DCTSIZE2);
Ybuf += (DCTSIZE2 << 1);
Ubuf += DCTSIZE2;
Vbuf += DCTSIZE2;
}
else
{
QUICKTIME_FASTJPG_HANDLE_RST(jpeg_info->jpg_rst_interval, rst_count);
quicktime_fastjpg_huffparse(jpeg_info, &(jpeg_info->jpg_comps[0]), jpeg_info->jpg_dct_buf, qtab0, Ybuf); Ybuf += DCTSIZE2;
quicktime_fastjpg_huffparse(jpeg_info, &(jpeg_info->jpg_comps[0]), jpeg_info->jpg_dct_buf, qtab0, Ybuf); Ybuf += DCTSIZE2;
quicktime_fastjpg_huffparse(jpeg_info, &(jpeg_info->jpg_comps[1]), jpeg_info->jpg_dct_buf, qtab1, Ubuf); Ubuf += DCTSIZE2;
quicktime_fastjpg_huffparse(jpeg_info, &(jpeg_info->jpg_comps[2]), jpeg_info->jpg_dct_buf, qtab2, Vbuf); Vbuf += DCTSIZE2;
if(jpeg_info->marker == 0)
jpeg_info->marker = quicktime_fastjpg_check_for_marker(jpeg_info);
QUICKTIME_FASTJPG_TEST_MARKER;
}
} /* end of mcu_cols */
/* NOTE: imagex already >> 1 above */
if(jpeg_width <= frame_width)
{
quicktime_fastjpg_double_mcu(jpeg_info->yuvbufs.ybuf, (mcu_cols << 1));
quicktime_fastjpg_double_mcu(jpeg_info->yuvbufs.ubuf, mcu_cols);
quicktime_fastjpg_double_mcu(jpeg_info->yuvbufs.vbuf, mcu_cols);
}
quicktime_fastjpg_MCU211111_to_RGB(jpeg_info,
output_rows,
frame_width,
(frame_height < 8 ? frame_height : 8),
((mcu_cols << 1) * DCTSIZE2),
orow_size,
&(jpeg_info->yuvbufs),
interlaced);
frame_height -= 8;
output_rows += interlaced ? 16 : 8;
} /* end of mcu_rows */
if(jpeg_info->marker)
{
jpeg_info->jpg_h_bbuf = 0;
jpeg_info->jpg_h_bnum = 0;
}
return 0;
}
int quicktime_fastjpg_MCU111111_to_RGB(QUICKTIME_MCU_ARGS)
{
QUICKTIME_MCU_VARS
QUICKTIME_MCU111111_MID_VARS
QUICKTIME_MCU_INNER_VARS
while(frame_height > 0)
{
yptr = ybuf;
uptr = ubuf;
vptr = vbuf;
for(yi = 0; yi < 8; yi++)
{
QUICKTIME_MCU111111_MID_DECL;
if(frame_height <= 0) return;
while(xi--)
{
QUICKTIME_MCU_INNER_INIT;
QUICKTIME_MCU_YUV_TO_RGB(YTab[*yp++], cr, cg, cb, ip);
QUICKTIME_MCU1H_INNER_TAIL(56);
}
yptr += 8;
uptr += 8;
vptr += 8;
frame_height--;
row_pointers += interlaced ? 2 : 1;
}
ybuf += mcu_row_size;
ubuf += mcu_row_size;
vbuf += mcu_row_size;
}
}
int quicktime_fastjpg_decode_111111(quicktime_jpeg_t *jpeg_info,
unsigned char **output_rows,
int jpeg_width,
int jpeg_height,
int interlaced,
int row_offset,
int frame_width,
int frame_height,
int grey)
{
long x, mcu_cols, mcu_rows;
long *qtab0, *qtab1, *qtab2;
unsigned char *Ybuf, *Ubuf, *Vbuf;
unsigned long rst_count;
unsigned long rst_skip = 0;
unsigned long orow_size = frame_width * 3 * (interlaced ? 2 : 1);
if(interlaced) frame_height >>= 1;
qtab0 = jpeg_info->quant_tables[jpeg_info->jpg_comps[0].qtbl_num];
qtab1 = jpeg_info->quant_tables[jpeg_info->jpg_comps[1].qtbl_num];
qtab2 = jpeg_info->quant_tables[jpeg_info->jpg_comps[2].qtbl_num];
mcu_cols = (jpeg_width + 7) / 8;
mcu_rows = (jpeg_height + 7) / 8;
jpeg_info->marker = 0x00;
rst_count = jpeg_info->jpg_rst_interval;
output_rows += row_offset;
while(mcu_rows--)
{
Ybuf = jpeg_info->yuvbufs.ybuf;
Ubuf = jpeg_info->yuvbufs.ubuf;
Vbuf = jpeg_info->yuvbufs.vbuf;
x = mcu_cols;
while(x--)
{
if(rst_skip)
{
rst_skip--;
if(Ybuf != jpeg_info->yuvbufs.ybuf)
{
unsigned char *prev;
prev = Ybuf - DCTSIZE2;
memcpy(Ybuf, prev, DCTSIZE2);
Ybuf += DCTSIZE2;
prev = Ubuf - DCTSIZE2;
memcpy(Ubuf, prev, DCTSIZE2);
prev = Vbuf - DCTSIZE2;
memcpy(Vbuf, prev, DCTSIZE2);
Ubuf += DCTSIZE2;
Vbuf += DCTSIZE2;
}
else
{
memset(Ybuf, 0, DCTSIZE2);
Ybuf += DCTSIZE2;
memset(Ubuf, 0x80, DCTSIZE2);
memset(Vbuf, 0x80, DCTSIZE2);
Ubuf += DCTSIZE2;
Vbuf += DCTSIZE2;
}
}
else
{
QUICKTIME_FASTJPG_HANDLE_RST(jpeg_info->jpg_rst_interval, rst_count);
quicktime_fastjpg_huffparse(jpeg_info, &(jpeg_info->jpg_comps[0]), jpeg_info->jpg_dct_buf, qtab0, Ybuf); Ybuf += DCTSIZE2;
quicktime_fastjpg_huffparse(jpeg_info, &(jpeg_info->jpg_comps[1]), jpeg_info->jpg_dct_buf, qtab1, Ubuf); Ubuf += DCTSIZE2;
quicktime_fastjpg_huffparse(jpeg_info, &(jpeg_info->jpg_comps[2]), jpeg_info->jpg_dct_buf, qtab2, Vbuf); Vbuf += DCTSIZE2;
if(jpeg_info->marker == 0)
jpeg_info->marker = quicktime_fastjpg_check_for_marker(jpeg_info);
QUICKTIME_FASTJPG_TEST_MARKER;
}
} /* end of mcu_cols */
/* NOTE: imagex already >> 1 above */
quicktime_fastjpg_MCU111111_to_RGB(jpeg_info,
output_rows,
frame_width,
(frame_height < 8 ? frame_height : 8),
(mcu_cols * DCTSIZE2),
orow_size,
&(jpeg_info->yuvbufs),
interlaced);
frame_height -= 8;
output_rows += interlaced ? 16 : 8;
} /* end of mcu_rows */
if(jpeg_info->marker)
{
jpeg_info->jpg_h_bbuf = 0;
jpeg_info->jpg_h_bnum = 0;
}
return 0;
}
int quicktime_fastjpg_decode(unsigned char *chunk,
long chunk_size,
unsigned char **output_rows,
quicktime_jpeg_t *jpeg_info,
int frame_width,
int frame_height,
int interlaced)
{
int base_y, row_offset;
int ijpeg = 0;
int result = 0;
jpeg_info->mjpa_info.valid = 0;
jpeg_info->chunk = chunk;
jpeg_info->chunk_size = chunk_size;
for(base_y = 0; base_y < (interlaced ? 2 : 1); base_y++)
{
/* Reset structures */
jpeg_info->jpg_saw_EOI = 0;
jpeg_info->jpg_saw_SOI = jpeg_info->jpg_saw_SOF = jpeg_info->jpg_saw_SOS = jpeg_info->jpg_saw_DHT = jpeg_info->jpg_saw_DQT = 0;
if(quicktime_fastjpg_read_markers(jpeg_info))
{
printf("quicktime_fastjpg_decode read markers failed\n");
}
quicktime_fastjpg_resethuffman(jpeg_info);
if(interlaced)
{
row_offset = (base_y == 0) ? 0 : 1;
}
else
row_offset = 0;
if((!jpeg_info->jpg_saw_DHT) && (!jpeg_info->jpg_std_DHT_flag))
{
quicktime_fastjpg_buildstdhuffman(jpeg_info);
}
if(!jpeg_info->jpg_saw_DQT)
{
quicktime_fastjpg_buildstdDQT(jpeg_info, 100);
}
jpeg_info->marker = 0x00;
/*if(jpeg_info->jpg_width > frame_width) */
quicktime_fastjpg_initMCU(jpeg_info, jpeg_info->jpg_width, 0, 0);
/* Perform the decompression */
if((jpeg_info->jpg_num_comps == 3) && (jpeg_info->jpg_comps_in_scan == 3) &&
(jpeg_info->jpg_comps[1].hvsample == 0x11) && (jpeg_info->jpg_comps[2].hvsample== 0x11))
{
if(jpeg_info->jpg_comps[0].hvsample == 0x41) /* 411 */
{
quicktime_fastjpg_decode_411111(jpeg_info,
output_rows,
jpeg_info->jpg_width,
jpeg_info->jpg_height,
interlaced,
row_offset,
frame_width,
frame_height);
}
else
if(jpeg_info->jpg_comps[0].hvsample == 0x22) /* 411 */
{
quicktime_fastjpg_decode_221111(jpeg_info,
output_rows,
jpeg_info->jpg_width,
jpeg_info->jpg_height,
interlaced,
row_offset,
frame_width,
frame_height);
}
else
if(jpeg_info->jpg_comps[0].hvsample == 0x21) /* 211 */
{
quicktime_fastjpg_decode_211111(jpeg_info,
output_rows,
jpeg_info->jpg_width,
jpeg_info->jpg_height,
interlaced,
row_offset,
frame_width,
frame_height);
}
else if(jpeg_info->jpg_comps[0].hvsample == 0x11) /* 111 */
{
quicktime_fastjpg_decode_111111(jpeg_info,
output_rows,
jpeg_info->jpg_width,
jpeg_info->jpg_height,
interlaced,
row_offset,
frame_width,
frame_height,
0);
}
else
{
printf("quicktime_fastjpg_decode: cmps %d %d mcu %04x %04x %04x unsupported\n",
jpeg_info->jpg_num_comps,
jpeg_info->jpg_comps_in_scan,
jpeg_info->jpg_comps[0].hvsample,
jpeg_info->jpg_comps[1].hvsample,
jpeg_info->jpg_comps[2].hvsample);
break;
}
}
else
if((jpeg_info->jpg_num_comps == 1) || (jpeg_info->jpg_comps_in_scan == 1))
{
/* Grayscale not supported */
quicktime_fastjpg_decode_111111(jpeg_info,
output_rows,
jpeg_info->jpg_width,
jpeg_info->jpg_height,
interlaced,
row_offset,
frame_width,
frame_height,
1);
}
else
{
printf("quicktime_fastjpg_decode: cmps %d %d mcu %04x %04x %04x unsupported.\n",
jpeg_info->jpg_num_comps,
jpeg_info->jpg_comps_in_scan,
jpeg_info->jpg_comps[0].hvsample,
jpeg_info->jpg_comps[1].hvsample,
jpeg_info->jpg_comps[2].hvsample);
break;
}
if(jpeg_info->marker == M_EOI)
{
jpeg_info->jpg_saw_EOI = 1;
jpeg_info->marker = 0x00;
}
else
if(!jpeg_info->jpg_saw_EOI)
if(quicktime_fastjpg_readEOI(jpeg_info))
break;
}
return result;
}