Fix AC RLE bug, and some tidyup

pull/2/head
Philip Heron 2010-10-04 19:59:42 +01:00
rodzic 0c74c11c2c
commit 0636d3c4ed
4 zmienionych plików z 72 dodań i 58 usunięć

Wyświetl plik

@ -55,7 +55,14 @@ typedef struct
uint8_t outlen; /* Number of bits in the output bit buffer */
/* JPEG decoder state */
enum { J_MARKER = 0, J_MARKER_LEN, J_MARKER_DATA, J_HUFF, J_INT } state;
enum {
S_MARKER = 0,
S_MARKER_LEN,
S_MARKER_DATA,
S_HUFF,
S_INT,
S_EOI,
} state;
uint16_t marker; /* Current marker */
uint16_t marker_len; /* Length of data following marker */
uint8_t *marker_data; /* Where to copy marker data too */
@ -91,11 +98,10 @@ extern char ssdv_enc_feed(ssdv_t *s, uint8_t *buffer, size_t length);
/* Decoding */
extern char ssdv_dec_init(ssdv_t *s);
extern char ssdv_dec_set_buffer(ssdv_t *s, uint8_t *buffer, size_t length);
extern char ssdv_dec_feed(ssdv_t *s, uint8_t *packet);
extern char ssdv_dec_get_jpeg(ssdv_t *s, uint8_t **jpeg, size_t *length);
extern char ssdv_dec_is_packet(uint8_t *packet);
extern char ssdv_dec_is_packet(uint8_t *packet, int *errors);
extern void ssdv_dec_header(ssdv_packet_info_t *info, uint8_t *packet);
#ifdef __cplusplus

Wyświetl plik

@ -44,6 +44,7 @@ private:
int image_width;
int image_height;
int image_lost_packets;
int image_errors;
/* Private functions */
void feed_buffer(uint8_t byte);

Wyświetl plik

