Add option to override packet length from the standard 256 bytes

This commit is contained in:
Philip Heron 2023-03-04 13:10:13 +00:00
parent 3f60ec89e9
commit 69944cb29a
3 changed files with 59 additions and 23 deletions

32
main.c
View File

@ -26,7 +26,8 @@
void exit_usage() void exit_usage()
{ {
fprintf(stderr, fprintf(stderr,
"Usage: ssdv [-e|-d] [-n] [-t <percentage>] [-c <callsign>] [-i <id>] [-q <level>] [<in file>] [<out file>]\n" "\n"
"Usage: ssdv [-e|-d] [-n] [-t <percentage>] [-c <callsign>] [-i <id>] [-q <level>] [-l <length>] [<in file>] [<out file>]\n"
"\n" "\n"
" -e Encode JPEG to SSDV packets.\n" " -e Encode JPEG to SSDV packets.\n"
" -d Decode SSDV packets to JPEG.\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" " -c Set the callign. Accepts A-Z 0-9 and space, up to 6 characters.\n"
" -i Set the image ID (0-255).\n" " -i Set the image ID (0-255).\n"
" -q Set the JPEG quality level (0 to 7, defaults to 4).\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" " -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"); "\n");
exit(-1); exit(-1);
} }
@ -54,6 +61,7 @@ int main(int argc, char *argv[])
char callsign[7]; char callsign[7];
uint8_t image_id = 0; uint8_t image_id = 0;
int8_t quality = 4; int8_t quality = 4;
int pkt_length = SSDV_PKT_SIZE;
ssdv_t ssdv; ssdv_t ssdv;
uint8_t pkt[SSDV_PKT_SIZE], b[128], *jpeg; uint8_t pkt[SSDV_PKT_SIZE], b[128], *jpeg;
@ -62,7 +70,7 @@ int main(int argc, char *argv[])
callsign[0] = '\0'; callsign[0] = '\0';
opterr = 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) switch(c)
{ {
@ -77,6 +85,7 @@ int main(int argc, char *argv[])
break; break;
case 'i': image_id = atoi(optarg); break; case 'i': image_id = atoi(optarg); break;
case 'q': quality = atoi(optarg); break; case 'q': quality = atoi(optarg); break;
case 'l': pkt_length = atoi(optarg); break;
case 't': droptest = atoi(optarg); break; case 't': droptest = atoi(optarg); break;
case 'v': verbose = 1; break; case 'v': verbose = 1; break;
case '?': exit_usage(); case '?': exit_usage();
@ -117,22 +126,26 @@ int main(int argc, char *argv[])
switch(encode) switch(encode)
{ {
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); if(ssdv_dec_init(&ssdv, pkt_length) != SSDV_OK)
{
return(-1);
}
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);
i = 0; i = 0;
while(fread(pkt, 1, SSDV_PKT_SIZE, fin) > 0) while(fread(pkt, 1, pkt_length, 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, &errors) != 0) continue; if(ssdv_dec_is_packet(pkt, pkt_length, &errors) != 0) continue;
if(verbose) if(verbose)
{ {
@ -171,7 +184,12 @@ int main(int argc, char *argv[])
break; break;
case 1: /* Encode */ 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); ssdv_enc_set_buffer(&ssdv, pkt);
i = 0; i = 0;
@ -201,7 +219,7 @@ int main(int argc, char *argv[])
return(-1); return(-1);
} }
fwrite(pkt, 1, SSDV_PKT_SIZE, fout); fwrite(pkt, 1, pkt_length, fout);
i++; i++;
} }

39
ssdv.c
View File

