Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Mathis Rosenhauer
libaec
Commits
adddb9a0
Commit
adddb9a0
authored
May 11, 2012
by
Moritz Hanke
Browse files
adds initial code for binary header decoding
parent
6b60d7ef
Changes
4
Hide whitespace changes
Inline
Side-by-side
include/bit_macros.h
0 → 100644
View file @
adddb9a0
#define B1 (0x0001)
#define B2 (0x0003)
#define B3 (0x0007)
#define B4 (0x000F)
#define B5 (0x001F)
#define B6 (0x003F)
#define B7 (0x007F)
#define B8 (0x00FF)
#define B9 (0x01FF)
#define B10 (0x03FF)
#define B11 (0x07FF)
#define B12 (0x0FFF)
#define B13 (0x1FFF)
#define B14 (0x3FFF)
#define B15 (0x7FFF)
#define B16 (0xFFFF)
include/cip.h
0 → 100644
View file @
adddb9a0
// Copyright © 2011 Moritz Hanke
// Based on Lossless Data Compression. Blue Book. Issue 1. May 1997.
// CCSDS 121.0-B-1
//
// http://public.ccsds.org/publications/bluebooks.aspx
// http://public.ccsds.org/publications/archive/121x0b1c2.pdf
// Compression Identification Packet (optinal)
// The CIP is used to configure the decompressor in case no configuration
// data is available.
// It is comprised of the cip Primary Header (as described in "CCSDS Space
// Packet Protocol Blue Book") and the Packet Data Field.
enum
cip_packet_type
{
TELEMETRY
,
// reporting
TELECOMMAND
,
// requesting (makes no sense for compression)
};
enum
cip_sequence_flag
{
CONTINUE
=
0
,
FIRST
=
1
,
LAST
=
2
,
UNSEGMENTED
=
3
,
};
enum
cip_compression_technique
{
NO
=
0
,
// no compression is used
LOSSLESS
=
1
,
// lossless compression is used
};
enum
cip_predictor_type
{
BYPASS_P
=
0
,
// bypass predictor
UNIT_DELAY_P
=
1
,
// unit delay predictor
APP_SPECIFIC_P
=
7
,
// application-specific predictor
};
enum
cip_mapper_type
{
STANDARD_M
=
0
,
// standard prediction error mapper as described in the reference
APP_SPECIFIC_M
=
3
,
// application-specific mapper
};
enum
cip_data_sense
{
TWOS_COMPLEMENT
=
0
,
// two's complement
POSITIVE
=
1
,
// positive (mandatory if preprocessor is bypassed)
};
enum
entropy_coder_option
{
OPTION_S
=
1
,
// for resolution n <= 8
OPTION_M
=
2
,
// for resolution 8 < n <= 16
OPTION_L
=
3
,
// for resolution 16 < n <= 32
};
struct
cip_header
{
//----------------------------
// Packet Primary Header data
//----------------------------
char
packet_version_number
;
// Packet Version Number
// Packet Identification
enum
cip_packet_type
type
;
// Packet Type
char
secondary_header_available
;
// Sequence Header Flag
unsigned
apid
;
// Application Process Identifier
// Packet Sequence Control
enum
cip_sequence_flag
sequence_flag
;
// Sequence Flags
unsigned
sequence_count
;
// Packet Sequence Count
// in case of a TELECOMMAND type cip
// data package this contains the
// Packet Name
unsigned
data_length
;
// length of the Packet Data Field - 1 in byte
};
struct
cip_preprocessor_configuration
{
char
preprocessor_present
;
// Preprocessor Status (0 - absent, 1 - present)
enum
cip_predictor_type
predictor_type
;
// Predictor type (undefined if preprocessor is absent)
enum
cip_mapper_type
mapper_type
;
// Mapper type (undefined if preprocessor is absent)
char
block_size
;
// Block size (8, 16 or application specific)
enum
cip_data_sense
data_sense
;
char
resolution
;
// Input data sample resolution (1-32)
};
struct
cip_entropy_coder_configuration
{
enum
entropy_coder_option
option
;
// Entropy Coder option
unsigned
num_cds_per_packet
;
// Number of coded data sets per packet
};
struct
cip_source_data_field
{
unsigned
grouping_data_length
;
// Grouping Data Length
enum
cip_compression_technique
compression_technique
;
// Compression Technique Identification
unsigned
reference_sample_interval
;
// Reference Sample Interval
// - in case a preprocessor is
// used that requires a
// reference sample
// - in case of the zero-block
// option it contains the
// interval of input data sample
// blocks
struct
cip_preprocessor_configuration
preprocessor_config
;
// Preprocessor Configuration
struct
cip_entropy_coder_configuration
entropy_coder_config
;
// Entropy Coder Configuration
};
struct
cip
{
struct
cip_header
header
;
// Information from the Primary Header
struct
cip_source_data_field
sdf
;
// Information on the data
};
void
*
decode_cip
(
void
*
buffer
,
struct
cip
*
cip
);
// data: buffer starting with a cip
// cip: in case cip is not NULL the configuration information
// contained in the cip is written to it
// returns a pointer to the compressed data without the cip
// returns NULL in case an error occured while decoding
src/cip.c
0 → 100644
View file @
adddb9a0
// Copyright 2011 Moritz Hanke
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "bit_macros.h"
#include "cip.h"
// decode Packet Primary Header
void
*
decode_pph
(
void
*
buffer
,
struct
cip
*
cip
);
// decode Secondary Header
void
*
decode_sh
(
void
*
buffer
,
struct
cip
*
cip
);
// decode Source Data Field
void
*
decode_sdf
(
void
*
buffer
,
struct
cip
*
cip
);
// decode Preprocessor Parameters
void
*
decode_preprocessor
(
void
*
buffer
,
struct
cip
*
cip
);
// decode Entopy Coder Parameters
void
*
decode_entropy_coder
(
void
*
buffer
,
struct
cip
*
cip
);
// decode Instrument Configuration
void
*
decode_instrument_configuration
(
void
*
buffer
,
struct
cip
*
cip
);
void
*
decode_cip
(
void
*
buffer
,
struct
cip
*
cip
)
{
void
*
pdf
;
// Packet Data Field
void
*
sdf
;
// Source Data Field
void
*
cds
;
// Coded data sets
pdf
=
decode_pph
(
buffer
,
cip
);
if
(
cip
->
header
.
secondary_header_available
)
sdf
=
decode_sh
(
pdf
,
cip
);
else
sdf
=
pdf
;
cds
=
decode_sdf
(
sdf
,
cip
);
if
((
char
*
)
cds
>
(
char
*
)
pdf
+
cip
->
header
.
data_length
+
1
)
{
fprintf
(
stderr
,
"Packet Data Field is bigger than specified in CIP Packet Primary Header
\n
"
);
exit
(
EXIT_FAILURE
);
}
return
(
char
*
)
pdf
+
cip
->
header
.
data_length
+
1
;
}
// decode Primary Header
void
*
decode_pph
(
void
*
buffer
,
struct
cip
*
cip
)
{
char
*
cip_buf
=
buffer
;
// Packet Version Number
cip
->
header
.
packet_version_number
=
(
cip_buf
[
0
]
>>
5
)
&
B3
;
if
(
cip
->
header
.
packet_version_number
!=
0
)
{
fprintf
(
stderr
,
"Undefined Packet Version Number
\n
"
);
exit
(
EXIT_FAILURE
);
}
// Packet Identification
{
// Packet Type
cip
->
header
.
type
=
((
cip_buf
[
0
]
>>
4
)
&
B1
)
?
TELECOMMAND
:
TELEMETRY
;
// is a Secondary Header available
cip
->
header
.
secondary_header_available
=
(
cip_buf
[
0
]
>>
3
)
&
B1
;
// Application Process Identifer
cip
->
header
.
apid
=
((
unsigned
)(
cip_buf
[
0
]
&
B3
)
<<
8
)
|
cip_buf
[
1
];
}
// Packet Sequence Control
{
// Sequence Flags
cip
->
header
.
sequence_flag
=
(
cip_buf
[
2
]
>>
6
)
&
B2
;
// Packet Sequence Count or Packet Name
assert
(
sizeof
(
unsigned
)
>
2
);
cip
->
header
.
sequence_count
=
((
unsigned
)(
cip_buf
[
2
]
&
B6
)
<<
8
)
|
cip_buf
[
3
];
}
// Packet Data Length
cip
->
header
.
data_length
=
((
unsigned
)
cip_buf
[
4
]
<<
8
)
|
cip_buf
[
5
];
return
(
char
*
)
cip
+
6
;
// the Packet Primary Header has a size of 48
// bits
}
void
*
decode_sh
(
void
*
buffer
,
struct
cip
*
cip
)
{
// The Secondary Header contains information like time and position
// or attitude of a spacecraft.
// The handling of a Secondary Header is currently not implemented.
fprintf
(
stderr
,
"Compression Identification Packet contains a Secondary Header
\n
"
);
exit
(
EXIT_FAILURE
);
return
buffer
;
}
void
*
decode_sdf
(
void
*
buffer
,
struct
cip
*
cip
)
{
char
*
sdf
=
buffer
;
// Grouping Data Length (number of packets containing compressed data)
cip
->
sdf
.
grouping_data_length
=
(((
unsigned
)(
sdf
[
0
]
&
B4
)
<<
8
)
|
sdf
[
1
])
+
1
;
// check whether a compression is used for the current group
if
(
sdf
[
2
]
>
1
)
{
fprintf
(
stderr
,
"Undefined compression technique
\n
"
);
exit
(
EXIT_FAILURE
);
}
cip
->
sdf
.
compression_technique
=
sdf
[
2
];
// Reference Sample Interval
cip
->
sdf
.
reference_sample_interval
=
sdf
[
3
]
+
1
;
if
(
cip
->
sdf
.
compression_technique
==
LOSSLESS
)
{
// decode Preprocessor Parameters
sdf
=
decode_preprocessor
(
sdf
,
cip
);
}
// decode Entropy Coder Parameters
sdf
=
decode_entropy_coder
(
sdf
,
cip
);
// decode Instrument Configuration
sdf
=
decode_instrument_configuration
(
sdf
,
cip
);
return
sdf
;
}
void
*
decode_preprocessor
(
void
*
buffer
,
struct
cip
*
cip
)
{
char
*
sdf
=
buffer
;
unsigned
header
;
// check for correct header
header
=
(
sdf
[
0
]
>>
6
)
&
B2
;
if
(
header
!=
0
)
{
fprintf
(
stderr
,
"Wrong header for preprocessor field
\n
"
);
exit
(
EXIT_FAILURE
);
}
// get preprocessor presents
cip
->
sdf
.
preprocessor_config
.
preprocessor_present
=
(
sdf
[
0
]
>>
5
)
&
B1
;
// if a preprocessor is present
if
(
cip
->
sdf
.
preprocessor_config
.
preprocessor_present
)
{
// Predictor type
switch
((
sdf
[
0
]
>>
2
)
&
B3
)
{
case
(
0
):
cip
->
sdf
.
preprocessor_config
.
predictor_type
=
BYPASS_P
;
break
;
case
(
1
):
cip
->
sdf
.
preprocessor_config
.
predictor_type
=
UNIT_DELAY_P
;
break
;
case
(
7
):
cip
->
sdf
.
preprocessor_config
.
predictor_type
=
APP_SPECIFIC_P
;
break
;
default:
fprintf
(
stderr
,
"Invalid predictor type
\n
"
);
exit
(
EXIT_FAILURE
);
};
// Mapper type
switch
(
sdf
[
0
]
&
B2
)
{
case
(
0
):
cip
->
sdf
.
preprocessor_config
.
mapper_type
=
STANDARD_M
;
break
;
case
(
3
):
cip
->
sdf
.
preprocessor_config
.
mapper_type
=
APP_SPECIFIC_M
;
break
;
default:
fprintf
(
stderr
,
"Invalid mapper type
\n
"
);
exit
(
EXIT_FAILURE
);
};
}
// Block size (J)
switch
((
sdf
[
1
]
>>
6
)
&
B2
)
{
case
(
0
):
cip
->
sdf
.
preprocessor_config
.
block_size
=
8
;
break
;
case
(
1
):
cip
->
sdf
.
preprocessor_config
.
block_size
=
16
;
break
;
case
(
3
):
fprintf
(
stderr
,
"Missing implementation for application-specific block size
\n
"
);
exit
(
EXIT_FAILURE
);
default:
fprintf
(
stderr
,
"Invalid block size
\n
"
);
exit
(
EXIT_FAILURE
);
};
// Data sense
cip
->
sdf
.
preprocessor_config
.
data_sense
=
(
sdf
[
1
]
>>
5
)
&
1
;
// check whether preprocessor presents and data sense match
if
(
!
cip
->
sdf
.
preprocessor_config
.
preprocessor_present
&&
cip
->
sdf
.
preprocessor_config
.
data_sense
!=
POSITIVE
)
{
fprintf
(
stderr
,
"If no preprocessor is present, the data sense has to be positive.
\n
"
);
exit
(
EXIT_FAILURE
);
}
// Input data sample resolution
cip
->
sdf
.
preprocessor_config
.
resolution
=
(
sdf
[
1
]
&
B5
)
+
1
;
return
(
char
*
)
buffer
+
2
;
// the preprocessor field has a size of 2 byte
}
void
*
decode_entropy_coder
(
void
*
buffer
,
struct
cip
*
cip
)
{
char
*
sdf
=
buffer
;
unsigned
header
;
// check for correct header
header
=
(
sdf
[
0
]
>>
6
)
&
B2
;
if
(
header
!=
1
)
{
fprintf
(
stderr
,
"Wrong header for entropy coder field
\n
"
);
exit
(
EXIT_FAILURE
);
}
// Entropy Coder option
switch
((
sdf
[
0
]
>>
4
)
&
B2
)
{
case
(
1
):
if
(
cip
->
sdf
.
preprocessor_config
.
resolution
>
8
)
{
fprintf
(
stderr
,
"Entropy coder option does not match input data sample resolution
\n
"
);
exit
(
EXIT_FAILURE
);
}
cip
->
sdf
.
entropy_coder_config
.
option
=
OPTION_S
;
break
;
case
(
2
):
if
((
cip
->
sdf
.
preprocessor_config
.
resolution
<=
8
)
||
(
cip
->
sdf
.
preprocessor_config
.
resolution
>
16
))
{
fprintf
(
stderr
,
"Entropy coder option does not match input data sample resolution
\n
"
);
exit
(
EXIT_FAILURE
);
}
cip
->
sdf
.
entropy_coder_config
.
option
=
OPTION_M
;
break
;
case
(
3
):
if
((
cip
->
sdf
.
preprocessor_config
.
resolution
<=
16
)
||
(
cip
->
sdf
.
preprocessor_config
.
resolution
>
32
))
{
fprintf
(
stderr
,
"Entropy coder option does not match input data sample resolution
\n
"
);
exit
(
EXIT_FAILURE
);
}
cip
->
sdf
.
entropy_coder_config
.
option
=
OPTION_L
;
break
;
default:
fprintf
(
stderr
,
"Invalid entropy coder option
\n
"
);
exit
(
EXIT_FAILURE
);
};
assert
(
sizeof
(
unsigned
)
>
2
);
// Number of coded data sets per packet
cip
->
sdf
.
entropy_coder_config
.
num_cds_per_packet
=
(((
unsigned
)(
sdf
[
0
]
&
B4
)
<<
8
)
|
sdf
[
1
])
+
1
;
return
(
char
*
)
buffer
+
2
;
// entropy coder field has a size of 2 byte
}
void
*
decode_instrument_configuration
(
void
*
buffer
,
struct
cip
*
cip
)
{
// Instrument Configuration is mission specific.
// This implementation assumes that there is no.
// In an one is added later, the first 2 bits of buffer have to 10.
return
buffer
;
}
src/main.c
0 → 100644
View file @
adddb9a0
// Copyright 2011 Moritz Hanke
#include <stdlib.h>
#include "cip.h"
int
main
()
{
return
EXIT_SUCCESS
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment