The decoder now auto detects packets without FEC.
Add a verbose option to print data about each packet.
This commit is contained in:
parent
062537a7e9
commit
421a9be721
9
main.c
9
main.c
|
@ -31,7 +31,7 @@ void exit_usage()
|
||||||
" -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"
|
||||||
"\n"
|
"\n"
|
||||||
" -n Encode or decode packets with no FEC.\n"
|
" -n Encode packets with no FEC.\n"
|
||||||
" -t For testing, drops the specified percentage of packets while decoding.\n"
|
" -t For testing, drops the specified percentage of packets while decoding.\n"
|
||||||
" -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"
|
||||||
|
@ -115,7 +115,7 @@ int main(int argc, char *argv[])
|
||||||
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, type);
|
ssdv_dec_init(&ssdv);
|
||||||
|
|
||||||
jpeg_length = 1024 * 1024 * 4;
|
jpeg_length = 1024 * 1024 * 4;
|
||||||
jpeg = malloc(jpeg_length);
|
jpeg = malloc(jpeg_length);
|
||||||
|
@ -128,7 +128,7 @@ int main(int argc, char *argv[])
|
||||||
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, type) != 0) continue;
|
if(ssdv_dec_is_packet(pkt, &errors) != 0) continue;
|
||||||
|
|
||||||
if(verbose)
|
if(verbose)
|
||||||
{
|
{
|
||||||
|
@ -136,13 +136,14 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
ssdv_dec_header(&p, pkt);
|
ssdv_dec_header(&p, pkt);
|
||||||
fprintf(stderr, "Decoded image packet. Callsign: %s, Image ID: %d, Resolution: %dx%d, Packet ID: %d (%d errors corrected)\n"
|
fprintf(stderr, "Decoded image packet. Callsign: %s, Image ID: %d, Resolution: %dx%d, Packet ID: %d (%d errors corrected)\n"
|
||||||
">> EOI: %d, MCU Mode: %d, MCU Offset: %d, MCU ID: %d/%d\n",
|
">> Type: %d, EOI: %d, MCU Mode: %d, MCU Offset: %d, MCU ID: %d/%d\n",
|
||||||
p.callsign_s,
|
p.callsign_s,
|
||||||
p.image_id,
|
p.image_id,
|
||||||
p.width,
|
p.width,
|
||||||
p.height,
|
p.height,
|
||||||
p.packet_id,
|
p.packet_id,
|
||||||
errors,
|
errors,
|
||||||
|
p.type,
|
||||||
p.eoi,
|
p.eoi,
|
||||||
p.mcu_mode,
|
p.mcu_mode,
|
||||||
p.mcu_offset,
|
p.mcu_offset,
|
||||||
|
|
46
ssdv.c
46
ssdv.c
|
@ -1115,15 +1115,13 @@ static void ssdv_fill_gap(ssdv_t *s, uint16_t next_mcu)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char ssdv_dec_init(ssdv_t *s, uint8_t type)
|
char ssdv_dec_init(ssdv_t *s)
|
||||||
{
|
{
|
||||||
memset(s, 0, sizeof(ssdv_t));
|
memset(s, 0, sizeof(ssdv_t));
|
||||||
|
|
||||||
/* 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->type = type;
|
|
||||||
ssdv_set_packet_conf(s);
|
|
||||||
|
|
||||||
/* 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));
|
||||||
|
@ -1178,6 +1176,7 @@ char ssdv_dec_feed(ssdv_t *s, uint8_t *packet)
|
||||||
char callsign[SSDV_MAX_CALLSIGN + 1];
|
char callsign[SSDV_MAX_CALLSIGN + 1];
|
||||||
|
|
||||||
/* Read the fixed headers from the packet */
|
/* Read the fixed headers from the packet */
|
||||||
|
s->type = packet[1] - 0x66;
|
||||||
s->callsign = (packet[2] << 24) | (packet[3] << 16) | (packet[4] << 8) | packet[5];
|
s->callsign = (packet[2] << 24) | (packet[3] << 16) | (packet[4] << 8) | packet[5];
|
||||||
s->image_id = packet[6];
|
s->image_id = packet[6];
|
||||||
s->width = packet[9] << 4;
|
s->width = packet[9] << 4;
|
||||||
|
@ -1185,6 +1184,9 @@ char ssdv_dec_feed(ssdv_t *s, uint8_t *packet)
|
||||||
s->mcu_count = packet[9] * packet[10];
|
s->mcu_count = packet[9] * packet[10];
|
||||||
s->mcu_mode = packet[11] & 0x03;
|
s->mcu_mode = packet[11] & 0x03;
|
||||||
|
|
||||||
|
/* Configure the payload size and CRC position */
|
||||||
|
ssdv_set_packet_conf(s);
|
||||||
|
|
||||||
switch(s->mcu_mode)
|
switch(s->mcu_mode)
|
||||||
{
|
{
|
||||||
case 0: factor = "2x2"; s->ycparts = 4; break;
|
case 0: factor = "2x2"; s->ycparts = 4; break;
|
||||||
|
@ -1284,9 +1286,10 @@ 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, uint8_t type)
|
char ssdv_dec_is_packet(uint8_t *packet, int *errors)
|
||||||
{
|
{
|
||||||
uint8_t pkt[SSDV_PKT_SIZE];
|
uint8_t pkt[SSDV_PKT_SIZE];
|
||||||
|
uint8_t type;
|
||||||
uint16_t pkt_size_payload;
|
uint16_t pkt_size_payload;
|
||||||
uint16_t pkt_size_crcdata;
|
uint16_t pkt_size_crcdata;
|
||||||
ssdv_packet_info_t p;
|
ssdv_packet_info_t p;
|
||||||
|
@ -1296,37 +1299,35 @@ char ssdv_dec_is_packet(uint8_t *packet, int *errors, uint8_t type)
|
||||||
/* Testing is destructive, work on a copy */
|
/* Testing is destructive, work on a copy */
|
||||||
memcpy(pkt, packet, SSDV_PKT_SIZE);
|
memcpy(pkt, packet, SSDV_PKT_SIZE);
|
||||||
pkt[0] = 0x55;
|
pkt[0] = 0x55;
|
||||||
pkt[1] = 0x66 + type;
|
|
||||||
|
|
||||||
switch(type)
|
if(pkt[1] == 0x66 + SSDV_TYPE_NOFEC)
|
||||||
{
|
{
|
||||||
case SSDV_TYPE_NORMAL:
|
type = SSDV_TYPE_NOFEC;
|
||||||
pkt_size_payload = SSDV_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 */
|
|
||||||
i = decode_rs_8(&pkt[1], 0, 0, 0);
|
|
||||||
if(errors) *errors = 0;
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SSDV_TYPE_NOFEC:
|
|
||||||
pkt_size_payload = SSDV_PKT_SIZE - SSDV_PKT_SIZE_HEADER - SSDV_PKT_SIZE_CRC;
|
pkt_size_payload = SSDV_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;
|
||||||
|
|
||||||
if(errors) *errors = 0;
|
if(errors) *errors = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
type = SSDV_TYPE_NORMAL;
|
||||||
|
|
||||||
break;
|
pkt_size_payload = SSDV_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;
|
||||||
|
|
||||||
default:
|
/* Run the reed-solomon decoder */
|
||||||
fprintf(stderr, "Invalid packet type\n");
|
pkt[1] = 0x66 + SSDV_TYPE_NORMAL;
|
||||||
return(-1);
|
i = decode_rs_8(&pkt[1], 0, 0, 0);
|
||||||
|
|
||||||
|
if(i < 0) return(-1); /* Reed-solomon decoder failed */
|
||||||
|
if(errors) *errors = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sanity checks */
|
/* Sanity checks */
|
||||||
if(pkt[1] != 0x66 + type) return(-1);
|
|
||||||
|
|
||||||
ssdv_dec_header(&p, pkt);
|
ssdv_dec_header(&p, pkt);
|
||||||
|
|
||||||
|
if(p.type != type) return(-1);
|
||||||
if(p.width == 0 || p.height == 0) return(-1);
|
if(p.width == 0 || p.height == 0) return(-1);
|
||||||
if(p.mcu_id != 0xFFFF)
|
if(p.mcu_id != 0xFFFF)
|
||||||
{
|
{
|
||||||
|
@ -1351,6 +1352,7 @@ char ssdv_dec_is_packet(uint8_t *packet, int *errors, uint8_t type)
|
||||||
|
|
||||||
void ssdv_dec_header(ssdv_packet_info_t *info, uint8_t *packet)
|
void ssdv_dec_header(ssdv_packet_info_t *info, uint8_t *packet)
|
||||||
{
|
{
|
||||||
|
info->type = packet[1] - 0x66;
|
||||||
info->callsign = (packet[2] << 24) | (packet[3] << 16) | (packet[4] << 8) | packet[5];
|
info->callsign = (packet[2] << 24) | (packet[3] << 16) | (packet[4] << 8) | packet[5];
|
||||||
decode_callsign(info->callsign_s, info->callsign);
|
decode_callsign(info->callsign_s, info->callsign);
|
||||||
info->image_id = packet[6];
|
info->image_id = packet[6];
|
||||||
|
|
5
ssdv.h
5
ssdv.h
|
@ -126,6 +126,7 @@ typedef struct
|
||||||
} ssdv_t;
|
} ssdv_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
uint8_t type;
|
||||||
uint32_t callsign;
|
uint32_t callsign;
|
||||||
char callsign_s[SSDV_MAX_CALLSIGN + 1];
|
char callsign_s[SSDV_MAX_CALLSIGN + 1];
|
||||||
uint8_t image_id;
|
uint8_t image_id;
|
||||||
|
@ -146,12 +147,12 @@ 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, uint8_t type);
|
extern char ssdv_dec_init(ssdv_t *s);
|
||||||
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, uint8_t fec);
|
extern char ssdv_dec_is_packet(uint8_t *packet, 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