@ -643,12 +643,12 @@ static void ssdv_set_packet_conf(ssdv_t *s)
switch(s->type) switch(s->type)
{ {
case SSDV_TYPE_NORMAL: 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; s->pkt_size_crcdata = SSDV_PKT_SIZE_HEADER + s->pkt_size_payload - 1;
break; break;
case SSDV_TYPE_NOFEC: 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; s->pkt_size_crcdata = SSDV_PKT_SIZE_HEADER + s->pkt_size_payload - 1;
break; break;
} }
@ -919,18 +919,27 @@ static char ssdv_have_marker_data(ssdv_t *s)
return(SSDV_OK); 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 */ /* Limit the quality level */
if(quality < 0) quality = 0; if(quality < 0) quality = 0;
if(quality > 7) quality = 7; 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)); 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->type = type; s->type = type;
s->quality = quality; s->quality = quality;
s->pkt_size = pkt_size;
ssdv_set_packet_conf(s); ssdv_set_packet_conf(s);
/* Prepare the output JPEG tables */ /* 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; 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, s->pkt_size);
/* Flush the output bits */ /* Flush the output bits */
ssdv_outbits(s, 0, 0); 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)); memset(s, 0, sizeof(ssdv_t));
s->pkt_size = pkt_size;
/* 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;
@ -1407,7 +1424,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 pkt_size, int *errors)
{ {
uint8_t pkt[SSDV_PKT_SIZE]; uint8_t pkt[SSDV_PKT_SIZE];
uint8_t type; uint8_t type;
@ -1418,7 +1435,7 @@ char ssdv_dec_is_packet(uint8_t *packet, int *errors)
int i; int i;
/* Testing is destructive, work on a copy */ /* Testing is destructive, work on a copy */
memcpy(pkt, packet, SSDV_PKT_SIZE); memcpy(pkt, packet, pkt_size);
pkt[0] = 0x55; pkt[0] = 0x55;
type = SSDV_TYPE_INVALID; 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) if(pkt[1] == 0x66 + SSDV_TYPE_NOFEC)
{ {
/* Test for a valid NOFEC packet */ /* 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; pkt_size_crcdata = SSDV_PKT_SIZE_HEADER + pkt_size_payload - 1;
/* No FEC scan */ /* 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) else if(pkt[1] == 0x66 + SSDV_TYPE_NORMAL)
{ {
/* Test for a valid NORMAL packet */ /* 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; pkt_size_crcdata = SSDV_PKT_SIZE_HEADER + pkt_size_payload - 1;
/* No FEC scan */ /* No FEC scan */
@ -1465,7 +1482,7 @@ char ssdv_dec_is_packet(uint8_t *packet, int *errors)
if(type == SSDV_TYPE_INVALID) if(type == SSDV_TYPE_INVALID)
{ {
/* Test for a valid NORMAL packet with correctable errors */ /* 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; pkt_size_crcdata = SSDV_PKT_SIZE_HEADER + pkt_size_payload - 1;
/* Run the reed-solomon decoder */ /* 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 */ /* Appears to be a valid packet! Copy it back */
memcpy(packet, pkt, SSDV_PKT_SIZE); memcpy(packet, pkt, pkt_size);
return(0); return(0);
} }

11
ssdv.h
View File

@ -49,10 +49,11 @@ extern "C" {
typedef struct typedef struct
{ {
/* Packet type configuration */ /* Packet type configuration */
uint8_t type; /* 0 = Normal mode (224 byte packet + 32 bytes FEC), uint8_t type; /* 0 = Normal mode (nom. 224 byte packet + 32 bytes FEC),
1 = No-FEC mode (256 byte packet) */ 1 = No-FEC mode (nom. 256 byte packet) */
uint16_t pkt_size_payload; uint16_t pkt_size_payload;
uint16_t pkt_size_crcdata; uint16_t pkt_size_crcdata;
int pkt_size;
/* Image information */ /* Image information */
uint16_t width; uint16_t width;
@ -146,18 +147,18 @@ typedef struct {
} ssdv_packet_info_t; } ssdv_packet_info_t;
/* Encoding */ /* 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_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, int pkt_size);
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);
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); extern void ssdv_dec_header(ssdv_packet_info_t *info, uint8_t *packet);
#ifdef __cplusplus #ifdef __cplusplus