Add option to override packet length from the standard 256 bytes
This commit is contained in:
parent
3f60ec89e9
commit
69944cb29a
32
main.c
32
main.c
|
@ -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
39
ssdv.c
|
@ -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
11
ssdv.h
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue