Add option to override packet length from the standard 256 bytes

master
Philip Heron 2023-03-04 13:10:13 +00:00
rodzic 3f60ec89e9
commit 69944cb29a
3 zmienionych plików z 59 dodań i 23 usunięć

32
main.c
Wyświetl plik

@ -26,7 +26,8 @@
void exit_usage()
{
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"
" -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++;
}

39
ssdv.c
Wyświetl plik

@ -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);
}

11
ssdv.h
Wyświetl plik

@ -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