Make the non-FEC packets 256 bytes long, same length as normal packets.

Non-FEC packets now have a packet type of 0x67.
This commit is contained in:
Philip Heron 2014-08-28 20:13:46 +01:00
parent 22d912f7de
commit 278004fb0c
3 changed files with 78 additions and 50 deletions

17
main.c
View File

@ -35,7 +35,7 @@ int main(int argc, char *argv[])
FILE *fin = stdin; FILE *fin = stdin;
FILE *fout = stdout; FILE *fout = stdout;
char encode = -1; char encode = -1;
char fec = -1; char type = SSDV_TYPE_NORMAL;
int droptest = 0; int droptest = 0;
char callsign[7]; char callsign[7];
uint8_t image_id = 0; uint8_t image_id = 0;
@ -53,7 +53,7 @@ int main(int argc, char *argv[])
{ {
case 'e': encode = 1; break; case 'e': encode = 1; break;
case 'd': encode = 0; break; case 'd': encode = 0; break;
case 'n': fec = 0; break; case 'n': type = SSDV_TYPE_NOFEC; break;
case 'c': case 'c':
if(strlen(optarg) > 6) if(strlen(optarg) > 6)
fprintf(stderr, "Warning: callsign is longer than 6 characters.\n"); fprintf(stderr, "Warning: callsign is longer than 6 characters.\n");
@ -101,22 +101,20 @@ int main(int argc, char *argv[])
case 0: /* Decode */ case 0: /* Decode */
if(droptest > 0) fprintf(stderr, "*** NOTE: Drop test enabled: %i ***\n", droptest); if(droptest > 0) fprintf(stderr, "*** NOTE: Drop test enabled: %i ***\n", droptest);
ssdv_dec_init(&ssdv); ssdv_dec_init(&ssdv, type);
jpeg_length = 1024 * 1024 * 4; jpeg_length = 1024 * 1024 * 4;
jpeg = malloc(jpeg_length); jpeg = malloc(jpeg_length);
ssdv_dec_set_buffer(&ssdv, jpeg, jpeg_length); ssdv_dec_set_buffer(&ssdv, jpeg, jpeg_length);
ssdv_set_fec(&ssdv, (fec ? 1 : 0));
i = 0; i = 0;
while(fread(pkt, 1, (fec ? SSDV_PKT_SIZE : SSDV_PKT_SIZE - SSDV_PKT_SIZE_RSCODES), fin) > 0) while(fread(pkt, 1, SSDV_PKT_SIZE, fin) > 0)
{ {
/* Drop % of packets */ /* Drop % of packets */
if(droptest && (rand() / (RAND_MAX / 100) < droptest)) continue; if(droptest && (rand() / (RAND_MAX / 100) < droptest)) continue;
/* Test the packet is valid */ /* Test the packet is valid */
if(ssdv_dec_is_packet(pkt, NULL, (fec ? 1 : 0)) != 0) continue; if(ssdv_dec_is_packet(pkt, NULL, type) != 0) continue;
/* Feed it to the decoder */ /* Feed it to the decoder */
ssdv_dec_feed(&ssdv, pkt); ssdv_dec_feed(&ssdv, pkt);
@ -132,9 +130,8 @@ int main(int argc, char *argv[])
break; break;
case 1: /* Encode */ case 1: /* Encode */
ssdv_enc_init(&ssdv, callsign, image_id); ssdv_enc_init(&ssdv, type, callsign, image_id);
ssdv_enc_set_buffer(&ssdv, pkt); ssdv_enc_set_buffer(&ssdv, pkt);
ssdv_set_fec(&ssdv, (fec ? 1 : 0));
i = 0; i = 0;
@ -163,7 +160,7 @@ int main(int argc, char *argv[])
return(-1); return(-1);
} }
fwrite(pkt, 1, (fec ? SSDV_PKT_SIZE : SSDV_PKT_SIZE - SSDV_PKT_SIZE_RSCODES), fout); fwrite(pkt, 1, SSDV_PKT_SIZE, fout);
i++; i++;
} }