@ -25,11 +25,6 @@ static uint8_t app0[14] = {
0x4A,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x00,0x48,0x00,0x48,0x00,0x00,
};
/* SOF0 header data */
static uint8_t sof0[15] = {
0x08,0x00,0xF0,0x01,0x40,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11,0x01,
};
/* SOS header data */
static uint8_t sos[10] = {
0x03,0x01,0x00,0x02,0x11,0x03,0x11,0x00,0x3F,0x00,
@ -242,7 +237,7 @@ static char ssdv_out_jpeg_int(ssdv_t *s, uint8_t rle, int value)
static char ssdv_process(ssdv_t *s)
{
if(s->state == J_HUFF)
if(s->state == S_HUFF)
{
uint8_t symbol, width;
int r;
@ -273,7 +268,7 @@ static char ssdv_process(ssdv_t *s)
else
{
/* DC value follows, 'symbol' bits wide */
s->state = J_INT;
s->state = S_INT;
s->needbits = symbol;
}
}
@ -288,14 +283,14 @@ static char ssdv_process(ssdv_t *s)
}
else if(symbol == 0xF0)
{
/* The next 15 AC parts are zero */
/* The next 16 AC parts are zero */
ssdv_out_jpeg_int(s, 15, 0);
s->acpart += 15;
s->acpart += 16;
}
else
{
/* Next bits are an integer value */
s->state = J_INT;
s->state = S_INT;
s->acrle = symbol >> 4;
s->acpart += s->acrle;
s->needbits = symbol & 0x0F;
@ -306,7 +301,7 @@ static char ssdv_process(ssdv_t *s)
s->worklen -= width;
s->workbits &= (1 << s->worklen) - 1;
}
else if(s->state == J_INT)
else if(s->state == S_INT)
{
int i;
@ -350,7 +345,7 @@ static char ssdv_process(ssdv_t *s)
s->acpart++;
/* Next bits are a huffman code */
s->state = J_HUFF;
s->state = S_HUFF;
/* Clear processed bits */
s->worklen -= s->needbits;
@ -405,7 +400,7 @@ static char ssdv_have_marker(ssdv_t *s)
s->marker_data = s->hbuff;
s->marker_data_len = 0;
s->state = J_MARKER_DATA;
s->state = S_MARKER_DATA;
break;
case J_DHT:
@ -413,13 +408,17 @@ static char ssdv_have_marker(ssdv_t *s)
/* Copy the tables into memory */
s->marker_data = malloc(s->marker_len);
s->marker_data_len = 0;
s->state = J_MARKER_DATA;
s->state = S_MARKER_DATA;
break;
case J_EOI:
s->state = S_EOI;
break;
default:
/* Ignore other marks, skipping any associated data */
s->in_skip = s->marker_len;
s->state = J_MARKER;
s->state = S_MARKER;
break;
}
@ -497,7 +496,7 @@ static char ssdv_have_marker_data(ssdv_t *s)
/* 00 3F 00 */
/* The SOS data is followed by the image data */
s->state = J_HUFF;
s->state = S_HUFF;
return(SSDV_OK);
@ -518,7 +517,7 @@ static char ssdv_have_marker_data(ssdv_t *s)
break;
}
s->state = J_MARKER;
s->state = S_MARKER;
return(SSDV_OK);
}
@ -549,6 +548,8 @@ char ssdv_enc_get_packet(ssdv_t *s)
int r;
uint8_t b;
if(s->state == S_EOI) return(SSDV_EOI);
/* If the output buffer is empty, re-initialise */
if(s->out_len == 0) ssdv_enc_set_buffer(s, s->out);
@ -562,7 +563,7 @@ char ssdv_enc_get_packet(ssdv_t *s)
switch(s->state)
{
case J_MARKER:
case S_MARKER:
s->marker = (s->marker << 8) | b;
if(s->marker == J_TEM ||
@ -576,12 +577,12 @@ char ssdv_enc_get_packet(ssdv_t *s)
{
/* All other markers are followed by data */
s->marker_len = 0;
s->state = J_MARKER_LEN;
s->state = S_MARKER_LEN;
s->needbits = 16;
}
break;
case J_MARKER_LEN:
case S_MARKER_LEN:
s->marker_len = (s->marker_len << 8) | b;
if((s->needbits -= 8) == 0)
{
@ -590,7 +591,7 @@ char ssdv_enc_get_packet(ssdv_t *s)
}
break;
case J_MARKER_DATA:
case S_MARKER_DATA:
s->marker_data[s->marker_data_len++] = b;
if(s->marker_data_len == s->marker_len)
{
@ -598,8 +599,8 @@ char ssdv_enc_get_packet(ssdv_t *s)
}
break;
case J_HUFF:
case J_INT:
case S_HUFF:
case S_INT:
/* Is the next byte a stuffing byte? Skip it */
/* TODO: Test the next byte is actually 0x00 */
if(b == 0xFF) s->in_skip++;
@ -647,7 +648,7 @@ char ssdv_enc_get_packet(ssdv_t *s)
s->packet_id++;
/* Have we reached the end of the image data? */
if(r == SSDV_EOI) s->state = J_MARKER;
if(r == SSDV_EOI) s->state = S_EOI;
return(SSDV_OK);
}
@ -658,6 +659,10 @@ char ssdv_enc_get_packet(ssdv_t *s)
return(SSDV_ERROR);
}
break;
case S_EOI:
/* Shouldn't reach this point */
break;
}
}
@ -686,11 +691,31 @@ static void ssdv_write_marker(ssdv_t *s, uint16_t id, uint16_t length, uint8_t *
static void ssdv_out_headers(ssdv_t *s)
{
uint8_t *b = s->hbuff;
ssdv_write_marker(s, J_SOI, 0, 0);
ssdv_write_marker(s, J_APP0, 14, app0);
ssdv_write_marker(s, J_DQT, 65, dqt0); /* DQT Luminance */
ssdv_write_marker(s, J_DQT, 65, dqt1); /* DQT Chrominance */
ssdv_write_marker(s, J_SOF0, 15, sof0); /* SOF0 (Baseline DCT) */
/* Build SOF0 header */
b[0] = 8; /* Precision */
b[1] = s->height >> 8;
b[2] = s->height & 0xFF;
b[3] = s->width >> 8;
b[4] = s->width & 0xFF;
b[5] = 3; /* Components (Y'Cb'Cr) */
b[6] = 1; /* Y */
b[7] = 0x22;
b[8] = 0x00;
b[9] = 2; /* Cb */
b[10] = 0x11;
b[11] = 0x01;
b[12] = 3; /* Cr */
b[13] = 0x11;
b[14] = 0x01;
ssdv_write_marker(s, J_SOF0, 15, b); /* SOF0 (Baseline DCT) */
ssdv_write_marker(s, J_DHT, 29, dht00); /* DHT (DC Luminance) */
ssdv_write_marker(s, J_DHT, 179, dht10); /* DHT (AC Luminance) */
ssdv_write_marker(s, J_DHT, 29, dht01); /* DHT (DC Chrominance */
@ -740,7 +765,7 @@ char ssdv_dec_init(ssdv_t *s)
memset(s, 0, sizeof(ssdv_t));
/* The packet data should contain only scan data, no headers */
s->state = J_HUFF;
s->state = S_HUFF;
/* Converting absolute values to relative */
s->dcmode = 1;
@ -757,20 +782,6 @@ char ssdv_dec_init(ssdv_t *s)
return(SSDV_OK);
}
//char ssdv_dec_set_buffer(ssdv_t *s, uint8_t *buffer, size_t length)
//{
// size_t c = s->outp - s->out;
//
// s->outp = buffer + c;
// s->out = buffer;
// s->out_len = length - c;
//
// /* Flush the output bits */
// ssdv_outbits(s, 0, 0);
//
// return(SSDV_OK);
//}
char ssdv_dec_feed(ssdv_t *s, uint8_t *packet)
{
int i = 0, r;
@ -825,7 +836,7 @@ char ssdv_dec_feed(ssdv_t *s, uint8_t *packet)
}
/* Reset the JPEG decoder state */
s->state = J_HUFF;
s->state = S_HUFF;
s->component = 0;
s->mcupart = 0;
s->acpart = 0;
@ -897,7 +908,7 @@ char ssdv_dec_get_jpeg(ssdv_t *s, uint8_t **jpeg, size_t *length)
return(SSDV_OK);
}
char ssdv_dec_is_packet(uint8_t *packet)
char ssdv_dec_is_packet(uint8_t *packet, int *errors)
{
int i;
@ -909,6 +920,8 @@ char ssdv_dec_is_packet(uint8_t *packet)
if(i < 0) return(-1); /* Reed-solomon decoder failed */
if(i > 0) fprintf(stderr, "ssdv: %i bytes corrected\n", i);
if(errors) *errors = i;
/* Appears to be a valid packet */
return(0);
}

