From 69944cb29a7bd632a1b5051dab47b95c4fb9c415 Mon Sep 17 00:00:00 2001 From: Philip Heron Date: Sat, 4 Mar 2023 13:10:13 +0000 Subject: [PATCH] Add option to override packet length from the standard 256 bytes --- main.c | 32 +++++++++++++++++++++++++------- ssdv.c | 39 ++++++++++++++++++++++++++++----------- ssdv.h | 11 ++++++----- 3 files changed, 59 insertions(+), 23 deletions(-) diff --git a/main.c b/main.c index 86797b8..8f1d405 100644 --- a/main.c +++ b/main.c @@ -26,7 +26,8 @@ void exit_usage() { fprintf(stderr, - "Usage: ssdv [-e|-d] [-n] [-t ] [-c ] [-i ] [-q ] [] []\n" + "\n" + "Usage: ssdv [-e|-d] [-n] [-t ] [-c ] [-i ] [-q ] [-l ] [] []\n" "\n" " -e Encode JPEG to SSDV packets.\n" " -d Decode SSDV packets to JPEG.\n" @@ -36,7 +37,13 @@ void exit_usage() " -c Set the callign. Accepts A-Z 0-9 and space, up to 6 characters.\n" " -i Set the image ID (0-255).\n" " -q Set the JPEG quality level (0 to 7, defaults to 4).\n" + " -l Set packet length in bytes (max: 256, default 256).\n" " -v Print data for each packet decoded.\n" + "\n" + "Packet Length\n" + "\n" + "The packet length must be specified for both encoding and decoding if not\n" + "the default 256 bytes. Smaller packets will increase overhead.\n" "\n"); exit(-1); } @@ -54,6 +61,7 @@ int main(int argc, char *argv[]) char callsign[7]; uint8_t image_id = 0; int8_t quality = 4; + int pkt_length = SSDV_PKT_SIZE; ssdv_t ssdv; uint8_t pkt[SSDV_PKT_SIZE], b[128], *jpeg; @@ -62,7 +70,7 @@ int main(int argc, char *argv[]) callsign[0] = '\0'; opterr = 0; - while((c = getopt(argc, argv, "ednc:i:q:t:v")) != -1) + while((c = getopt(argc, argv, "ednc:i:q:l:t:v")) != -1) { switch(c) { @@ -77,6 +85,7 @@ int main(int argc, char *argv[]) break; case 'i': image_id = atoi(optarg); break; case 'q': quality = atoi(optarg); break; + case 'l': pkt_length = atoi(optarg); break; case 't': droptest = atoi(optarg); break; case 'v': verbose = 1; break; case '?': exit_usage(); @@ -117,22 +126,26 @@ int main(int argc, char *argv[]) switch(encode) { case 0: /* Decode */ + if(droptest > 0) fprintf(stderr, "*** NOTE: Drop test enabled: %i ***\n", droptest); - ssdv_dec_init(&ssdv); + if(ssdv_dec_init(&ssdv, pkt_length) != SSDV_OK) + { + return(-1); + } jpeg_length = 1024 * 1024 * 4; jpeg = malloc(jpeg_length); ssdv_dec_set_buffer(&ssdv, jpeg, jpeg_length); i = 0; - while(fread(pkt, 1, SSDV_PKT_SIZE, fin) > 0) + while(fread(pkt, 1, pkt_length, fin) > 0) { /* Drop % of packets */ if(droptest && (rand() / (RAND_MAX / 100) < droptest)) continue; /* Test the packet is valid */ - if(ssdv_dec_is_packet(pkt, &errors) != 0) continue; + if(ssdv_dec_is_packet(pkt, pkt_length, &errors) != 0) continue; if(verbose) { @@ -171,7 +184,12 @@ int main(int argc, char *argv[]) break; case 1: /* Encode */ - ssdv_enc_init(&ssdv, type, callsign, image_id, quality); + + if(ssdv_enc_init(&ssdv, type, callsign, image_id, quality, pkt_length) != SSDV_OK) + { + return(-1); + } + ssdv_enc_set_buffer(&ssdv, pkt); i = 0; @@ -201,7 +219,7 @@ int main(int argc, char *argv[]) return(-1); } - fwrite(pkt, 1, SSDV_PKT_SIZE, fout); + fwrite(pkt, 1, pkt_length, fout); i++; } diff --git a/ssdv.c b/ssdv.c index c6f8b84..578f60a 100644 --- a/ssdv.c +++ b/ssdv.c @@ -643,12 +643,12 @@ static void ssdv_set_packet_conf(ssdv_t *s) 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_payload = s->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_payload = s->pkt_size - SSDV_PKT_SIZE_HEADER - SSDV_PKT_SIZE_CRC; s->pkt_size_crcdata = SSDV_PKT_SIZE_HEADER + s->pkt_size_payload - 1; break; } @@ -919,18 +919,27 @@ static char ssdv_have_marker_data(ssdv_t *s) return(SSDV_OK); } -char ssdv_enc_init(ssdv_t *s, uint8_t type, char *callsign, uint8_t image_id, int8_t quality) +char ssdv_enc_init(ssdv_t *s, uint8_t type, char *callsign, uint8_t image_id, int8_t quality, int pkt_size) { /* Limit the quality level */ if(quality < 0) quality = 0; if(quality > 7) quality = 7; + /* Limit the packet length */ + if(pkt_size > SSDV_PKT_SIZE || + pkt_size - SSDV_PKT_SIZE_HEADER - SSDV_PKT_SIZE_CRC - (type == SSDV_TYPE_NORMAL ? SSDV_PKT_SIZE_RSCODES : 0) < 2) + { + fprintf(stderr, "Invalid SSDV packet length\n"); + return(SSDV_ERROR); + } + memset(s, 0, sizeof(ssdv_t)); s->image_id = image_id; s->callsign = encode_callsign(callsign); s->mode = S_ENCODING; s->type = type; s->quality = quality; + s->pkt_size = pkt_size; ssdv_set_packet_conf(s); /* Prepare the output JPEG tables */ @@ -951,7 +960,7 @@ char ssdv_enc_set_buffer(ssdv_t *s, uint8_t *buffer) s->out_len = s->pkt_size_payload; /* Zero the payload memory */ - memset(s->out, 0, SSDV_PKT_SIZE); + memset(s->out, 0, s->pkt_size); /* Flush the output bits */ ssdv_outbits(s, 0, 0); @@ -1210,9 +1219,17 @@ 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, int pkt_size) { + /* Limit the packet length */ + if(pkt_size > SSDV_PKT_SIZE) + { + fprintf(stderr, "Invalid SSDV packet length\n"); + return(SSDV_ERROR); + } + memset(s, 0, sizeof(ssdv_t)); + s->pkt_size = pkt_size; /* The packet data should contain only scan data, no headers */ s->state = S_HUFF; @@ -1407,7 +1424,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, int *errors) +char ssdv_dec_is_packet(uint8_t *packet, int pkt_size, int *errors) { uint8_t pkt[SSDV_PKT_SIZE]; uint8_t type; @@ -1418,7 +1435,7 @@ char ssdv_dec_is_packet(uint8_t *packet, int *errors) int i; /* Testing is destructive, work on a copy */ - memcpy(pkt, packet, SSDV_PKT_SIZE); + memcpy(pkt, packet, pkt_size); pkt[0] = 0x55; type = SSDV_TYPE_INVALID; @@ -1426,7 +1443,7 @@ char ssdv_dec_is_packet(uint8_t *packet, int *errors) if(pkt[1] == 0x66 + SSDV_TYPE_NOFEC) { /* Test for a valid NOFEC packet */ - pkt_size_payload = SSDV_PKT_SIZE - SSDV_PKT_SIZE_HEADER - SSDV_PKT_SIZE_CRC; + pkt_size_payload = pkt_size - SSDV_PKT_SIZE_HEADER - SSDV_PKT_SIZE_CRC; pkt_size_crcdata = SSDV_PKT_SIZE_HEADER + pkt_size_payload - 1; /* No FEC scan */ @@ -1445,7 +1462,7 @@ char ssdv_dec_is_packet(uint8_t *packet, int *errors) else if(pkt[1] == 0x66 + SSDV_TYPE_NORMAL) { /* Test for a valid NORMAL packet */ - pkt_size_payload = SSDV_PKT_SIZE - SSDV_PKT_SIZE_HEADER - SSDV_PKT_SIZE_CRC - SSDV_PKT_SIZE_RSCODES; + pkt_size_payload = 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; /* No FEC scan */ @@ -1465,7 +1482,7 @@ char ssdv_dec_is_packet(uint8_t *packet, int *errors) if(type == SSDV_TYPE_INVALID) { /* Test for a valid NORMAL packet with correctable errors */ - pkt_size_payload = SSDV_PKT_SIZE - SSDV_PKT_SIZE_HEADER - SSDV_PKT_SIZE_CRC - SSDV_PKT_SIZE_RSCODES; + pkt_size_payload = 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 */ @@ -1504,7 +1521,7 @@ char ssdv_dec_is_packet(uint8_t *packet, int *errors) } /* Appears to be a valid packet! Copy it back */ - memcpy(packet, pkt, SSDV_PKT_SIZE); + memcpy(packet, pkt, pkt_size); return(0); } diff --git a/ssdv.h b/ssdv.h index a536562..59fa59c 100644 --- a/ssdv.h +++ b/ssdv.h @@ -49,10 +49,11 @@ extern "C" { typedef struct { /* Packet type configuration */ - uint8_t type; /* 0 = Normal mode (224 byte packet + 32 bytes FEC), - 1 = No-FEC mode (256 byte packet) */ + uint8_t type; /* 0 = Normal mode (nom. 224 byte packet + 32 bytes FEC), + 1 = No-FEC mode (nom. 256 byte packet) */ uint16_t pkt_size_payload; uint16_t pkt_size_crcdata; + int pkt_size; /* Image information */ uint16_t width; @@ -146,18 +147,18 @@ typedef struct { } ssdv_packet_info_t; /* Encoding */ -extern char ssdv_enc_init(ssdv_t *s, uint8_t type, char *callsign, uint8_t image_id, int8_t quality); +extern char ssdv_enc_init(ssdv_t *s, uint8_t type, char *callsign, uint8_t image_id, int8_t quality, int pkt_size); 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, int pkt_size); 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, int *errors); +extern char ssdv_dec_is_packet(uint8_t *packet, int pkt_size, int *errors); extern void ssdv_dec_header(ssdv_packet_info_t *info, uint8_t *packet); #ifdef __cplusplus