39" ____ ____ ____ ____ ____ _ ____ _ _ \n"
40" / ___/ ___/ ___|| _ \\/ ___| / |___ \\| || | \n"
41"| | | | \\___ \\| | | \\___ \\ | | __) | || |_ \n"
42"| |__| |___ ___) | |_| |___) | | |/ __/|__ _| \n"
43" \\____\\____|____/|____/|____/ |_|_____| |_| \n"
45" by T A N A G R A S P A C E \n"
54 printf(
"ccsds124 %d.%d.%d\n",
62 printf(
"CCSDS 124.0-B-1 Lossless Compression (v%d.%d.%d)\n",
64 printf(
"=================================================\n\n");
65 printf(
"References:\n");
66 printf(
" CCSDS 124.0-B-1: https://ccsds.org/Pubs/124x0b1.pdf\n");
67 printf(
" Documentation: https://tanagraspace.com/ccsds124\n\n");
68 printf(
"Citation:\n");
69 printf(
" D. Evans, G. Labreche, D. Marszk, S. Bammens, M. Hernandez-Cabronero,\n");
70 printf(
" V. Zelenevskiy, V. Shiradhonkar, M. Starcik, and M. Henkel. 2022.\n");
71 printf(
" \"Implementing the New CCSDS Housekeeping Data Compression Standard\n");
72 printf(
" 124.0-B-1 (based on POCKET+) on OPS-SAT-1,\" Proceedings of the\n");
73 printf(
" Small Satellite Conference, Communications, SSC22-XII-03.\n");
74 printf(
" https://digitalcommons.usu.edu/smallsat/2022/all2022/133/\n\n");
76 printf(
" %s <input> <packet_size> <pt> <ft> <rt> <robustness>\n", prog_name);
77 printf(
" %s -d <input.pkt> <packet_size> <robustness>\n\n", prog_name);
79 printf(
" -d Decompress (default is compress)\n");
80 printf(
" -h, --help Show this help message\n");
81 printf(
" -v, --version Show version information\n\n");
82 printf(
"Compress arguments:\n");
83 printf(
" input Input file to compress\n");
84 printf(
" packet_size Packet size in bytes (e.g., 90)\n");
85 printf(
" pt New mask period (e.g., 10, 20)\n");
86 printf(
" ft Send mask period (e.g., 20, 50)\n");
87 printf(
" rt Uncompressed period (e.g., 50, 100)\n");
88 printf(
" robustness Robustness level 0-7 (e.g., 1, 2)\n\n");
89 printf(
"Decompress arguments:\n");
90 printf(
" input.pkt Compressed input file\n");
91 printf(
" packet_size Original packet size in bytes\n");
92 printf(
" robustness Robustness level (must match compression)\n\n");
94 printf(
" Compress: <input>.pkt\n");
95 printf(
" Decompress: <input>.depkt (or <base>.depkt if input ends in .pkt)\n\n");
96 printf(
"Examples:\n");
97 printf(
" %s data.bin 90 10 20 50 1 # compress\n", prog_name);
98 printf(
" %s -d data.bin.pkt 90 1 # decompress\n\n", prog_name);
111 size_t len = strlen(input);
114 if ((len > 4) && (strcmp(&input[len - 4],
".pkt") == 0)) {
116 size_t base_len = len - 4;
117 if ((base_len + 7) < output_len) {
118 (void)strncpy(output, input, base_len);
119 output[base_len] =
'\0';
120 (void)strcat(output,
".depkt");
122 (void)snprintf(output, output_len,
"%s.depkt", input);
125 (void)snprintf(output, output_len,
"%s.depkt", input);
142 int pt_period,
int ft_period,
int rt_period,
145 FILE *fin = fopen(input_path,
"rb");
147 fprintf(stderr,
"Error: Cannot open input file: %s\n", input_path);
151 (void)fseek(fin, 0, SEEK_END);
152 long file_len = ftell(fin);
153 (void)fseek(fin, 0, SEEK_SET);
156 fprintf(stderr,
"Error: Input file is empty or invalid\n");
161 size_t input_size = (size_t)file_len;
163 if ((input_size % (
size_t)packet_size) != 0U) {
164 fprintf(stderr,
"Error: Input size (%zu) not divisible by packet size (%d)\n",
165 input_size, packet_size);
170 uint8_t *input_data = malloc(input_size);
171 if (input_data == NULL) {
172 fprintf(stderr,
"Error: Cannot allocate memory\n");
177 if (fread(input_data, 1, input_size, fin) != input_size) {
178 fprintf(stderr,
"Error: Failed to read input file\n");
186 char output_path[1024];
187 (void)snprintf(output_path,
sizeof(output_path),
"%s.pkt", input_path);
190 size_t packet_length = (size_t)packet_size * 8U;
193 pt_period, ft_period, rt_period);
196 size_t max_output = input_size * 2U;
197 uint8_t *output_data = malloc(max_output);
198 if (output_data == NULL) {
199 fprintf(stderr,
"Error: Cannot allocate output buffer\n");
205 size_t output_size = 0U;
207 output_data, max_output, &output_size);
210 fprintf(stderr,
"Error: Compression failed with code %d\n", result);
217 FILE *fout = fopen(output_path,
"wb");
219 fprintf(stderr,
"Error: Cannot create output file: %s\n", output_path);
225 if (fwrite(output_data, 1, output_size, fout) != output_size) {
226 fprintf(stderr,
"Error: Failed to write output file\n");
235 size_t num_packets = input_size / (size_t)packet_size;
236 double ratio = (double)input_size / (
double)output_size;
237 printf(
"Input: %s (%zu bytes, %zu packets)\n", input_path, input_size, num_packets);
238 printf(
"Output: %s (%zu bytes)\n", output_path, output_size);
239 printf(
"Ratio: %.2fx\n", ratio);
240 printf(
"Parameters: R=%d, pt=%d, ft=%d, rt=%d\n",
241 robustness, pt_period, ft_period, rt_period);
257static int do_decompress(
const char *input_path,
int packet_size,
int robustness) {
259 FILE *fin = fopen(input_path,
"rb");
261 fprintf(stderr,
"Error: Cannot open input file: %s\n", input_path);
265 (void)fseek(fin, 0, SEEK_END);
266 long file_len = ftell(fin);
267 (void)fseek(fin, 0, SEEK_SET);
270 fprintf(stderr,
"Error: Input file is empty or invalid\n");
275 size_t input_size = (size_t)file_len;
276 uint8_t *input_data = malloc(input_size);
277 if (input_data == NULL) {
278 fprintf(stderr,
"Error: Cannot allocate memory for input\n");
283 if (fread(input_data, 1, input_size, fin) != input_size) {
284 fprintf(stderr,
"Error: Failed to read input file\n");
292 char output_path[1024];
296 size_t packet_length = (size_t)packet_size * 8U;
301 fprintf(stderr,
"Error: Decompressor init failed with code %d\n", result);
307 size_t max_output = input_size * 20U;
308 uint8_t *output_data = malloc(max_output);
309 if (output_data == NULL) {
310 fprintf(stderr,
"Error: Cannot allocate output buffer\n");
316 size_t output_size = 0U;
318 output_data, max_output, &output_size);
321 fprintf(stderr,
"Error: Decompression failed with code %d\n", result);
328 FILE *fout = fopen(output_path,
"wb");
330 fprintf(stderr,
"Error: Cannot create output file: %s\n", output_path);
336 if (fwrite(output_data, 1, output_size, fout) != output_size) {
337 fprintf(stderr,
"Error: Failed to write output file\n");
346 size_t num_packets = output_size / (size_t)packet_size;
347 double ratio = (double)output_size / (
double)input_size;
348 printf(
"Input: %s (%zu bytes)\n", input_path, input_size);
349 printf(
"Output: %s (%zu bytes, %zu packets)\n", output_path, output_size, num_packets);
350 printf(
"Expansion: %.2fx\n", ratio);
351 printf(
"Parameters: packet_size=%d, R=%d\n", packet_size, robustness);
366int main(
int argc,
char **argv) {
367 int decompress_mode = 0;
372 (strcmp(argv[1],
"-h") == 0) ||
373 (strcmp(argv[1],
"--help") == 0)) {
375 return (argc < 2) ? 1 : 0;
379 if ((strcmp(argv[1],
"-v") == 0) ||
380 (strcmp(argv[1],
"--version") == 0)) {
386 if (strcmp(argv[1],
"-d") == 0) {
391 if (decompress_mode != 0) {
394 fprintf(stderr,
"Error: Decompress requires 3 arguments after -d\n");
395 fprintf(stderr,
"Usage: %s -d <input.pkt> <packet_size> <robustness>\n", argv[0]);
399 const char *input_path = argv[arg_offset];
400 int packet_size = atoi(argv[arg_offset + 1]);
401 int robustness = atoi(argv[arg_offset + 2]);
404 if ((packet_size <= 0) || (packet_size > 8192)) {
405 fprintf(stderr,
"Error: packet_size must be 1-8192 bytes\n");
408 if ((robustness < 0) || (robustness > 7)) {
409 fprintf(stderr,
"Error: robustness must be 0-7\n");
418 fprintf(stderr,
"Error: Compress requires 6 arguments\n");
419 fprintf(stderr,
"Usage: %s <input> <packet_size> <pt> <ft> <rt> <robustness>\n", argv[0]);
423 const char *input_path = argv[1];
424 int packet_size = atoi(argv[2]);
425 int pt_period = atoi(argv[3]);
426 int ft_period = atoi(argv[4]);
427 int rt_period = atoi(argv[5]);
428 int robustness = atoi(argv[6]);
431 if ((packet_size <= 0) || (packet_size > 8192)) {
432 fprintf(stderr,
"Error: packet_size must be 1-8192 bytes\n");
435 if ((robustness < 0) || (robustness > 7)) {
436 fprintf(stderr,
"Error: robustness must be 0-7\n");
439 if ((pt_period <= 0) || (ft_period <= 0) || (rt_period <= 0)) {
440 fprintf(stderr,
"Error: periods must be positive\n");
444 return do_compress(input_path, packet_size, pt_period, ft_period, rt_period, robustness);
CCSDS 124.0-B-1 Compression Library - Public API.
static void print_version(void)
Print help message with usage information.
int main(int argc, char **argv)
CLI entry point.
static const char * BANNER
ASCII art banner for help output.
static int do_decompress(const char *input_path, int packet_size, int robustness)
Decompress a file.
static int do_compress(const char *input_path, int packet_size, int pt_period, int ft_period, int rt_period, int robustness)
Compress a file.
static void make_decompress_filename(char *output, size_t output_len, const char *input)
Create output filename for decompression.
static void print_help(const char *prog_name)
int ccsds124_compressor_init(ccsds124_compressor_t *comp, size_t F, const bitvector_t *initial_mask, uint8_t robustness, int pt_limit, int ft_limit, int rt_limit)
Initialize compressor state.
int ccsds124_compress(ccsds124_compressor_t *comp, const uint8_t *input_data, size_t input_size, uint8_t *output_buffer, size_t output_buffer_size, size_t *output_size)
Compress entire input data stream.
int ccsds124_decompress(ccsds124_decompressor_t *decomp, const uint8_t *input_data, size_t input_size, uint8_t *output_buffer, size_t output_buffer_size, size_t *output_size)
Decompress entire compressed data stream.
int ccsds124_decompressor_init(ccsds124_decompressor_t *decomp, size_t F, const bitvector_t *initial_mask, uint8_t robustness)
Initialize decompressor state.
#define CCSDS124_VERSION_MAJOR
#define CCSDS124_VERSION_PATCH
#define CCSDS124_VERSION_MINOR
Compressor state structure.
Decompressor state structure.