Add an option to encode/decode without FEC

This commit is contained in:
Philip Heron 2014-08-27 23:49:25 +01:00
parent 17766a8447
commit 22d912f7de
3 changed files with 37 additions and 12 deletions

15
main.c
View File

@ -25,7 +25,7 @@
void exit_usage() void exit_usage()
{ {
fprintf(stderr, "Usage: ssdv [-e|-d] [-t <percentage>] [-c <callsign>] [-i <id>] [<in file>] [<out file>]\n"); fprintf(stderr, "Usage: ssdv [-e|-d] [-n] [-t <percentage>] [-c <callsign>] [-i <id>] [<in file>] [<out file>]\n");
exit(-1); exit(-1);
} }
@ -35,6 +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;
int droptest = 0; int droptest = 0;
char callsign[7]; char callsign[7];
uint8_t image_id = 0; uint8_t image_id = 0;
@ -46,12 +47,13 @@ int main(int argc, char *argv[])
callsign[0] = '\0'; callsign[0] = '\0';
opterr = 0; opterr = 0;
while((c = getopt(argc, argv, "edc:i:t:")) != -1) while((c = getopt(argc, argv, "ednc:i:t:")) != -1)
{ {
switch(c) switch(c)
{ {
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 '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");
@ -105,14 +107,16 @@ int main(int argc, char *argv[])
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, SSDV_PKT_SIZE, fin) > 0) while(fread(pkt, 1, (fec ? SSDV_PKT_SIZE : SSDV_PKT_SIZE - SSDV_PKT_SIZE_RSCODES), 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) != 0) continue; if(ssdv_dec_is_packet(pkt, NULL, (fec ? 1 : 0)) != 0) continue;
/* Feed it to the decoder */ /* Feed it to the decoder */
ssdv_dec_feed(&ssdv, pkt); ssdv_dec_feed(&ssdv, pkt);
@ -130,6 +134,7 @@ int main(int argc, char *argv[])
case 1: /* Encode */ case 1: /* Encode */
ssdv_enc_init(&ssdv, callsign, image_id); ssdv_enc_init(&ssdv, 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;
@ -158,7 +163,7 @@ int main(int argc, char *argv[])
return(-1); return(-1);
} }
fwrite(pkt, 1, SSDV_PKT_SIZE, fout); fwrite(pkt, 1, (fec ? SSDV_PKT_SIZE : SSDV_PKT_SIZE - SSDV_PKT_SIZE_RSCODES), fout);
i++; i++;
} }

18
ssdv.c
View File

@ -820,6 +820,7 @@ char ssdv_enc_init(ssdv_t *s, char *callsign, uint8_t image_id)
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;
/* 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));
@ -970,7 +971,7 @@ char ssdv_enc_get_packet(ssdv_t *s)
s->out[i++] = x & 0xFF; s->out[i++] = x & 0xFF;
/* Generate the RS codes */ /* Generate the RS codes */
encode_rs_8(&s->out[1], &s->out[i], 0); if(s->fec == 1) encode_rs_8(&s->out[1], &s->out[i], 0);
s->packet_id++; s->packet_id++;
@ -1100,6 +1101,7 @@ char ssdv_dec_init(ssdv_t *s)
/* 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;
/* 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));
@ -1260,7 +1262,7 @@ 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) char ssdv_dec_is_packet(uint8_t *packet, int *errors, uint8_t fec)
{ {
uint8_t pkt[SSDV_PKT_SIZE]; uint8_t pkt[SSDV_PKT_SIZE];
ssdv_packet_info_t p; ssdv_packet_info_t p;
@ -1272,10 +1274,17 @@ char ssdv_dec_is_packet(uint8_t *packet, int *errors)
pkt[0] = 0x55; pkt[0] = 0x55;
pkt[1] = 0x66; pkt[1] = 0x66;
if(fec == 0)
{
if(errors) *errors = 0;
}
else if(fec == 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(i < 0) return(-1); /* Reed-solomon decoder failed */
if(errors) *errors = i; if(errors) *errors = i;
}
/* Sanity checks */ /* Sanity checks */
if(pkt[1] != 0x66) return(-1); if(pkt[1] != 0x66) return(-1);
@ -1320,3 +1329,8 @@ 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;
}

8
ssdv.h
View File

@ -45,6 +45,9 @@ extern "C" {
typedef struct typedef struct
{ {
/* Flags */
uint8_t fec; /* 0 == None, 1 = RS8 */
/* Image information */ /* Image information */
uint16_t width; uint16_t width;
uint16_t height; uint16_t height;
@ -141,9 +144,12 @@ 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);
extern char ssdv_dec_is_packet(uint8_t *packet, int *errors); 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