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

Non-FEC packets now have a packet type of 0x67.
pull/4/head
Philip Heron 2014-08-28 20:13:46 +01:00
rodzic 22d912f7de
commit 278004fb0c
3 zmienionych plików z 78 dodań i 50 usunięć

17
main.c
Wyświetl plik

@ -35,7 +35,7 @@ int main(int argc, char *argv[])
FILE *fin = stdin;
FILE *fout = stdout;
char encode = -1;
char fec = -1;
char type = SSDV_TYPE_NORMAL;
int droptest = 0;
char callsign[7];
uint8_t image_id = 0;
@ -53,7 +53,7 @@ int main(int argc, char *argv[])
{
case 'e': encode = 1; break;
case 'd': encode = 0; break;
case 'n': fec = 0; break;
case 'n': type = SSDV_TYPE_NOFEC; break;
case 'c':
if(strlen(optarg) > 6)
fprintf(stderr, "Warning: callsign is longer than 6 characters.\n");
@ -101,22 +101,20 @@ int main(int argc, char *argv[])
case 0: /* Decode */
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 = malloc(jpeg_length);
ssdv_dec_set_buffer(&ssdv, jpeg, jpeg_length);
ssdv_set_fec(&ssdv, (fec ? 1 : 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 */
if(droptest && (rand() / (RAND_MAX / 100) < droptest)) continue;
/* 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 */
ssdv_dec_feed(&ssdv, pkt);
@ -132,9 +130,8 @@ int main(int argc, char *argv[])
break;
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_set_fec(&ssdv, (fec ? 1 : 0));
i = 0;
@ -163,7 +160,7 @@ int main(int argc, char *argv[])
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++;
}

92
ssdv.c
Wyświetl plik

@ -531,7 +531,7 @@ static char ssdv_process(ssdv_t *s)
s->reset_mcu = 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)
@ -557,6 +557,23 @@ static char ssdv_process(ssdv_t *s)
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)
@ -814,13 +831,14 @@ static char ssdv_have_marker_data(ssdv_t *s)
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));
s->image_id = image_id;
s->callsign = encode_callsign(callsign);
s->mode = S_ENCODING;
s->fec = 1;
s->type = type;
ssdv_set_packet_conf(s);
/* Prepare the output JPEG tables */
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->outp = buffer + SSDV_PKT_SIZE_HEADER;
s->out_len = SSDV_PKT_SIZE_PAYLOAD;
s->out_len = s->pkt_size_payload;
/* Zero the payload memory */
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;
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 */
mcu_id = 0xFFFF;
mcu_offset = 0xFF;
s->packet_mcu_offset -= SSDV_PKT_SIZE_PAYLOAD;
s->packet_mcu_offset -= s->pkt_size_payload;
}
else
{
@ -943,7 +961,7 @@ char ssdv_enc_get_packet(ssdv_t *s)
/* A packet is ready, create the headers */
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[3] = s->callsign >> 16;
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);
/* 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 >> 16) & 0xFF;
s->out[i++] = (x >> 8) & 0xFF;
s->out[i++] = x & 0xFF;
/* 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++;
@ -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));
/* The packet data should contain only scan data, no headers */
s->state = S_HUFF;
s->mode = S_DECODING;
s->fec = 1;
s->type = type;
ssdv_set_packet_conf(s);
/* Prepare the source JPEG tables */
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 */
for(; i < SSDV_PKT_SIZE_PAYLOAD; i++)
for(; i < s->pkt_size_payload; 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);
}
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];
uint16_t pkt_size_payload;
uint16_t pkt_size_crcdata;
ssdv_packet_info_t p;
uint32_t x;
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 */
memcpy(pkt, packet, SSDV_PKT_SIZE);
pkt[0] = 0x55;
pkt[1] = 0x66;
pkt[1] = 0x66 + type;
if(fec == 0)
{
if(errors) *errors = 0;
}
else if(fec == 1)
switch(type)
{
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 */
i = decode_rs_8(&pkt[1], 0, 0, 0);
if(i < 0) return(-1); /* Reed-solomon decoder failed */
if(errors) *errors = i;
if(errors) *errors = 0;
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 */
if(pkt[1] != 0x66) return(-1);
if(pkt[1] != 0x66 + type) return(-1);
ssdv_dec_header(&p, pkt);
if(p.width == 0 || p.height == 0) return(-1);
if(p.mcu_id != 0xFFFF)
{
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 */
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 >> 16) & 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
Wyświetl plik

@ -36,17 +36,21 @@ extern "C" {
#define SSDV_PKT_SIZE_HEADER (0x0F)
#define SSDV_PKT_SIZE_CRC (0x04)
#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 HBUFF_LEN (16) /* Extra space for reading marker data */
//#define COMPONENTS (3)
#define SSDV_TYPE_NORMAL (0)
#define SSDV_TYPE_NOFEC (1)
typedef struct
{
/* Flags */
uint8_t fec; /* 0 == None, 1 = RS8 */
/* Packet type configuration */
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 */
uint16_t width;
@ -133,13 +137,13 @@ typedef struct {
} ssdv_packet_info_t;
/* 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_get_packet(ssdv_t *s);
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_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_feed(ssdv_t *s, uint8_t *packet);
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 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
}
#endif