Wyświetl plik

@ -379,7 +379,10 @@ void ssdv_rx::put_byte(uint8_t byte, int lost)
/* Test if this is a packet and is valid */
uint8_t *b = &buffer[bc];
if(ssdv_dec_is_packet(b) != 0) return;
if(ssdv_dec_is_packet(b, &i) != 0) return;
/* Make a note of the number of errors */
image_errors += i;
/* Packet received.. upload to server */
if(progdefaults.dl_online) upload_packet();
@ -398,6 +401,7 @@ void ssdv_rx::put_byte(uint8_t byte, int lost)
image_width = pkt_info.width;
image_height = pkt_info.height;
image_lost_packets = 0;
image_errors = 0;
/* Clear the image buffer */
memset(image, 0x80, IMG_SIZE);
@ -446,19 +450,9 @@ void ssdv_rx::put_byte(uint8_t byte, int lost)
habCustom->color(FL_GREEN);
}
/* TODO: Dynamic allocation */
//size_t length = 128 * 1024;
//uint8_t *jpeg = (uint8_t *) malloc(length);
//if(!jpeg)
//{
// perror("malloc");
// return;
//}
/* Initialise the decoder */
ssdv_t dec;
ssdv_dec_init(&dec);
//ssdv_dec_set_buffer(&dec, jpeg, length);
image_lost_packets = 0;
for(i = 0; i < packets_len; i++)
@ -499,8 +493,8 @@ void ssdv_rx::put_byte(uint8_t byte, int lost)
snprintf(s, 16, "%d", image_lost_packets);
flmissing->copy_label(s);
//snprintf(s, 16, "%d", img_errors);
//flfixes->copy_label(s);
snprintf(s, 16, "%d", image_errors);
flfixes->copy_label(s);
flprogress->maximum(dec.mcu_count);
flprogress->value(mcu_id);