92
ssdv.c
View File

@ -531,7 +531,7 @@ static char ssdv_process(ssdv_t *s)
s->reset_mcu = s->mcu_id; s->reset_mcu = s->mcu_id;
s->packet_mcu_id = s->mcu_id; s->packet_mcu_id = s->mcu_id;
s->packet_mcu_offset = SSDV_PKT_SIZE_PAYLOAD - s->out_len; s->packet_mcu_offset = s->pkt_size_payload - s->out_len;
} }
if(s->mode == S_DECODING && s->mcu_id == s->reset_mcu) if(s->mode == S_DECODING && s->mcu_id == s->reset_mcu)
@ -557,6 +557,23 @@ static char ssdv_process(ssdv_t *s)
return(SSDV_OK); return(SSDV_OK);
} }
static void ssdv_set_packet_conf(ssdv_t *s)
{
/* Configure the payload size and CRC position */
switch(s->type)
{
case SSDV_TYPE_NORMAL:
s->pkt_size_payload = SSDV_PKT_SIZE - SSDV_PKT_SIZE_HEADER - SSDV_PKT_SIZE_CRC - SSDV_PKT_SIZE_RSCODES;
s->pkt_size_crcdata = SSDV_PKT_SIZE_HEADER + s->pkt_size_payload - 1;
break;
case SSDV_TYPE_NOFEC:
s->pkt_size_payload = SSDV_PKT_SIZE - SSDV_PKT_SIZE_HEADER - SSDV_PKT_SIZE_CRC;
s->pkt_size_crcdata = SSDV_PKT_SIZE_HEADER + s->pkt_size_payload - 1;
break;
}
}
/*****************************************************************************/ /*****************************************************************************/
static void ssdv_memset_prng(uint8_t *s, size_t n) static void ssdv_memset_prng(uint8_t *s, size_t n)
@ -814,13 +831,14 @@ static char ssdv_have_marker_data(ssdv_t *s)
return(SSDV_OK); return(SSDV_OK);
} }
char ssdv_enc_init(ssdv_t *s, char *callsign, uint8_t image_id) char ssdv_enc_init(ssdv_t *s, uint8_t type, char *callsign, uint8_t image_id)
{ {
memset(s, 0, sizeof(ssdv_t)); memset(s, 0, sizeof(ssdv_t));
s->image_id = image_id; s->image_id = image_id;
s->callsign = encode_callsign(callsign); s->callsign = encode_callsign(callsign);
s->mode = S_ENCODING; s->mode = S_ENCODING;
s->fec = 1; s->type = type;
ssdv_set_packet_conf(s);
/* Prepare the output JPEG tables */ /* Prepare the output JPEG tables */
s->ddqt[0] = dtblcpy(s, std_dqt0, sizeof(std_dqt0)); s->ddqt[0] = dtblcpy(s, std_dqt0, sizeof(std_dqt0));
@ -837,7 +855,7 @@ char ssdv_enc_set_buffer(ssdv_t *s, uint8_t *buffer)
{ {
s->out = buffer; s->out = buffer;
s->outp = buffer + SSDV_PKT_SIZE_HEADER; s->outp = buffer + SSDV_PKT_SIZE_HEADER;
s->out_len = SSDV_PKT_SIZE_PAYLOAD; s->out_len = s->pkt_size_payload;
/* Zero the payload memory */ /* Zero the payload memory */
memset(s->out, 0, SSDV_PKT_SIZE); memset(s->out, 0, SSDV_PKT_SIZE);
@ -927,12 +945,12 @@ char ssdv_enc_get_packet(ssdv_t *s)
uint8_t i, mcu_offset = s->packet_mcu_offset; uint8_t i, mcu_offset = s->packet_mcu_offset;
uint32_t x; uint32_t x;
if(mcu_offset != 0xFF && mcu_offset >= SSDV_PKT_SIZE_PAYLOAD) if(mcu_offset != 0xFF && mcu_offset >= s->pkt_size_payload)
{ {
/* The first MCU begins in the next packet, not this one */ /* The first MCU begins in the next packet, not this one */
mcu_id = 0xFFFF; mcu_id = 0xFFFF;
mcu_offset = 0xFF; mcu_offset = 0xFF;
s->packet_mcu_offset -= SSDV_PKT_SIZE_PAYLOAD; s->packet_mcu_offset -= s->pkt_size_payload;
} }
else else
{ {
@ -943,7 +961,7 @@ char ssdv_enc_get_packet(ssdv_t *s)
/* A packet is ready, create the headers */ /* A packet is ready, create the headers */
s->out[0] = 0x55; /* Sync */ s->out[0] = 0x55; /* Sync */
s->out[1] = 0x66; /* Type */ s->out[1] = 0x66 + s->type; /* Type */
s->out[2] = s->callsign >> 24; s->out[2] = s->callsign >> 24;
s->out[3] = s->callsign >> 16; s->out[3] = s->callsign >> 16;
s->out[4] = s->callsign >> 8; s->out[4] = s->callsign >> 8;
@ -962,16 +980,17 @@ char ssdv_enc_get_packet(ssdv_t *s)
if(s->out_len > 0) ssdv_memset_prng(s->outp, s->out_len); if(s->out_len > 0) ssdv_memset_prng(s->outp, s->out_len);
/* Calculate the CRC codes */ /* Calculate the CRC codes */
x = crc32(&s->out[1], SSDV_PKT_SIZE_CRCDATA); x = crc32(&s->out[1], s->pkt_size_crcdata);
i = 1 + SSDV_PKT_SIZE_CRCDATA; i = 1 + s->pkt_size_crcdata;
s->out[i++] = (x >> 24) & 0xFF; s->out[i++] = (x >> 24) & 0xFF;
s->out[i++] = (x >> 16) & 0xFF; s->out[i++] = (x >> 16) & 0xFF;
s->out[i++] = (x >> 8) & 0xFF; s->out[i++] = (x >> 8) & 0xFF;
s->out[i++] = x & 0xFF; s->out[i++] = x & 0xFF;
/* Generate the RS codes */ /* Generate the RS codes */
if(s->fec == 1) encode_rs_8(&s->out[1], &s->out[i], 0); if(s->type == SSDV_TYPE_NORMAL)
encode_rs_8(&s->out[1], &s->out[i], 0);
s->packet_id++; s->packet_id++;
@ -1094,14 +1113,15 @@ static void ssdv_fill_gap(ssdv_t *s, uint16_t next_mcu)
} }
} }
char ssdv_dec_init(ssdv_t *s) char ssdv_dec_init(ssdv_t *s, uint8_t type)
{ {
memset(s, 0, sizeof(ssdv_t)); memset(s, 0, sizeof(ssdv_t));
/* The packet data should contain only scan data, no headers */ /* The packet data should contain only scan data, no headers */
s->state = S_HUFF; s->state = S_HUFF;
s->mode = S_DECODING; s->mode = S_DECODING;
s->fec = 1; s->type = type;
ssdv_set_packet_conf(s);
/* Prepare the source JPEG tables */ /* Prepare the source JPEG tables */
s->sdqt[0] = stblcpy(s, std_dqt0, sizeof(std_dqt0)); s->sdqt[0] = stblcpy(s, std_dqt0, sizeof(std_dqt0));
@ -1212,7 +1232,7 @@ char ssdv_dec_feed(ssdv_t *s, uint8_t *packet)
} }
/* Feed the JPEG data into the processor */ /* Feed the JPEG data into the processor */
for(; i < SSDV_PKT_SIZE_PAYLOAD; i++) for(; i < s->pkt_size_payload; i++)
{ {
b = packet[SSDV_PKT_SIZE_HEADER + i]; b = packet[SSDV_PKT_SIZE_HEADER + i];
@ -1262,9 +1282,11 @@ char ssdv_dec_get_jpeg(ssdv_t *s, uint8_t **jpeg, size_t *length)
return(SSDV_OK); return(SSDV_OK);
} }
char ssdv_dec_is_packet(uint8_t *packet, int *errors, uint8_t fec) char ssdv_dec_is_packet(uint8_t *packet, int *errors, uint8_t type)
{ {
uint8_t pkt[SSDV_PKT_SIZE]; uint8_t pkt[SSDV_PKT_SIZE];
uint16_t pkt_size_payload;
uint16_t pkt_size_crcdata;
ssdv_packet_info_t p; ssdv_packet_info_t p;
uint32_t x; uint32_t x;
int i; int i;
@ -1272,35 +1294,48 @@ char ssdv_dec_is_packet(uint8_t *packet, int *errors, uint8_t fec)
/* Testing is destructive, work on a copy */ /* Testing is destructive, work on a copy */
memcpy(pkt, packet, SSDV_PKT_SIZE); memcpy(pkt, packet, SSDV_PKT_SIZE);
pkt[0] = 0x55; pkt[0] = 0x55;
pkt[1] = 0x66; pkt[1] = 0x66 + type;
if(fec == 0) switch(type)
{
if(errors) *errors = 0;
}
else if(fec == 1)
{ {
case SSDV_TYPE_NORMAL:
pkt_size_payload = SSDV_PKT_SIZE - SSDV_PKT_SIZE_HEADER - SSDV_PKT_SIZE_CRC - SSDV_PKT_SIZE_RSCODES;
pkt_size_crcdata = SSDV_PKT_SIZE_HEADER + pkt_size_payload - 1;
/* Run the reed-solomon decoder */ /* Run the reed-solomon decoder */
i = decode_rs_8(&pkt[1], 0, 0, 0); i = decode_rs_8(&pkt[1], 0, 0, 0);
if(i < 0) return(-1); /* Reed-solomon decoder failed */ if(errors) *errors = 0;
if(errors) *errors = i;
break;
case SSDV_TYPE_NOFEC:
pkt_size_payload = SSDV_PKT_SIZE - SSDV_PKT_SIZE_HEADER - SSDV_PKT_SIZE_CRC;
pkt_size_crcdata = SSDV_PKT_SIZE_HEADER + pkt_size_payload - 1;
if(errors) *errors = 0;
break;
default:
fprintf(stderr, "Invalid packet type\n");
return(-1);
} }
/* Sanity checks */ /* Sanity checks */
if(pkt[1] != 0x66) return(-1); if(pkt[1] != 0x66 + type) return(-1);
ssdv_dec_header(&p, pkt); ssdv_dec_header(&p, pkt);
if(p.width == 0 || p.height == 0) return(-1); if(p.width == 0 || p.height == 0) return(-1);
if(p.mcu_id != 0xFFFF) if(p.mcu_id != 0xFFFF)
{ {
if(p.mcu_id >= p.mcu_count) return(-1); if(p.mcu_id >= p.mcu_count) return(-1);
if(p.mcu_offset >= SSDV_PKT_SIZE_PAYLOAD) return(-1); if(p.mcu_offset >= pkt_size_payload) return(-1);
} }
/* Test the checksum */ /* Test the checksum */
x = crc32(&pkt[1], SSDV_PKT_SIZE_CRCDATA); x = crc32(&pkt[1], pkt_size_crcdata);
i = 1 + SSDV_PKT_SIZE_CRCDATA; i = 1 + pkt_size_crcdata;
if(pkt[i++] != ((x >> 24) & 0xFF)) return(-1); if(pkt[i++] != ((x >> 24) & 0xFF)) return(-1);
if(pkt[i++] != ((x >> 16) & 0xFF)) return(-1); if(pkt[i++] != ((x >> 16) & 0xFF)) return(-1);
if(pkt[i++] != ((x >> 8) & 0xFF)) return(-1); if(pkt[i++] != ((x >> 8) & 0xFF)) return(-1);
@ -1329,8 +1364,3 @@ void ssdv_dec_header(ssdv_packet_info_t *info, uint8_t *packet)
/*****************************************************************************/ /*****************************************************************************/
void ssdv_set_fec(ssdv_t *s, uint8_t fec)
{
s->fec = fec;
}

19
ssdv.h
View File

@ -36,17 +36,21 @@ extern "C" {
#define SSDV_PKT_SIZE_HEADER (0x0F) #define SSDV_PKT_SIZE_HEADER (0x0F)
#define SSDV_PKT_SIZE_CRC (0x04) #define SSDV_PKT_SIZE_CRC (0x04)
#define SSDV_PKT_SIZE_RSCODES (0x20) #define SSDV_PKT_SIZE_RSCODES (0x20)
#define SSDV_PKT_SIZE_PAYLOAD (SSDV_PKT_SIZE - SSDV_PKT_SIZE_HEADER - SSDV_PKT_SIZE_CRC - SSDV_PKT_SIZE_RSCODES)
#define SSDV_PKT_SIZE_CRCDATA (SSDV_PKT_SIZE_HEADER + SSDV_PKT_SIZE_PAYLOAD - 1)
#define TBL_LEN (546) /* Maximum size of the DQT and DHT tables */ #define TBL_LEN (546) /* Maximum size of the DQT and DHT tables */
#define HBUFF_LEN (16) /* Extra space for reading marker data */ #define HBUFF_LEN (16) /* Extra space for reading marker data */
//#define COMPONENTS (3) //#define COMPONENTS (3)
#define SSDV_TYPE_NORMAL (0)
#define SSDV_TYPE_NOFEC (1)
typedef struct typedef struct
{ {
/* Flags */ /* Packet type configuration */
uint8_t fec; /* 0 == None, 1 = RS8 */ uint8_t type; /* 0 = Normal mode (224 byte packet + 32 bytes FEC),
1 = No-FEC mode (256 byte packet) */
uint16_t pkt_size_payload;
uint16_t pkt_size_crcdata;
/* Image information */ /* Image information */
uint16_t width; uint16_t width;
@ -133,13 +137,13 @@ typedef struct {
} ssdv_packet_info_t; } ssdv_packet_info_t;
/* Encoding */ /* Encoding */
extern char ssdv_enc_init(ssdv_t *s, char *callsign, uint8_t image_id); extern char ssdv_enc_init(ssdv_t *s, uint8_t type, char *callsign, uint8_t image_id);
extern char ssdv_enc_set_buffer(ssdv_t *s, uint8_t *buffer); extern char ssdv_enc_set_buffer(ssdv_t *s, uint8_t *buffer);
extern char ssdv_enc_get_packet(ssdv_t *s); extern char ssdv_enc_get_packet(ssdv_t *s);
extern char ssdv_enc_feed(ssdv_t *s, uint8_t *buffer, size_t length); extern char ssdv_enc_feed(ssdv_t *s, uint8_t *buffer, size_t length);
/* Decoding */ /* Decoding */
extern char ssdv_dec_init(ssdv_t *s); extern char ssdv_dec_init(ssdv_t *s, uint8_t type);
extern char ssdv_dec_set_buffer(ssdv_t *s, uint8_t *buffer, size_t length); 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_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_get_jpeg(ssdv_t *s, uint8_t **jpeg, size_t *length);
@ -147,9 +151,6 @@ extern char ssdv_dec_get_jpeg(ssdv_t *s, uint8_t **jpeg, size_t *length);
extern char ssdv_dec_is_packet(uint8_t *packet, int *errors, uint8_t fec); extern char ssdv_dec_is_packet(uint8_t *packet, int *errors, uint8_t fec);
extern void ssdv_dec_header(ssdv_packet_info_t *info, uint8_t *packet); extern void ssdv_dec_header(ssdv_packet_info_t *info, uint8_t *packet);
/* Common */
extern void ssdv_set_fec(ssdv_t *s, uint8_t fec);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif