diff --git a/.gitignore b/.gitignore index 852f22f613dc7c0b368b0deab5364fbe323a3769..d4e5f782b9e51c3f8b30915bbb333d9a04a437a1 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,7 @@ cmp_tool !test/cmp_tool -# cmp_tool files +#cmp_tool files *.cfg *.info *.dat diff --git a/INSTALL.md b/INSTALL.md index 5162e704972513f43923b91aacd97d51a1a35010..70a4e0c93824557bbba73313085c476c6502d8c7 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -45,7 +45,7 @@ cd builddir meson compile cmp_tool ``` -Now you should find the cmp\_tool executable in the folder. +Now you should find the cmp\_tool executable in the programs folder. ### Release Build @@ -57,7 +57,7 @@ cd build_relase_dir meson compile cmp_tool ``` -You find the build executable in the `build_relase_dir` directory +You find the build cmp\_tool executable in the `build_relase_dir/programs` directory. ### Build for Windows diff --git a/doc/doxygen/meson.build b/doc/doxygen/meson.build index 5c6a0d038f73c447de4b10b8b2ed0918d6ca4a07..05010211d9d8214aaa22a5969fafaf80ca3c3643 100644 --- a/doc/doxygen/meson.build +++ b/doc/doxygen/meson.build @@ -37,7 +37,7 @@ if doxygen.found() custom_target('doc', input : doxy_file, output : 'generated_documentation', - depend_files : [doxy_file, doc_layout_files, doxygen_awesome_css_files, main, cmplib_sources], # test files are missing + depend_files : [doxy_file, doc_layout_files, doxygen_awesome_css_files, cmp_tool_src, common_sources, decompress_sources, icu_compress_sources, rdcu_compress_sources], # test files are missing command : [doxygen, '@INPUT@'], build_by_default : false, console : true, diff --git a/examples/example_cmp_icu.c b/examples/example_cmp_icu.c new file mode 100644 index 0000000000000000000000000000000000000000..ba704fcb2eeffcfb062082ab75be014766eaa8ce --- /dev/null +++ b/examples/example_cmp_icu.c @@ -0,0 +1,175 @@ +/** + * @file example_cmp_icu.c + * @author Dominik Loidolt (dominik.loidolt@univie.ac.at) + * @date Oct 2023 + * + * @copyright GPLv2 + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * @brief demonstration of the use of the software compressor and the + * compression entity library + */ + + +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> + +#include <leon_inttypes.h> + +#include <cmp_entity.h> +#include <cmp_icu.h> + + +#define DATA_SAMPLES 6 /* number of 16 bit samples to compress */ +#define CMP_BUF_LEN_SAMPLES DATA_SAMPLES /* compressed buffer has the same sample size as the data buffer */ +#define CMP_ASW_VERSION_ID 1 +/* The start_time, end_time, model_id and counter have to be managed by the ASW + * here we use arbitrary values for demonstration */ +#define START_TIME 0 +#define END_TIME 0x23 +#define MODEL_ID 42 +#define MODEL_COUNTER 1 + + +int demo_icu_compression(void) +{ + struct cmp_cfg example_cfg; + struct cmp_entity *cmp_entity = NULL; + uint32_t i, cmp_buf_size, entity_buf_size, entity_size; + int cmp_size_bits; + void *ent_cmp_data; + + /* declare data buffers with some example data */ + enum cmp_data_type example_data_type = DATA_TYPE_IMAGETTE; + uint16_t example_data[DATA_SAMPLES] = {42, 23, 1, 13, 20, 1000}; + uint16_t example_model[DATA_SAMPLES] = {0, 22, 3, 42, 23, 16}; + uint16_t updated_model[DATA_SAMPLES] = {0}; + + /* create a compression configuration with default values */ + example_cfg = cmp_cfg_icu_create(example_data_type, CMP_DEF_IMA_MODEL_CMP_MODE, + CMP_DEF_IMA_MODEL_MODEL_VALUE, CMP_LOSSLESS); + if (example_cfg.data_type == DATA_TYPE_UNKNOWN) { + printf("Error occurred during cmp_cfg_icu_create()\n"); + goto fail; + } + + /* configure imagette specific compression parameters with default values */ + if (cmp_cfg_icu_imagette(&example_cfg, CMP_DEF_IMA_MODEL_GOLOMB_PAR, + CMP_DEF_IMA_MODEL_SPILL_PAR)) { + printf("Error occurred during cmp_cfg_icu_imagette()\n"); + goto fail; + } + + /* get the size of the buffer for the compressed data in bytes */ + cmp_buf_size = cmp_cfg_icu_buffers(&example_cfg, example_data, + DATA_SAMPLES, example_model, + updated_model, NULL, + CMP_BUF_LEN_SAMPLES); + if (!cmp_buf_size) { + printf("Error occurred during cmp_cfg_icu_buffers()\n"); + goto fail; + } + + /* create a compression entity */ + #define NO_CMP_MODE_RAW_USED 0 + entity_buf_size = cmp_ent_create(NULL, example_data_type, NO_CMP_MODE_RAW_USED, + cmp_buf_size); + if (!entity_buf_size) { + printf("Error occurred during cmp_ent_create()\n"); + goto fail; + } + cmp_entity = malloc(entity_buf_size); /* allocated memory for the compression entity */ + if (!cmp_entity) { + printf("malloc failed!\n"); + goto fail; + } + entity_buf_size = cmp_ent_create(cmp_entity, example_data_type, + NO_CMP_MODE_RAW_USED, cmp_buf_size); + if (!entity_buf_size) { + printf("Error occurred during cmp_ent_create()\n"); + goto fail; + } + + /* + * Configure the buffer related settings. We put the compressed data directly + * into the compression entity. In this way we do not need to copy the + * compressed data into the compression entity + */ + ent_cmp_data = cmp_ent_get_data_buf(cmp_entity); + if (!ent_cmp_data) { + printf("Error occurred during cmp_ent_get_data_buf()\n"); + goto fail; + } + cmp_buf_size = cmp_cfg_icu_buffers(&example_cfg, example_data, + DATA_SAMPLES, example_model, + updated_model, ent_cmp_data, + CMP_BUF_LEN_SAMPLES); + if (!cmp_buf_size) { + printf("Error occurred during cmp_cfg_icu_buffers()\n"); + goto fail; + } + + /* now we compress the data on the ICU */ + cmp_size_bits = icu_compress_data(&example_cfg); + if (cmp_size_bits < 0) { + printf("Error occurred during icu_compress_data()\n"); + if (cmp_size_bits == CMP_ERROR_SMALL_BUF) + printf("The compressed data buffer is too small to hold all compressed data!\n"); + if (cmp_size_bits == CMP_ERROR_HIGH_VALUE) + printf("A data or model value is bigger than the max_used_bits parameter " + "allows (set with the cmp_cfg_icu_max_used_bits() function)!\n"); + goto fail; + } + + /* now we set all the parameters in the compression entity header */ + /* + * NOTE: the size of the compress entity is smaller than the buffer size + * we have allocated for it (entity_buf_size), because the compressed + * data (fortunately) does not use the entire buffer we have provided + * for it + */ + entity_size = cmp_ent_build(cmp_entity, CMP_ASW_VERSION_ID, START_TIME, END_TIME, + MODEL_ID, MODEL_COUNTER, &example_cfg, cmp_size_bits); + if (!entity_size) { + printf("Error occurred during cmp_ent_build()\n"); + goto fail; + } + + printf("Here's the compressed entity (size %"PRIu32"):\n" + "=========================================\n", entity_size); + for (i = 0; i < entity_size; i++) { + uint8_t *p = (uint8_t *)cmp_entity; /* the compression entity is big-endian */ + printf("%02X ", p[i]); + if (i && !((i + 1) % 32)) + printf("\n"); + } + printf("\n\nHere's the updated model (samples=%u):\n" + "=========================================\n", DATA_SAMPLES); + for (i = 0; i < DATA_SAMPLES; i++) { + printf("%04X ", updated_model[i]); + if (i && !((i + 1) % 20)) + printf("\n"); + } + printf("\n"); + + free(cmp_entity); + return 0; + +fail: + free(cmp_entity); + return -1; +} + + +int main(void) +{ + return demo_icu_compression(); +} diff --git a/examples/example_cmp_rdcu.c b/examples/example_cmp_rdcu.c new file mode 100644 index 0000000000000000000000000000000000000000..9bf81cea40f715b6f563496768618a2c2e1e039e --- /dev/null +++ b/examples/example_cmp_rdcu.c @@ -0,0 +1,233 @@ +/** + * @file example_cmp_rdcu.c + * @author Dominik Loidolt (dominik.loidolt@univie.ac.at) + * @date Oct 2023 + * + * @copyright GPLv2 + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * @brief demonstration of the use of the rdcu compressor library + */ + + +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> + +#include <cmp_rdcu.h> +#include <cmp_entity.h> + +#define MAX_PAYLOAD_SIZE 4096 +#define DATA_SAMPLES 6 /* number of 16 bit samples to compress */ +#define CMP_ASW_VERSION_ID 1 +#define CMP_BUF_LEN_SAMPLES DATA_SAMPLES /* compressed buffer has the same sample size as the data buffer */ +/* The start_time, end_time, model_id and counter have to be managed by the ASW + * here we use arbitrary values for demonstration */ +#define START_TIME 0 +#define END_TIME 0x23 +#define MODEL_ID 42 +#define MODEL_COUNTER 1 + + +/* + * generic calls for receive and transmit RMAP packets, + * see lib/rdcu_compress/rdcu_rmap.c for more details + */ +uint32_t rmap_rx(uint8_t *pkt); + +int32_t rmap_tx(const void *hdr, uint32_t hdr_size, const uint8_t non_crc_bytes, + const void *data, uint32_t data_size); + + +int demo_rdcu_compression(void) +{ + int cnt = 0; + + /* declare configuration, status and information structure */ + struct cmp_cfg example_cfg; + struct cmp_status example_status; + struct cmp_info example_info; + + /* declare data buffers with some example data */ + enum cmp_data_type example_data_type = DATA_TYPE_IMAGETTE_ADAPTIVE; + uint16_t data[DATA_SAMPLES] = {42, 23, 1, 13, 20, 1000}; + uint16_t model[DATA_SAMPLES] = {0, 22, 3, 42, 23, 16}; + + /* initialise the libraries */ + rdcu_ctrl_init(); + rdcu_rmap_init(MAX_PAYLOAD_SIZE, rmap_tx, rmap_rx); + + /* set up compressor configuration */ + example_cfg = rdcu_cfg_create(example_data_type, CMP_DEF_IMA_MODEL_CMP_MODE, + CMP_DEF_IMA_MODEL_MODEL_VALUE, CMP_DEF_IMA_MODEL_LOSSY_PAR); + if (example_cfg.data_type == DATA_TYPE_UNKNOWN) { + printf("Error occurred during rdcu_cfg_create()\n"); + return -1; + } + + if (rdcu_cfg_buffers(&example_cfg, data, DATA_SAMPLES, model, CMP_DEF_IMA_MODEL_RDCU_DATA_ADR, + CMP_DEF_IMA_MODEL_RDCU_MODEL_ADR, CMP_DEF_IMA_MODEL_RDCU_UP_MODEL_ADR, + CMP_DEF_IMA_MODEL_RDCU_BUFFER_ADR, CMP_BUF_LEN_SAMPLES)) { + printf("Error occurred during rdcu_cfg_buffers()\n"); + return -1; + } + if (rdcu_cfg_imagette(&example_cfg, + CMP_DEF_IMA_MODEL_GOLOMB_PAR, CMP_DEF_IMA_MODEL_SPILL_PAR, + CMP_DEF_IMA_MODEL_AP1_GOLOMB_PAR, CMP_DEF_IMA_MODEL_AP1_SPILL_PAR, + CMP_DEF_IMA_MODEL_AP2_GOLOMB_PAR, CMP_DEF_IMA_MODEL_AP2_SPILL_PAR)) { + printf("Error occurred during rdcu_cfg_imagette()\n"); + return -1; + } + + /* start HW compression */ + if (rdcu_compress_data(&example_cfg)) { + printf("Error occurred during rdcu_compress_data()\n"); + return -1; + } + /* start polling the compression status */ + /* alternatively you can wait for an interrupt from the RDCU */ + do { + /* check compression status */ + if (rdcu_read_cmp_status(&example_status)) { + printf("Error occurred during rdcu_read_cmp_status()"); + return -1; + } + cnt++; + if (cnt > 5) { /* wait for 5 polls */ + printf("Not waiting for compressor to become ready, will " + "check status and abort\n"); + /* interrupt the data compression */ + rdcu_interrupt_compression(); + /* now we may read the compression info register to get the error code */ + if (rdcu_read_cmp_info(&example_info)) { + printf("Error occurred during rdcu_read_cmp_info()"); + return -1; + } + printf("Compressor error code: 0x%02X\n", example_info.cmp_err); + return -1; + } + } while (!example_status.cmp_ready); + + printf("Compression took %d polling cycles\n\n", cnt); + + printf("Compressor status: ACT: %d, RDY: %d, DATA VALID: %d, INT: %d, INT_EN: %d\n", + example_status.cmp_active, example_status.cmp_ready, example_status.data_valid, + example_status.cmp_interrupted, example_status.rdcu_interrupt_en); + + /* now we may read the compressor registers */ + if (rdcu_read_cmp_info(&example_info)) { + printf("Error occurred during rdcu_read_cmp_info()"); + return -1; + } + + printf("\n\nHere's the content of the compressor registers:\n" + "===============================================\n"); + print_cmp_info(&example_info); + + /* check if data are valid or a compression error occurred */ + if (example_info.cmp_err != 0 || example_status.data_valid == 0) { + printf("Compression error occurred! Compressor error code: 0x%02X\n", + example_info.cmp_err); + return -1; + } + + /* build a compression entity and put compressed data from the RDCU into it and print */ + if (1) { + struct cmp_entity *cmp_ent; + void *cmp_ent_data; + size_t cmp_ent_size; + uint32_t i, s; + + /* get the size of the compression entity */ + cmp_ent_size = cmp_ent_build(NULL, CMP_ASW_VERSION_ID, + START_TIME, END_TIME, MODEL_ID, MODEL_COUNTER, + &example_cfg, example_info.cmp_size); + if (!cmp_ent_size) { + printf("Error occurred during cmp_ent_build()\n"); + return -1; + } + + /* get memory for the compression entity */ + cmp_ent = malloc(cmp_ent_size); + if (!cmp_ent) { + printf("Error occurred during malloc()\n"); + return -1; + } + + /* now let us build the compression entity */ + cmp_ent_size = cmp_ent_build(cmp_ent, CMP_ASW_VERSION_ID, + START_TIME, END_TIME, MODEL_ID, MODEL_COUNTER, + &example_cfg, example_info.cmp_size); + if (!cmp_ent_size) { + printf("Error occurred during cmp_ent_build()\n"); + return -1; + } + + /* get the address to store the compressed data in the + * compression entity */ + cmp_ent_data = cmp_ent_get_data_buf(cmp_ent); + if (!cmp_ent_data) { + printf("Error occurred during cmp_ent_get_data_buf()\n"); + return -1; + } + + /* now get the compressed data form RDCU and copy it into the + * compression entity */ + if (rdcu_read_cmp_bitstream(&example_info, cmp_ent_data) < 0) { + printf("Error occurred while reading in the compressed data from the RDCU\n"); + return -1; + } + + s = cmp_ent_get_size(cmp_ent); + printf("\n\nHere's the compressed data including the header (size %lu):\n" + "============================================================\n", s); + for (i = 0; i < s; i++) { + uint8_t *p = (uint8_t *)cmp_ent; + printf("%02X ", p[i]); + if (i && !((i+1) % 40)) + printf("\n"); + } + printf("\n"); + + /* now have a look into the compression entity */ + printf("\n\nParse the compression entity header:\n" + "====================================\n"); + cmp_ent_parse(cmp_ent); + + free(cmp_ent); + } + + /* read updated model to some buffer and print */ + { + int i; + int s = rdcu_read_model(&example_info, NULL); + uint8_t *mymodel = malloc((size_t)s); + + if (!mymodel) { + printf("malloc failed!\n"); + return -1; + } + + if (rdcu_read_model(&example_info, mymodel) < 0) + printf("Error occurred while reading in the updated model\n"); + + printf("\n\nHere's the updated model (size %d):\n" + "====================================\n", s); + for (i = 0; i < s; i++) { + printf("%02X ", mymodel[i]); + if (i && !((i+1) % 40)) + printf("\n"); + } + printf("\n"); + + free(mymodel); + } + return 0; +} diff --git a/examples/example_compress_chunk.c b/examples/example_compress_chunk.c new file mode 100644 index 0000000000000000000000000000000000000000..4dac0d85186eb68c8769ef9e23502d8dac5f44c3 --- /dev/null +++ b/examples/example_compress_chunk.c @@ -0,0 +1,277 @@ +/** + * @file example_compress_chunk.c + * @author Dominik Loidolt (dominik.loidolt@univie.ac.at) + * @date Feb 2024 + * + * @copyright GPLv2 + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * @brief demonstration of the chunk compressor + */ + + +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <leon_inttypes.h> + +#include <cmp_chunk.h> +#include <cmp_data_types.h> + + +/* + * The asw_version_id, model_id and counter have to be managed by the ASW here we + * use arbitrary values for demonstration + */ +#define ASW_VERSION_ID 1 +#define MODEL_ID 42 +#define MODEL_COUNTER 1 + + +/** + * @brief This is a dummy implementation of a function returning a current timestamp + */ + +static uint64_t dummy_return_timestamp(void) +{ + return 0x0FF1CC0FFEE; /* arbitrary value */ +} + + +/** + * @brief Demonstration of a 1d chunk compression + * + * Compressing a background/offset chunk in 1d-differencing mode with zero escape + * mechanism + */ + +static int demo_comperss_chunk_1d(void) +{ + struct background background_data[1] = {{0, 1, 0xF0}}; + struct offset offset_data[2] = {{1, 2}, {3, 4}}; + enum { CHUNK_SIZE = 2*COLLECTION_HDR_SIZE + sizeof(background_data) + + sizeof(offset_data) }; + uint8_t chunk[CHUNK_SIZE] = {0}; /* Do not put large amount of data on the stack! */ + + uint32_t *compressed_data; + int cmp_size_bytes; + + { /* build a chunk of a background and an offset collection */ + struct collection_hdr *col = (struct collection_hdr *)chunk; + + if (cmp_col_set_subservice(col, SST_NCxx_S_SCIENCE_BACKGROUND)) + return -1; + if (cmp_col_set_data_length(col, sizeof(background_data))) + return -1; + memcpy(col->entry, background_data, sizeof(background_data)); + + col = (struct collection_hdr *)(chunk + cmp_col_get_size(col)); + if (cmp_col_set_subservice(col, SST_NCxx_S_SCIENCE_OFFSET)) + return -1; + if (cmp_col_set_data_length(col, sizeof(offset_data))) + return -1; + memcpy(col->entry, offset_data, sizeof(offset_data)); + } + + /* the chunk compression only needs to be initialised once */ + compress_chunk_init(&dummy_return_timestamp, ASW_VERSION_ID); + + { /* compress the chunk */ + struct cmp_par cmp_par; + uint32_t cmp_size_bound; + + /* prepare the compression parameters needed to compress a + * background/offset chunk (arbitrary values) + */ + memset(&cmp_par, 0, sizeof(cmp_par)); + cmp_par.cmp_mode = CMP_MODE_DIFF_ZERO; + cmp_par.nc_offset_mean = 1; + cmp_par.nc_offset_variance = 2; + cmp_par.nc_background_mean = 3; + cmp_par.nc_background_variance = 4; + cmp_par.nc_background_outlier_pixels = 5; + + /* prepare the buffer for the compressed data */ + cmp_size_bound = compress_chunk_cmp_size_bound(chunk, CHUNK_SIZE); + if (!cmp_size_bound) { + printf("Error occurred during compress_chunk_cmp_size_bound()\n"); + /* error handling */ + return -1; + } + compressed_data = malloc(cmp_size_bound); + if (!compressed_data) { + printf("Error occurred during malloc()\n"); + /* error handling */ + return -1; + } + + cmp_size_bytes = compress_chunk(chunk, CHUNK_SIZE, NULL, NULL, + compressed_data, cmp_size_bound, + &cmp_par); + if (cmp_size_bytes < 0) { + printf("Error occurred during compress_chunk()\n"); + if (cmp_size_bytes == CMP_ERROR_SMALL_BUF) + printf("The compressed data buffer is too small to hold all compressed data!\n"); + free(compressed_data); + /* error handling */ + return -1; + } + if (compress_chunk_set_model_id_and_counter(compressed_data, cmp_size_bytes, + MODEL_ID, 0)) { + printf("Error occurred during compress_chunk_set_model_id_and_counter()\n"); + free(compressed_data); + /* error handling */ + return -1; + } + } + + { /* have a look at the compressed data */ + int i; + + printf("Here's the compressed data including the compression entity header (size %d):\n", cmp_size_bytes); + for (i = 0; i < cmp_size_bytes; i++) { + const uint8_t *p = (uint8_t *)compressed_data; /* the compression entity is big-endian */ + printf("%02X ", p[i]); + if (i && !((i + 1) % 32)) + printf("\n"); + } + printf("\n\n"); + } + free(compressed_data); + return 0; +} + + +/** + * @brief Demonstration of a model chunk compression + * + * Compressing a background/offset chunk in model mode with multi escape + * mechanism + */ + +static int demo_comperss_chunk_model(void) +{ + struct background background_model[1] = {{0, 1, 0xF0}}; + struct offset offset_model[2] = {{1, 2}, {3, 4}}; + struct background background_data[1] = {{1, 2, 0xFA}}; + struct offset offset_data[2] = {{1, 32}, {23, 42}}; + enum { CHUNK_SIZE = 2*COLLECTION_HDR_SIZE + sizeof(background_data) + + sizeof(offset_data) }; + uint8_t chunk[CHUNK_SIZE] = {0}; /* Do not put large amount of data on the stack! */ + uint8_t model_chunk[(CHUNK_SIZE)] = {0}; /* Do not put large amount of data on the stack! */ + uint8_t updated_chunk_model[CHUNK_SIZE] = {0}; /* Do not put large amount of data on the stack! */ + + /* + * Here we use the COMPRESS_CHUNK_BOUND macro to determine the worst + * case compression size; to do this we need to know the chunk_size and + * the number of collections in the chunk (2 in this demo) + */ + uint32_t compressed_data[COMPRESS_CHUNK_BOUND(CHUNK_SIZE, 2)/4]; /* Do not put large amount of data on the stack! */ + int cmp_size_bytes; + + { /* build a chunk of a background and an offset collection */ + struct collection_hdr *col = (struct collection_hdr *)chunk; + + if (cmp_col_set_subservice(col, SST_NCxx_S_SCIENCE_BACKGROUND)) + return -1; + if (cmp_col_set_data_length(col, sizeof(background_data))) + return -1; + memcpy(col->entry, background_data, sizeof(background_data)); + + col = (struct collection_hdr *)(chunk + cmp_col_get_size(col)); + if (cmp_col_set_subservice(col, SST_NCxx_S_SCIENCE_OFFSET)) + return -1; + if (cmp_col_set_data_length(col, sizeof(offset_data))) + return -1; + memcpy(col->entry, offset_data, sizeof(offset_data)); + + /* build a model_chunk of a background and an offset collection */ + col = (struct collection_hdr *)model_chunk; + + if (cmp_col_set_subservice(col, SST_NCxx_S_SCIENCE_BACKGROUND)) + return -1; + if (cmp_col_set_data_length(col, sizeof(background_model))) + return -1; + memcpy(col->entry, background_model, sizeof(background_model)); + + col = (struct collection_hdr *)(model_chunk + cmp_col_get_size(col)); + if (cmp_col_set_subservice(col, SST_NCxx_S_SCIENCE_OFFSET)) + return -1; + if (cmp_col_set_data_length(col, sizeof(offset_model))) + return -1; + memcpy(col->entry, offset_model, sizeof(offset_model)); + } + + /* the chunk compression only needs to be initialised once */ + compress_chunk_init(&dummy_return_timestamp, ASW_VERSION_ID); + + { /* compress the chunk */ + struct cmp_par cmp_par; + + /* prepare the compression parameters needed to compress a + * background/offset chunk + */ + memset(&cmp_par, 0, sizeof(cmp_par)); + cmp_par.cmp_mode = CMP_MODE_MODEL_MULTI; + cmp_par.model_value = 11; + cmp_par.nc_offset_mean = 1; + cmp_par.nc_offset_variance = 2; + cmp_par.nc_background_mean = 3; + cmp_par.nc_background_variance = 4; + cmp_par.nc_background_outlier_pixels = 5; + + cmp_size_bytes = compress_chunk(chunk, CHUNK_SIZE, model_chunk, + updated_chunk_model, compressed_data, + sizeof(compressed_data), &cmp_par); + if (cmp_size_bytes < 0) { + printf("Error occurred during compress_chunk()\n"); + if (cmp_size_bytes == CMP_ERROR_SMALL_BUF) + printf("The compressed data buffer is too small to hold all compressed data!\n"); + /* error handling */ + return -1; + } + if (compress_chunk_set_model_id_and_counter(compressed_data, cmp_size_bytes, + MODEL_ID, MODEL_COUNTER)) { + printf("Error occurred during compress_chunk_set_model_id_and_counter()\n"); + /* error handling */ + return -1; + } + } + + { /* have a look at the compressed data */ + int i; + + printf("Here's the compressed data including the compression entity header (size %d):\n", cmp_size_bytes); + for (i = 0; i < cmp_size_bytes; i++) { + const uint8_t *p = (uint8_t *)compressed_data; /* the compression entity is big-endian */ + printf("%02X ", p[i]); + if (i && !((i + 1) % 32)) + printf("\n"); + } + printf("\n"); + } + + return 0; +} + + +int main(void) +{ + int error = 0; + + error |= demo_comperss_chunk_1d(); + error |= demo_comperss_chunk_model(); + + if (error) + return EXIT_FAILURE; + return EXIT_SUCCESS; +} diff --git a/examples/meson.build b/examples/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..d83ac4014ab4ab398fa868f68db5cd3d55a3f9ab --- /dev/null +++ b/examples/meson.build @@ -0,0 +1,31 @@ +example_cmp_icu_src = files([ + 'example_cmp_icu.c' +]) + +example_cmp_icu_exe = executable('example_cmp_icu', + sources : example_cmp_icu_src, + include_directories : incdir, + link_with : cmp_lib, +) + + +example_cmp_rdcu_src = files([ + 'example_cmp_rdcu.c' +]) + +example_cmp_rdcu_lib = executable('example_cmp_rdcu', + sources : example_cmp_rdcu_src, + include_directories : incdir, + link_with : cmp_lib, +) + + +example_compress_chunk_src = files([ + 'example_compress_chunk.c' +]) + +example_cmp_rdcu_lib = executable('example_compress_chunk', + sources : example_compress_chunk_src, + include_directories : incdir, + link_with : cmp_lib, +) diff --git a/header_pars.c b/header_pars.c new file mode 100644 index 0000000000000000000000000000000000000000..28109543acfecd7b25e9f1fe8183a50a3865e7c4 --- /dev/null +++ b/header_pars.c @@ -0,0 +1,134 @@ +#include <stdlib.h> + +#include <leon_inttypes.h> + +#include <cmp_io.h> +#include <cmp_debug.h> +#include <cmp_entity.h> + +static void cmp_ent_parse_generic_header(struct cmp_entity *ent) +{ + uint32_t version_id, cmp_ent_size, original_size, cmp_mode_used, + model_value_used, model_id, model_counter, max_used_bits_version, + lossy_cmp_par_used, start_coarse_time, end_coarse_time; + uint16_t start_fine_time, end_fine_time; + enum cmp_data_type data_type; + int raw_bit; + + version_id = cmp_ent_get_version_id(ent); + if (version_id & CMP_TOOL_VERSION_ID_BIT) { + uint16_t major = (version_id & 0x7FFF0000U) >> 16U; + uint16_t minor = version_id & 0xFFFFU; + + debug_print("Compressed with cmp_tool version: %u.%02u\n", major, minor); + } else + debug_print("ICU ASW Version ID: %" PRIu32 "\n", version_id); + + cmp_ent_size = cmp_ent_get_size(ent); + debug_print("Compression Entity Size: %" PRIu32 " byte\n", cmp_ent_size); + + original_size = cmp_ent_get_original_size(ent); + debug_print("Original Data Size: %" PRIu32 " byte\n", original_size); + + start_coarse_time = cmp_ent_get_coarse_start_time(ent); + debug_print("Compression Coarse Start Time: %" PRIu32 "\n", start_coarse_time); + + start_fine_time = cmp_ent_get_fine_start_time(ent); + debug_print("Compression Fine Start Time: %d\n", start_fine_time); + + end_coarse_time = cmp_ent_get_coarse_end_time(ent); + debug_print("Compression Coarse End Time: %" PRIu32 "\n", end_coarse_time); + + end_fine_time = cmp_ent_get_fine_end_time(ent); + debug_print("Compression Fine End Time: %d\n", end_fine_time); + +#ifdef HAS_TIME_H + { + struct tm epoch_date = PLATO_EPOCH_DATE; + time_t time = my_timegm(&epoch_date) + start_coarse_time; + + debug_print("Data were compressed on (local time): %s", ctime(&time)); + } +#endif + debug_print("The compression took %f second\n", end_coarse_time - start_coarse_time + + ((end_fine_time - start_fine_time)/256./256.)); + + data_type = cmp_ent_get_data_type(ent); + debug_print("Data Product Type: %d\n", data_type); + + raw_bit = cmp_ent_get_data_type_raw_bit(ent); + debug_print("RAW bit in the Data Product Type is%s set\n", raw_bit ? "" : " not"); + + cmp_mode_used = cmp_ent_get_cmp_mode(ent); + debug_print("Used Compression Mode: %" PRIu32 "\n", cmp_mode_used); + + model_value_used = cmp_ent_get_model_value(ent); + debug_print("Used Model Updating Weighing Value: %" PRIu32 "\n", model_value_used); + + model_id = cmp_ent_get_model_id(ent); + debug_print("Model ID: %" PRIu32 "\n", model_id); + + model_counter = cmp_ent_get_model_counter(ent); + debug_print("Model Counter: %" PRIu32 "\n", model_counter); + + max_used_bits_version = cmp_ent_get_max_used_bits_version(ent); + debug_print("Maximum Used Bits Registry Version: %" PRIu32 "\n", max_used_bits_version); + + lossy_cmp_par_used = cmp_ent_get_lossy_cmp_par(ent); + debug_print("Used Lossy Compression Parameters: %" PRIu32 "\n", lossy_cmp_par_used); +} +static void cmp_ent_parese_imagette_header(struct cmp_entity *ent) +{ + uint32_t spill_used, golomb_par_used; + + spill_used = cmp_ent_get_ima_spill(ent); + debug_print("Used Spillover Threshold Parameter: %" PRIu32 "\n", spill_used); + + golomb_par_used = cmp_ent_get_ima_golomb_par(ent); + debug_print("Used Golomb Parameter: %" PRIu32 "\n", golomb_par_used); +} +static void cmp_ent_parese_adaptive_imagette_header(struct cmp_entity *ent) +{ + uint32_t spill_used, golomb_par_used, ap1_spill_used, + ap1_golomb_par_used, ap2_spill_used, ap2_golomb_par_used; + + spill_used = cmp_ent_get_ima_spill(ent); + debug_print("Used Spillover Threshold Parameter: %" PRIu32 "\n", spill_used); + + golomb_par_used = cmp_ent_get_ima_golomb_par(ent); + debug_print("Used Golomb Parameter: %" PRIu32 "\n", golomb_par_used); + + ap1_spill_used = cmp_ent_get_ima_ap1_spill(ent); + debug_print("Used Adaptive 1 Spillover Threshold Parameter: %" PRIu32 "\n", ap1_spill_used); + + ap1_golomb_par_used = cmp_ent_get_ima_ap1_golomb_par(ent); + debug_print("Used Adaptive 1 Golomb Parameter: %" PRIu32 "\n", ap1_golomb_par_used); + + ap2_spill_used = cmp_ent_get_ima_ap2_spill(ent); + debug_print("Used Adaptive 2 Spillover Threshold Parameter: %" PRIu32 "\n", ap2_spill_used); + + ap2_golomb_par_used = cmp_ent_get_ima_ap2_golomb_par(ent); + debug_print("Used Adaptive 2 Golomb Parameter: %" PRIu32 "\n", ap2_golomb_par_used); +} + +int main(int argc, char *argv[]) +{ + ssize_t f_size; + char *data_file_name = argv[1]; + int verbose_en = 0; + void *data; + + f_size = read_file8(data_file_name, NULL, 0, verbose_en); + if (f_size < 0) + return 1; + + data = malloc(f_size); + + f_size = read_file8(data_file_name, data, f_size, verbose_en); + if (f_size < 0) + return 1; + + cmp_ent_parse(data); + /* cmp_ent_parese_adaptive_imagette_header(data); */ + return 0; +} diff --git a/include/cmp_data_types.h b/include/cmp_data_types.h deleted file mode 100644 index 734621e2b2d75b57c8f8f6d0f112ee0ca124ad60..0000000000000000000000000000000000000000 --- a/include/cmp_data_types.h +++ /dev/null @@ -1,261 +0,0 @@ -/** - * @file cmp_data_types.h - * @author Dominik Loidolt (dominik.loidolt@univie.ac.at) - * @date 2020 - * @brief definition of the different compression data types - * - * @copyright GPLv2 - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * @see for N-DPU packed definition: PLATO-LESIA-PL-RP-0031 Issue: 2.9 (N-DPU->ICU data rate) - * @see for calculation of the max used bits: PLATO-LESIA-PDC-TN-0054 Issue: 1.7 - * - * Three data rates (for N-DPU): - * fast cadence (nominally 25s) - * short cadence (nominally 50s) - * long cadence (nominally 600s) - * - * The science products are identified as this: - * exp_flags = selected exposure flags - * fx = normal light flux - * ncob = normal center of brightness - * efx = extended light flux - * ecob = extended center of brightness - * The prefixes f, s and l stand for fast, short and long cadence - */ - -#ifndef CMP_DATA_TYPE_H -#define CMP_DATA_TYPE_H - -#include <stdint.h> - -#include <compiler.h> -#include <cmp_support.h> - - -/* size of the source data header structure for multi entry packet */ -#define MULTI_ENTRY_HDR_SIZE 12 - - -/** - * @brief source data header structure for multi entry packet - * @note a scientific package contains a multi-entry header followed by multiple - * entries of the same entry definition - * @see PLATO-LESIA-PL-RP-0031(N-DPU->ICU data rate) - */ - -__extension__ -struct multi_entry_hdr { - uint32_t timestamp_coarse; - uint16_t timestamp_fine; - uint16_t configuration_id; - uint16_t collection_id; - uint16_t collection_length; - uint8_t entry[]; -} __attribute__((packed)); -compile_time_assert(sizeof(struct multi_entry_hdr) == MULTI_ENTRY_HDR_SIZE, N_DPU_ICU_MULTI_ENTRY_HDR_SIZE_IS_NOT_CORRECT); -compile_time_assert(sizeof(struct multi_entry_hdr) % sizeof(uint32_t) == 0, N_DPU_ICU_MULTI_ENTRY_HDR_NOT_4_BYTE_ALLIED); - - -/** - * @brief short cadence normal light flux entry definition - */ - -struct s_fx { - uint8_t exp_flags; /**< selected exposure flags (2 flags + 6 spare bits) */ - uint32_t fx; /**< normal light flux */ -} __attribute__((packed)); - - -/** - * @brief short cadence normal and extended light flux entry definition - */ - -struct s_fx_efx { - uint8_t exp_flags; - uint32_t fx; - uint32_t efx; -} __attribute__((packed)); - - -/** - * @brief short cadence normal light flux, normal center of brightness entry definition - */ - -struct s_fx_ncob { - uint8_t exp_flags; - uint32_t fx; - uint32_t ncob_x; - uint32_t ncob_y; -} __attribute__((packed)); - - -/** - * @brief short cadence normal and extended flux, normal and extended center of brightness entry definition - */ - -struct s_fx_efx_ncob_ecob { - uint8_t exp_flags; - uint32_t fx; - uint32_t ncob_x; - uint32_t ncob_y; - uint32_t efx; - uint32_t ecob_x; - uint32_t ecob_y; -} __attribute__((packed)); - - -/** - * @brief fast cadence normal light flux entry definition - */ - -struct f_fx { - uint32_t fx; -} __attribute__((packed)); - - -/** - * @brief fast cadence normal and extended light flux entry definition - */ - -struct f_fx_efx { - uint32_t fx; - uint32_t efx; -} __attribute__((packed)); - - -/** - * @brief fast cadence normal light flux, normal center of brightness entry definition - */ - -struct f_fx_ncob { - uint32_t fx; - uint32_t ncob_x; - uint32_t ncob_y; -} __attribute__((packed)); - - -/** - * @brief fast cadence normal and extended flux, normal and extended center of - * brightness entry definition - */ - -struct f_fx_efx_ncob_ecob { - uint32_t fx; - uint32_t ncob_x; - uint32_t ncob_y; - uint32_t efx; - uint32_t ecob_x; - uint32_t ecob_y; -} __attribute__((packed)); - - -/** - * @brief long cadence normal light flux entry definition - */ - -__extension__ -struct l_fx { - uint32_t exp_flags:24; /* selected exposure flags (24 flags) */ - uint32_t fx; - uint32_t fx_variance; -} __attribute__((packed)); - - -/** - * @brief long cadence normal and extended light flux entry definition - */ - -__extension__ -struct l_fx_efx { - uint32_t exp_flags:24; /* selected exposure flags (24 flags) */ - uint32_t fx; - uint32_t efx; - uint32_t fx_variance; -} __attribute__((packed)); - - -/** - * @brief long cadence normal light flux, normal center of brightness entry definition - */ - -__extension__ -struct l_fx_ncob { - uint32_t exp_flags:24; /* selected exposure flags (24 flags) */ - uint32_t fx; - uint32_t ncob_x; - uint32_t ncob_y; - uint32_t fx_variance; - uint32_t cob_x_variance; - uint32_t cob_y_variance; -} __attribute__((packed)); - - -/** - * @brief long cadence normal and extended flux, normal and extended center of - * brightness entry definition - */ - -__extension__ -struct l_fx_efx_ncob_ecob { - uint32_t exp_flags:24; /* selected exposure flags (24 flags) */ - uint32_t fx; - uint32_t ncob_x; - uint32_t ncob_y; - uint32_t efx; - uint32_t ecob_x; - uint32_t ecob_y; - uint32_t fx_variance; - uint32_t cob_x_variance; - uint32_t cob_y_variance; -} __attribute__((packed)); - - -/** - * @brief normal offset entry definition - */ - -struct nc_offset { - uint32_t mean; - uint32_t variance; -} __attribute__((packed)); - - -/** - * @brief normal background entry definition - */ - -struct nc_background { - uint32_t mean; - uint32_t variance; - uint16_t outlier_pixels; -} __attribute__((packed)); - - -/** - * @brief smearing entry definition - */ - -struct smearing { - uint32_t mean; - uint16_t variance_mean; - uint16_t outlier_pixels; -} __attribute__((packed)); - - - -size_t size_of_a_sample(enum cmp_data_type data_type); -uint32_t cmp_cal_size_of_data(uint32_t samples, enum cmp_data_type data_type); -int32_t cmp_input_size_to_samples(uint32_t size, enum cmp_data_type data_type); - -int cmp_input_big_to_cpu_endianness(void *data, uint32_t data_size_byte, - enum cmp_data_type data_type); - -#endif /* CMP_DATA_TYPE_H */ diff --git a/include/cmp_rdcu.h b/include/cmp_rdcu.h deleted file mode 100644 index d269db16c62483e6bfbdc16638f7925b0fa0c618..0000000000000000000000000000000000000000 --- a/include/cmp_rdcu.h +++ /dev/null @@ -1,54 +0,0 @@ -/** - * @file cmp_rdcu.h - * @author Dominik Loidolt (dominik.loidolt@univie.ac.at) - * @date 2019 - * - * @copyright GPLv2 - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * @brief hardware compressor control library - * @see Data Compression User Manual PLATO-UVIE-PL-UM-0001 - */ - - -#ifndef _CMP_RDCU_H_ -#define _CMP_RDCU_H_ - -#include <cmp_support.h> -#include <cmp_rdcu_cfg.h> - - -/* Compression Error Register bits definition, see RDCU-FRS-FN-0952 */ -#define SMALL_BUFFER_ERR_BIT 0x00 /* The length for the compressed data buffer is too small */ -#define CMP_MODE_ERR_BIT 0x01 /* The cmp_mode parameter is not set correctly */ -#define MODEL_VALUE_ERR_BIT 0x02 /* The model_value parameter is not set correctly */ -#define CMP_PAR_ERR_BIT 0x03 /* The spill, golomb_par combination is not set correctly */ -#define AP1_CMP_PAR_ERR_BIT 0x04 /* The ap1_spill, ap1_golomb_par combination is not set correctly (only HW compression) */ -#define AP2_CMP_PAR_ERR_BIT 0x05 /* The ap2_spill, ap2_golomb_par combination is not set correctly (only HW compression) */ -#define MB_ERR_BIT 0x06 /* Multi bit error detected by the memory controller (only HW compression) */ -#define SLAVE_BUSY_ERR_BIT 0x07 /* The bus master has received the "slave busy" status (only HW compression) */ - - -int rdcu_compress_data(const struct cmp_cfg *cfg); - -int rdcu_read_cmp_status(struct cmp_status *status); - -int rdcu_read_cmp_info(struct cmp_info *info); - -int rdcu_read_cmp_bitstream(const struct cmp_info *info, void *compressed_data); - -int rdcu_read_model(const struct cmp_info *info, void *updated_model); - -int rdcu_interrupt_compression(void); - -void rdcu_enable_interrput_signal(void); -void rdcu_disable_interrput_signal(void); - -#endif /* _CMP_RDCU_H_ */ diff --git a/include/compiler.h b/include/compiler.h deleted file mode 100644 index 006170035f692eeb5bc6ddc0f1f0f506850bc25c..0000000000000000000000000000000000000000 --- a/include/compiler.h +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @file compiler.h - * @author Armin Luntzer (armin.luntzer@univie.ac.at) - * @date 2015 - * - * @copyright GPLv2 - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * @brief a collection of preprocessor macros - */ - - -#ifndef COMPILER_H -#define COMPILER_H - - -/** - * Compile time check usable outside of function scope. - * Stolen from Linux (hpi_internal.h) - */ -#define compile_time_assert(cond, msg) typedef char ASSERT_##msg[(cond) ? 1 : -1] - - -/** - * same with the stuff below - */ - -#define likely(x) __builtin_expect(!!(x), 1) -#define unlikely(x) __builtin_expect(!!(x), 0) - - -#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) - -/* optimisation barrier */ -#define barrier() __asm__ __volatile__("": : :"memory") - -#define cpu_relax() barrier() - -#endif diff --git a/include/meson.build b/include/meson.build deleted file mode 100644 index 491eef5ecebc527e3df0fb677d7e81907bcb9895..0000000000000000000000000000000000000000 --- a/include/meson.build +++ /dev/null @@ -1,13 +0,0 @@ -# generate the configuration file -cdata = configuration_data() -cdata.set_quoted('PROGRAM_NAME', 'cmp_tool') -cdata.set_quoted('CMP_TOOL_VERSION', meson.project_version()) -if get_option('argument_input_mode') - cdata.set('ARGUMENT_INPUT_MODE', '') -endif - -configure_file( - output : 'cmp_tool-config.h', - configuration : cdata) - -incdir = include_directories('.') diff --git a/lib/cmp_chunk.h b/lib/cmp_chunk.h new file mode 100644 index 0000000000000000000000000000000000000000..ea305e52a31a48eaee146a4ba7bf6a1d469c6fb3 --- /dev/null +++ b/lib/cmp_chunk.h @@ -0,0 +1,190 @@ +/** + * @file cmp_chunk.h + * @author Dominik Loidolt (dominik.loidolt@univie.ac.at) + * @date 2024 + * + * @copyright GPLv2 + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * @brief software chunk compression library + * @see Data Compression User Manual PLATO-UVIE-PL-UM-0001 + */ + +#ifndef CMP_CHUNK_H +#define CMP_CHUNK_H + +#include "common/cmp_support.h" +#include "common/cmp_entity.h" + + +#define ROUND_UP_TO_4(x) ((((x)+3)/4)*4) + +#define COMPRESS_CHUNK_BOUND_UNSAFE(chunk_size, num_col) ( \ + ROUND_UP_TO_4(NON_IMAGETTE_HEADER_SIZE + \ + (num_col) * CMP_COLLECTION_FILD_SIZE + \ + (chunk_size) \ + ) \ +) + + +/** + * @brief returns the maximum compressed size in a worst case scenario + * + * In case the input data is not compressible + * This macro is primarily useful for compilation-time evaluation + * (stack memory allocation for example) + * + * @note if the number of collections is not know you can use the + * compress_chunk_cmp_size_bound function + * + * @param chunk_size size in bytes of the chunk + * @param num_col number of collections in the chunk + * + * @returns maximum compressed size for chunk compression; 0 on error + */ + +#define COMPRESS_CHUNK_BOUND(chunk_size, num_col) ( \ + (num_col) > 0 && \ + (num_col) <= CMP_ENTITY_MAX_SIZE/COLLECTION_HDR_SIZE && \ + (chunk_size) >= COLLECTION_HDR_SIZE * (num_col) && \ + (chunk_size) <= CMP_ENTITY_MAX_SIZE && \ + COMPRESS_CHUNK_BOUND_UNSAFE(chunk_size, num_col) <= CMP_ENTITY_MAX_SIZE ? \ + COMPRESS_CHUNK_BOUND_UNSAFE(chunk_size, num_col) : 0 \ +) + + +struct cmp_par { + enum cmp_mode cmp_mode; /**< compression mode parameter */ + uint32_t model_value; /**< model weighting parameter */ + uint32_t lossy_par; /**< lossy compression parameter */ + + uint32_t nc_imagette; /**< compression parameter for imagette data compression */ + + uint32_t s_exp_flags; /**< compression parameter for exposure flags compression */ + uint32_t s_fx; /**< compression parameter for normal flux compression */ + uint32_t s_ncob; /**< compression parameter for normal center of brightness compression */ + uint32_t s_efx; /**< compression parameter for extended flux compression */ + uint32_t s_ecob; /**< compression parameter for executed center of brightness compression */ + + uint32_t l_exp_flags; /**< compression parameter for exposure flags compression */ + uint32_t l_fx; /**< compression parameter for normal flux compression */ + uint32_t l_ncob; /**< compression parameter for normal center of brightness compression */ + uint32_t l_efx; /**< compression parameter for extended flux compression */ + uint32_t l_ecob; /**< compression parameter for executed center of brightness compression */ + uint32_t l_fx_cob_variance; /**< compression parameter for flux/COB variance compression */ + + uint32_t saturated_imagette; /**< compression parameter for saturated imagette data compression */ + + uint32_t nc_offset_mean; + uint32_t nc_offset_variance; + uint32_t nc_background_mean; + uint32_t nc_background_variance; + uint32_t nc_background_outlier_pixels; + + uint32_t smearing_mean; + uint32_t smearing_variance_mean; + uint32_t smearing_outlier_pixels; + + uint32_t fc_imagette; + uint32_t fc_offset_mean; + uint32_t fc_offset_variance; + uint32_t fc_background_mean; + uint32_t fc_background_variance; + uint32_t fc_background_outlier_pixels; +}; + + +/** + * @brief returns the maximum compressed size in a worst case scenario + * + * In case the input data is not compressible + * This function is primarily useful for memory allocation purposes + * (destination buffer size). + * + * @note if the number of collections is known you can use the + * COMPRESS_CHUNK_BOUND macro for compilation-time evaluation + * (stack memory allocation for example) + * + * @param chunk pointer to the chunk you want compress + * @param chunk_size size of the chunk in bytes + * + * @returns maximum compressed size for a chunk compression; 0 on error + */ + +uint32_t compress_chunk_cmp_size_bound(const void *chunk, size_t chunk_size); + + +/** + * @brief initialise the compress_chunk() function + * + * If not initialised the compress_chunk() function sets the timestamps and + * version_id in the compression entity header to zero + * + * @param return_timestamp pointer to a function returning a current 48-bit + * timestamp + * @param version_id version identifier of the applications software + */ + +void compress_chunk_init(uint64_t(return_timestamp)(void), uint32_t version_id); + + +/** + * @brief compress a data chunk consisting of put together data collections + * + * @param chunk pointer to the chunk to be compressed + * @param chunk_size byte size of the chunk + * @param chunk_model pointer to a model of a chunk; has the same size + * as the chunk (can be NULL if no model compression + * mode is used) + * @param updated_chunk_model pointer to store the updated model for the next + * model mode compression; has the same size as the + * chunk (can be the same as the model_of_data + * buffer for in-place update or NULL if updated + * model is not needed) + * @param dst destination pointer to the compressed data + * buffer; has to be 4-byte aligned; can be NULL to + * only get the compressed data size + * @param dst_capacity capacity of the dst buffer; it's recommended to + * provide a dst_capacity >= + * compress_chunk_cmp_size_bound(chunk, chunk_size) + * as it eliminates one potential failure scenario: + * not enough space in the dst buffer to write the + * compressed data; size is internally round down + * to a multiple of 4 + * @returns the byte size of the compressed_data buffer on success; negative on + * error, CMP_ERROR_SMALL_BUF (-2) if the compressed data buffer is too + * small to hold the whole compressed data; the compressed and updated + * model are only valid on positive return values + */ + +int32_t compress_chunk(void *chunk, uint32_t chunk_size, + void *chunk_model, void *updated_chunk_model, + uint32_t *dst, uint32_t dst_capacity, + const struct cmp_par *cmp_par); + + +/** + * @brief set the model id and model counter in the compression entity header + * + * @param dst pointer to the compressed data starting with a + * compression entity header + * @param dst_size byte size of the dst buffer + * @param model_id model identifier; for identifying entities that originate + * from the same starting model + * @param model_counter model_counter; counts how many times the model was + * updated; for non model mode compression use 0 + * + * @returns 0 on success, otherwise error + */ + +int compress_chunk_set_model_id_and_counter(void *dst, int dst_size, + uint16_t model_id, uint8_t model_counter); + +#endif /* CMP_CHUNK_H */ diff --git a/lib/cmp_data_types.c b/lib/cmp_data_types.c deleted file mode 100644 index 333f5b4c6813b8d1887e30b85a9d51c37956fe7a..0000000000000000000000000000000000000000 --- a/lib/cmp_data_types.c +++ /dev/null @@ -1,468 +0,0 @@ -/** - * @file cmp_data_types.c - * @author Dominik Loidolt (dominik.loidolt@univie.ac.at) - * @date 2020 - * - * @copyright GPLv2 - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * @brief collection of functions to handle the different compression data types - */ - - -#include <stdint.h> -#include <limits.h> - - -#include <cmp_support.h> -#include <cmp_data_types.h> -#include <cmp_debug.h> -#include <byteorder.h> - - - -/** - * @brief calculate the size of a sample for the different compression data type - * - * @param data_type compression data_type - * - * @returns the size of a data sample in bytes for the selected compression - * data type; zero on unknown data type - */ - -size_t size_of_a_sample(enum cmp_data_type data_type) -{ - size_t sample_size = 0; - - switch (data_type) { - case DATA_TYPE_IMAGETTE: - case DATA_TYPE_IMAGETTE_ADAPTIVE: - case DATA_TYPE_SAT_IMAGETTE: - case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE: - case DATA_TYPE_F_CAM_IMAGETTE: - case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE: - sample_size = sizeof(uint16_t); - break; - case DATA_TYPE_OFFSET: - sample_size = sizeof(struct nc_offset); - break; - case DATA_TYPE_BACKGROUND: - sample_size = sizeof(struct nc_background); - break; - case DATA_TYPE_SMEARING: - sample_size = sizeof(struct smearing); - break; - case DATA_TYPE_S_FX: - sample_size = sizeof(struct s_fx); - break; - case DATA_TYPE_S_FX_EFX: - sample_size = sizeof(struct s_fx_efx); - break; - case DATA_TYPE_S_FX_NCOB: - sample_size = sizeof(struct s_fx_ncob); - break; - case DATA_TYPE_S_FX_EFX_NCOB_ECOB: - sample_size = sizeof(struct s_fx_efx_ncob_ecob); - break; - case DATA_TYPE_L_FX: - sample_size = sizeof(struct l_fx); - break; - case DATA_TYPE_L_FX_EFX: - sample_size = sizeof(struct l_fx_efx); - break; - case DATA_TYPE_L_FX_NCOB: - sample_size = sizeof(struct l_fx_ncob); - break; - case DATA_TYPE_L_FX_EFX_NCOB_ECOB: - sample_size = sizeof(struct l_fx_efx_ncob_ecob); - break; - case DATA_TYPE_F_FX: - sample_size = sizeof(struct f_fx); - break; - case DATA_TYPE_F_FX_EFX: - sample_size = sizeof(struct f_fx_efx); - break; - case DATA_TYPE_F_FX_NCOB: - sample_size = sizeof(struct f_fx_ncob); - break; - case DATA_TYPE_F_FX_EFX_NCOB_ECOB: - sample_size = sizeof(struct f_fx_efx_ncob_ecob); - break; - case DATA_TYPE_F_CAM_OFFSET: - case DATA_TYPE_F_CAM_BACKGROUND: - case DATA_TYPE_UNKNOWN: - default: - debug_print("Error: Compression data type is not supported.\n"); - break; - } - return sample_size; -} - - -/** - * @brief calculate the need bytes for the data - * - * @param samples number of data samples - * @param data_type compression data_type - * - * @note for non-imagette data program types the multi entry header size is added - * - * @returns the size in bytes to store the data sample; zero on failure - */ - -uint32_t cmp_cal_size_of_data(uint32_t samples, enum cmp_data_type data_type) -{ - size_t s = size_of_a_sample(data_type); - uint64_t x; /* use 64 bit to catch overflow */ - - if (!s) - return 0; - - x = (uint64_t)s*samples; - - if (!rdcu_supported_data_type_is_used(data_type)) - x += MULTI_ENTRY_HDR_SIZE; - - if (x > UINT_MAX) /* catch overflow */ - return 0; - - return (unsigned int)x; -} - - -/** - * @brief calculates the number of samples for a given data size for the - * different compression modes - * - * @param size size of the data in bytes - * @param data_type compression data type - * - * @returns the number samples for the given compression mode; negative on error - */ - -int32_t cmp_input_size_to_samples(uint32_t size, enum cmp_data_type data_type) -{ - uint32_t samples_size = size_of_a_sample(data_type); - - if (!samples_size) - return -1; - - if (!rdcu_supported_data_type_is_used(data_type)) { - if (size < MULTI_ENTRY_HDR_SIZE) - return -1; - size -= MULTI_ENTRY_HDR_SIZE; - } - - if (size % samples_size) - return -1; - - return (int)(size/samples_size); -} - - -static uint32_t be24_to_cpu(uint32_t a) -{ - return be32_to_cpu(a) >> 8; -} - - -static void be_to_cpus_16(uint16_t *a, int samples) -{ - int i; - - for (i = 0; i < samples; ++i) - be16_to_cpus(&a[i]); -} - - -static void be_to_cpus_nc_offset(struct nc_offset *a, int samples) -{ - int i; - - for (i = 0; i < samples; ++i) { - a[i].mean = be32_to_cpu(a[i].mean); - a[i].variance = be32_to_cpu(a[i].variance); - } -} - - -static void be_to_cpus_nc_background(struct nc_background *a, int samples) -{ - int i; - - for (i = 0; i < samples; ++i) { - a[i].mean = be32_to_cpu(a[i].mean); - a[i].variance = be32_to_cpu(a[i].variance); - a[i].outlier_pixels = be16_to_cpu(a[i].outlier_pixels); - } -} - - -static void be_to_cpus_smearing(struct smearing *a, int samples) -{ - int i; - - for (i = 0; i < samples; ++i) { - a[i].mean = be32_to_cpu(a[i].mean); - a[i].variance_mean = be16_to_cpu(a[i].variance_mean); - a[i].outlier_pixels = be16_to_cpu(a[i].outlier_pixels); - } -} - - -static void be_to_cpus_s_fx(struct s_fx *a, int samples) -{ - int i; - - for (i = 0; i < samples; ++i) - a[i].fx = be32_to_cpu(a[i].fx); -} - - -static void be_to_cpus_s_fx_efx(struct s_fx_efx *a, int samples) -{ - int i; - - for (i = 0; i < samples; ++i) { - a[i].fx = be32_to_cpu(a[i].fx); - a[i].efx = be32_to_cpu(a[i].efx); - } -} - - -static void be_to_cpus_s_fx_ncob(struct s_fx_ncob *a, int samples) -{ - int i; - - for (i = 0; i < samples; ++i) { - a[i].fx = be32_to_cpu(a[i].fx); - a[i].ncob_x = be32_to_cpu(a[i].ncob_x); - a[i].ncob_y = be32_to_cpu(a[i].ncob_y); - } -} - - -static void be_to_cpus_s_fx_efx_ncob_ecob(struct s_fx_efx_ncob_ecob *a, int samples) -{ - int i; - - for (i = 0; i < samples; ++i) { - a[i].fx = be32_to_cpu(a[i].fx); - a[i].ncob_x = be32_to_cpu(a[i].ncob_x); - a[i].ncob_y = be32_to_cpu(a[i].ncob_y); - a[i].efx = be32_to_cpu(a[i].efx); - a[i].ecob_x = be32_to_cpu(a[i].ecob_x); - a[i].ecob_y = be32_to_cpu(a[i].ecob_y); - } -} - - -static void be_to_cpus_l_fx(struct l_fx *a, int samples) -{ - int i; - - for (i = 0; i < samples; ++i) { - a[i].exp_flags = be24_to_cpu(a[i].exp_flags); - a[i].fx = be32_to_cpu(a[i].fx); - a[i].fx_variance = be32_to_cpu(a[i].fx_variance); - } -} - - -static void be_to_cpus_l_fx_efx(struct l_fx_efx *a, int samples) -{ - int i; - - for (i = 0; i < samples; ++i) { - a[i].exp_flags = be24_to_cpu(a[i].exp_flags); - a[i].fx = be32_to_cpu(a[i].fx); - a[i].efx = be32_to_cpu(a[i].efx); - a[i].fx_variance = be32_to_cpu(a[i].fx_variance); - } -} - - -static void be_to_cpus_l_fx_ncob(struct l_fx_ncob *a, int samples) -{ - int i; - - for (i = 0; i < samples; ++i) { - a[i].exp_flags = be24_to_cpu(a[i].exp_flags); - a[i].fx = be32_to_cpu(a[i].fx); - a[i].ncob_x = be32_to_cpu(a[i].ncob_x); - a[i].ncob_y = be32_to_cpu(a[i].ncob_y); - a[i].fx_variance = be32_to_cpu(a[i].fx_variance); - a[i].cob_x_variance = be32_to_cpu(a[i].cob_x_variance); - a[i].cob_y_variance = be32_to_cpu(a[i].cob_y_variance); - } -} - - -static void be_to_cpus_l_fx_efx_ncob_ecob(struct l_fx_efx_ncob_ecob *a, int samples) -{ - int i; - - for (i = 0; i < samples; ++i) { - a[i].exp_flags = be24_to_cpu(a[i].exp_flags); - a[i].fx = be32_to_cpu(a[i].fx); - a[i].ncob_x = be32_to_cpu(a[i].ncob_x); - a[i].ncob_y = be32_to_cpu(a[i].ncob_y); - a[i].efx = be32_to_cpu(a[i].efx); - a[i].ecob_x = be32_to_cpu(a[i].ecob_x); - a[i].ecob_y = be32_to_cpu(a[i].ecob_y); - a[i].fx_variance = be32_to_cpu(a[i].fx_variance); - a[i].cob_x_variance = be32_to_cpu(a[i].cob_x_variance); - a[i].cob_y_variance = be32_to_cpu(a[i].cob_y_variance); - } -} - - -static void be_to_cpus_f_fx(struct f_fx *a, int samples) -{ - int i; - - for (i = 0; i < samples; ++i) - a[i].fx = be32_to_cpu(a[i].fx); -} - - -static void be_to_cpus_f_fx_efx(struct f_fx_efx *a, int samples) -{ - int i; - - for (i = 0; i < samples; ++i) { - a[i].fx = be32_to_cpu(a[i].fx); - a[i].efx = be32_to_cpu(a[i].efx); - } -} - - -static void be_to_cpus_f_fx_ncob(struct f_fx_ncob *a, int samples) -{ - int i; - - for (i = 0; i < samples; ++i) { - a[i].fx = be32_to_cpu(a[i].fx); - a[i].ncob_x = be32_to_cpu(a[i].ncob_x); - a[i].ncob_y = be32_to_cpu(a[i].ncob_y); - } -} - - -static void be_to_cpus_f_fx_efx_ncob_ecob(struct f_fx_efx_ncob_ecob *a, int samples) -{ - int i; - - for (i = 0; i < samples; ++i) { - a[i].fx = be32_to_cpu(a[i].fx); - a[i].ncob_x = be32_to_cpu(a[i].ncob_x); - a[i].ncob_y = be32_to_cpu(a[i].ncob_y); - a[i].efx = be32_to_cpu(a[i].efx); - a[i].ecob_x = be32_to_cpu(a[i].ecob_x); - a[i].ecob_y = be32_to_cpu(a[i].ecob_y); - } -} - - -/** - * @brief swap the endianness of uncompressed data form big endian to the cpu - * endianness (or the other way around) in place - * - * @param data pointer to a data sample - * @param data_size_byte size of the data in bytes - * @param data_type compression data type - * - * @returns 0 on success; non-zero on failure - */ - -int cmp_input_big_to_cpu_endianness(void *data, uint32_t data_size_byte, - enum cmp_data_type data_type) -{ - int32_t samples = cmp_input_size_to_samples(data_size_byte, data_type); - - if (!data) /* nothing to do */ - return 0; - - if (samples < 0) { - debug_print("Error: Can not convert data size in samples.\n"); - return -1; - } - - /* we do not convert the endianness of the multi entry header */ - if (!rdcu_supported_data_type_is_used(data_type)) - data = (uint8_t *)data + MULTI_ENTRY_HDR_SIZE; - - switch (data_type) { - case DATA_TYPE_IMAGETTE: - case DATA_TYPE_IMAGETTE_ADAPTIVE: - case DATA_TYPE_SAT_IMAGETTE: - case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE: - case DATA_TYPE_F_CAM_IMAGETTE: - case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE: - be_to_cpus_16(data, samples); - break; - case DATA_TYPE_OFFSET: - be_to_cpus_nc_offset(data, samples); - break; - case DATA_TYPE_BACKGROUND: - be_to_cpus_nc_background(data, samples); - break; - case DATA_TYPE_SMEARING: - be_to_cpus_smearing(data, samples); - break; - case DATA_TYPE_S_FX: - be_to_cpus_s_fx(data, samples); - break; - case DATA_TYPE_S_FX_EFX: - be_to_cpus_s_fx_efx(data, samples); - break; - case DATA_TYPE_S_FX_NCOB: - be_to_cpus_s_fx_ncob(data, samples); - break; - case DATA_TYPE_S_FX_EFX_NCOB_ECOB: - be_to_cpus_s_fx_efx_ncob_ecob(data, samples); - break; - case DATA_TYPE_L_FX: - be_to_cpus_l_fx(data, samples); - break; - case DATA_TYPE_L_FX_EFX: - be_to_cpus_l_fx_efx(data, samples); - break; - case DATA_TYPE_L_FX_NCOB: - be_to_cpus_l_fx_ncob(data, samples); - break; - case DATA_TYPE_L_FX_EFX_NCOB_ECOB: - be_to_cpus_l_fx_efx_ncob_ecob(data, samples); - break; - case DATA_TYPE_F_FX: - be_to_cpus_f_fx(data, samples); - break; - case DATA_TYPE_F_FX_EFX: - be_to_cpus_f_fx_efx(data, samples); - break; - case DATA_TYPE_F_FX_NCOB: - be_to_cpus_f_fx_ncob(data, samples); - break; - case DATA_TYPE_F_FX_EFX_NCOB_ECOB: - be_to_cpus_f_fx_efx_ncob_ecob(data, samples); - break; - /* TODO: implement F_CAM conversion */ - case DATA_TYPE_F_CAM_OFFSET: - case DATA_TYPE_F_CAM_BACKGROUND: - /* LCOV_EXCL_START */ - case DATA_TYPE_UNKNOWN: - default: - debug_print("Error: Can not swap endianness for this compression data type.\n"); - return -1; - /* LCOV_EXCL_STOP */ - } - - return 0; -} diff --git a/include/cmp_icu.h b/lib/cmp_icu.h similarity index 94% rename from include/cmp_icu.h rename to lib/cmp_icu.h index 75f8114719e4c0b68e3fb30f6fde09a10e8b2024..1dedf3ebda3cb13d2b7082fc7a7b7d34457dabac 100644 --- a/include/cmp_icu.h +++ b/lib/cmp_icu.h @@ -17,10 +17,10 @@ * @see Data Compression User Manual PLATO-UVIE-PL-UM-0001 */ -#ifndef _CMP_ICU_H_ -#define _CMP_ICU_H_ +#ifndef CMP_ICU_H +#define CMP_ICU_H -#include <cmp_support.h> +#include "common/cmp_support.h" #define CMP_PAR_UNUSED 0 @@ -54,9 +54,9 @@ int cmp_cfg_aux(struct cmp_cfg *cfg, uint32_t cmp_par_pixels_error, uint32_t spillover_pixels_error); /* set up the max_used_bits used for the compression */ -int cmp_cfg_icu_max_used_bits(struct cmp_cfg *cfg, const struct cmp_max_used_bits *max_used_bits_repo); +int cmp_cfg_icu_max_used_bits(struct cmp_cfg *cfg, const struct cmp_max_used_bits *max_used_bits); /* start the compression */ int icu_compress_data(const struct cmp_cfg *cfg); -#endif /* _CMP_ICU_H_ */ +#endif /* CMP_ICU_H */ diff --git a/lib/cmp_rdcu.h b/lib/cmp_rdcu.h new file mode 100644 index 0000000000000000000000000000000000000000..0f4fe20549fb0afb089ad36e810d2d8a37e546e8 --- /dev/null +++ b/lib/cmp_rdcu.h @@ -0,0 +1,57 @@ +/** + * @file cmp_rdcu.h + * @author Dominik Loidolt (dominik.loidolt@univie.ac.at) + * @date 2019 + * + * @copyright GPLv2 + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * @brief hardware compressor control library + * @see Data Compression User Manual PLATO-UVIE-PL-UM-0001 + */ + +#ifndef CMP_RDCU_H +#define CMP_RDCU_H + +#include "common/cmp_support.h" +#include "rdcu_compress/cmp_rdcu_cfg.h" +#include "rdcu_compress/rdcu_ctrl.h" +#include "rdcu_compress/rdcu_rmap.h" + + +/* Compression Error Register bits definition, see RDCU-FRS-FN-0952 */ +#define SMALL_BUFFER_ERR_BIT 0 /* The length for the compressed data buffer is too small */ +#define CMP_MODE_ERR_BIT 1 /* The cmp_mode parameter is not set correctly */ +#define MODEL_VALUE_ERR_BIT 2 /* The model_value parameter is not set correctly */ +#define CMP_PAR_ERR_BIT 3 /* The spill, golomb_par combination is not set correctly */ +#define AP1_CMP_PAR_ERR_BIT 4 /* The ap1_spill, ap1_golomb_par combination is not set correctly (only HW compression) */ +#define AP2_CMP_PAR_ERR_BIT 5 /* The ap2_spill, ap2_golomb_par combination is not set correctly (only HW compression) */ +#define MB_ERR_BIT 6 /* Multi bit error detected by the memory controller (only HW compression) */ +#define SLAVE_BUSY_ERR_BIT 7 /* The bus master has received the "slave busy" status (only HW compression) */ +#define SLAVE_BLOCKED_ERR_BIT 8 /* The bus master has received the “slave blocked” status */ +#define INVALID_ADDRESS_ERR_BIT 9 /* The bus master has received the “invalid address” status */ + + +int rdcu_compress_data(const struct cmp_cfg *cfg); + +int rdcu_read_cmp_status(struct cmp_status *status); + +int rdcu_read_cmp_info(struct cmp_info *info); + +int rdcu_read_cmp_bitstream(const struct cmp_info *info, void *compressed_data); + +int rdcu_read_model(const struct cmp_info *info, void *updated_model); + +int rdcu_interrupt_compression(void); + +void rdcu_enable_interrput_signal(void); +void rdcu_disable_interrput_signal(void); + +#endif /* CMP_RDCU_H */ diff --git a/include/byteorder.h b/lib/common/byteorder.h similarity index 99% rename from include/byteorder.h rename to lib/common/byteorder.h index d6ebce239e532868d8db205f3161d0436ec5a9ba..4b58a45658958e168b8b0dab51ee21eeba6a5d6a 100644 --- a/include/byteorder.h +++ b/lib/common/byteorder.h @@ -53,13 +53,13 @@ #undef __LITTLE_ENDIAN #endif -#if defined __sparc__ +#if defined(__sparc__) #ifndef __BIG_ENDIAN #define __BIG_ENDIAN 4321 #endif #endif -#if (defined __i386__ || defined __x86_64__) +#if defined(__i386__) || defined(__x86_64__) #ifndef __LITTLE_ENDIAN #define __LITTLE_ENDIAN 1234 #endif diff --git a/lib/common/cmp_cal_up_model.h b/lib/common/cmp_cal_up_model.h new file mode 100644 index 0000000000000000000000000000000000000000..afd8e0c8f15e1c321c6f4b5c3151763fcda7c4ba --- /dev/null +++ b/lib/common/cmp_cal_up_model.h @@ -0,0 +1,118 @@ +/** + * @file cmp_cal_up_model.h + * @author Dominik Loidolt (dominik.loidolt@univie.ac.at) + * @date 2023 + * + * @copyright GPLv2 + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * @brief functions to calculate the update (new) model + */ + +#ifndef CMP_CAL_UP_MODEL_H +#define CMP_CAL_UP_MODEL_H + +#include <stdint.h> + + +/* the maximal model values used in the update equation for the new model */ +#define MAX_MODEL_VALUE 16U + + +/** + * @brief method for lossy rounding + * @note This function is implemented as a macro for the sake of performance + * + * @param value the value to round + * @param round rounding parameter + * + * @return rounded value + */ + +#define round_fwd(value, round) ((uint32_t)(value) >> (round)) + + +/** + * @brief inverse method for lossy rounding + * @note This function is implemented as a macro for the sake of performance + * + * @param value the value to round back + * @param round rounding parameter + * + * @return back rounded value + */ + +#define round_inv(value, round) ((uint32_t)(value) << (round)) + + +/** + * @brief implantation of the model update equation + * @note check before that model_value is not greater than MAX_MODEL_VALUE + * + * @warning: Do not use this macro with types larger than uint32_t + * + * @param data data to process + * @param model (current) model of the data to process + * @param model_value model weighting parameter + * @param round routing parameter + * + * @returns (new) updated model + */ + +#define cmp_up_model(data, model, model_value, round) \ + __extension__ \ + ({ \ + __typeof__(data) __ret; \ + switch (sizeof(data)) { \ + case sizeof(uint8_t): \ + case sizeof(uint16_t): \ + __ret = (__typeof__(__ret))cmp_up_model16(data, model, model_value, round); \ + break; \ + case sizeof(uint32_t): \ + __ret = (__typeof__(__ret))cmp_up_model32(data, model, model_value, round); \ + break; \ + } \ + __ret; \ + }) + + +/* fast calculation for data size smaller that uint32_t */ +static inline uint16_t cmp_up_model16(uint32_t data, uint32_t model, + unsigned int model_value, unsigned int round) +{ + /* round and round back input because for decompression the accurate + * data values are not available + */ + uint32_t const weighted_data = round_inv(round_fwd(data, round), round) + * (MAX_MODEL_VALUE - model_value); + uint32_t const weighted_model = model * model_value; + + /* truncation is intended */ + return (uint16_t)((weighted_model + weighted_data) / MAX_MODEL_VALUE); +} + + +/* slow calculation for uint32_t data size */ +static inline uint32_t cmp_up_model32(uint32_t data, uint32_t model, + unsigned int model_value, unsigned int round) +{ + /* round and round back input because for decompression the accurate + * data values are not available + * cast to uint64_t to prevent overflow in the multiplication + */ + uint64_t const weighted_data = (uint64_t)round_inv(round_fwd(data, round), round) + * (MAX_MODEL_VALUE - model_value); + uint64_t const weighted_model = (uint64_t)model * model_value; + + /* truncation is intended */ + return (uint32_t)((weighted_model + weighted_data) / MAX_MODEL_VALUE); +} + +#endif /* CMP_CAL_UP_MODEL */ diff --git a/lib/common/cmp_data_types.c b/lib/common/cmp_data_types.c new file mode 100644 index 0000000000000000000000000000000000000000..bba86c89ddf92ea9191cc6f37b004ec8f8a4d19d --- /dev/null +++ b/lib/common/cmp_data_types.c @@ -0,0 +1,1023 @@ +/** + * @file cmp_data_types.c + * @author Dominik Loidolt (dominik.loidolt@univie.ac.at) + * @date 2020 + * + * @copyright GPLv2 + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * @brief collection of functions to handle the different compression data types + */ + + +#include <stdint.h> +#include <limits.h> + +#include "byteorder.h" +#include "cmp_debug.h" +#include "cmp_support.h" +#include "cmp_data_types.h" + + +/** + * @brief get the collection timestamp from the collection header + * + * @param col pointer to a collection header + * + * @returns the collection timestamp + */ + +uint64_t cmp_col_get_timestamp(const struct collection_hdr *col) +{ +#ifdef __LITTLE_ENDIAN + return be64_to_cpu(col->timestamp) >> 16; +#else + return col->timestamp; +#endif /* __LITTLE_ENDIAN */ +} + + +/** + * @brief get the configuration identifier from the collection header + * + * @param col pointer to a collection header + * + * @returns the configuration identifier + */ + +uint16_t cmp_col_get_configuration_id(const struct collection_hdr *col) +{ + return be16_to_cpu(col->configuration_id); +} + + +/** + * @brief get the collection identifier from the collection header + * + * @param col pointer to a collection header + * + * @returns the collection identifier + */ + +uint16_t cmp_col_get_col_id(const struct collection_hdr *col) +{ + return be16_to_cpu(col->collection_id); +} + + +/** + * @brief get the packet type bit in the collection identifier field of the + * collection header + * + * @param col pointer to a collection header + * + * @returns the collection packet type a collection; 1 for science packets and + * 0 for window packets + * + */ + +uint8_t cmp_col_get_pkt_type(const struct collection_hdr *col) +{ + union collection_id cid; + + cid.collection_id = be16_to_cpu(col->collection_id); + return cid.field.pkt_type; +} + + +/** + * @brief get the subservice field in the collection identifier field of the + * collection header + * + * @param col pointer to a collection header + * + * @returns the collection subservice type + */ + +uint8_t cmp_col_get_subservice(const struct collection_hdr *col) +{ + union collection_id cid; + + cid.collection_id = be16_to_cpu(col->collection_id); + return cid.field.subservice; +} + + +/** + * @brief get the CCD identifier field in the collection identifier field of + * the collection header + * + * @param col pointer to a collection header + * + * @returns the collection CCD identifier + */ + +uint8_t cmp_col_get_ccd_id(const struct collection_hdr *col) +{ + union collection_id cid; + + cid.collection_id = be16_to_cpu(col->collection_id); + return cid.field.ccd_id; +} + + +/** + * @brief get the sequence number field in the collection identifier field of + * the collection header + * + * @param col pointer to a collection header + * + * @returns the collection sequence number + */ + +uint8_t cmp_col_get_sequence_num(const struct collection_hdr *col) +{ + union collection_id cid; + + cid.collection_id = be16_to_cpu(col->collection_id); + return cid.field.sequence_num; +} + + +/** + * @brief get the collection length from the collection header + * + * @param col pointer to a collection header + * + * @returns the collection length in bytes + */ + +uint16_t cmp_col_get_data_length(const struct collection_hdr *col) +{ + return be16_to_cpu(col->collection_length); +} + + +/** + * @brief get the entire collection size (header plus data size) + * + * @param col pointer to a collection header + * + * @returns the collection size in bytes + */ + +uint32_t cmp_col_get_size(const struct collection_hdr *col) +{ + return COLLECTION_HDR_SIZE + cmp_col_get_data_length(col); +} + + +/** + * @brief set the timestamp in the collection header + * + * @param col pointer to a collection header + * @param timestamp collection timestamp (coarse and fine) + * + * @returns 0 on success, otherwise error + */ + +int cmp_col_set_timestamp(struct collection_hdr *col, uint64_t timestamp) +{ + if (!col) + return -1; + if (timestamp >> 48) + return -1; + +#ifdef __LITTLE_ENDIAN + col->timestamp = cpu_to_be64(timestamp) >> 16; +#else + col->timestamp = timestamp; +#endif /* __LITTLE_ENDIAN */ + + return 0; +} + + +/** + * @brief set the configuration identifier in the collection header + * + * @param col pointer to a collection header + * @param configuration_id configuration identifier + * + * @returns 0 on success, otherwise error + */ + +int cmp_col_set_configuration_id(struct collection_hdr *col, uint16_t configuration_id) +{ + if (!col) + return 1; + + col->configuration_id = cpu_to_be16(configuration_id); + return 0; +} + + +/** + * @brief set the collection identifier in the collection header + * + * @param col pointer to a collection header + * @param collection_id collection identifier + * + * @returns 0 on success, otherwise error + */ + +int cmp_col_set_col_id(struct collection_hdr *col, uint16_t collection_id) +{ + if (!col) + return -1; + + col->collection_id = cpu_to_be16(collection_id); + return 0; +} + + +/** + * @brief set the packet type bit in the collection identifier field of the + * collection header + * + * @param col pointer to a collection header + * @param pkt_type packet type bit; 1 for science packets and 0 for window packets + * + * @returns 0 on success, otherwise error + */ + +int cmp_col_set_pkt_type(struct collection_hdr *col, uint8_t pkt_type) +{ + union collection_id cid; + + if (!col) + return -1; + if (pkt_type >> 1) + return -1; + + cid.collection_id = be16_to_cpu(col->collection_id); + cid.field.pkt_type = pkt_type; + cmp_col_set_col_id(col, cid.collection_id); + return 0; +} + + +/** + * @brief set the packet subservice field in the collection identifier field of + * the collection header + * + * @param col pointer to a collection header + * @param subservice collection subservice type + * + * @returns 0 on success, otherwise error + */ + +int cmp_col_set_subservice(struct collection_hdr *col, uint8_t subservice) +{ + union collection_id cid; + + if (!col) + return -1; + if (subservice >> 6) + return -1; + + cid.collection_id = be16_to_cpu(col->collection_id); + cid.field.subservice = subservice; + cmp_col_set_col_id(col, cid.collection_id); + return 0; +} + + +/** + * @brief set the packet CCD identifier field in the collection identifier field + * of the collection header + * + * @param col pointer to a collection header + * @param ccd_id collection CCD identifier + * + * @returns 0 on success, otherwise error + */ + +int cmp_col_set_ccd_id(struct collection_hdr *col, uint8_t ccd_id) +{ + union collection_id cid; + + if (!col) + return -1; + if (ccd_id >> 2) + return -1; + + cid.collection_id = be16_to_cpu(col->collection_id); + cid.field.ccd_id = ccd_id; + cmp_col_set_col_id(col, cid.collection_id); + return 0; +} + + +/** + * @brief set the collection sequence number bit field in the collection + * identifier of the collection header + * + * @param col pointer to a collection header + * @param sequence_num collection sequence number + * + * @returns 0 on success, otherwise error + */ + +int cmp_col_set_sequence_num(struct collection_hdr *col, uint8_t sequence_num) +{ + union collection_id cid; + + if (!col) + return -1; + + if (sequence_num >> 7) + return -1; + + cid.collection_id = be16_to_cpu(col->collection_id); + cid.field.sequence_num = sequence_num; + return cmp_col_set_col_id(col, cid.collection_id); +} + + +/** + * @brief set the collection length in the collection header + * + * @param col pointer to a collection header + * @param length length of the collection in bytes TBC: without the + * header size itself + * + * @returns 0 on success, otherwise error + */ + +int cmp_col_set_data_length(struct collection_hdr *col, uint16_t length) +{ + if (!col) + return -1; + + col->collection_length = cpu_to_be16(length); + return 0; +} + + +/** + * @brief converts a subservice to its associated compression data type + * + * @param subservice collection subservice type + * + * @returns the converted compression data type; DATA_TYPE_UNKNOWN if the + * subservice is unknown + */ + +enum cmp_data_type convert_subservice_to_cmp_data_type(uint8_t subservice) +{ + switch (subservice) { + case SST_NCxx_S_SCIENCE_IMAGETTE: + return DATA_TYPE_IMAGETTE; + case SST_NCxx_S_SCIENCE_SAT_IMAGETTE: + return DATA_TYPE_SAT_IMAGETTE; + case SST_NCxx_S_SCIENCE_OFFSET: + return DATA_TYPE_OFFSET; + case SST_NCxx_S_SCIENCE_BACKGROUND: + return DATA_TYPE_BACKGROUND; + case SST_NCxx_S_SCIENCE_SMEARING: + return DATA_TYPE_SMEARING; + case SST_NCxx_S_SCIENCE_S_FX: + return DATA_TYPE_S_FX; + case SST_NCxx_S_SCIENCE_S_FX_EFX: + return DATA_TYPE_S_FX_EFX; + case SST_NCxx_S_SCIENCE_S_FX_NCOB: + return DATA_TYPE_S_FX_NCOB; + case SST_NCxx_S_SCIENCE_S_FX_EFX_NCOB_ECOB: + return DATA_TYPE_S_FX_EFX_NCOB_ECOB; + case SST_NCxx_S_SCIENCE_L_FX: + return DATA_TYPE_L_FX; + case SST_NCxx_S_SCIENCE_L_FX_EFX: + return DATA_TYPE_L_FX_EFX; + case SST_NCxx_S_SCIENCE_L_FX_NCOB: + return DATA_TYPE_L_FX_NCOB; + case SST_NCxx_S_SCIENCE_L_FX_EFX_NCOB_ECOB: + return DATA_TYPE_L_FX_EFX_NCOB_ECOB; + case SST_NCxx_S_SCIENCE_F_FX: + return DATA_TYPE_F_FX; + case SST_NCxx_S_SCIENCE_F_FX_EFX: + return DATA_TYPE_F_FX_EFX; + case SST_NCxx_S_SCIENCE_F_FX_NCOB: + return DATA_TYPE_F_FX_NCOB; + case SST_NCxx_S_SCIENCE_F_FX_EFX_NCOB_ECOB: + return DATA_TYPE_F_FX_EFX_NCOB_ECOB; + case SST_FCx_S_SCIENCE_IMAGETTE: + return DATA_TYPE_F_CAM_IMAGETTE; + case SST_FCx_S_SCIENCE_OFFSET_VALUES: + return DATA_TYPE_F_CAM_OFFSET; + case SST_FCx_S_BACKGROUND_VALUES: + return DATA_TYPE_F_CAM_BACKGROUND; + default: + return DATA_TYPE_UNKNOWN; + }; +} + + +/** + * @brief converts a compression data type to its associated subservice. + * + * @param data_type compression data type + * + * @returns the converted subservice; -1 if the data type is unknown. + */ + +uint8_t convert_cmp_data_type_to_subservice(enum cmp_data_type data_type) +{ + uint8_t sst = 0; + + switch (data_type) { + case DATA_TYPE_IMAGETTE: + case DATA_TYPE_IMAGETTE_ADAPTIVE: + sst = SST_NCxx_S_SCIENCE_IMAGETTE; + break; + case DATA_TYPE_SAT_IMAGETTE: + case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE: + sst = SST_NCxx_S_SCIENCE_SAT_IMAGETTE; + break; + case DATA_TYPE_OFFSET: + sst = SST_NCxx_S_SCIENCE_OFFSET; + break; + case DATA_TYPE_BACKGROUND: + sst = SST_NCxx_S_SCIENCE_BACKGROUND; + break; + case DATA_TYPE_SMEARING: + sst = SST_NCxx_S_SCIENCE_SMEARING; + break; + case DATA_TYPE_S_FX: + sst = SST_NCxx_S_SCIENCE_S_FX; + break; + case DATA_TYPE_S_FX_EFX: + sst = SST_NCxx_S_SCIENCE_S_FX_EFX; + break; + case DATA_TYPE_S_FX_NCOB: + sst = SST_NCxx_S_SCIENCE_S_FX_NCOB; + break; + case DATA_TYPE_S_FX_EFX_NCOB_ECOB: + sst = SST_NCxx_S_SCIENCE_S_FX_EFX_NCOB_ECOB; + break; + case DATA_TYPE_L_FX: + sst = SST_NCxx_S_SCIENCE_L_FX; + break; + case DATA_TYPE_L_FX_EFX: + sst = SST_NCxx_S_SCIENCE_L_FX_EFX; + break; + case DATA_TYPE_L_FX_NCOB: + sst = SST_NCxx_S_SCIENCE_L_FX_NCOB; + break; + case DATA_TYPE_L_FX_EFX_NCOB_ECOB: + sst = SST_NCxx_S_SCIENCE_L_FX_EFX_NCOB_ECOB; + break; + case DATA_TYPE_F_FX: + sst = SST_NCxx_S_SCIENCE_F_FX; + break; + case DATA_TYPE_F_FX_EFX: + sst = SST_NCxx_S_SCIENCE_F_FX_EFX; + break; + case DATA_TYPE_F_FX_NCOB: + sst = SST_NCxx_S_SCIENCE_F_FX_NCOB; + break; + case DATA_TYPE_F_FX_EFX_NCOB_ECOB: + sst = SST_NCxx_S_SCIENCE_F_FX_EFX_NCOB_ECOB; + break; + case DATA_TYPE_F_CAM_IMAGETTE: + case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE: + sst = SST_FCx_S_SCIENCE_IMAGETTE; + break; + case DATA_TYPE_F_CAM_OFFSET: + sst = SST_FCx_S_SCIENCE_OFFSET_VALUES; + break; + case DATA_TYPE_F_CAM_BACKGROUND: + sst = SST_FCx_S_BACKGROUND_VALUES; + break; + default: + case DATA_TYPE_UNKNOWN: + debug_print("Error: Unknown compression data type!"); + sst = (uint8_t)-1; + }; + + return sst; +} + + +/** + * @brief calculate the size of a sample for the different compression data type + * + * @param data_type compression data_type + * + * @returns the size of a data sample in bytes for the selected compression + * data type; zero on unknown data type + */ + +size_t size_of_a_sample(enum cmp_data_type data_type) +{ + size_t sample_size = 0; + + switch (data_type) { + case DATA_TYPE_IMAGETTE: + case DATA_TYPE_IMAGETTE_ADAPTIVE: + case DATA_TYPE_SAT_IMAGETTE: + case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE: + case DATA_TYPE_F_CAM_IMAGETTE: + case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE: + sample_size = sizeof(uint16_t); + break; + case DATA_TYPE_OFFSET: + case DATA_TYPE_F_CAM_OFFSET: + sample_size = sizeof(struct offset); + break; + case DATA_TYPE_BACKGROUND: + case DATA_TYPE_F_CAM_BACKGROUND: + sample_size = sizeof(struct background); + break; + case DATA_TYPE_SMEARING: + sample_size = sizeof(struct smearing); + break; + case DATA_TYPE_S_FX: + sample_size = sizeof(struct s_fx); + break; + case DATA_TYPE_S_FX_EFX: + sample_size = sizeof(struct s_fx_efx); + break; + case DATA_TYPE_S_FX_NCOB: + sample_size = sizeof(struct s_fx_ncob); + break; + case DATA_TYPE_S_FX_EFX_NCOB_ECOB: + sample_size = sizeof(struct s_fx_efx_ncob_ecob); + break; + case DATA_TYPE_L_FX: + sample_size = sizeof(struct l_fx); + break; + case DATA_TYPE_L_FX_EFX: + sample_size = sizeof(struct l_fx_efx); + break; + case DATA_TYPE_L_FX_NCOB: + sample_size = sizeof(struct l_fx_ncob); + break; + case DATA_TYPE_L_FX_EFX_NCOB_ECOB: + sample_size = sizeof(struct l_fx_efx_ncob_ecob); + break; + case DATA_TYPE_F_FX: + sample_size = sizeof(struct f_fx); + break; + case DATA_TYPE_F_FX_EFX: + sample_size = sizeof(struct f_fx_efx); + break; + case DATA_TYPE_F_FX_NCOB: + sample_size = sizeof(struct f_fx_ncob); + break; + case DATA_TYPE_F_FX_EFX_NCOB_ECOB: + sample_size = sizeof(struct f_fx_efx_ncob_ecob); + break; + case DATA_TYPE_UNKNOWN: + default: + debug_print("Error: Compression data type is not supported."); + break; + } + return sample_size; +} + + +/** + * @brief calculate the need bytes for the data + * + * @param samples number of data samples + * @param data_type compression data_type + * + * @note for non-imagette data program types the collection header size is added + * + * @returns the size in bytes to store the data sample; zero on failure + */ + +uint32_t cmp_cal_size_of_data(uint32_t samples, enum cmp_data_type data_type) +{ + size_t s = size_of_a_sample(data_type); + uint64_t x; /* use 64 bit to catch overflow */ + + if (!s) + return 0; + + x = (uint64_t)s*samples; + + if (!rdcu_supported_data_type_is_used(data_type)) + x += COLLECTION_HDR_SIZE; + + if (x > UINT_MAX) /* catch overflow */ + return 0; + + return (unsigned int)x; +} + + +/** + * @brief calculates the number of samples for a given data size for the + * different compression modes + * + * @param size size of the data in bytes + * @param data_type compression data type + * + * @returns the number samples for the given compression mode; negative on error + */ + +int32_t cmp_input_size_to_samples(uint32_t size, enum cmp_data_type data_type) +{ + uint32_t samples_size = (uint32_t)size_of_a_sample(data_type); + + if (!samples_size) + return -1; + + if (!rdcu_supported_data_type_is_used(data_type)) { + if (size < COLLECTION_HDR_SIZE) + return -1; + size -= COLLECTION_HDR_SIZE; + } + + if (size % samples_size) + return -1; + + return (int)(size/samples_size); +} + + +static uint32_t be24_to_cpu(uint32_t a) +{ + return be32_to_cpu(a) >> 8; +} + + +static void be_to_cpus_16(uint16_t *a, uint32_t samples) +{ + uint32_t i; + + for (i = 0; i < samples; ++i) { + uint16_t tmp; + + tmp = be16_to_cpu(get_unaligned(&a[i])); + put_unaligned(tmp, &a[i]); + } +} + + +static void be_to_cpus_offset(struct offset *a, uint32_t samples) +{ + uint32_t i; + + for (i = 0; i < samples; ++i) { + a[i].mean = be32_to_cpu(a[i].mean); + a[i].variance = be32_to_cpu(a[i].variance); + } +} + + +static void be_to_cpus_background(struct background *a, uint32_t samples) +{ + uint32_t i; + + for (i = 0; i < samples; ++i) { + a[i].mean = be32_to_cpu(a[i].mean); + a[i].variance = be32_to_cpu(a[i].variance); + a[i].outlier_pixels = be16_to_cpu(a[i].outlier_pixels); + } +} + + +static void be_to_cpus_smearing(struct smearing *a, uint32_t samples) +{ + uint32_t i; + + for (i = 0; i < samples; ++i) { + a[i].mean = be32_to_cpu(a[i].mean); + a[i].variance_mean = be16_to_cpu(a[i].variance_mean); + a[i].outlier_pixels = be16_to_cpu(a[i].outlier_pixels); + } +} + + +static void be_to_cpus_s_fx(struct s_fx *a, uint32_t samples) +{ + uint32_t i; + + for (i = 0; i < samples; ++i) + a[i].fx = be32_to_cpu(a[i].fx); +} + + +static void be_to_cpus_s_fx_efx(struct s_fx_efx *a, uint32_t samples) +{ + uint32_t i; + + for (i = 0; i < samples; ++i) { + a[i].fx = be32_to_cpu(a[i].fx); + a[i].efx = be32_to_cpu(a[i].efx); + } +} + + +static void be_to_cpus_s_fx_ncob(struct s_fx_ncob *a, uint32_t samples) +{ + uint32_t i; + + for (i = 0; i < samples; ++i) { + a[i].fx = be32_to_cpu(a[i].fx); + a[i].ncob_x = be32_to_cpu(a[i].ncob_x); + a[i].ncob_y = be32_to_cpu(a[i].ncob_y); + } +} + + +static void be_to_cpus_s_fx_efx_ncob_ecob(struct s_fx_efx_ncob_ecob *a, uint32_t samples) +{ + uint32_t i; + + for (i = 0; i < samples; ++i) { + a[i].fx = be32_to_cpu(a[i].fx); + a[i].ncob_x = be32_to_cpu(a[i].ncob_x); + a[i].ncob_y = be32_to_cpu(a[i].ncob_y); + a[i].efx = be32_to_cpu(a[i].efx); + a[i].ecob_x = be32_to_cpu(a[i].ecob_x); + a[i].ecob_y = be32_to_cpu(a[i].ecob_y); + } +} + + +static void be_to_cpus_l_fx(struct l_fx *a, uint32_t samples) +{ + uint32_t i; + + for (i = 0; i < samples; ++i) { + a[i].exp_flags = be24_to_cpu(a[i].exp_flags); + a[i].fx = be32_to_cpu(a[i].fx); + a[i].fx_variance = be32_to_cpu(a[i].fx_variance); + } +} + + +static void be_to_cpus_l_fx_efx(struct l_fx_efx *a, uint32_t samples) +{ + uint32_t i; + + for (i = 0; i < samples; ++i) { + a[i].exp_flags = be24_to_cpu(a[i].exp_flags); + a[i].fx = be32_to_cpu(a[i].fx); + a[i].efx = be32_to_cpu(a[i].efx); + a[i].fx_variance = be32_to_cpu(a[i].fx_variance); + } +} + + +static void be_to_cpus_l_fx_ncob(struct l_fx_ncob *a, uint32_t samples) +{ + uint32_t i; + + for (i = 0; i < samples; ++i) { + a[i].exp_flags = be24_to_cpu(a[i].exp_flags); + a[i].fx = be32_to_cpu(a[i].fx); + a[i].ncob_x = be32_to_cpu(a[i].ncob_x); + a[i].ncob_y = be32_to_cpu(a[i].ncob_y); + a[i].fx_variance = be32_to_cpu(a[i].fx_variance); + a[i].cob_x_variance = be32_to_cpu(a[i].cob_x_variance); + a[i].cob_y_variance = be32_to_cpu(a[i].cob_y_variance); + } +} + + +static void be_to_cpus_l_fx_efx_ncob_ecob(struct l_fx_efx_ncob_ecob *a, uint32_t samples) +{ + uint32_t i; + + for (i = 0; i < samples; ++i) { + a[i].exp_flags = be24_to_cpu(a[i].exp_flags); + a[i].fx = be32_to_cpu(a[i].fx); + a[i].ncob_x = be32_to_cpu(a[i].ncob_x); + a[i].ncob_y = be32_to_cpu(a[i].ncob_y); + a[i].efx = be32_to_cpu(a[i].efx); + a[i].ecob_x = be32_to_cpu(a[i].ecob_x); + a[i].ecob_y = be32_to_cpu(a[i].ecob_y); + a[i].fx_variance = be32_to_cpu(a[i].fx_variance); + a[i].cob_x_variance = be32_to_cpu(a[i].cob_x_variance); + a[i].cob_y_variance = be32_to_cpu(a[i].cob_y_variance); + } +} + + +static void be_to_cpus_f_fx(struct f_fx *a, uint32_t samples) +{ + uint32_t i; + + for (i = 0; i < samples; ++i) + a[i].fx = be32_to_cpu(a[i].fx); +} + + +static void be_to_cpus_f_fx_efx(struct f_fx_efx *a, uint32_t samples) +{ + uint32_t i; + + for (i = 0; i < samples; ++i) { + a[i].fx = be32_to_cpu(a[i].fx); + a[i].efx = be32_to_cpu(a[i].efx); + } +} + + +static void be_to_cpus_f_fx_ncob(struct f_fx_ncob *a, uint32_t samples) +{ + uint32_t i; + + for (i = 0; i < samples; ++i) { + a[i].fx = be32_to_cpu(a[i].fx); + a[i].ncob_x = be32_to_cpu(a[i].ncob_x); + a[i].ncob_y = be32_to_cpu(a[i].ncob_y); + } +} + + +static void be_to_cpus_f_fx_efx_ncob_ecob(struct f_fx_efx_ncob_ecob *a, uint32_t samples) +{ + uint32_t i; + + for (i = 0; i < samples; ++i) { + a[i].fx = be32_to_cpu(a[i].fx); + a[i].ncob_x = be32_to_cpu(a[i].ncob_x); + a[i].ncob_y = be32_to_cpu(a[i].ncob_y); + a[i].efx = be32_to_cpu(a[i].efx); + a[i].ecob_x = be32_to_cpu(a[i].ecob_x); + a[i].ecob_y = be32_to_cpu(a[i].ecob_y); + } +} + + +/** + * @brief swaps the endianness of (collection) data from big endian to the CPU + * endianness (or vice versa) in place. + * @note if you want to swap the data of a whole collection, including a + * collection header or a chunk of collections use the be_to_cpu_chunk() or + * cpu_to_be_chunk() functions + * + * @param data a pointer to the data to swap (not including a + * collection header); can be NULL + * @param data_size_byte size of the data in bytes + * @param data_type compression data type + * + * @returns 0 on success; -1 on failure + */ + +int be_to_cpu_data_type(void *data, uint32_t data_size_byte, enum cmp_data_type data_type) +{ + uint32_t sample_size = (uint32_t)size_of_a_sample(data_type); + uint32_t samples; + + if (!data) /* nothing to do */ + return 0; + + if (!sample_size) + return -1; + + if (data_size_byte % sample_size) { + debug_print("Error: Can not convert data size in samples."); + return -1; + } + samples = data_size_byte / sample_size; + +#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) + switch (data_type) { + case DATA_TYPE_IMAGETTE: + case DATA_TYPE_IMAGETTE_ADAPTIVE: + case DATA_TYPE_SAT_IMAGETTE: + case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE: + case DATA_TYPE_F_CAM_IMAGETTE: + case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE: + be_to_cpus_16(data, samples); + break; + case DATA_TYPE_OFFSET: + case DATA_TYPE_F_CAM_OFFSET: + be_to_cpus_offset(data, samples); + break; + case DATA_TYPE_BACKGROUND: + case DATA_TYPE_F_CAM_BACKGROUND: + be_to_cpus_background(data, samples); + break; + case DATA_TYPE_SMEARING: + be_to_cpus_smearing(data, samples); + break; + case DATA_TYPE_S_FX: + be_to_cpus_s_fx(data, samples); + break; + case DATA_TYPE_S_FX_EFX: + be_to_cpus_s_fx_efx(data, samples); + break; + case DATA_TYPE_S_FX_NCOB: + be_to_cpus_s_fx_ncob(data, samples); + break; + case DATA_TYPE_S_FX_EFX_NCOB_ECOB: + be_to_cpus_s_fx_efx_ncob_ecob(data, samples); + break; + case DATA_TYPE_L_FX: + be_to_cpus_l_fx(data, samples); + break; + case DATA_TYPE_L_FX_EFX: + be_to_cpus_l_fx_efx(data, samples); + break; + case DATA_TYPE_L_FX_NCOB: + be_to_cpus_l_fx_ncob(data, samples); + break; + case DATA_TYPE_L_FX_EFX_NCOB_ECOB: + be_to_cpus_l_fx_efx_ncob_ecob(data, samples); + break; + case DATA_TYPE_F_FX: + be_to_cpus_f_fx(data, samples); + break; + case DATA_TYPE_F_FX_EFX: + be_to_cpus_f_fx_efx(data, samples); + break; + case DATA_TYPE_F_FX_NCOB: + be_to_cpus_f_fx_ncob(data, samples); + break; + case DATA_TYPE_F_FX_EFX_NCOB_ECOB: + be_to_cpus_f_fx_efx_ncob_ecob(data, samples); + break; + /* LCOV_EXCL_START */ + case DATA_TYPE_UNKNOWN: + default: + debug_print("Error: Can not swap endianness for this compression data type."); + return -1; + /* LCOV_EXCL_STOP */ + } +#endif /*__BYTE_ORDER__ */ + + return 0; +} + + +/** + * @brief swaps the endianness of chunk data from big endian to the CPU + * endianness (or vice versa) in place + * @note the endianness of the collection header is not changed! + * + * @param chunk pointer to a chunk of collections (can be NULL) + * @param chunk_size size in bytes of the chunk + * + * @returns 0 on success; -1 on failure + */ + +int be_to_cpu_chunk(uint8_t *chunk, size_t chunk_size) +{ + uint8_t *col_p = chunk; + + if (!chunk) /* nothing to do */ + return 0; + + if (chunk_size < COLLECTION_HDR_SIZE) + return -1; + + while (col_p <= chunk + chunk_size - COLLECTION_HDR_SIZE) { + struct collection_hdr *col_hdr = (struct collection_hdr *)col_p; + enum cmp_data_type data_type = convert_subservice_to_cmp_data_type(cmp_col_get_subservice(col_hdr)); + uint32_t data_size = cmp_col_get_data_length(col_hdr); + + col_p += cmp_col_get_size(col_hdr); + if (col_p > chunk + chunk_size) /* over read chunk? */ + break; + + if (be_to_cpu_data_type(col_hdr->entry, data_size, data_type)) + return -1; + } + + if (col_p != chunk + chunk_size) { + debug_print("Error: The chunk size does not match the sum of the collection sizes."); + return -1; + } + + return 0; +} + + +/** + * @brief swap the endianness of uncompressed data from big endian to the cpu + * endianness (or the other way around) in place + * + * @param data pointer to a data sample + * @param data_size_byte size of the data in bytes + * @param data_type compression data type + * + * @returns 0 on success; non-zero on failure + */ + +int cmp_input_big_to_cpu_endianness(void *data, uint32_t data_size_byte, + enum cmp_data_type data_type) +{ + if (data && !rdcu_supported_data_type_is_used(data_type)) { + /* skip collection header for non RDCU data types */ + data = (uint8_t *)data + COLLECTION_HDR_SIZE; + if (data_size_byte < COLLECTION_HDR_SIZE) + return -1; + data_size_byte -= COLLECTION_HDR_SIZE; + } + return be_to_cpu_data_type(data, data_size_byte, data_type); +} diff --git a/lib/common/cmp_data_types.h b/lib/common/cmp_data_types.h new file mode 100644 index 0000000000000000000000000000000000000000..a64661e8e85c3ecba44b4911f2bc3f78d91009eb --- /dev/null +++ b/lib/common/cmp_data_types.h @@ -0,0 +1,344 @@ +/** + * @file cmp_data_types.h + * @author Dominik Loidolt (dominik.loidolt@univie.ac.at) + * @date 2020 + * @brief definition of the different compression data types + * + * @copyright GPLv2 + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * @see for N-DPU packed definition: PLATO-LESIA-PL-RP-0031 Issue: 2.9 (N-DPU->ICU data rate) + * @see for calculation of the max used bits: PLATO-LESIA-PDC-TN-0054 Issue: 1.7 + * + * Three data rates (for N-DPU): + * fast cadence (nominally 25s) + * short cadence (nominally 50s) + * long cadence (nominally 600s) + * + * The science products are identified as this: + * exp_flags = selected exposure flags + * fx = normal light flux + * ncob = normal center of brightness + * efx = extended light flux + * ecob = extended center of brightness + * The prefixes f, s and l stand for fast, short and long cadence + */ + +#ifndef CMP_DATA_TYPE_H +#define CMP_DATA_TYPE_H + +#include <stdint.h> + +#include "compiler.h" +#include "../common/cmp_support.h" + + +/* subservice types for service 212 */ +#define SST_NCxx_S_SCIENCE_IMAGETTE 3 /* N-Camera image data */ +#define SST_NCxx_S_SCIENCE_SAT_IMAGETTE 4 /* Extended imagettes for saturated star extra pixels */ +#define SST_NCxx_S_SCIENCE_OFFSET 5 /* Offset values Mean of the pixels of offset windows */ +#define SST_NCxx_S_SCIENCE_BACKGROUND 6 /* Background values Mean of the pixels of background windows */ +#define SST_NCxx_S_SCIENCE_SMEARING 7 /* Smearing array values */ +/* subservice Type 8 is not defined */ +#define SST_NCxx_S_SCIENCE_S_FX 9 /* Short cadence FX data using normal masks */ +#define SST_NCxx_S_SCIENCE_S_FX_EFX 10 /* Short cadence FX data using normal and extended masks */ +#define SST_NCxx_S_SCIENCE_S_FX_NCOB 11 /* Short cadence FX and CoB using normal masks */ +#define SST_NCxx_S_SCIENCE_S_FX_EFX_NCOB_ECOB 12 /* Short cadence FX and CoB using normal and extended masks */ +#define SST_NCxx_S_SCIENCE_L_FX 13 /* Long cadence FX data using normal masks */ +#define SST_NCxx_S_SCIENCE_L_FX_EFX 14 /* Long cadence FX data using normal and extended masks */ +#define SST_NCxx_S_SCIENCE_L_FX_NCOB 15 /* Long cadence FX and CoB data using normal masks */ +#define SST_NCxx_S_SCIENCE_L_FX_EFX_NCOB_ECOB 16 /* Long cadence FX and CoB data using normal and extended masks */ +#define SST_NCxx_S_SCIENCE_F_FX 17 /* Fast cadence FX data using normal masks */ +#define SST_NCxx_S_SCIENCE_F_FX_EFX 18 /* Fast cadence FX and CoB using normal and extended masks */ +#define SST_NCxx_S_SCIENCE_F_FX_NCOB 19 /* Fast cadence FX and CoB using normal masks */ +#define SST_NCxx_S_SCIENCE_F_FX_EFX_NCOB_ECOB 20 /* Fast cadence FX and CoB using normal and extended masks */ + +/* subservice types for service 228 */ +#define SST_FCx_S_SCIENCE_IMAGETTE 1 /* Imagettes from F-camera. */ +#define SST_FCx_S_SCIENCE_OFFSET_VALUES 2 /* Offset values Mean of the pixels of offset windows */ +#define SST_FCx_S_BACKGROUND_VALUES 25 /* TBC: Background values. Mean of the pixels of background windows */ + +/* size of a collection (multi entry) header */ +#define COLLECTION_HDR_SIZE 12 + +enum col_packet_type { + COL_WINDOW_PKT_TYPE = 0, + COL_SCI_PKTS_TYPE = 1 +}; + + +/** + * @brief source data header structure for collection packet + * @note a collection package contains a collection header followed by multiple + * entries of the same science data + * @see PLATO-LESIA-PL-RP-0031(N-DPU->ICU data rate) + */ +union collection_id { + uint16_t collection_id; + __extension__ + struct { +#ifdef __LITTLE_ENDIAN + uint16_t sequence_num:7; + uint16_t ccd_id:2; + uint16_t subservice:6; + uint16_t pkt_type:1; +#else + uint16_t pkt_type:1; + uint16_t subservice:6; + uint16_t ccd_id:2; + uint16_t sequence_num:7; +#endif + } field __attribute__((packed)); +} __attribute__((packed)); + +__extension__ +struct collection_hdr { + uint64_t timestamp:48; /**< Time when the science observation was made */ + uint16_t configuration_id; /**< ID of the configuration of the instrument */ + uint16_t collection_id; /**< ID of a collection */ + uint16_t collection_length; /**< Expected number of data bytes in the target science packet */ + char entry[]; +} __attribute__((packed)); +compile_time_assert(sizeof(struct collection_hdr) == COLLECTION_HDR_SIZE, N_DPU_ICU_COLLECTION_HDR_SIZE_IS_NOT_CORRECT); +compile_time_assert(sizeof(struct collection_hdr) % sizeof(uint32_t) == 0, N_DPU_ICU_COLLECTION_HDR_NOT_4_BYTE_ALLIED); +/* TODO: compile_time_assert(sizeof(struct collection_hdr.collection_id) == sizeof(union collection_id), N_DPU_ICU_COLLECTION_COLLECTION_ID_DO_NOT_MATCH); */ + + +/** + * @brief short cadence normal light flux entry definition + */ + +struct s_fx { + uint8_t exp_flags; /**< selected exposure flags (2 flags + 6 spare bits) */ + uint32_t fx; /**< normal light flux */ +} __attribute__((packed)); + + +/** + * @brief short cadence normal and extended light flux entry definition + */ + +struct s_fx_efx { + uint8_t exp_flags; + uint32_t fx; + uint32_t efx; +} __attribute__((packed)); + + +/** + * @brief short cadence normal light flux, normal center of brightness entry definition + */ + +struct s_fx_ncob { + uint8_t exp_flags; + uint32_t fx; + uint32_t ncob_x; + uint32_t ncob_y; +} __attribute__((packed)); + + +/** + * @brief short cadence normal and extended flux, normal and extended center of brightness entry definition + */ + +struct s_fx_efx_ncob_ecob { + uint8_t exp_flags; + uint32_t fx; + uint32_t ncob_x; + uint32_t ncob_y; + uint32_t efx; + uint32_t ecob_x; + uint32_t ecob_y; +} __attribute__((packed)); + + +/** + * @brief fast cadence normal light flux entry definition + */ + +struct f_fx { + uint32_t fx; +} __attribute__((packed)); + + +/** + * @brief fast cadence normal and extended light flux entry definition + */ + +struct f_fx_efx { + uint32_t fx; + uint32_t efx; +} __attribute__((packed)); + + +/** + * @brief fast cadence normal light flux, normal center of brightness entry definition + */ + +struct f_fx_ncob { + uint32_t fx; + uint32_t ncob_x; + uint32_t ncob_y; +} __attribute__((packed)); + + +/** + * @brief fast cadence normal and extended flux, normal and extended center of + * brightness entry definition + */ + +struct f_fx_efx_ncob_ecob { + uint32_t fx; + uint32_t ncob_x; + uint32_t ncob_y; + uint32_t efx; + uint32_t ecob_x; + uint32_t ecob_y; +} __attribute__((packed)); + + +/** + * @brief long cadence normal light flux entry definition + */ + +__extension__ +struct l_fx { + uint32_t exp_flags:24; /* selected exposure flags (24 flags) */ + uint32_t fx; + uint32_t fx_variance; +} __attribute__((packed)); + + +/** + * @brief long cadence normal and extended light flux entry definition + */ + +__extension__ +struct l_fx_efx { + uint32_t exp_flags:24; /* selected exposure flags (24 flags) */ + uint32_t fx; + uint32_t efx; + uint32_t fx_variance; +} __attribute__((packed)); + + +/** + * @brief long cadence normal light flux, normal center of brightness entry definition + */ + +__extension__ +struct l_fx_ncob { + uint32_t exp_flags:24; /* selected exposure flags (24 flags) */ + uint32_t fx; + uint32_t ncob_x; + uint32_t ncob_y; + uint32_t fx_variance; + uint32_t cob_x_variance; + uint32_t cob_y_variance; +} __attribute__((packed)); + + +/** + * @brief long cadence normal and extended flux, normal and extended center of + * brightness entry definition + */ + +__extension__ +struct l_fx_efx_ncob_ecob { + uint32_t exp_flags:24; /* selected exposure flags (24 flags) */ + uint32_t fx; + uint32_t ncob_x; + uint32_t ncob_y; + uint32_t efx; + uint32_t ecob_x; + uint32_t ecob_y; + uint32_t fx_variance; + uint32_t cob_x_variance; + uint32_t cob_y_variance; +} __attribute__((packed)); + + +/** + * @brief normal and fast offset entry definition + */ + +struct offset { + uint32_t mean; + uint32_t variance; +} __attribute__((packed)); + + +/** + * @brief normal and fast background entry definition + */ + +struct background { + uint32_t mean; + uint32_t variance; + uint16_t outlier_pixels; +} __attribute__((packed)); + + +/** + * @brief smearing entry definition + */ + +struct smearing { + uint32_t mean; + uint16_t variance_mean; + uint16_t outlier_pixels; +} __attribute__((packed)); + + +/* collection header setter functions */ +uint64_t cmp_col_get_timestamp(const struct collection_hdr *col); +uint16_t cmp_col_get_configuration_id(const struct collection_hdr *col); + +uint16_t cmp_col_get_col_id(const struct collection_hdr *col); +uint8_t cmp_col_get_pkt_type(const struct collection_hdr *col); +uint8_t cmp_col_get_subservice(const struct collection_hdr *col); +uint8_t cmp_col_get_ccd_id(const struct collection_hdr *col); +uint8_t cmp_col_get_sequence_num(const struct collection_hdr *col); + +uint16_t cmp_col_get_data_length(const struct collection_hdr *col); +uint32_t cmp_col_get_size(const struct collection_hdr *col); + + +/* collection header getter functions */ +int cmp_col_set_timestamp(struct collection_hdr *col, uint64_t timestamp); +int cmp_col_set_configuration_id(struct collection_hdr *col, uint16_t configuration_id); + +int cmp_col_set_col_id(struct collection_hdr *col, uint16_t collection_id); +int cmp_col_set_pkt_type(struct collection_hdr *col, uint8_t pkt_type); +int cmp_col_set_subservice(struct collection_hdr *col, uint8_t subservice); +int cmp_col_set_ccd_id(struct collection_hdr *col, uint8_t ccd_id); +int cmp_col_set_sequence_num(struct collection_hdr *col, uint8_t sequence_num); + +int cmp_col_set_data_length(struct collection_hdr *col, uint16_t length); + +enum cmp_data_type convert_subservice_to_cmp_data_type(uint8_t subservice); +uint8_t convert_cmp_data_type_to_subservice(enum cmp_data_type data_type); + +size_t size_of_a_sample(enum cmp_data_type data_type); +uint32_t cmp_cal_size_of_data(uint32_t samples, enum cmp_data_type data_type); +int32_t cmp_input_size_to_samples(uint32_t size, enum cmp_data_type data_type); + + +/* endianness functions */ +int be_to_cpu_data_type(void *data, uint32_t data_size_byte, enum cmp_data_type data_type); +#define cpu_to_be_data_type(data, data_size_byte, data_type) be_to_cpu_data_type(data, data_size_byte, data_type) + +int be_to_cpu_chunk(uint8_t *chunk, size_t chunk_size); +#define cpu_to_be_chunk(chunk, chunk_size) be_to_cpu_chunk(chunk, chunk_size) + +int cmp_input_big_to_cpu_endianness(void *data, uint32_t data_size_byte, + enum cmp_data_type data_type); + +#endif /* CMP_DATA_TYPE_H */ diff --git a/include/cmp_debug.h b/lib/common/cmp_debug.h similarity index 67% rename from include/cmp_debug.h rename to lib/common/cmp_debug.h index 475c5a72a763c4240057292d2029b68f2bb8e54d..f95dc2e96964cef2ba81c41f8d1675740606c42a 100644 --- a/include/cmp_debug.h +++ b/lib/common/cmp_debug.h @@ -19,16 +19,24 @@ #ifndef CMP_DEBUG_H #define CMP_DEBUG_H -#include <stdio.h> -#if defined(DEBUG) || DEBUGLEVEL > 0 +/* DEBUGLEVEL should be externally defined, usually via the compiler command + * line. Its value must be a numeric value. */ +#ifndef DEBUGLEVEL +# define DEBUGLEVEL 0 +#endif + +#if !defined(ICU_ASW) && (defined(DEBUG) || DEBUGLEVEL > 0) + #include <stdio.h> __extension__ - #define debug_print(...) \ - do { fprintf(stderr, __VA_ARGS__); } while (0) + #define debug_print(...) \ + do { \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); \ + } while (0) #else #define debug_print(...) \ do {} while (0) #endif - #endif /* CMP_DEBUG_H */ diff --git a/lib/cmp_entity.c b/lib/common/cmp_entity.c similarity index 82% rename from lib/cmp_entity.c rename to lib/common/cmp_entity.c index 5841ecf72b3b8bddf51611a622ec13f513cecf45..46df7e957266a35fa69606ac94a8969527455ec0 100644 --- a/lib/cmp_entity.c +++ b/lib/common/cmp_entity.c @@ -19,23 +19,25 @@ #include <stdint.h> -#include <stdio.h> #include <string.h> -#if defined __has_include -# if __has_include(<time.h>) -# include <time.h> -# include <stdlib.h> -# define HAS_TIME_H 1 -# define my_timercmp(s, t, op) (((s)->tv_sec == (t)->tv_sec) ? ((s)->tv_nsec op (t)->tv_nsec) : ((s)->tv_sec op (t)->tv_sec)) + +#ifndef ICU_ASW +# if defined __has_include +# if __has_include(<time.h>) +# include <time.h> +# include <stdlib.h> +# define HAS_TIME_H 1 +# define my_timercmp(s, t, op) (((s)->tv_sec == (t)->tv_sec) ? ((s)->tv_nsec op (t)->tv_nsec) : ((s)->tv_sec op (t)->tv_sec)) +# endif # endif #endif -#include <byteorder.h> -#include <cmp_debug.h> -#include <cmp_support.h> -#include <cmp_data_types.h> -#include <cmp_entity.h> -#include <my_inttypes.h> +#include "byteorder.h" +#include "cmp_debug.h" +#include "cmp_support.h" +#include "cmp_data_types.h" +#include "cmp_entity.h" +#include "leon_inttypes.h" #ifdef HAS_TIME_H @@ -96,6 +98,7 @@ uint32_t cmp_ent_cal_hdr_size(enum cmp_data_type data_type, int raw_mode_flag) case DATA_TYPE_F_FX_EFX_NCOB_ECOB: case DATA_TYPE_F_CAM_OFFSET: case DATA_TYPE_F_CAM_BACKGROUND: + case DATA_TYPE_CHUNK: size = NON_IMAGETTE_HEADER_SIZE; break; case DATA_TYPE_UNKNOWN: @@ -962,7 +965,7 @@ int cmp_ent_set_non_ima_cmp_par6(struct cmp_entity *ent, uint32_t cmp_par_6_used * @returns the ASW version identifier on success, 0 on error */ -uint32_t cmp_ent_get_version_id(struct cmp_entity *ent) +uint32_t cmp_ent_get_version_id(const struct cmp_entity *ent) { if (!ent) return 0; @@ -979,7 +982,7 @@ uint32_t cmp_ent_get_version_id(struct cmp_entity *ent) * @returns the size of the compression entity in bytes on success, 0 on error */ -uint32_t cmp_ent_get_size(struct cmp_entity *ent) +uint32_t cmp_ent_get_size(const struct cmp_entity *ent) { if (!ent) return 0; @@ -1000,7 +1003,7 @@ uint32_t cmp_ent_get_size(struct cmp_entity *ent) * @returns the original size of the compressed data in bytes on success, 0 on error */ -uint32_t cmp_ent_get_original_size(struct cmp_entity *ent) +uint32_t cmp_ent_get_original_size(const struct cmp_entity *ent) { if (!ent) return 0; @@ -1021,7 +1024,7 @@ uint32_t cmp_ent_get_original_size(struct cmp_entity *ent) * @returns the compression start timestamp on success, 0 on error */ -uint64_t cmp_ent_get_start_timestamp(struct cmp_entity *ent) +uint64_t cmp_ent_get_start_timestamp(const struct cmp_entity *ent) { if (!ent) return 0; @@ -1042,7 +1045,7 @@ uint64_t cmp_ent_get_start_timestamp(struct cmp_entity *ent) * error */ -uint32_t cmp_ent_get_coarse_start_time(struct cmp_entity *ent) +uint32_t cmp_ent_get_coarse_start_time(const struct cmp_entity *ent) { if (!ent) return 0; @@ -1059,7 +1062,7 @@ uint32_t cmp_ent_get_coarse_start_time(struct cmp_entity *ent) * error */ -uint16_t cmp_ent_get_fine_start_time(struct cmp_entity *ent) +uint16_t cmp_ent_get_fine_start_time(const struct cmp_entity *ent) { if (!ent) return 0; @@ -1076,7 +1079,7 @@ uint16_t cmp_ent_get_fine_start_time(struct cmp_entity *ent) * @returns the compression end timestamp on success, 0 on error */ -uint64_t cmp_ent_get_end_timestamp(struct cmp_entity *ent) +uint64_t cmp_ent_get_end_timestamp(const struct cmp_entity *ent) { if (!ent) return 0; @@ -1097,7 +1100,7 @@ uint64_t cmp_ent_get_end_timestamp(struct cmp_entity *ent) * error */ -uint32_t cmp_ent_get_coarse_end_time(struct cmp_entity *ent) +uint32_t cmp_ent_get_coarse_end_time(const struct cmp_entity *ent) { if (!ent) return 0; @@ -1114,7 +1117,7 @@ uint32_t cmp_ent_get_coarse_end_time(struct cmp_entity *ent) * error */ -uint16_t cmp_ent_get_fine_end_time(struct cmp_entity *ent) +uint16_t cmp_ent_get_fine_end_time(const struct cmp_entity *ent) { if (!ent) return 0; @@ -1132,7 +1135,7 @@ uint16_t cmp_ent_get_fine_end_time(struct cmp_entity *ent) * DATA_TYPE_UNKNOWN on error */ -enum cmp_data_type cmp_ent_get_data_type(struct cmp_entity *ent) +enum cmp_data_type cmp_ent_get_data_type(const struct cmp_entity *ent) { enum cmp_data_type data_type; @@ -1157,7 +1160,7 @@ enum cmp_data_type cmp_ent_get_data_type(struct cmp_entity *ent) * @returns the data_type raw bit on success, 0 on error */ -int cmp_ent_get_data_type_raw_bit(struct cmp_entity *ent) +int cmp_ent_get_data_type_raw_bit(const struct cmp_entity *ent) { if (!ent) return 0; @@ -1174,7 +1177,7 @@ int cmp_ent_get_data_type_raw_bit(struct cmp_entity *ent) * @returns the used compression mode on success, 0 on error */ -uint8_t cmp_ent_get_cmp_mode(struct cmp_entity *ent) +uint8_t cmp_ent_get_cmp_mode(const struct cmp_entity *ent) { if (!ent) return 0; @@ -1191,7 +1194,7 @@ uint8_t cmp_ent_get_cmp_mode(struct cmp_entity *ent) * @returns the used model value used on success, 0 on error */ -uint8_t cmp_ent_get_model_value(struct cmp_entity *ent) +uint8_t cmp_ent_get_model_value(const struct cmp_entity *ent) { if (!ent) return 0; @@ -1209,7 +1212,7 @@ uint8_t cmp_ent_get_model_value(struct cmp_entity *ent) * @returns the model identifier on success, 0 on error */ -uint16_t cmp_ent_get_model_id(struct cmp_entity *ent) +uint16_t cmp_ent_get_model_id(const struct cmp_entity *ent) { if (!ent) return 0; @@ -1226,7 +1229,7 @@ uint16_t cmp_ent_get_model_id(struct cmp_entity *ent) * @returns the model counter on success, 0 on error */ -uint8_t cmp_ent_get_model_counter(struct cmp_entity *ent) +uint8_t cmp_ent_get_model_counter(const struct cmp_entity *ent) { if (!ent) return 0; @@ -1245,7 +1248,7 @@ uint8_t cmp_ent_get_model_counter(struct cmp_entity *ent) * 0 on error */ -uint8_t cmp_ent_get_max_used_bits_version(struct cmp_entity *ent) +uint8_t cmp_ent_get_max_used_bits_version(const struct cmp_entity *ent) { if (!ent) return 0; @@ -1262,7 +1265,7 @@ uint8_t cmp_ent_get_max_used_bits_version(struct cmp_entity *ent) * @returns the used lossy compression/round parameter on success, 0 on error */ -uint16_t cmp_ent_get_lossy_cmp_par(struct cmp_entity *ent) +uint16_t cmp_ent_get_lossy_cmp_par(const struct cmp_entity *ent) { if (!ent) return 0; @@ -1280,7 +1283,7 @@ uint16_t cmp_ent_get_lossy_cmp_par(struct cmp_entity *ent) * @returns the used spillover threshold on success, 0 on error */ -uint16_t cmp_ent_get_ima_spill(struct cmp_entity *ent) +uint16_t cmp_ent_get_ima_spill(const struct cmp_entity *ent) { if (!ent) return 0; @@ -1298,7 +1301,7 @@ uint16_t cmp_ent_get_ima_spill(struct cmp_entity *ent) * @returns the used Golomb parameter on success, 0 on error */ -uint8_t cmp_ent_get_ima_golomb_par(struct cmp_entity *ent) +uint8_t cmp_ent_get_ima_golomb_par(const struct cmp_entity *ent) { if (!ent) return 0; @@ -1316,7 +1319,7 @@ uint8_t cmp_ent_get_ima_golomb_par(struct cmp_entity *ent) * @returns the used adaptive 1 spillover threshold on success, 0 on error */ -uint16_t cmp_ent_get_ima_ap1_spill(struct cmp_entity *ent) +uint16_t cmp_ent_get_ima_ap1_spill(const struct cmp_entity *ent) { if (!ent) return 0; @@ -1334,7 +1337,7 @@ uint16_t cmp_ent_get_ima_ap1_spill(struct cmp_entity *ent) * @returns the used adaptive 1 Golomb parameter on success, 0 on error */ -uint8_t cmp_ent_get_ima_ap1_golomb_par(struct cmp_entity *ent) +uint8_t cmp_ent_get_ima_ap1_golomb_par(const struct cmp_entity *ent) { if (!ent) return 0; @@ -1352,7 +1355,7 @@ uint8_t cmp_ent_get_ima_ap1_golomb_par(struct cmp_entity *ent) * @returns the used adaptive 2 spillover threshold on success, 0 on error */ -uint16_t cmp_ent_get_ima_ap2_spill(struct cmp_entity *ent) +uint16_t cmp_ent_get_ima_ap2_spill(const struct cmp_entity *ent) { if (!ent) return 0; @@ -1370,7 +1373,7 @@ uint16_t cmp_ent_get_ima_ap2_spill(struct cmp_entity *ent) * @returns the used adaptive 2 Golomb parameter on success, 0 on error */ -uint8_t cmp_ent_get_ima_ap2_golomb_par(struct cmp_entity *ent) +uint8_t cmp_ent_get_ima_ap2_golomb_par(const struct cmp_entity *ent) { if (!ent) return 0; @@ -1388,7 +1391,7 @@ uint8_t cmp_ent_get_ima_ap2_golomb_par(struct cmp_entity *ent) * @returns the used spillover threshold 1 parameter on success, 0 on error */ -uint32_t cmp_ent_get_non_ima_spill1(struct cmp_entity *ent) +uint32_t cmp_ent_get_non_ima_spill1(const struct cmp_entity *ent) { if (!ent) return 0; @@ -1410,7 +1413,7 @@ uint32_t cmp_ent_get_non_ima_spill1(struct cmp_entity *ent) * @returns the used compression parameter 1 on success, 0 on error */ -uint16_t cmp_ent_get_non_ima_cmp_par1(struct cmp_entity *ent) +uint16_t cmp_ent_get_non_ima_cmp_par1(const struct cmp_entity *ent) { if (!ent) return 0; @@ -1428,7 +1431,7 @@ uint16_t cmp_ent_get_non_ima_cmp_par1(struct cmp_entity *ent) * @returns the used spillover threshold 2 parameter on success, 0 on error */ -uint32_t cmp_ent_get_non_ima_spill2(struct cmp_entity *ent) +uint32_t cmp_ent_get_non_ima_spill2(const struct cmp_entity *ent) { if (!ent) return 0; @@ -1450,7 +1453,7 @@ uint32_t cmp_ent_get_non_ima_spill2(struct cmp_entity *ent) * @returns the used compression parameter 2 on success, 0 on error */ -uint16_t cmp_ent_get_non_ima_cmp_par2(struct cmp_entity *ent) +uint16_t cmp_ent_get_non_ima_cmp_par2(const struct cmp_entity *ent) { if (!ent) return 0; @@ -1468,7 +1471,7 @@ uint16_t cmp_ent_get_non_ima_cmp_par2(struct cmp_entity *ent) * @returns the used spillover threshold 3 parameter on success, 0 on error */ -uint32_t cmp_ent_get_non_ima_spill3(struct cmp_entity *ent) +uint32_t cmp_ent_get_non_ima_spill3(const struct cmp_entity *ent) { if (!ent) return 0; @@ -1490,7 +1493,7 @@ uint32_t cmp_ent_get_non_ima_spill3(struct cmp_entity *ent) * @returns the used compression parameter 3 on success, 0 on error */ -uint16_t cmp_ent_get_non_ima_cmp_par3(struct cmp_entity *ent) +uint16_t cmp_ent_get_non_ima_cmp_par3(const struct cmp_entity *ent) { if (!ent) return 0; @@ -1508,7 +1511,7 @@ uint16_t cmp_ent_get_non_ima_cmp_par3(struct cmp_entity *ent) * @returns the used spillover threshold 4 parameter on success, 0 on error */ -uint32_t cmp_ent_get_non_ima_spill4(struct cmp_entity *ent) +uint32_t cmp_ent_get_non_ima_spill4(const struct cmp_entity *ent) { if (!ent) return 0; @@ -1530,7 +1533,7 @@ uint32_t cmp_ent_get_non_ima_spill4(struct cmp_entity *ent) * @returns the used compression parameter 4 on success, 0 on error */ -uint16_t cmp_ent_get_non_ima_cmp_par4(struct cmp_entity *ent) +uint16_t cmp_ent_get_non_ima_cmp_par4(const struct cmp_entity *ent) { if (!ent) return 0; @@ -1548,7 +1551,7 @@ uint16_t cmp_ent_get_non_ima_cmp_par4(struct cmp_entity *ent) * @returns the used spillover threshold 5 parameter on success, 0 on error */ -uint32_t cmp_ent_get_non_ima_spill5(struct cmp_entity *ent) +uint32_t cmp_ent_get_non_ima_spill5(const struct cmp_entity *ent) { if (!ent) return 0; @@ -1570,7 +1573,7 @@ uint32_t cmp_ent_get_non_ima_spill5(struct cmp_entity *ent) * @returns the used compression parameter 5 on success, 0 on error */ -uint16_t cmp_ent_get_non_ima_cmp_par5(struct cmp_entity *ent) +uint16_t cmp_ent_get_non_ima_cmp_par5(const struct cmp_entity *ent) { if (!ent) return 0; @@ -1588,7 +1591,7 @@ uint16_t cmp_ent_get_non_ima_cmp_par5(struct cmp_entity *ent) * @returns the used spillover threshold 6 parameter on success, 0 on error */ -uint32_t cmp_ent_get_non_ima_spill6(struct cmp_entity *ent) +uint32_t cmp_ent_get_non_ima_spill6(const struct cmp_entity *ent) { if (!ent) return 0; @@ -1610,7 +1613,7 @@ uint32_t cmp_ent_get_non_ima_spill6(struct cmp_entity *ent) * @returns the used compression parameter 6 on success, 0 on error */ -uint16_t cmp_ent_get_non_ima_cmp_par6(struct cmp_entity *ent) +uint16_t cmp_ent_get_non_ima_cmp_par6(const struct cmp_entity *ent) { if (!ent) return 0; @@ -1634,28 +1637,24 @@ uint16_t cmp_ent_get_non_ima_cmp_par6(struct cmp_entity *ent) void *cmp_ent_get_data_buf(struct cmp_entity *ent) { enum cmp_data_type data_type; + void *data_ptr; if (!ent) return NULL; data_type = cmp_ent_get_data_type(ent); - if (data_type == DATA_TYPE_UNKNOWN) { - debug_print("Error: Compression data type not supported.\n"); - return NULL; - } - - if (cmp_ent_get_data_type_raw_bit(ent)) - return (uint8_t *)ent + GENERIC_HEADER_SIZE; switch (data_type) { case DATA_TYPE_IMAGETTE: case DATA_TYPE_SAT_IMAGETTE: case DATA_TYPE_F_CAM_IMAGETTE: - return ent->ima.ima_cmp_dat; + data_ptr = ent->ima.ima_cmp_dat; + break; case DATA_TYPE_IMAGETTE_ADAPTIVE: case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE: case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE: - return ent->ima.ap_ima_cmp_data; + data_ptr = ent->ima.ap_ima_cmp_data; + break; case DATA_TYPE_OFFSET: case DATA_TYPE_BACKGROUND: case DATA_TYPE_SMEARING: @@ -1673,13 +1672,20 @@ void *cmp_ent_get_data_buf(struct cmp_entity *ent) case DATA_TYPE_F_FX_EFX_NCOB_ECOB: case DATA_TYPE_F_CAM_OFFSET: case DATA_TYPE_F_CAM_BACKGROUND: - return ent->non_ima.cmp_data; - /* LCOV_EXCL_START */ + case DATA_TYPE_CHUNK: + data_ptr = ent->non_ima.cmp_data; + break; case DATA_TYPE_UNKNOWN: default: + debug_print("Error: Compression data type not supported."); return NULL; - /* LCOV_EXCL_STOP */ } + + /* the uncompressed data do not have a specific entity header */ + if (cmp_ent_get_data_type_raw_bit(ent)) + return (uint8_t *)ent + GENERIC_HEADER_SIZE; + + return data_ptr; } @@ -1693,7 +1699,6 @@ void *cmp_ent_get_data_buf(struct cmp_entity *ent) * * @returns the size in bytes to store the compressed data; negative on error * - * @note the destination and source buffer can overlap * @note converts the data to the system endianness */ @@ -1708,13 +1713,13 @@ int32_t cmp_ent_get_cmp_data(struct cmp_entity *ent, uint32_t *data_buf, cmp_ent_data_adr = cmp_ent_get_data_buf(ent); if (!cmp_ent_data_adr) { - debug_print("Error: Compression data type is not supported.\n"); + debug_print("Error: Compression data type is not supported."); return -1; } cmp_size_byte = cmp_ent_get_cmp_data_size(ent); if (cmp_size_byte & 0x3) { - debug_print("Error: The compressed data are not correct formatted. Expected multiple of 4 hex words.\n"); + debug_print("Error: The compressed data are not correct formatted. Expected multiple of 4 hex words."); return -1; } @@ -1723,11 +1728,11 @@ int32_t cmp_ent_get_cmp_data(struct cmp_entity *ent, uint32_t *data_buf, uint32_t cmp_data_len_32; if (cmp_size_byte > data_buf_size) { - fprintf(stderr, "Error: data_buf size to small to hold the data.\n"); + debug_print("Error: data_buf size to small to hold the data."); return -1; } - memmove(data_buf, cmp_ent_data_adr, cmp_size_byte); + memcpy(data_buf, cmp_ent_data_adr, cmp_size_byte); cmp_data_len_32 = cmp_size_byte/sizeof(uint32_t); for (i = 0; i < cmp_data_len_32; i++) @@ -1747,7 +1752,7 @@ int32_t cmp_ent_get_cmp_data(struct cmp_entity *ent, uint32_t *data_buf, * @returns the size of the entity header in bytes on success, 0 on error */ -static uint32_t cmp_ent_get_hdr_size(struct cmp_entity *ent) +static uint32_t cmp_ent_get_hdr_size(const struct cmp_entity *ent) { return cmp_ent_cal_hdr_size(cmp_ent_get_data_type(ent), cmp_ent_get_data_type_raw_bit(ent)); @@ -1763,7 +1768,7 @@ static uint32_t cmp_ent_get_hdr_size(struct cmp_entity *ent) * @returns the size of the compressed data in bytes on success, 0 on error */ -uint32_t cmp_ent_get_cmp_data_size(struct cmp_entity *ent) +uint32_t cmp_ent_get_cmp_data_size(const struct cmp_entity *ent) { uint32_t cmp_ent_size, header_size; @@ -1802,20 +1807,20 @@ int cmp_ent_write_cmp_pars(struct cmp_entity *ent, const struct cmp_cfg *cfg, return -1; if (cfg->data_type != cmp_ent_get_data_type(ent)) { - debug_print("Error: The entity data product type dos not match the configuration data product type.\n"); + debug_print("Error: The entity data product type dos not match the configuration data product type."); return -1; } if (cmp_ent_get_data_type_raw_bit(ent) != (cfg->cmp_mode == CMP_MODE_RAW)) { - debug_print("Error: The entity's raw data bit does not match up with the compression mode.\n"); + debug_print("Error: The entity's raw data bit does not match up with the compression mode."); return -1; } ent_cmp_data_size = cmp_ent_get_cmp_data_size(ent); /* check if the entity can hold the compressed data */ - if (ent_cmp_data_size < cmp_bit_to_4byte((unsigned int)cmp_size_bits)) { - debug_print("Error: The entity size is to small to hold the compressed data.\n"); + if (ent_cmp_data_size < cmp_bit_to_byte((unsigned int)cmp_size_bits)) { + debug_print("Error: The entity size is to small to hold the compressed data."); return -2; } @@ -1859,32 +1864,10 @@ int cmp_ent_write_cmp_pars(struct cmp_entity *ent, const struct cmp_cfg *cfg, return -1; break; case DATA_TYPE_OFFSET: + case DATA_TYPE_F_CAM_OFFSET: case DATA_TYPE_BACKGROUND: + case DATA_TYPE_F_CAM_BACKGROUND: case DATA_TYPE_SMEARING: - if (cmp_ent_set_non_ima_cmp_par1(ent, cfg->cmp_par_mean)) - return -1; - if (cmp_ent_set_non_ima_spill1(ent, cfg->spill_mean)) - return -1; - - if (cmp_ent_set_non_ima_cmp_par2(ent, cfg->cmp_par_variance)) - return -1; - if (cmp_ent_set_non_ima_spill2(ent, cfg->spill_variance)) - return -1; - - if (cmp_ent_set_non_ima_cmp_par3(ent, cfg->cmp_par_pixels_error)) - return -1; - if (cmp_ent_set_non_ima_spill3(ent, cfg->spill_pixels_error)) - return -1; - - cmp_ent_set_non_ima_cmp_par4(ent, 0); - cmp_ent_set_non_ima_spill4(ent, 0); - - cmp_ent_set_non_ima_cmp_par5(ent, 0); - cmp_ent_set_non_ima_spill5(ent, 0); - - cmp_ent_set_non_ima_cmp_par6(ent, 0); - cmp_ent_set_non_ima_spill6(ent, 0); - break; case DATA_TYPE_S_FX: case DATA_TYPE_S_FX_EFX: case DATA_TYPE_S_FX_NCOB: @@ -1897,40 +1880,37 @@ int cmp_ent_write_cmp_pars(struct cmp_entity *ent, const struct cmp_cfg *cfg, case DATA_TYPE_F_FX_EFX: case DATA_TYPE_F_FX_NCOB: case DATA_TYPE_F_FX_EFX_NCOB_ECOB: - if (cmp_ent_set_non_ima_cmp_par1(ent, cfg->cmp_par_exp_flags)) + if (cmp_ent_set_non_ima_cmp_par1(ent, cfg->cmp_par_1)) return -1; - if (cmp_ent_set_non_ima_spill1(ent, cfg->spill_exp_flags)) + if (cmp_ent_set_non_ima_spill1(ent, cfg->spill_par_1)) return -1; - if (cmp_ent_set_non_ima_cmp_par2(ent, cfg->cmp_par_fx)) + if (cmp_ent_set_non_ima_cmp_par2(ent, cfg->cmp_par_2)) return -1; - if (cmp_ent_set_non_ima_spill2(ent, cfg->spill_fx)) + if (cmp_ent_set_non_ima_spill2(ent, cfg->spill_par_2)) return -1; - if (cmp_ent_set_non_ima_cmp_par3(ent, cfg->cmp_par_ncob)) + if (cmp_ent_set_non_ima_cmp_par3(ent, cfg->cmp_par_3)) return -1; - if (cmp_ent_set_non_ima_spill3(ent, cfg->spill_ncob)) + if (cmp_ent_set_non_ima_spill3(ent, cfg->spill_par_3)) return -1; - if (cmp_ent_set_non_ima_cmp_par4(ent, cfg->cmp_par_efx)) + if (cmp_ent_set_non_ima_cmp_par4(ent, cfg->cmp_par_4)) return -1; - if (cmp_ent_set_non_ima_spill4(ent, cfg->spill_efx)) + if (cmp_ent_set_non_ima_spill4(ent, cfg->spill_par_4)) return -1; - if (cmp_ent_set_non_ima_cmp_par5(ent, cfg->cmp_par_ecob)) + if (cmp_ent_set_non_ima_cmp_par5(ent, cfg->cmp_par_5)) return -1; - if (cmp_ent_set_non_ima_spill5(ent, cfg->spill_ecob)) + if (cmp_ent_set_non_ima_spill5(ent, cfg->spill_par_5)) return -1; - if (cmp_ent_set_non_ima_cmp_par6(ent, cfg->cmp_par_fx_cob_variance)) + if (cmp_ent_set_non_ima_cmp_par6(ent, cfg->cmp_par_6)) return -1; - if (cmp_ent_set_non_ima_spill6(ent, cfg->spill_fx_cob_variance)) + if (cmp_ent_set_non_ima_spill6(ent, cfg->spill_par_6)) return -1; break; - case DATA_TYPE_F_CAM_OFFSET: - case DATA_TYPE_F_CAM_BACKGROUND: - /* TODO: implement this*/ case DATA_TYPE_UNKNOWN: default: return -1; @@ -1967,25 +1947,25 @@ int cmp_ent_write_rdcu_cmp_pars(struct cmp_entity *ent, const struct cmp_info *i return -1; if (info->cmp_err) { - debug_print("Error: The decompression information contains an compression error.\n"); + debug_print("Error: The decompression information contains an compression error."); return -1; } data_type = cmp_ent_get_data_type(ent); if (!rdcu_supported_data_type_is_used(data_type)) { - debug_print("Error: The compression data type is not one of the types supported by the RDCU.\n"); + debug_print("Error: The compression data type is not one of the types supported by the RDCU."); return -1; } if (cmp_ent_get_data_type_raw_bit(ent) != raw_mode_is_used(info->cmp_mode_used)) { - debug_print("Error: The entity's raw data bit does not match up with the compression mode.\n"); + debug_print("Error: The entity's raw data bit does not match up with the compression mode."); return -1; } /* check if the entity can hold the compressed data */ ent_cmp_data_size = cmp_ent_get_cmp_data_size(ent); - if (ent_cmp_data_size < cmp_bit_to_4byte(info->cmp_size)) { - debug_print("Error: The entity size is to small to hold the compressed data.\n"); + if (ent_cmp_data_size < cmp_bit_to_byte(info->cmp_size)) { + debug_print("Error: The entity size is to small to hold the compressed data."); return -2; } @@ -2015,7 +1995,7 @@ int cmp_ent_write_rdcu_cmp_pars(struct cmp_entity *ent, const struct cmp_info *i */ if (cmp_ap_imagette_data_type_is_used(data_type)) { if (!cfg) { - debug_print("Error: Need the compression configuration to get the adaptive parameters.\n"); + debug_print("Error: Need the compression configuration to get the adaptive parameters."); return -1; } if (cmp_ent_set_ima_ap1_spill(ent, cfg->ap1_spill)) @@ -2101,11 +2081,12 @@ uint32_t cmp_ent_create(struct cmp_entity *ent, enum cmp_data_type data_type, * @returns the size of the compression entity or 0 on error */ -size_t cmp_ent_build(struct cmp_entity *ent, uint32_t version_id, - uint64_t start_time, uint64_t end_time, uint16_t model_id, - uint8_t model_counter, struct cmp_cfg *cfg, int cmp_size_bits) +uint32_t cmp_ent_build(struct cmp_entity *ent, uint32_t version_id, + uint64_t start_time, uint64_t end_time, uint16_t model_id, + uint8_t model_counter, const struct cmp_cfg *cfg, int cmp_size_bits) { - uint32_t ent_size; + uint32_t cmp_size_bytes = cmp_bit_to_byte((unsigned int)cmp_size_bits); + uint32_t hdr_size; if (!cfg) return 0; @@ -2113,9 +2094,7 @@ size_t cmp_ent_build(struct cmp_entity *ent, uint32_t version_id, if (cmp_size_bits < 0) return 0; - ent_size = cmp_ent_create(ent, cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW, - cmp_bit_to_4byte((unsigned int)cmp_size_bits)); - if (!ent_size) + if (!cmp_ent_create(ent, cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW, cmp_size_bytes)) return 0; if (ent) { @@ -2130,7 +2109,9 @@ size_t cmp_ent_build(struct cmp_entity *ent, uint32_t version_id, return 0; } - return ent_size; + hdr_size = cmp_ent_cal_hdr_size(cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW); + + return hdr_size + cmp_size_bytes; } @@ -2204,7 +2185,7 @@ uint64_t cmp_ent_create_timestamp(const struct timespec *ts) if (ts) { if (my_timercmp(ts, &epoch, <)) { - debug_print("Error: Time is before PLATO epoch.\n"); + debug_print("Error: Time is before PLATO epoch."); return 0; } now = *ts; @@ -2229,18 +2210,14 @@ uint64_t cmp_ent_create_timestamp(const struct timespec *ts) * @param ent pointer to a compression entity */ -void cmp_ent_print_header(struct cmp_entity *ent) +void cmp_ent_print_header(const struct cmp_entity *ent) { - uint8_t *p = (uint8_t *)ent; + MAYBE_UNUSED const uint8_t *p = (const uint8_t *)ent; uint32_t hdr_size = cmp_ent_get_hdr_size(ent); size_t i; - for (i = 0; i < hdr_size; ++i) { - printf("%02X ", p[i]); - if (i && !((i+1) % 32)) - printf("\n"); - } - printf("\n"); + for (i = 0; i < hdr_size; ++i) + debug_print("%02X", p[i]); } @@ -2252,19 +2229,15 @@ void cmp_ent_print_header(struct cmp_entity *ent) void cmp_ent_print_data(struct cmp_entity *ent) { - uint8_t *p = cmp_ent_get_data_buf(ent); + const uint8_t *p = cmp_ent_get_data_buf(ent); size_t data_size = cmp_ent_get_cmp_data_size(ent); size_t i; if (!p) return; - for (i = 0; i < data_size; ++i) { - printf("%02X ", p[i]); - if (i && !((i+1) % 32)) - printf("\n"); - } - printf("\n"); + for (i = 0; i < data_size; ++i) + debug_print("%02X", p[i]); } @@ -2276,9 +2249,9 @@ void cmp_ent_print_data(struct cmp_entity *ent) void cmp_ent_print(struct cmp_entity *ent) { - printf("compression entity header:\n"); + debug_print("compression entity header:"); cmp_ent_print_header(ent); - printf("compressed data in the compressed entity:\n"); + debug_print("compressed data in the compressed entity:"); cmp_ent_print_data(ent); } @@ -2289,76 +2262,76 @@ void cmp_ent_print(struct cmp_entity *ent) * @param ent pointer to a compression entity */ -static void cmp_ent_parse_generic_header(struct cmp_entity *ent) +static void cmp_ent_parse_generic_header(const struct cmp_entity *ent) { - uint32_t version_id, cmp_ent_size, original_size, cmp_mode_used, + MAYBE_UNUSED uint32_t version_id, cmp_ent_size, original_size, cmp_mode_used, model_value_used, model_id, model_counter, max_used_bits_version, lossy_cmp_par_used, start_coarse_time, end_coarse_time; - uint16_t start_fine_time, end_fine_time; - enum cmp_data_type data_type; - int raw_bit; + MAYBE_UNUSED uint16_t start_fine_time, end_fine_time; + MAYBE_UNUSED enum cmp_data_type data_type; + MAYBE_UNUSED int raw_bit; version_id = cmp_ent_get_version_id(ent); if (version_id & CMP_TOOL_VERSION_ID_BIT) { - uint16_t major = (version_id & 0x7FFF0000U) >> 16U; - uint16_t minor = version_id & 0xFFFFU; + MAYBE_UNUSED uint16_t major = (version_id & 0x7FFF0000U) >> 16U; + MAYBE_UNUSED uint16_t minor = version_id & 0xFFFFU; - printf("Compressed with cmp_tool version: %u.%02u\n", major, minor); + debug_print("Compressed with cmp_tool version: %u.%02u", major, minor); } else - printf("ICU ASW Version ID: %08" PRIx32 "\n", version_id); + debug_print("ICU ASW Version ID: %08" PRIx32, version_id); cmp_ent_size = cmp_ent_get_size(ent); - printf("Compression Entity Size: %" PRIu32 " byte\n", cmp_ent_size); + debug_print("Compression Entity Size: %" PRIu32 " byte", cmp_ent_size); original_size = cmp_ent_get_original_size(ent); - printf("Original Data Size: %" PRIu32 " byte\n", original_size); + debug_print("Original Data Size: %" PRIu32 " byte", original_size); start_coarse_time = cmp_ent_get_coarse_start_time(ent); - printf("Compression Coarse Start Time: %" PRIu32 "\n", start_coarse_time); + debug_print("Compression Coarse Start Time: %" PRIu32, start_coarse_time); start_fine_time = cmp_ent_get_fine_start_time(ent); - printf("Compression Fine Start Time: %d\n", start_fine_time); + debug_print("Compression Fine Start Time: %d", start_fine_time); end_coarse_time = cmp_ent_get_coarse_end_time(ent); - printf("Compression Coarse End Time: %" PRIu32 "\n", end_coarse_time); + debug_print("Compression Coarse End Time: %" PRIu32, end_coarse_time); end_fine_time = cmp_ent_get_fine_end_time(ent); - printf("Compression Fine End Time: %d\n", end_fine_time); + debug_print("Compression Fine End Time: %d", end_fine_time); #ifdef HAS_TIME_H { struct tm epoch_date = PLATO_EPOCH_DATE; - time_t time = my_timegm(&epoch_date) + start_coarse_time; + MAYBE_UNUSED time_t time = my_timegm(&epoch_date) + start_coarse_time; - printf("Data were compressed on (local time): %s", ctime(&time)); + debug_print("Data were compressed on (local time): %s", ctime(&time)); } #endif - printf("The compression took %f second\n", end_coarse_time - start_coarse_time + debug_print("The compression took %f second", end_coarse_time - start_coarse_time + ((end_fine_time - start_fine_time)/256./256.)); data_type = cmp_ent_get_data_type(ent); - printf("Data Product Type: %d\n", data_type); + debug_print("Data Product Type: %d", data_type); raw_bit = cmp_ent_get_data_type_raw_bit(ent); - printf("RAW bit in the Data Product Type is%s set\n", raw_bit ? "" : " not"); + debug_print("RAW bit in the Data Product Type is%s set", raw_bit ? "" : " not"); cmp_mode_used = cmp_ent_get_cmp_mode(ent); - printf("Used Compression Mode: %" PRIu32 "\n", cmp_mode_used); + debug_print("Used Compression Mode: %" PRIu32, cmp_mode_used); model_value_used = cmp_ent_get_model_value(ent); - printf("Used Model Updating Weighing Value: %" PRIu32 "\n", model_value_used); + debug_print("Used Model Updating Weighing Value: %" PRIu32, model_value_used); model_id = cmp_ent_get_model_id(ent); - printf("Model ID: %" PRIu32 "\n", model_id); + debug_print("Model ID: %" PRIu32, model_id); model_counter = cmp_ent_get_model_counter(ent); - printf("Model Counter: %" PRIu32 "\n", model_counter); + debug_print("Model Counter: %" PRIu32, model_counter); max_used_bits_version = cmp_ent_get_max_used_bits_version(ent); - printf("Maximum Used Bits Registry Version: %" PRIu32 "\n", max_used_bits_version); + debug_print("Maximum Used Bits Registry Version: %" PRIu32, max_used_bits_version); lossy_cmp_par_used = cmp_ent_get_lossy_cmp_par(ent); - printf("Used Lossy Compression Parameters: %" PRIu32 "\n", lossy_cmp_par_used); + debug_print("Used Lossy Compression Parameters: %" PRIu32, lossy_cmp_par_used); } @@ -2368,15 +2341,15 @@ static void cmp_ent_parse_generic_header(struct cmp_entity *ent) * @param ent pointer to a compression entity */ -static void cmp_ent_parese_imagette_header(struct cmp_entity *ent) +static void cmp_ent_parese_imagette_header(const struct cmp_entity *ent) { - uint32_t spill_used, golomb_par_used; + MAYBE_UNUSED uint32_t spill_used, golomb_par_used; spill_used = cmp_ent_get_ima_spill(ent); - printf("Used Spillover Threshold Parameter: %" PRIu32 "\n", spill_used); + debug_print("Used Spillover Threshold Parameter: %" PRIu32, spill_used); golomb_par_used = cmp_ent_get_ima_golomb_par(ent); - printf("Used Golomb Parameter: %" PRIu32 "\n", golomb_par_used); + debug_print("Used Golomb Parameter: %" PRIu32, golomb_par_used); } @@ -2386,28 +2359,72 @@ static void cmp_ent_parese_imagette_header(struct cmp_entity *ent) * @param ent pointer to a compression entity */ -static void cmp_ent_parese_adaptive_imagette_header(struct cmp_entity *ent) +static void cmp_ent_parese_adaptive_imagette_header(const struct cmp_entity *ent) { - uint32_t spill_used, golomb_par_used, ap1_spill_used, + MAYBE_UNUSED uint32_t spill_used, golomb_par_used, ap1_spill_used, ap1_golomb_par_used, ap2_spill_used, ap2_golomb_par_used; spill_used = cmp_ent_get_ima_spill(ent); - printf("Used Spillover Threshold Parameter: %" PRIu32 "\n", spill_used); + debug_print("Used Spillover Threshold Parameter: %" PRIu32, spill_used); golomb_par_used = cmp_ent_get_ima_golomb_par(ent); - printf("Used Golomb Parameter: %" PRIu32 "\n", golomb_par_used); + debug_print("Used Golomb Parameter: %" PRIu32, golomb_par_used); ap1_spill_used = cmp_ent_get_ima_ap1_spill(ent); - printf("Used Adaptive 1 Spillover Threshold Parameter: %" PRIu32 "\n", ap1_spill_used); + debug_print("Used Adaptive 1 Spillover Threshold Parameter: %" PRIu32, ap1_spill_used); ap1_golomb_par_used = cmp_ent_get_ima_ap1_golomb_par(ent); - printf("Used Adaptive 1 Golomb Parameter: %" PRIu32 "\n", ap1_golomb_par_used); + debug_print("Used Adaptive 1 Golomb Parameter: %" PRIu32, ap1_golomb_par_used); ap2_spill_used = cmp_ent_get_ima_ap2_spill(ent); - printf("Used Adaptive 2 Spillover Threshold Parameter: %" PRIu32 "\n", ap2_spill_used); + debug_print("Used Adaptive 2 Spillover Threshold Parameter: %" PRIu32, ap2_spill_used); ap2_golomb_par_used = cmp_ent_get_ima_ap2_golomb_par(ent); - printf("Used Adaptive 2 Golomb Parameter: %" PRIu32 "\n", ap2_golomb_par_used); + debug_print("Used Adaptive 2 Golomb Parameter: %" PRIu32, ap2_golomb_par_used); +} + + +/** + * @brief parse the non-imagette specific compressed entity header + * + * @param ent pointer to a compression entity + */ + +static void cmp_ent_parese_non_imagette_header(const struct cmp_entity *ent) +{ + MAYBE_UNUSED uint32_t spill_1_used, cmp_par_1_used, spill_2_used, cmp_par_2_used, + spill_3_used, cmp_par_3_used, spill_4_used, cmp_par_4_used, + spill_5_used, cmp_par_5_used; + + spill_1_used = cmp_ent_get_non_ima_spill1(ent); + debug_print("Used Spillover Threshold Parameter 1: %" PRIu32, spill_1_used); + + cmp_par_1_used = cmp_ent_get_non_ima_cmp_par1(ent); + debug_print("Used Compression Parameter 1: %" PRIu32, cmp_par_1_used); + + spill_2_used = cmp_ent_get_non_ima_spill2(ent); + debug_print("Used Spillover Threshold Parameter 2: %" PRIu32, spill_2_used); + + cmp_par_2_used = cmp_ent_get_non_ima_cmp_par2(ent); + debug_print("Used Compression Parameter 2: %" PRIu32, cmp_par_2_used); + + spill_3_used = cmp_ent_get_non_ima_spill3(ent); + debug_print("Used Spillover Threshold Parameter 3: %" PRIu32, spill_3_used); + + cmp_par_3_used = cmp_ent_get_non_ima_cmp_par3(ent); + debug_print("Used Compression Parameter 3: %" PRIu32, cmp_par_3_used); + + spill_4_used = cmp_ent_get_non_ima_spill4(ent); + debug_print("Used Spillover Threshold Parameter 4: %" PRIu32, spill_4_used); + + cmp_par_4_used = cmp_ent_get_non_ima_cmp_par4(ent); + debug_print("Used Compression Parameter 4: %" PRIu32, cmp_par_4_used); + + spill_5_used = cmp_ent_get_non_ima_spill5(ent); + debug_print("Used Spillover Threshold Parameter 5: %" PRIu32, spill_5_used); + + cmp_par_5_used = cmp_ent_get_non_ima_cmp_par5(ent); + debug_print("Used Compression Parameter 5: %" PRIu32, cmp_par_5_used); } @@ -2417,12 +2434,12 @@ static void cmp_ent_parese_adaptive_imagette_header(struct cmp_entity *ent) * @param ent pointer to a compression entity */ -static void cmp_ent_parese_specific_header(struct cmp_entity *ent) +static void cmp_ent_parese_specific_header(const struct cmp_entity *ent) { enum cmp_data_type data_type = cmp_ent_get_data_type(ent); if (cmp_ent_get_data_type_raw_bit(ent)) { - printf("Uncompressed data bit is set. No specific header is used.\n"); + debug_print("Uncompressed data bit is set. No specific header is used."); return; } @@ -2437,8 +2454,28 @@ static void cmp_ent_parese_specific_header(struct cmp_entity *ent) case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE: cmp_ent_parese_adaptive_imagette_header(ent); break; + case DATA_TYPE_OFFSET: + case DATA_TYPE_BACKGROUND: + case DATA_TYPE_SMEARING: + case DATA_TYPE_S_FX: + case DATA_TYPE_S_FX_EFX: + case DATA_TYPE_S_FX_NCOB: + case DATA_TYPE_S_FX_EFX_NCOB_ECOB: + case DATA_TYPE_L_FX: + case DATA_TYPE_L_FX_EFX: + case DATA_TYPE_L_FX_NCOB: + case DATA_TYPE_L_FX_EFX_NCOB_ECOB: + case DATA_TYPE_F_FX: + case DATA_TYPE_F_FX_EFX: + case DATA_TYPE_F_FX_NCOB: + case DATA_TYPE_F_FX_EFX_NCOB_ECOB: + case DATA_TYPE_F_CAM_OFFSET: + case DATA_TYPE_F_CAM_BACKGROUND: + case DATA_TYPE_CHUNK: + cmp_ent_parese_non_imagette_header(ent); + break; default: - printf("For this data product type no parse functions is implemented!\n"); + debug_print("For this data product type no parse functions is implemented!"); break; } } diff --git a/include/cmp_entity.h b/lib/common/cmp_entity.h similarity index 78% rename from include/cmp_entity.h rename to lib/common/cmp_entity.h index 8f6d6574352636f8a098a9d51575aa79b9cadb33..33c0edbfd8b3673c23f864231620fa3c944759c7 100644 --- a/include/cmp_entity.h +++ b/lib/common/cmp_entity.h @@ -29,8 +29,8 @@ #include <stdint.h> -#include <compiler.h> -#include <cmp_support.h> +#include "compiler.h" +#include "cmp_support.h" #define GENERIC_HEADER_SIZE 32 @@ -46,6 +46,7 @@ (GENERIC_HEADER_SIZE + SPECIFIC_NON_IMAGETTE_HEADER_SIZE) #define CMP_ENTITY_MAX_SIZE 0xFFFFFFUL +#define CMP_ENTITY_MAX_ORIGINAL_SIZE 0xFFFFFFUL #define RAW_BIT_DATA_TYPE_POS 15U @@ -155,9 +156,9 @@ uint32_t cmp_ent_create(struct cmp_entity *ent, enum cmp_data_type data_type, int raw_mode_flag, uint32_t cmp_size_byte); /* create a compression entity and set the header fields */ -size_t cmp_ent_build(struct cmp_entity *ent, uint32_t version_id, - uint64_t start_time, uint64_t end_time, uint16_t model_id, - uint8_t model_counter, struct cmp_cfg *cfg, int cmp_size_bits); +uint32_t cmp_ent_build(struct cmp_entity *ent, uint32_t version_id, + uint64_t start_time, uint64_t end_time, uint16_t model_id, + uint8_t model_counter, const struct cmp_cfg *cfg, int cmp_size_bits); /* * write the compression parameters from a compression configuration into the @@ -239,71 +240,71 @@ int cmp_ent_set_non_ima_cmp_par6(struct cmp_entity *ent, uint32_t cmp_par_6_used /* get functions for generic compression entity header */ -uint32_t cmp_ent_get_version_id(struct cmp_entity *ent); -uint32_t cmp_ent_get_size(struct cmp_entity *ent); -uint32_t cmp_ent_get_original_size(struct cmp_entity *ent); +uint32_t cmp_ent_get_version_id(const struct cmp_entity *ent); +uint32_t cmp_ent_get_size(const struct cmp_entity *ent); +uint32_t cmp_ent_get_original_size(const struct cmp_entity *ent); -uint64_t cmp_ent_get_start_timestamp(struct cmp_entity *ent); -uint32_t cmp_ent_get_coarse_start_time(struct cmp_entity *ent); -uint16_t cmp_ent_get_fine_start_time(struct cmp_entity *ent); +uint64_t cmp_ent_get_start_timestamp(const struct cmp_entity *ent); +uint32_t cmp_ent_get_coarse_start_time(const struct cmp_entity *ent); +uint16_t cmp_ent_get_fine_start_time(const struct cmp_entity *ent); -uint64_t cmp_ent_get_end_timestamp(struct cmp_entity *ent); -uint32_t cmp_ent_get_coarse_end_time(struct cmp_entity *ent); -uint16_t cmp_ent_get_fine_end_time(struct cmp_entity *ent); +uint64_t cmp_ent_get_end_timestamp(const struct cmp_entity *ent); +uint32_t cmp_ent_get_coarse_end_time(const struct cmp_entity *ent); +uint16_t cmp_ent_get_fine_end_time(const struct cmp_entity *ent); -enum cmp_data_type cmp_ent_get_data_type(struct cmp_entity *ent); -int cmp_ent_get_data_type_raw_bit(struct cmp_entity *ent); -uint8_t cmp_ent_get_cmp_mode(struct cmp_entity *ent); -uint8_t cmp_ent_get_model_value(struct cmp_entity *ent); +enum cmp_data_type cmp_ent_get_data_type(const struct cmp_entity *ent); +int cmp_ent_get_data_type_raw_bit(const struct cmp_entity *ent); +uint8_t cmp_ent_get_cmp_mode(const struct cmp_entity *ent); +uint8_t cmp_ent_get_model_value(const struct cmp_entity *ent); -uint16_t cmp_ent_get_model_id(struct cmp_entity *ent); -uint8_t cmp_ent_get_model_counter(struct cmp_entity *ent); -uint8_t cmp_ent_get_max_used_bits_version(struct cmp_entity *ent); -uint16_t cmp_ent_get_lossy_cmp_par(struct cmp_entity *ent); +uint16_t cmp_ent_get_model_id(const struct cmp_entity *ent); +uint8_t cmp_ent_get_model_counter(const struct cmp_entity *ent); +uint8_t cmp_ent_get_max_used_bits_version(const struct cmp_entity *ent); +uint16_t cmp_ent_get_lossy_cmp_par(const struct cmp_entity *ent); /* * get functions for specific entity header for imagette and adaptive imagette * data product types */ -uint16_t cmp_ent_get_ima_spill(struct cmp_entity *ent); -uint8_t cmp_ent_get_ima_golomb_par(struct cmp_entity *ent); +uint16_t cmp_ent_get_ima_spill(const struct cmp_entity *ent); +uint8_t cmp_ent_get_ima_golomb_par(const struct cmp_entity *ent); /* * get functions for specific entity header for adaptive imagette data product * types */ -uint16_t cmp_ent_get_ima_ap1_spill(struct cmp_entity *ent); -uint8_t cmp_ent_get_ima_ap1_golomb_par(struct cmp_entity *ent); +uint16_t cmp_ent_get_ima_ap1_spill(const struct cmp_entity *ent); +uint8_t cmp_ent_get_ima_ap1_golomb_par(const struct cmp_entity *ent); -uint16_t cmp_ent_get_ima_ap2_spill(struct cmp_entity *ent); -uint8_t cmp_ent_get_ima_ap2_golomb_par(struct cmp_entity *ent); +uint16_t cmp_ent_get_ima_ap2_spill(const struct cmp_entity *ent); +uint8_t cmp_ent_get_ima_ap2_golomb_par(const struct cmp_entity *ent); /* get functions for specific entity header for non-imagette data product types */ -uint32_t cmp_ent_get_non_ima_spill1(struct cmp_entity *ent); -uint16_t cmp_ent_get_non_ima_cmp_par1(struct cmp_entity *ent); +uint32_t cmp_ent_get_non_ima_spill1(const struct cmp_entity *ent); +uint16_t cmp_ent_get_non_ima_cmp_par1(const struct cmp_entity *ent); -uint32_t cmp_ent_get_non_ima_spill2(struct cmp_entity *ent); -uint16_t cmp_ent_get_non_ima_cmp_par2(struct cmp_entity *ent); +uint32_t cmp_ent_get_non_ima_spill2(const struct cmp_entity *ent); +uint16_t cmp_ent_get_non_ima_cmp_par2(const struct cmp_entity *ent); -uint32_t cmp_ent_get_non_ima_spill3(struct cmp_entity *ent); -uint16_t cmp_ent_get_non_ima_cmp_par3(struct cmp_entity *ent); +uint32_t cmp_ent_get_non_ima_spill3(const struct cmp_entity *ent); +uint16_t cmp_ent_get_non_ima_cmp_par3(const struct cmp_entity *ent); -uint32_t cmp_ent_get_non_ima_spill4(struct cmp_entity *ent); -uint16_t cmp_ent_get_non_ima_cmp_par4(struct cmp_entity *ent); +uint32_t cmp_ent_get_non_ima_spill4(const struct cmp_entity *ent); +uint16_t cmp_ent_get_non_ima_cmp_par4(const struct cmp_entity *ent); -uint32_t cmp_ent_get_non_ima_spill5(struct cmp_entity *ent); -uint16_t cmp_ent_get_non_ima_cmp_par5(struct cmp_entity *ent); +uint32_t cmp_ent_get_non_ima_spill5(const struct cmp_entity *ent); +uint16_t cmp_ent_get_non_ima_cmp_par5(const struct cmp_entity *ent); -uint32_t cmp_ent_get_non_ima_spill6(struct cmp_entity *ent); -uint16_t cmp_ent_get_non_ima_cmp_par6(struct cmp_entity *ent); +uint32_t cmp_ent_get_non_ima_spill6(const struct cmp_entity *ent); +uint16_t cmp_ent_get_non_ima_cmp_par6(const struct cmp_entity *ent); /* get function for the compressed data buffer in the entity */ void *cmp_ent_get_data_buf(struct cmp_entity *ent); -uint32_t cmp_ent_get_cmp_data_size(struct cmp_entity *ent); +uint32_t cmp_ent_get_cmp_data_size(const struct cmp_entity *ent); int32_t cmp_ent_get_cmp_data(struct cmp_entity *ent, uint32_t *data_buf, uint32_t data_buf_size); @@ -321,7 +322,7 @@ uint64_t cmp_ent_create_timestamp(const struct timespec *ts); #endif /* print and parse functions */ -void cmp_ent_print_header(struct cmp_entity *ent); +void cmp_ent_print_header(const struct cmp_entity *ent); void cmp_ent_print_data(struct cmp_entity *ent); void cmp_ent_print(struct cmp_entity *ent); diff --git a/lib/cmp_max_used_bits.c b/lib/common/cmp_max_used_bits.c similarity index 87% rename from lib/cmp_max_used_bits.c rename to lib/common/cmp_max_used_bits.c index 3471e7ea7a66f7a028024d91a1b1aa92d729d20b..eaedea3d83e203a960ef056e4bd7fd9c99bbeffa 100644 --- a/lib/cmp_max_used_bits.c +++ b/lib/common/cmp_max_used_bits.c @@ -18,9 +18,9 @@ #include <stdint.h> -#include <stdio.h> -#include <cmp_data_types.h> +#include "cmp_data_types.h" + #define MAX_USED_NC_IMAGETTE_BITS 16 #define MAX_USED_SATURATED_IMAGETTE_BITS 16 /* TBC */ @@ -80,8 +80,7 @@ const struct cmp_max_used_bits MAX_USED_BITS_SAFE = { member_bit_size(struct f_fx_efx_ncob_ecob, efx), /* f_efx */ member_bit_size(struct f_fx_efx_ncob_ecob, ncob_x), /* f_ncob_x and f_ncob_y */ member_bit_size(struct f_fx_efx_ncob_ecob, ecob_x), /* f_ecob_x and f_ncob_y */ - /* member_bit_size(struct l_fx_efx_ncob_ecob, exp_flags), /1* l_fx_exp_flags *1/ */ - 24, + 24, /* member_bit_size(struct l_fx_efx_ncob_ecob, exp_flags), /1* l_fx_exp_flags *1/ */ member_bit_size(struct l_fx_efx_ncob_ecob, fx), /* l_fx */ member_bit_size(struct l_fx_efx_ncob_ecob, fx_variance), /* l_fx_variance */ member_bit_size(struct l_fx_efx_ncob_ecob, efx), /* l_efx */ @@ -90,21 +89,20 @@ const struct cmp_max_used_bits MAX_USED_BITS_SAFE = { member_bit_size(struct l_fx_efx_ncob_ecob, cob_x_variance), /* l_cob_x_variance and l_cob_y_variance */ sizeof(uint16_t)*8, /* nc_imagette */ sizeof(uint16_t)*8, /* saturated_imagette */ - member_bit_size(struct nc_offset, mean), /* nc_offset_mean */ - member_bit_size(struct nc_offset, variance), /* nc_offset_variance */ - member_bit_size(struct nc_background, mean), /* nc_background_mean */ - member_bit_size(struct nc_background, variance), /* nc_background_variance */ - member_bit_size(struct nc_background, outlier_pixels), /* nc_background_outlier_pixels */ + member_bit_size(struct offset, mean), /* nc_offset_mean */ + member_bit_size(struct offset, variance), /* nc_offset_variance */ + member_bit_size(struct background, mean), /* nc_background_mean */ + member_bit_size(struct background, variance), /* nc_background_variance */ + member_bit_size(struct background, outlier_pixels), /* nc_background_outlier_pixels */ member_bit_size(struct smearing, mean), /* smearing_mean */ member_bit_size(struct smearing, variance_mean), /* smearing_variance_mean */ member_bit_size(struct smearing, outlier_pixels), /* smearing_outlier_pixels */ - sizeof(uint32_t)*8, /* TBC */ /* fc_imagette */ - sizeof(uint32_t)*8, /* TBC */ /* fc_offset_mean */ - sizeof(uint32_t)*8, /* TBC */ /* fc_offset_variance */ - sizeof(uint32_t)*8, /* TBC */ /* fc_offset_pixel_in_error */ - sizeof(uint32_t)*8, /* TBC */ /* fc_background_mean */ - sizeof(uint32_t)*8, /* TBC */ /* fc_background_variance */ - sizeof(uint32_t)*8, /* TBC */ /* fc_background_outlier_pixels */ + sizeof(uint16_t)*8, /* fc_imagette */ + member_bit_size(struct offset, mean), /* fc_offset_mean */ + member_bit_size(struct offset, variance), /* fc_offset_variance */ + member_bit_size(struct background, mean), /* fc_background_mean */ + member_bit_size(struct background, variance), /* fc_background_variance */ + member_bit_size(struct background, outlier_pixels), /* fc_background_outlier_pixels */ }; @@ -140,7 +138,6 @@ const struct cmp_max_used_bits MAX_USED_BITS_V1 = { MAX_USED_FC_IMAGETTE_BITS, /* fc_imagette */ MAX_USED_FC_OFFSET_MEAN_BITS, /* fc_offset_mean */ MAX_USED_FC_OFFSET_VARIANCE_BITS, /* fc_offset_variance */ - MAX_USED_FC_OFFSET_PIXEL_IN_ERROR_BITS, /* fc_offset_pixel_in_error */ MAX_USED_FC_BACKGROUND_MEAN_BITS, /* fc_background_mean */ MAX_USED_FC_BACKGROUND_VARIANCE_BITS, /* fc_background_variance */ MAX_USED_FC_BACKGROUND_OUTLIER_PIXELS_BITS /* fc_background_outlier_pixels */ diff --git a/include/cmp_max_used_bits.h b/lib/common/cmp_max_used_bits.h similarity index 93% rename from include/cmp_max_used_bits.h rename to lib/common/cmp_max_used_bits.h index ba9db083a6c5d4de814a83f8fabfc2a0f4461656..21e7dd452403923061fe7b813c4f65632a5ea5dd 100644 --- a/include/cmp_max_used_bits.h +++ b/lib/common/cmp_max_used_bits.h @@ -22,6 +22,10 @@ #include <stdint.h> +/* Up to this number (not included), the maximum used bits registry versions cannot be used by the user. */ +#define CMP_MAX_USED_BITS_RESERVED_VERSIONS 32 + + /* predefined maximum used bits registry constants */ extern const struct cmp_max_used_bits MAX_USED_BITS_SAFE; extern const struct cmp_max_used_bits MAX_USED_BITS_V1; @@ -62,7 +66,6 @@ struct cmp_max_used_bits { unsigned int fc_imagette; unsigned int fc_offset_mean; unsigned int fc_offset_variance; - unsigned int fc_offset_pixel_in_error; unsigned int fc_background_mean; unsigned int fc_background_variance; unsigned int fc_background_outlier_pixels; diff --git a/lib/cmp_support.c b/lib/common/cmp_support.c similarity index 82% rename from lib/cmp_support.c rename to lib/common/cmp_support.c index 7bc88b213d7eace8f2b95a2fb758a3cf08517a9a..a211c3c4acad03e11b3f8b1e8780a32de2de6000 100644 --- a/lib/cmp_support.c +++ b/lib/common/cmp_support.c @@ -17,10 +17,11 @@ * @see Data Compression User Manual PLATO-UVIE-PL-UM-0001 */ +#include "compiler.h" -#include <cmp_support.h> -#include <cmp_debug.h> -#include <my_inttypes.h> +#include "cmp_support.h" +#include "cmp_debug.h" +#include "leon_inttypes.h" /** @@ -32,12 +33,12 @@ * @returns the result of floor(log2(x)) */ -int ilog_2(uint32_t x) +unsigned int ilog_2(uint32_t x) { if (!x) - return -1; + return -1U; - return 31 - __builtin_clz(x); + return 31 - (unsigned int)__builtin_clz(x); } @@ -68,12 +69,7 @@ int is_a_pow_of_2(unsigned int v) int cmp_data_type_is_invalid(enum cmp_data_type data_type) { - if (data_type == DATA_TYPE_F_CAM_OFFSET) - debug_print("Error: DATA_TYPE_F_CAM_OFFSET is TBD and not implemented yet.\n"); - if (data_type == DATA_TYPE_F_CAM_BACKGROUND) - debug_print("Error: DATA_TYPE_F_CAM_BACKGROUND is TBD and not implemented yet.\n"); - - if (data_type <= DATA_TYPE_UNKNOWN || data_type > DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE) + if (data_type <= DATA_TYPE_UNKNOWN || data_type > DATA_TYPE_CHUNK) return 1; return 0; @@ -136,7 +132,6 @@ int rdcu_supported_cmp_mode_is_used(enum cmp_mode cmp_mode) default: return 0; } - } @@ -312,36 +307,6 @@ int cmp_aux_data_type_is_used(enum cmp_data_type data_type) } -/** - * @brief implantation of the model update equation - * @note check before that model_value is not greater than MAX_MODEL_VALUE - * - * @param data data to process - * @param model (current) model of the data to process - * @param model_value model weighting parameter - * @param round routing parameter - * - * @returns (new) updated model - */ - -unsigned int cmp_up_model(unsigned int data, unsigned int model, - unsigned int model_value, unsigned int round) - -{ - uint64_t weighted_model, weighted_data; - - /* round and round back input because for decompression the accurate - * data values are not available - */ - data = round_inv(round_fwd(data, round), round); - /* cast uint64_t to prevent overflow in the multiplication */ - weighted_model = (uint64_t)model * model_value; - weighted_data = (uint64_t)data * (MAX_MODEL_VALUE - model_value); - /* truncation is intended */ - return (unsigned int)((weighted_model + weighted_data) / MAX_MODEL_VALUE); -} - - /** * @brief get the maximum valid spill threshold value for a imagette * compression in diff or model mode @@ -362,8 +327,7 @@ uint32_t cmp_ima_max_spill(unsigned int golomb_par) 452, 461, 470, 479, 488, 497, 506, 515, 524, 533, 542, 551, 560, 569, 578, 587, 596, 605, 614, 623 }; - - if (golomb_par > MAX_IMA_GOLOMB_PAR) + if (golomb_par >= ARRAY_SIZE(LUT_MAX_RDCU)) return 0; return LUT_MAX_RDCU[golomb_par]; @@ -383,9 +347,9 @@ uint32_t cmp_ima_max_spill(unsigned int golomb_par) uint32_t cmp_icu_max_spill(unsigned int cmp_par) { /* the ICU compressor can generate code words with a length of maximal 32 bits. */ - unsigned int max_cw_bits = 32; - unsigned int cutoff = (1UL << (ilog_2(cmp_par)+1)) - cmp_par; - unsigned int max_n_sym_offset = max_cw_bits/2 - 1; + unsigned int const max_cw_bits = 32; + unsigned int const cutoff = (0x2U << (ilog_2(cmp_par) & 0x1FU)) - cmp_par; + unsigned int const max_n_sym_offset = max_cw_bits/2 - 1; if (!cmp_par || cmp_par > MAX_NON_IMA_GOLOMB_PAR) return 0; @@ -401,12 +365,26 @@ uint32_t cmp_icu_max_spill(unsigned int cmp_par) * @param cmp_size_bit compressed data size, measured in bits * * @returns the size in bytes to store the hole bitstream + */ + +unsigned int cmp_bit_to_byte(unsigned int cmp_size_bit) +{ + return (cmp_size_bit + 7) / 8; +} + + +/** + * @brief calculate the need bytes to hold a bitstream * @note we round up the result to multiples of 4 bytes + * + * @param cmp_size_bit compressed data size, measured in bits + * + * @returns the size in bytes to store the hole bitstream */ unsigned int cmp_bit_to_4byte(unsigned int cmp_size_bit) { - return (((cmp_size_bit + 7) / 8) + 3) & ~0x3UL; + return (cmp_bit_to_byte(cmp_size_bit) + 3) & ~0x3UL; } @@ -428,11 +406,11 @@ unsigned int cmp_bit_to_4byte(unsigned int cmp_size_bit) int cmp_cfg_gen_par_is_invalid(const struct cmp_cfg *cfg, enum check_opt opt) { int cfg_invalid = 0; - int invalid_data_type = 1; - int unsupported_cmp_mode = 1; - int check_model_value = 1; + int invalid_data_type; + int unsupported_cmp_mode; + int check_model_value; uint32_t max_round_value = 0; - char *str = ""; + MAYBE_UNUSED const char *str = ""; if (!cfg) return 1; @@ -453,28 +431,30 @@ int cmp_cfg_gen_par_is_invalid(const struct cmp_cfg *cfg, enum check_opt opt) max_round_value = MAX_ICU_ROUND; check_model_value = model_mode_is_used(cfg->cmp_mode); break; + default: + return 1; } if (invalid_data_type) { - debug_print("Error: selected compression data type is not supported%s.\n", str); + debug_print("Error: selected compression data type is not supported%s.", str); cfg_invalid++; } if (unsupported_cmp_mode) { - debug_print("Error: selected cmp_mode: %i is not supported%s.\n", cfg->cmp_mode, str); + debug_print("Error: selected cmp_mode: %i is not supported%s.", cfg->cmp_mode, str); cfg_invalid++; } if (check_model_value) { if (cfg->model_value > MAX_MODEL_VALUE) { - debug_print("Error: selected model_value: %" PRIu32 " is invalid. The largest supported value is: %u.\n", + debug_print("Error: selected model_value: %" PRIu32 " is invalid. The largest supported value is: %u.", cfg->model_value, MAX_MODEL_VALUE); cfg_invalid++; } } if (cfg->round > max_round_value) { - debug_print("Error: selected lossy parameter: %" PRIu32 " is not supported%s. The largest supported value is: %" PRIu32 ".\n", + debug_print("Error: selected lossy parameter: %" PRIu32 " is not supported%s. The largest supported value is: %" PRIu32 ".", cfg->round, str, max_round_value); cfg_invalid++; } @@ -482,7 +462,6 @@ int cmp_cfg_gen_par_is_invalid(const struct cmp_cfg *cfg, enum check_opt opt) #ifdef SKIP_CMP_PAR_CHECK return 0; #endif - return cfg_invalid; } @@ -490,9 +469,9 @@ int cmp_cfg_gen_par_is_invalid(const struct cmp_cfg *cfg, enum check_opt opt) /** * @brief check if the ICU buffer parameters are invalid * -* @param cfg pointer to the compressor configuration -* -* @returns 0 if the buffer parameters are valid, otherwise invalid + * @param cfg pointer to the compressor configuration + * + * @returns 0 if the buffer parameters are valid, otherwise invalid */ int cmp_cfg_icu_buffers_is_invalid(const struct cmp_cfg *cfg) @@ -503,54 +482,54 @@ int cmp_cfg_icu_buffers_is_invalid(const struct cmp_cfg *cfg) return 1; if (cfg->input_buf == NULL) { - debug_print("Error: The data_to_compress buffer for the data to be compressed is NULL.\n"); + debug_print("Error: The data_to_compress buffer for the data to be compressed is NULL."); cfg_invalid++; } if (cfg->samples == 0) - debug_print("Warning: The samples parameter is 0. No data are compressed. This behavior may not be intended.\n"); + debug_print("Warning: The samples parameter is 0. No data are compressed. This behavior may not be intended."); if (cfg->icu_output_buf) { if (cfg->buffer_length == 0 && cfg->samples != 0) { - debug_print("Error: The buffer_length is set to 0. There is no space to store the compressed data.\n"); + debug_print("Error: The buffer_length is set to 0. There is no space to store the compressed data."); cfg_invalid++; } if (raw_mode_is_used(cfg->cmp_mode) && cfg->buffer_length < cfg->samples) { - debug_print("Error: The compressed_data_len_samples is to small to hold the data form the data_to_compress.\n"); + debug_print("Error: The compressed_data_len_samples is to small to hold the data form the data_to_compress."); cfg_invalid++; } if (cfg->icu_output_buf == cfg->input_buf) { - debug_print("Error: The compressed_data buffer is the same as the data_to_compress buffer.\n"); + debug_print("Error: The compressed_data buffer is the same as the data_to_compress buffer."); cfg_invalid++; } } if (model_mode_is_used(cfg->cmp_mode)) { if (cfg->model_buf == NULL) { - debug_print("Error: The model_of_data buffer for the model data is NULL.\n"); + debug_print("Error: The model_of_data buffer for the model data is NULL."); cfg_invalid++; } if (cfg->model_buf == cfg->input_buf) { - debug_print("Error: The model_of_data buffer is the same as the data_to_compress buffer.\n"); + debug_print("Error: The model_of_data buffer is the same as the data_to_compress buffer."); cfg_invalid++; } if (cfg->model_buf == cfg->icu_output_buf) { - debug_print("Error: The model_of_data buffer is the same as the compressed_data buffer.\n"); + debug_print("Error: The model_of_data buffer is the same as the compressed_data buffer."); cfg_invalid++; } if (cfg->icu_new_model_buf) { if (cfg->icu_new_model_buf == cfg->input_buf) { - debug_print("Error: The updated_model buffer is the same as the data_to_compress buffer.\n"); + debug_print("Error: The updated_model buffer is the same as the data_to_compress buffer."); cfg_invalid++; } if (cfg->icu_new_model_buf == cfg->icu_output_buf) { - debug_print("Error: The compressed_data buffer is the same as the compressed_data buffer.\n"); + debug_print("Error: The compressed_data buffer is the same as the compressed_data buffer."); cfg_invalid++; } } @@ -563,9 +542,9 @@ int cmp_cfg_icu_buffers_is_invalid(const struct cmp_cfg *cfg) /** * @brief check if all entries in the max_used_bits structure are in the allowed range * -* @param max_used_bits pointer to max_used_bits structure to check -* -* @returns 0 if all entries are valid, otherwise one or more entries are invalid + * @param max_used_bits pointer to max_used_bits structure to check + * + * @returns 0 if all entries are valid, otherwise one or more entries are invalid */ @@ -573,16 +552,16 @@ int cmp_cfg_icu_max_used_bits_out_of_limit(const struct cmp_max_used_bits *max_u { #define CHECK_MAX_USED_BITS_LIMIT(entry) \ do { \ - if (max_used_bits->entry > MAX_USED_BITS_SAFE.entry) { \ - debug_print("Error: The " #entry " entry in the max_used_bits structure is too large (actual: %x, max: %x).\n", max_used_bits->entry, MAX_USED_BITS_SAFE.entry); \ - error++; \ - } \ + if (max_used_bits->entry > MAX_USED_BITS_SAFE.entry) { \ + debug_print("Error: The " #entry " entry in the max_used_bits structure is too large (actual: %x, max: %x).", max_used_bits->entry, MAX_USED_BITS_SAFE.entry); \ + error++; \ + } \ } while (0) int error = 0; if (!max_used_bits) { - debug_print("Error: The pointer to the max_used_bits structure is NULL.\n"); + debug_print("Error: The pointer to the max_used_bits structure is NULL."); return 1; } @@ -615,12 +594,13 @@ int cmp_cfg_icu_max_used_bits_out_of_limit(const struct cmp_max_used_bits *max_u CHECK_MAX_USED_BITS_LIMIT(fc_imagette); CHECK_MAX_USED_BITS_LIMIT(fc_offset_mean); CHECK_MAX_USED_BITS_LIMIT(fc_offset_variance); - CHECK_MAX_USED_BITS_LIMIT(fc_offset_pixel_in_error); CHECK_MAX_USED_BITS_LIMIT(fc_background_mean); CHECK_MAX_USED_BITS_LIMIT(fc_background_variance); CHECK_MAX_USED_BITS_LIMIT(fc_background_outlier_pixels); return error; + +#undef CHECK_MAX_USED_BITS_LIMIT } @@ -638,7 +618,7 @@ int cmp_cfg_icu_max_used_bits_out_of_limit(const struct cmp_max_used_bits *max_u */ static int cmp_pars_are_invalid(uint32_t cmp_par, uint32_t spill, enum cmp_mode cmp_mode, - enum cmp_data_type data_type, char *par_name) + enum cmp_data_type data_type, const char *par_name MAYBE_UNUSED) { int cfg_invalid = 0; uint32_t min_golomb_par; @@ -670,17 +650,17 @@ static int cmp_pars_are_invalid(uint32_t cmp_par, uint32_t spill, enum cmp_mode case CMP_MODE_MODEL_ZERO: case CMP_MODE_MODEL_MULTI: if (cmp_par < min_golomb_par || cmp_par > max_golomb_par) { - debug_print("Error: The selected %s compression parameter: %" PRIu32 " is not supported in the selected compression mode. The compression parameter has to be between [%" PRIu32 ", %" PRIu32 "] in this mode.\n", + debug_print("Error: The selected %s compression parameter: %" PRIu32 " is not supported in the selected compression mode. The compression parameter has to be between [%" PRIu32 ", %" PRIu32 "] in this mode.", par_name, cmp_par, min_golomb_par, max_golomb_par); cfg_invalid++; } if (spill < min_spill) { - debug_print("Error: The selected %s spillover threshold value: %" PRIu32 " is too small. The smallest possible spillover value is: %" PRIu32 ".\n", + debug_print("Error: The selected %s spillover threshold value: %" PRIu32 " is too small. The smallest possible spillover value is: %" PRIu32 ".", par_name, spill, min_spill); cfg_invalid++; } if (spill > max_spill) { - debug_print("Error: The selected %s spillover threshold value: %" PRIu32 " is too large for the selected %s compression parameter: %" PRIu32 ". The largest possible spillover value in the selected compression mode is: %" PRIu32 ".\n", + debug_print("Error: The selected %s spillover threshold value: %" PRIu32 " is too large for the selected %s compression parameter: %" PRIu32 ". The largest possible spillover value in the selected compression mode is: %" PRIu32 ".", par_name, spill, par_name, cmp_par, max_spill); cfg_invalid++; } @@ -688,17 +668,20 @@ static int cmp_pars_are_invalid(uint32_t cmp_par, uint32_t spill, enum cmp_mode break; case CMP_MODE_STUFF: if (cmp_par > MAX_STUFF_CMP_PAR) { - debug_print("Error: The selected %s stuff mode compression parameter: %" PRIu32 " is too large. The largest possible value in the selected compression mode is: %u.\n", + debug_print("Error: The selected %s stuff mode compression parameter: %" PRIu32 " is too large. The largest possible value in the selected compression mode is: %u.", par_name, cmp_par, MAX_STUFF_CMP_PAR); cfg_invalid++; } break; default: - debug_print("Error: The compression mode is not supported.\n"); + debug_print("Error: The compression mode is not supported."); cfg_invalid++; break; } +#ifdef SKIP_CMP_PAR_CHECK + return 0; +#endif return cfg_invalid; } @@ -718,12 +701,13 @@ int cmp_cfg_imagette_is_invalid(const struct cmp_cfg *cfg, enum check_opt opt) { int cfg_invalid = 0; enum cmp_mode cmp_mode; + enum cmp_data_type data_type; if (!cfg) return 1; if (!cmp_imagette_data_type_is_used(cfg->data_type)) { - debug_print("Error: The compression data type is not an imagette compression data type.\n"); + debug_print("Error: The compression data type is not an imagette compression data type."); cfg_invalid++; } @@ -733,8 +717,14 @@ int cmp_cfg_imagette_is_invalid(const struct cmp_cfg *cfg, enum check_opt opt) else cmp_mode = cfg->cmp_mode; + if (opt == ICU_CHECK) + data_type = DATA_TYPE_CHUNK; + else + data_type = cfg->data_type; + + cfg_invalid += cmp_pars_are_invalid(cfg->golomb_par, cfg->spill, cmp_mode, - cfg->data_type, "imagette"); + data_type, "imagette"); /* for the RDCU the adaptive parameters have to be always valid */ if (opt == RDCU_CHECK || cmp_ap_imagette_data_type_is_used(cfg->data_type)) { @@ -852,7 +842,7 @@ int cmp_cfg_fx_cob_is_invalid(const struct cmp_cfg *cfg) return 1; if (!cmp_fx_cob_data_type_is_used(cfg->data_type)) { - debug_print("Error: The compression data type is not a flux/center of brightness compression data type.\n"); + debug_print("Error: The compression data type is not a flux/center of brightness compression data type."); cfg_invalid++; } @@ -888,7 +878,6 @@ int cmp_cfg_fx_cob_is_invalid(const struct cmp_cfg *cfg) * * @returns 0 if the auxiliary science specific parameters are valid, otherwise * invalid - * TODO: implemented DATA_TYPE_F_CAM_OFFSET and DATA_TYPE_F_CAM_BACKGROUND */ int cmp_cfg_aux_is_invalid(const struct cmp_cfg *cfg) @@ -898,21 +887,35 @@ int cmp_cfg_aux_is_invalid(const struct cmp_cfg *cfg) if (!cfg) return 1; - if (!cmp_aux_data_type_is_used(cfg->data_type)) { - debug_print("Error: The compression data type is not an auxiliary science compression data type.\n"); + switch (cfg->data_type) { + case DATA_TYPE_OFFSET: + case DATA_TYPE_F_CAM_OFFSET: + cfg_invalid += cmp_pars_are_invalid(cfg->cmp_par_offset_mean, cfg->spill_offset_mean, + cfg->cmp_mode, cfg->data_type, "offset mean"); + cfg_invalid += cmp_pars_are_invalid(cfg->cmp_par_offset_variance, cfg->spill_offset_variance, + cfg->cmp_mode, cfg->data_type, "offset variance"); + break; + case DATA_TYPE_BACKGROUND: + case DATA_TYPE_F_CAM_BACKGROUND: + cfg_invalid += cmp_pars_are_invalid(cfg->cmp_par_background_mean, cfg->spill_background_mean, + cfg->cmp_mode, cfg->data_type, "background mean"); + cfg_invalid += cmp_pars_are_invalid(cfg->cmp_par_background_variance, cfg->spill_background_variance, + cfg->cmp_mode, cfg->data_type, "background variance"); + cfg_invalid += cmp_pars_are_invalid(cfg->cmp_par_background_pixels_error, cfg->spill_background_pixels_error, + cfg->cmp_mode, cfg->data_type, "background outlier pixls num"); + break; + case DATA_TYPE_SMEARING: + cfg_invalid += cmp_pars_are_invalid(cfg->cmp_par_smearing_mean, cfg->spill_smearing_mean, + cfg->cmp_mode, cfg->data_type, "smearing mean"); + cfg_invalid += cmp_pars_are_invalid(cfg->cmp_par_smearing_variance, cfg->spill_smearing_variance, + cfg->cmp_mode, cfg->data_type, "smearing variance"); + cfg_invalid += cmp_pars_are_invalid(cfg->cmp_par_smearing_pixels_error, cfg->spill_smearing_pixels_error, + cfg->cmp_mode, cfg->data_type, "smearing outlier pixls num"); + break; + default: + debug_print("Error: The compression data type is not an auxiliary science compression data type."); cfg_invalid++; } - - cfg_invalid += cmp_pars_are_invalid(cfg->cmp_par_mean, cfg->spill_mean, - cfg->cmp_mode, cfg->data_type, "mean"); - cfg_invalid += cmp_pars_are_invalid(cfg->cmp_par_variance, cfg->spill_variance, - cfg->cmp_mode, cfg->data_type, "variance"); - - /* if (cfg->data_type != DATA_TYPE_OFFSET && cfg->data_type != DATA_TYPE_F_CAM_OFFSET) */ - if (cfg->data_type != DATA_TYPE_OFFSET) - cfg_invalid += cmp_pars_are_invalid(cfg->cmp_par_pixels_error, cfg->spill_pixels_error, - cfg->cmp_mode, cfg->data_type, "outlier pixls num"); - return cfg_invalid; } @@ -962,20 +965,20 @@ int cmp_cfg_icu_is_invalid(const struct cmp_cfg *cfg) void print_cmp_info(const struct cmp_info *info) { if (!info) { - debug_print("Pointer to the compressor information is NULL.\n"); + debug_print("Pointer to the compressor information is NULL."); return; } - debug_print("cmp_mode_used: %" PRIu32 "\n", info->cmp_mode_used); - debug_print("spill_used: %" PRIu32 "\n", info->spill_used); - debug_print("golomb_par_used: %" PRIu32 "\n", info->golomb_par_used); - debug_print("samples_used: %" PRIu32 "\n", info->samples_used); - debug_print("cmp_size: %" PRIu32 "\n", info->cmp_size); - debug_print("ap1_cmp_size: %" PRIu32 "\n", info->ap1_cmp_size); - debug_print("ap2_cmp_size: %" PRIu32 "\n", info->ap2_cmp_size); - debug_print("rdcu_new_model_adr_used: 0x%06"PRIX32"\n", info->rdcu_new_model_adr_used); - debug_print("rdcu_cmp_adr_used: 0x%06"PRIX32"\n", info->rdcu_cmp_adr_used); - debug_print("model_value_used: %u\n", info->model_value_used); - debug_print("round_used: %u\n", info->round_used); - debug_print("cmp_err: %#X\n", info->cmp_err); + debug_print("cmp_mode_used: %" PRIu32 "", info->cmp_mode_used); + debug_print("spill_used: %" PRIu32 "", info->spill_used); + debug_print("golomb_par_used: %" PRIu32 "", info->golomb_par_used); + debug_print("samples_used: %" PRIu32 "", info->samples_used); + debug_print("cmp_size: %" PRIu32 "", info->cmp_size); + debug_print("ap1_cmp_size: %" PRIu32 "", info->ap1_cmp_size); + debug_print("ap2_cmp_size: %" PRIu32 "", info->ap2_cmp_size); + debug_print("rdcu_new_model_adr_used: 0x%06"PRIX32"", info->rdcu_new_model_adr_used); + debug_print("rdcu_cmp_adr_used: 0x%06"PRIX32"", info->rdcu_cmp_adr_used); + debug_print("model_value_used: %u", info->model_value_used); + debug_print("round_used: %u", info->round_used); + debug_print("cmp_err: %#X", info->cmp_err); } diff --git a/include/cmp_support.h b/lib/common/cmp_support.h similarity index 69% rename from include/cmp_support.h rename to lib/common/cmp_support.h index 3319206e4628057a0a6501fa42ca5235cef99b09..693d7c6267465e7153315a5828cdc84b961d2e2f 100644 --- a/include/cmp_support.h +++ b/lib/common/cmp_support.h @@ -22,7 +22,10 @@ #include <stdint.h> #include <stddef.h> -#include <cmp_max_used_bits.h> +#include "cmp_max_used_bits.h" +#include "cmp_cal_up_model.h" + +#define CMP_COLLECTION_FILD_SIZE 2 /* return code if the bitstream buffer is too small to store the whole bitstream */ @@ -36,9 +39,6 @@ #define CMP_LOSSLESS 0 #define CMP_PAR_UNUNSED 0 -/* the maximal model values used in the update equation for the new model */ -#define MAX_MODEL_VALUE 16U - /* valid compression parameter ranges for RDCU/ICU imagette compression according to PLATO-UVIE-PL-UM-0001 */ #define MAX_RDCU_CMP_MODE 4U #define MIN_IMA_GOLOMB_PAR 1U @@ -93,6 +93,9 @@ #define CMP_DEF_IMA_DIFF_RDCU_BUFFER_ADR 0x600000 +/* imagette sample to byte conversion factor; one imagette samples has 16 bits (2 bytes) */ +#define IMA_SAM2BYT 2 + /** * @brief options for configuration check functions */ @@ -128,7 +131,8 @@ enum cmp_data_type { DATA_TYPE_F_CAM_IMAGETTE, DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE, DATA_TYPE_F_CAM_OFFSET, - DATA_TYPE_F_CAM_BACKGROUND + DATA_TYPE_F_CAM_BACKGROUND, + DATA_TYPE_CHUNK }; @@ -153,6 +157,7 @@ enum cmp_mode { * @note the rdcu_***_adr parameters are ignored for SW compression */ +__extension__ struct cmp_cfg { void *input_buf; /**< Pointer to the data to compress buffer */ void *model_buf; /**< Pointer to the model buffer */ @@ -175,31 +180,84 @@ struct cmp_cfg { */ uint32_t model_value; /**< Model weighting parameter */ uint32_t round; /**< lossy compression parameter */ - uint32_t golomb_par; /**< Golomb parameter for imagette data compression */ - uint32_t spill; /**< Spillover threshold parameter for imagette compression */ - uint32_t ap1_golomb_par; /**< Adaptive 1 spillover threshold for imagette data; HW only */ - uint32_t ap1_spill; /**< Adaptive 1 Golomb parameter for imagette data; HW only */ - uint32_t ap2_golomb_par; /**< Adaptive 2 spillover threshold for imagette data; HW only */ - uint32_t ap2_spill; /**< Adaptive 2 Golomb parameter; HW only */ - uint32_t cmp_par_exp_flags; /**< Compression parameter for exposure flags compression */ - uint32_t spill_exp_flags; /**< Spillover threshold parameter for exposure flags compression */ - uint32_t cmp_par_fx; /**< Compression parameter for normal flux compression */ - uint32_t spill_fx; /**< Spillover threshold parameter for normal flux compression */ - uint32_t cmp_par_ncob; /**< Compression parameter for normal center of brightness compression */ - uint32_t spill_ncob; /**< Spillover threshold parameter for normal center of brightness compression */ - uint32_t cmp_par_efx; /**< Compression parameter for extended flux compression */ - uint32_t spill_efx; /**< Spillover threshold parameter for extended flux compression */ - uint32_t cmp_par_ecob; /**< Compression parameter for executed center of brightness compression */ - uint32_t spill_ecob; /**< Spillover threshold parameter for executed center of brightness compression */ - uint32_t cmp_par_fx_cob_variance; /**< Compression parameter for flux/COB variance compression */ - uint32_t spill_fx_cob_variance; /**< Spillover threshold parameter for flux/COB variance compression */ - uint32_t cmp_par_mean; /**< Compression parameter for auxiliary science mean compression */ - uint32_t spill_mean; /**< Spillover threshold parameter for auxiliary science mean compression */ - uint32_t cmp_par_variance; /**< Compression parameter for auxiliary science variance compression */ - uint32_t spill_variance; /**< Spillover threshold parameter for auxiliary science variance compression */ - uint32_t cmp_par_pixels_error; /**< Compression parameter for auxiliary science outlier pixels number compression */ - uint32_t spill_pixels_error; /**< Spillover threshold parameter for auxiliary science outlier pixels number compression */ - const struct cmp_max_used_bits *max_used_bits; /**< the maximum length of the different data products types in bits */ + union { + uint32_t cmp_par_1; + uint32_t golomb_par; /* TODO: remove this */ /**< Golomb parameter for imagette data compression */ + uint32_t cmp_par_imagette; /**< Golomb parameter for imagette data compression */ + uint32_t cmp_par_exp_flags; /**< Compression parameter for exposure flags compression */ + }; + union { + uint32_t spill_par_1; + uint32_t spill; /* TODO: remove this */ /**< Spillover threshold parameter for imagette data compression */ + uint32_t spill_imagette; /**< Spillover threshold parameter for imagette data compression */ + uint32_t spill_exp_flags; /**< Spillover threshold parameter for exposure flags compression */ + }; + + union { + uint32_t cmp_par_2; + uint32_t ap1_golomb_par; /**< Adaptive 2 spillover threshold for imagette data; HW only */ + uint32_t cmp_par_fx; /**< Compression parameter for normal flux compression */ + uint32_t cmp_par_offset_mean; /**< Compression parameter for auxiliary science mean compression */ + }; + union { + uint32_t spill_par_2; + uint32_t ap1_spill; /**< Adaptive 2 Golomb parameter; HW only */ + uint32_t spill_fx; /**< Spillover threshold parameter for normal flux compression */ + uint32_t spill_offset_mean; /**< Spillover threshold parameter for auxiliary science mean compression */ + }; + + union { + uint32_t cmp_par_3; + uint32_t ap2_golomb_par; /**< Adaptive 2 spillover threshold for imagette data; HW only */ + uint32_t cmp_par_ncob; /**< Compression parameter for normal center of brightness compression */ + uint32_t cmp_par_offset_variance; /**< Compression parameter for auxiliary science variance compression */ + }; + union { + uint32_t spill_par_3; + uint32_t ap2_spill; /**< Adaptive 2 Golomb parameter; HW only */ + uint32_t spill_ncob; /**< Spillover threshold parameter for normal center of brightness compression */ + uint32_t spill_offset_variance; /**< Spillover threshold parameter for auxiliary science variance compression */ + }; + + union { + uint32_t cmp_par_4; + uint32_t cmp_par_efx; /**< Compression parameter for extended flux compression */ + uint32_t cmp_par_background_mean; /**< Compression parameter for auxiliary science mean compression */ + uint32_t cmp_par_smearing_mean; /**< Compression parameter for auxiliary science mean compression */ + }; + union { + uint32_t spill_par_4; + uint32_t spill_efx; /**< Spillover threshold parameter for extended flux compression */ + uint32_t spill_background_mean; /**< Spillover threshold parameter for auxiliary science mean compression */ + uint32_t spill_smearing_mean; /**< Spillover threshold parameter for auxiliary science mean compression */ + }; + + union { + uint32_t cmp_par_5; + uint32_t cmp_par_ecob; /**< Compression parameter for executed center of brightness compression */ + uint32_t cmp_par_background_variance; /**< Compression parameter for auxiliary science variance compression */ + uint32_t cmp_par_smearing_variance; /**< Compression parameter for auxiliary science variance compression */ + }; + union { + uint32_t spill_par_5; + uint32_t spill_ecob; /**< Spillover threshold parameter for executed center of brightness compression */ + uint32_t spill_background_variance; /**< Spillover threshold parameter for auxiliary science variance compression */ + uint32_t spill_smearing_variance; /**< Spillover threshold parameter for auxiliary science variance compression */ + }; + + union { + uint32_t cmp_par_6; + uint32_t cmp_par_fx_cob_variance; /**< Compression parameter for flux/COB variance compression */ + uint32_t cmp_par_background_pixels_error; /**< Compression parameter for auxiliary science outlier pixels number compression */ + uint32_t cmp_par_smearing_pixels_error; /**< Compression parameter for auxiliary science outlier pixels number compression */ + }; + union { + uint32_t spill_par_6; + uint32_t spill_fx_cob_variance; /**< Spillover threshold parameter for flux/COB variance compression */ + uint32_t spill_background_pixels_error; /**< Spillover threshold parameter for auxiliary science outlier pixels number compression */ + uint32_t spill_smearing_pixels_error; /**< Spillover threshold parameter for auxiliary science outlier pixels number compression */ + }; + const struct cmp_max_used_bits *max_used_bits; /**< the maximum length of the different data products types in bits */ }; @@ -265,41 +323,16 @@ struct fx_cob_par { }; -/** - * @brief method for lossy rounding - * @note This function is implemented as a macro for the sake of performance - * - * @param value the value to round - * @param round rounding parameter - * - * @return rounded value - */ - -#define round_fwd(value, round) ((uint32_t)(value) >> (round)) - - -/** - * @brief inverse method for lossy rounding - * @note This function is implemented as a macro for the sake of performance - * - * @param value the value to round back - * @param round rounding parameter - * - * @return back rounded value - */ - -#define round_inv(value, round) ((uint32_t)(value) << (round)) - - int is_a_pow_of_2(unsigned int v); -int ilog_2(uint32_t x); +unsigned int ilog_2(uint32_t x); +unsigned int cmp_bit_to_byte(unsigned int cmp_size_bit); unsigned int cmp_bit_to_4byte(unsigned int cmp_size_bit); int cmp_cfg_icu_is_invalid(const struct cmp_cfg *cfg); int cmp_cfg_gen_par_is_invalid(const struct cmp_cfg *cfg, enum check_opt opt); int cmp_cfg_icu_buffers_is_invalid(const struct cmp_cfg *cfg); -int cmp_cfg_icu_max_used_bits_out_of_limit(const struct cmp_max_used_bits *max_used_bits_repo); +int cmp_cfg_icu_max_used_bits_out_of_limit(const struct cmp_max_used_bits *max_used_bits); int cmp_cfg_imagette_is_invalid(const struct cmp_cfg *cfg, enum check_opt opt); int cmp_cfg_fx_cob_is_invalid(const struct cmp_cfg *cfg); int cmp_cfg_aux_is_invalid(const struct cmp_cfg *cfg); @@ -321,9 +354,6 @@ int rdcu_supported_cmp_mode_is_used(enum cmp_mode cmp_mode); int zero_escape_mech_is_used(enum cmp_mode cmp_mode); int multi_escape_mech_is_used(enum cmp_mode cmp_mode); -unsigned int cmp_up_model(unsigned int data, unsigned int model, - unsigned int model_value, unsigned int round); - void print_cmp_info(const struct cmp_info *info); diff --git a/lib/common/compiler.h b/lib/common/compiler.h new file mode 100644 index 0000000000000000000000000000000000000000..983ffa46d046fa6bafbf102a8271387741ea0c6c --- /dev/null +++ b/lib/common/compiler.h @@ -0,0 +1,157 @@ +/** + * @file compiler.h + * @author Armin Luntzer (armin.luntzer@univie.ac.at) + * @date 2015 + * + * @copyright GPLv2 + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * @brief a collection of preprocessor macros + */ + + +#ifndef COMPILER_H +#define COMPILER_H + + +/* Derived from Linux "Features Test Macro" header Convenience macros to test + * the versions of gcc (or a compatible compiler). + * Use them like this: + * #if GNUC_PREREQ (2,8) + * ... code requiring gcc 2.8 or later ... + * #endif +*/ + +#if defined(__GNUC__) && defined(__GNUC_MINOR__) +# define GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +#else + #define GNUC_PREREQ(maj, min) 0 +#endif + + +/** + * Compile time check usable outside of function scope. + * Stolen from Linux (hpi_internal.h) + */ +#define compile_time_assert(cond, msg) typedef char ASSERT_##msg[(cond) ? 1 : -1] + + +/** + * same with the stuff below + */ + +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) + +/** + * + * ARRAY_SIZE - get the number of elements in a visible array + * @param x the array whose size you want + * + * This does not work on pointers, or arrays declared as [], or + * function parameters. With correct compiler support, such usage + * will cause a build error + */ + +#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) + +#define bitsizeof(x) (CHAR_BIT * sizeof(x)) + +#define maximum_signed_value_of_type(a) \ + (INTMAX_MAX >> (bitsizeof(intmax_t) - bitsizeof(a))) + +#define maximum_unsigned_value_of_type(a) \ + (UINTMAX_MAX >> (bitsizeof(uintmax_t) - bitsizeof(a))) + +/* + * Signed integer overflow is undefined in C, so here's a helper macro + * to detect if the sum of two integers will overflow. + * + * Requires: a >= 0, typeof(a) equals typeof(b) + */ +#define signed_add_overflows(a, b) \ + ((b) > maximum_signed_value_of_type(a) - (a)) + +#define unsigned_add_overflows(a, b) \ + ((b) > maximum_unsigned_value_of_type(a) - (a)) + + +#define __get_unaligned_t(type, ptr) __extension__ ({ \ + const struct { type x; } __attribute__((packed)) *__pptr = (__typeof__(__pptr))(ptr); \ + __pptr->x; \ +}) + +#define __put_unaligned_t(type, val, ptr) do { \ + struct { type x; } __attribute__((packed)) *__pptr = (__typeof__(__pptr))(ptr); \ + __pptr->x = (val); \ +} while (0) + + +/** + * @brief read from an unaligned address + * + * @param ptr pointer to the address to read from (can be unaligned) + * + * @return the value read from the (unaligned) address in system endianness + * @note the size of the value is determined by the pointer type + */ + +#define get_unaligned(ptr) __get_unaligned_t(__typeof__(*(ptr)), (ptr)) + + +/** + * @brief write to an unaligned address + * + * @param val the value to write + * @param ptr pointer to the address to write to (can be unaligned) + * + * @note the size of the value is determined by the pointer type + */ + +#define put_unaligned(val, ptr) __put_unaligned_t(__typeof__(*(ptr)), (val), (ptr)) + + +/** + * @brief mark a variable as unused to suppress compiler warnings. + * + * This macro is used to indicate that a variable is intentionally left unused + * in the code. It helps suppress compiler warnings about unused variables. + * It also tries to prevent the actual use of the "unused" variables. + */ + +#if GNUC_PREREQ(4, 5) +#define UNUSED __attribute__((unused)) \ + __attribute__((deprecated ("parameter declared as UNUSED"))) +#elif defined(__GNUC__) +#define UNUSED __attribute__((unused)) \ + __attribute__((deprecated)) +#else +#define UNUSED +#endif + + + +/** + * @brief mark a variable as potentially unused to suppress compiler warnings. + * + * This macro is used to indicate that a variable may be intentionally left unused + * in the code. It helps suppress compiler warnings about unused variables. + * It does *not* protect against the actual use of the "unused" variables. + */ + +#if (DEBUGLEVEL == 0) +#define MAYBE_UNUSED __attribute__((unused)) +#else +#define MAYBE_UNUSED +#endif + + +#endif /* COMPILER_H */ diff --git a/include/my_inttypes.h b/lib/common/leon_inttypes.h similarity index 72% rename from include/my_inttypes.h rename to lib/common/leon_inttypes.h index 3d7f91151b67dd594f79df354a22763d1e3b722f..694af3e1e217129e775ee5d7a5ba5656be2b206a 100644 --- a/include/my_inttypes.h +++ b/lib/common/leon_inttypes.h @@ -1,5 +1,5 @@ /** - * @file my_inttypes.h + * @file leon_inttypes.h * @author Dominik Loidolt (dominik.loidolt@univie.ac.at) * @date 2021 * @@ -18,9 +18,8 @@ * @warning Does not fully implement the standard. */ - -#ifndef _MY_INTTYPES_H -#define _MY_INTTYPES_H +#ifndef LEON_INTTYPES_H +#define LEON_INTTYPES_H #ifndef __sparc__ # include <inttypes.h> @@ -50,6 +49,30 @@ # define PRIX32 "lX" #endif /*PRIX32*/ +#ifndef PRId64 +# define PRId64 "lld" +#endif /*PRId64*/ + +#ifndef PRIi64 +# define PRIi64 "lli" +#endif /*PRIi64*/ + +#ifndef PRIo64 +# define PRIo64 "llo" +#endif /*PRIo64*/ + +#ifndef PRIu64 +# define PRIu64 "llu" +#endif /* PRIu64 */ + +#ifndef PRIx64 +# define PRIx64 "llx" +#endif /*PRIx64*/ + +#ifndef PRIX64 +# define PRIX64 "llX" +#endif /*PRIX64*/ + #endif /* __sparc__ */ -#endif /* _MY_INTTYPES_H */ +#endif /* LEON_INTTYPES_H */ diff --git a/include/list.h b/lib/common/list.h similarity index 66% rename from include/list.h rename to lib/common/list.h index 3fb02e1048e688785b2fc7bf2aad620bf8cd2bae..5613c64f0e6d53782407924f189d7c70e96dc6a0 100644 --- a/include/list.h +++ b/lib/common/list.h @@ -1,5 +1,5 @@ /** - * @file include/list.h + * @file list.h * @ingroup linked_list * * @note This list implementation was shamelessly stolen and modified from the @@ -61,6 +61,7 @@ * */ + #ifndef LIST_H #define LIST_H @@ -87,8 +88,8 @@ static inline void __list_add(struct list_head *new, struct list_head *prev, str /** * @brief add a new entry - * @param new: new entry to be added - * @param head: list head to add it after + * @param new new entry to be added + * @param head list head to add it after * * Insert a new entry after the specified head. * This is good for implementing stacks. @@ -108,18 +109,19 @@ static inline void INIT_LIST_HEAD(struct list_head *list) /** * @brief get the struct for this entry - * @param ptr: the &struct list_head pointer. - * @param type: the type of the struct this is embedded in. - * @param member: the name of the list_struct within the struct. + * @param ptr the &struct list_head pointer. + * @param type the type of the struct this is embedded in. + * @param member the name of the list_struct within the struct. + * @note add (void *) cast to suppress wcast-align warning */ #define list_entry(ptr, type, member) \ - ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) + ((type *)((void *)((char *)(ptr)-__builtin_offsetof(type, member)))) /** * list_first_entry - get the first element from a list - * @ptr: the list head to take the element from. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_head within the struct. + * @param ptr the list head to take the element from. + * @param type the type of the struct this is embedded in. + * @param member the name of the list_head within the struct. * * Note, that list is expected to be not empty. */ @@ -128,9 +130,9 @@ static inline void INIT_LIST_HEAD(struct list_head *list) /** * list_last_entry - get the last element from a list - * @ptr: the list head to take the element from. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_head within the struct. + * @param ptr the list head to take the element from. + * @param type the type of the struct this is embedded in. + * @param member the name of the list_head within the struct. * * Note, that list is expected to be not empty. */ @@ -139,9 +141,9 @@ static inline void INIT_LIST_HEAD(struct list_head *list) /** * list_first_entry_or_null - get the first element from a list - * @ptr: the list head to take the element from. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_head within the struct. + * @param ptr the list head to take the element from. + * @param type the type of the struct this is embedded in. + * @param member the name of the list_head within the struct. * * Note that if the list is empty, it returns NULL. */ @@ -153,49 +155,50 @@ static inline void INIT_LIST_HEAD(struct list_head *list) /** * list_next_entry - get the next element in list - * @pos: the type * to cursor - * @member: the name of the list_head within the struct. + * @param pos the type * to cursor + * @param member the name of the list_head within the struct. + * @note modified to use __typeof__() */ #define list_next_entry(pos, member) \ - list_entry((pos)->member.next, typeof(*(pos)), member) + list_entry((pos)->member.next, __typeof__(*(pos)), member) /** * list_prev_entry - get the prev element in list - * @pos: the type * to cursor - * @member: the name of the list_head within the struct. + * @param pos the type * to cursor + * @param member the name of the list_head within the struct. */ #define list_prev_entry(pos, member) \ - list_entry((pos)->member.prev, typeof(*(pos)), member) + list_entry((pos)->member.prev, __typeof__(*(pos)), member) /** * list_for_each - iterate over a list - * @pos: the &struct list_head to use as a loop cursor. - * @head: the head for your list. + * @pos the &struct list_head to use as a loop cursor. + * @head the head for your list. */ #define list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next) /** * @brief iterate over list of given type - * @param pos: the type * to use as a loop counter. - * @param head: the head for your list. - * @param member: the name of the list_struct within the struct. - * @param note modified to use __typeof__() + * @param pos the type * to use as a loop counter. + * @param head the head for your list. + * @param member the name of the list_struct within the struct. + * @note modified to use __typeof__() */ #define list_for_each_entry(pos, head, member) \ - for (pos = list_entry((head)->next, __typeof__(*pos), member); \ + for (pos = list_first_entry(head, __typeof__(*pos), member); \ &pos->member != (head); \ - pos = list_entry(pos->member.next, __typeof__(*pos), member)) - + pos = list_next_entry(pos, member)) /** * @brief iterate over list of given type safe against removal of list entry - * @param pos: the type * to use as a loop counter. - * @param n: another type * to use as temporary storage - * @param head: the head for your list. - * @param member: the name of the list_struct within the struct. + * @param pos the type * to use as a loop counter. + * @param n another type * to use as temporary storage + * @param head the head for your list. + * @param member the name of the list_struct within the struct. */ + #define list_for_each_entry_safe(pos, n, head, member) \ for (pos = list_entry((head)->next, __typeof__(*pos), member), \ n = list_entry(pos->member.next, __typeof__(*pos), member);\ @@ -205,15 +208,15 @@ static inline void INIT_LIST_HEAD(struct list_head *list) /** * @brief iterator wrapper start - * @param pos: the type * to use as a loop counter. - * @param head: the head for your list. - * @param member: the name of the list_struct within the struct. - * @param type: the type of struct - * @param warning requires list_entry_while() to close statement - * @param note this construction is necessary for a truly circular list that is "headless" - * @param note and can be iterated from any starting element without additional overhead - * @param note compared to the LIST_HEAD/list_for_each_entry approach - * @param todo check if this is functional for all targets (confirmed: gcc 4.8.2) + * @param pos the type * to use as a loop counter. + * @param head the head for your list. + * @param member the name of the list_struct within the struct. + * @param type the type of struct + * @warning requires list_entry_while() to close statement + * @note this construction is necessary for a truly circular list that is "headless" + * and can be iterated from any starting element without additional overhead + * compared to the LIST_HEAD/list_for_each_entry approach + * TODO: check if this is functional for all targets (confirmed: gcc 4.8.2) */ #define list_entry_do(pos, head, member, type) \ @@ -222,15 +225,14 @@ static inline void INIT_LIST_HEAD(struct list_head *list) do \ { \ - /** * @brief list iterator wrapper stop - * @param pos: the type * to use as a loop counter. - * @param head: the head for your list. - * @param member: the name of the list_struct within the struct. - * @param type: the type of struct - * @param warning requires list_entry_do() to open statement - * @param note see list_entry_while() + * @param pos the type * to use as a loop counter. + * @param head the head for your list. + * @param member the name of the list_struct within the struct. + * @param type the type of struct + * @warning requires list_entry_do() to open statement + * @note see list_entry_while() */ #define list_entry_while(pos, head, member, type) \ @@ -241,33 +243,32 @@ static inline void INIT_LIST_HEAD(struct list_head *list) /** * @brief the list entry do-while equivalent for a code block - * @param pos: the type * to use as a loop counter. - * @param head: the head for your list. - * @param member: the name of the list_struct within the struct. - * @param type: the type of struct - * @param _CODE_: a code segment - * @param note see list_entry_while(), list_entry_do() + * @param pos the type * to use as a loop counter. + * @param head the head for your list. + * @param member the name of the list_struct within the struct. + * @param type the type of struct + * @param _CODE_ a code segment + * @note see list_entry_while(), list_entry_do() */ #define list_entry_do_while(pos, head, member, type, _CODE_) \ - list_entry_do(pos,head,member,type) \ + list_entry_do(pos, head, member, type) \ { \ _CODE_; \ - } list_entry_while(pos,head,member,type) - + } list_entry_while(pos, head, member, type) /** * @brief reverse iterate over list of given type - * @param pos: the type * to use as a loop counter. - * @param head: the head for your list. - * @param member: the name of the list_struct within the struct. - * (slightly modified in case there is no typeof() functionality in target compiler) + * @param pos the type * to use as a loop counter. + * @param head the head for your list. + * @param member the name of the list_struct within the struct. + * @note slightly modified in case there is no typeof() functionality in target compiler */ #define list_for_each_entry_rev(pos, head, member) \ for (pos = list_entry((head)->prev, __typeof__(*pos), member); \ &pos->member != (head); \ - pos = list_entry(pos->member.prev, __typeof(*pos), member)) + pos = list_entry(pos->member.prev, __typeof__(*pos), member)) /* @@ -286,7 +287,7 @@ static inline void __list_del(struct list_head *prev, struct list_head *next) /** * @brief deletes entry from list. - * @param entry: the element to delete from the list. + * @param entry the element to delete from the list. * @note list_empty on entry does not return true after this, * the entry is in an undefined state. */ @@ -301,8 +302,8 @@ static inline void list_del(struct list_head *entry) /** * @brief deletes entry from list. - * @param entry: the element to delete from the list. - * @brief list_empty() on entry does not return true after this, the entry is + * @param entry the element to delete from the list. + * @note list_empty() on entry does not return true after this, the entry is * in an undefined state. */ @@ -313,7 +314,7 @@ static inline void __list_del_entry(struct list_head *entry) /** * @brief deletes entry from list and reinitialize it. - * @param entry: the element to delete from the list. + * @param entry the element to delete from the list. */ static inline void list_del_init(struct list_head *entry) { @@ -335,8 +336,8 @@ static inline void list_move(struct list_head *list, struct list_head *head) /** * @brief add a new entry - * @param new: new entry to be added - * @param head: list head to add it before + * @param new new entry to be added + * @param head list head to add it before * * Insert a new entry before the specified head. * This is useful for implementing queues. @@ -350,10 +351,10 @@ static inline void list_add_tail(struct list_head *new, struct list_head *head) /** * @brief replace old entry by new one - * @param old : the element to be replaced - * @param new : the new element to insert + * @param old the element to be replaced + * @param new the new element to insert * - * If @param old was empty, it will be overwritten. + * If the old parameter was empty, it will be overwritten. */ static inline void list_replace(struct list_head *old, @@ -368,8 +369,8 @@ static inline void list_replace(struct list_head *old, /** * @brief replace entry1 with entry2 and re-add entry1 at entry2's position - * @param entry1: the location to place entry2 - * @param entry2: the location to place entry1 + * @param entry1 the location to place entry2 + * @param entry2 the location to place entry1 */ static inline void list_swap(struct list_head *entry1, struct list_head *entry2) @@ -385,7 +386,7 @@ static inline void list_swap(struct list_head *entry1, /** * @brief tests whether a list is empty - * @param head: the list to test. + * @param head the list to test. */ static inline int list_empty(struct list_head *head) @@ -395,7 +396,7 @@ static inline int list_empty(struct list_head *head) /** * @brief tests whether there is at least one element in the list - * @param head: the list to test. + * @param head the list to test. */ static inline int list_filled(struct list_head *head) @@ -406,31 +407,31 @@ static inline int list_filled(struct list_head *head) /** * @brief delete from one list and add as another's tail - * @param list: the entry to move - * @param head: the head that will follow our entry + * @param list the entry to move + * @param head the head that will follow our entry */ static inline void list_move_tail(struct list_head *list, struct list_head *head) { - __list_del(list->prev, list->next); - list_add_tail(list, head); + __list_del(list->prev, list->next); + list_add_tail(list, head); } /** * @brief rotate the list to the left - * @param head: the head of the list + * @param head the head of the list */ static inline void list_rotate_left(struct list_head *head) { - struct list_head *first; + struct list_head *first; - if (!list_empty(head)) { - first = head->next; - list_move_tail(first, head); - } + if (!list_empty(head)) { + first = head->next; + list_move_tail(first, head); + } } diff --git a/lib/common/meson.build b/lib/common/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..c4d8b68cca24c0148eddfc042604639d236760dd --- /dev/null +++ b/lib/common/meson.build @@ -0,0 +1,6 @@ +common_sources = files([ + 'cmp_data_types.c', + 'cmp_entity.c', + 'cmp_max_used_bits.c', + 'cmp_support.c' +]) diff --git a/lib/decmp.c b/lib/decmp.c deleted file mode 100644 index 41d90a6dbf4560b881d43107922ec60fe9ecd846..0000000000000000000000000000000000000000 --- a/lib/decmp.c +++ /dev/null @@ -1,2348 +0,0 @@ -/** - * @file decmp.c - * @author Dominik Loidolt (dominik.loidolt@univie.ac.at) - * @date 2020 - * - * @copyright GPLv2 - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * @brief software decompression library - * @see Data Compression User Manual PLATO-UVIE-PL-UM-0001 - * - * To decompress a compression entity (consisting of a compression entity header - * and the compressed data) use the decompress_cmp_entiy() function. - */ - -#include <stdint.h> -#include <stdio.h> -#include <limits.h> -#include <string.h> - -#include "byteorder.h" -#include "cmp_debug.h" -#include "cmp_support.h" -#include "cmp_data_types.h" -#include "cmp_max_used_bits.h" -#include "cmp_max_used_bits_list.h" -#include "cmp_entity.h" - - -#define MAX_CW_LEN 32 /* maximum Golomb code word bit length */ - - - -/** - * @brief function pointer to a code word decoder function - */ - -typedef int (*decoder_ptr)(uint32_t, unsigned int, unsigned int, uint32_t *); - - -/** - * @brief structure to hold a setup to encode a value - */ - -struct decoder_setup { - decoder_ptr decode_cw_f; /* pointer to the code word decoder (Golomb/Rice)*/ - int (*decode_method_f)(uint32_t *decoded_value, int stream_pos, - const struct decoder_setup *setup); /* pointer to the decoding function */ - uint32_t *bitstream_adr; /* start address of the compressed data bitstream */ - uint32_t max_stream_len; /* maximum length of the bitstream/icu_output_buf in bits */ - uint32_t encoder_par1; /* encoding parameter 1 */ - uint32_t encoder_par2; /* encoding parameter 2 */ - uint32_t outlier_par; /* outlier parameter */ - uint32_t lossy_par; /* lossy compression parameter */ - uint32_t model_value; /* model value parameter */ - uint32_t max_data_bits; /* how many bits are needed to represent the highest possible value */ -}; - - -/** - * @brief count leading 1-bits - * - * @param value input vale to count - * - * @returns the number of leading 1-bits in value, starting at the most - * significant bit position - */ - -static unsigned int count_leading_ones(uint32_t value) -{ - if (value == 0xFFFFFFFF) - return 32; - - return __builtin_clz(~value); -} - - -/** - * @brief decode a Rice code word - * - * @param code_word Rice code word bitstream starting at the MSB - * @param m Golomb parameter (not used) - * @param log2_m Rice parameter, must be the same used for encoding - * @param decoded_cw pointer where decoded value is written - * - * @returns the length of the decoded code word in bits (NOT the decoded value); - * 0 on failure - */ - -static int rice_decoder(uint32_t code_word, unsigned int m, unsigned int log2_m, - uint32_t *decoded_cw) -{ - unsigned int q; /* quotient code */ - unsigned int ql; /* length of the quotient code */ - unsigned int r; /* remainder code */ - unsigned int rl = log2_m; /* length of the remainder code */ - unsigned int cw_len; /* length of the decoded code word in bits */ - - (void)m; /* we don't need the Golomb parameter */ - - if (log2_m > 32) /* because m has 32 bits log2_m can not be bigger than 32 */ - return 0; - - q = count_leading_ones(code_word); /* decode unary coding */ - ql = q + 1; /* Number of 1's + following 0 */ - - cw_len = rl + ql; - - if (cw_len > 32) /* can only decode code words with maximum 32 bits */ - return 0; - - code_word = code_word << ql; /* shift quotient code out */ - - /* Right shifting an integer by a number of bits equal or greater than - * its size is undefined behavior */ - if (rl == 0) - r = 0; - else - r = code_word >> (32 - rl); - - *decoded_cw = (q << rl) + r; - - return cw_len; -} - - -/** - * @brief decode a Golomb code word - * - * @param code_word Golomb code word bitstream starting at the MSB - * @param m Golomb parameter (have to be bigger than 0) - * @param log2_m is log_2(m) calculate outside function for better - * performance - * @param decoded_cw pointer where decoded value is written - * - * @returns the length of the decoded code word in bits (NOT the decoded value); - * 0 on failure - */ - -static int golomb_decoder(uint32_t code_word, unsigned int m, - unsigned int log2_m, uint32_t *decoded_cw) -{ - unsigned int q; /* quotient code */ - unsigned int r1; /* remainder code group 1 */ - unsigned int r2; /* remainder code group 2 */ - unsigned int r; /* remainder code */ - unsigned int rl; /* length of the remainder code */ - unsigned int cutoff; /* cutoff between group 1 and 2 */ - unsigned int cw_len; /* length of the decoded code word in bits */ - - q = count_leading_ones(code_word); /* decode unary coding */ - - rl = log2_m + 1; - code_word <<= (q+1); /* shift quotient code out */ - - r2 = code_word >> (32 - rl); - r1 = r2 >> 1; - - cutoff = (1UL << rl) - m; - - if (r1 < cutoff) { /* group 1 */ - cw_len = q + rl; - r = r1; - } else { /* group 2 */ - cw_len = q + rl + 1; - r = r2 - cutoff; - } - - if (cw_len > 32) - return 0; - - *decoded_cw = q*m + r; - return cw_len; -} - - -/** - * @brief select the decoder based on the used Golomb parameter - * @note if the Golomb parameter is a power of 2 we can use the faster Rice - * decoder - * - * @param golomb_par Golomb parameter (have to be bigger than 0) - * - * @returns function pointer to the select decoder function; NULL on failure - */ - -static decoder_ptr select_decoder(unsigned int golomb_par) -{ - if (!golomb_par) - return NULL; - - if (is_a_pow_of_2(golomb_par)) - return &rice_decoder; - else - return &golomb_decoder; -} - - -/** - * @brief read a value of up to 32 bits from a bitstream - * - * @param p_value pointer to the read value, the - * read value will be converted to the system - * endianness - * @param n_bits number of bits to read from the bitstream - * @param bit_offset bit index where the bits will be read, seen from - * the very beginning of the bitstream - * @param bitstream_adr this is the pointer to the beginning of the - * bitstream - * @param max_stream_len maximum length of the bitstream in bits * - * - * @returns bit position of the last read bit in the bitstream on success; - * returns negative in case of erroneous input; returns CMP_ERROR_SMALL_BUF - * if the bitstream buffer is too small to read the value from the - * bitstream - */ - -static int get_n_bits32(uint32_t *p_value, unsigned int n_bits, int bit_offset, - uint32_t *bitstream_adr, unsigned int max_stream_len) -{ - uint32_t *local_adr; - unsigned int bitsLeft, bitsRight, localEndPos; - unsigned int mask; - int stream_len = (int)(n_bits + (unsigned int)bit_offset); /* overflow results in a negative return value */ - - /*leave in case of erroneous input */ - if (bit_offset < 0) - return -1; - if (n_bits == 0) - return -1; - if (n_bits > 32) - return -1; - if (!bitstream_adr) - return -1; - if (!p_value) - return -1; - - /* Check if bitstream buffer is large enough */ - if ((unsigned int)stream_len > max_stream_len) { - debug_print("Error: Buffer overflow detected.\n"); - return CMP_ERROR_SMALL_BUF; - - } - - /* separate the bit_offset into word offset (set local_adr pointer) and - * local bit offset (bitsLeft) - */ - local_adr = bitstream_adr + (bit_offset >> 5); - bitsLeft = bit_offset & 0x1f; - - localEndPos = bitsLeft + n_bits; - - if (localEndPos <= 32) { - unsigned int shiftRight = 32 - n_bits; - - bitsRight = shiftRight - bitsLeft; - - *(p_value) = cpu_to_be32(*(local_adr)) >> bitsRight; - - mask = (0xffffffff >> shiftRight); - - *(p_value) &= mask; - } else { - unsigned int n1 = 32 - bitsLeft; - unsigned int n2 = n_bits - n1; - /* part 1 ; */ - mask = 0xffffffff >> bitsLeft; - *(p_value) = cpu_to_be32(*(local_adr)) & mask; - *(p_value) <<= n2; - /*part 2: */ - /* adjust address*/ - local_adr += 1; - - bitsRight = 32 - n2; - *(p_value) |= cpu_to_be32(*(local_adr)) >> bitsRight; - } - - return stream_len; -} - - -/** - * @brief decode a Golomb/Rice encoded code word from the bitstream - * - * @param decoded_value pointer to the decoded value - * @param stream_pos start bit position code word to be decoded in the bitstream - * @param setup pointer to the decoder setup - * - * @returns bit index of the next code word in the bitstream on success; returns - * negative in case of erroneous input; returns CMP_ERROR_SMALL_BUF if the - * bitstream buffer is too small to read the value from the bitstream - */ - -static int decode_normal(uint32_t *decoded_value, int stream_pos, - const struct decoder_setup *setup) -{ - uint32_t read_val; - unsigned int n_read_bits; - int stream_pos_read, cw_len; - - /* check if we can read max_cw_len or less; we do not know how long the - * code word actually is so we try to read the maximum cw length */ - if ((unsigned int)stream_pos + 32 > setup->max_stream_len) - n_read_bits = setup->max_stream_len - (unsigned int)stream_pos; - else - n_read_bits = MAX_CW_LEN; - - stream_pos_read = get_n_bits32(&read_val, n_read_bits, stream_pos, - setup->bitstream_adr, setup->max_stream_len); - if (stream_pos_read < 0) - return stream_pos_read; - - /* if we read less than 32, we shift the bitstream so that it starts at the MSB */ - read_val = read_val << (32 - n_read_bits); - - cw_len = setup->decode_cw_f(read_val, setup->encoder_par1, - setup->encoder_par2, decoded_value); - if (cw_len <= 0) - return -1; - /* consistency check: code word length can not be bigger than the read bits */ - if (cw_len > (int)n_read_bits) - return -1; - - return stream_pos + cw_len; -} - - -/** - * @brief decode a Golomb/Rice encoded code word with zero escape system - * mechanism from the bitstream - * - * @param decoded_value pointer to the decoded value - * @param stream_pos start bit position code word to be decoded in the bitstream - * @param setup pointer to the decoder setup - * - * @returns bit index of the next code word in the bitstream on success; returns - * negative in case of erroneous input; returns CMP_ERROR_SMALL_BUF if the - * bitstream buffer is too small to read the value from the bitstream - */ - -static int decode_zero(uint32_t *decoded_value, int stream_pos, - const struct decoder_setup *setup) -{ - stream_pos = decode_normal(decoded_value, stream_pos, setup); - if (stream_pos < 0) - return stream_pos; - - /* consistency check: value lager than the outlier parameter should not - * be Golomb/Rice encoded */ - if (*decoded_value > setup->outlier_par) - return -1; - - if (*decoded_value == 0) { - /* escape symbol mechanism was used; read unencoded value */ - uint32_t unencoded_val; - - stream_pos = get_n_bits32(&unencoded_val, setup->max_data_bits, stream_pos, - setup->bitstream_adr, setup->max_stream_len); - if (stream_pos < 0) - return stream_pos; - /* consistency check: outliers must be bigger than the outlier_par */ - if (unencoded_val < setup->outlier_par && unencoded_val != 0) - return -1; - - *decoded_value = unencoded_val; - } - - (*decoded_value)--; - if (*decoded_value == 0xFFFFFFFF) /* catch underflow */ - (*decoded_value) >>= (32 - setup->max_data_bits); - - return stream_pos; -} - - -/** - * @brief decode a Golomb/Rice encoded code word with multi escape system - * mechanism from the bitstream - * - * @param decoded_value pointer to the decoded value - * @param stream_pos start bit position code word to be decoded in the bitstream - * @param setup pointer to the decoder setup - * - * @returns bit index of the next code word in the bitstream on success; returns - * negative in case of erroneous input; returns CMP_ERROR_SMALL_BUF if the - * bitstream buffer is too small to read the value from the bitstream - */ - -static int decode_multi(uint32_t *decoded_value, int stream_pos, - const struct decoder_setup *setup) -{ - stream_pos = decode_normal(decoded_value, stream_pos, setup); - if (stream_pos < 0) - return stream_pos; - - if (*decoded_value >= setup->outlier_par) { - /* escape symbol mechanism was used; read unencoded value */ - uint32_t unencoded_val; - unsigned int unencoded_len; - - unencoded_len = (*decoded_value - setup->outlier_par + 1) * 2; - - stream_pos = get_n_bits32(&unencoded_val, unencoded_len, stream_pos, - setup->bitstream_adr, setup->max_stream_len); - if (stream_pos >= 0) - *decoded_value = unencoded_val + setup->outlier_par; - } - return stream_pos; -} - - -/** - * @brief get the value unencoded with setup->cmp_par_1 bits without any - * additional changes from the bitstream - * - * @param decoded_value pointer to the decoded value - * @param stream_pos start bit position code word to be decoded in the bitstream - * @param setup pointer to the decoder setup - * - * @returns bit index of the next code word in the bitstream on success; returns - * negative in case of erroneous input; returns CMP_ERROR_SMALL_BUF if the - * bitstream buffer is too small to read the value from the bitstream - * - */ - -static int decode_none(uint32_t *decoded_value, int stream_pos, - const struct decoder_setup *setup) -{ - stream_pos = get_n_bits32(decoded_value, setup->encoder_par1, stream_pos, - setup->bitstream_adr, setup->max_stream_len); - - return stream_pos; -} - - -/** - * @brief remap an unsigned value back to a signed value - * @note this is the reverse function of map_to_pos() - * - * @param value_to_unmap unsigned value to remap - * - * @returns the signed remapped value - */ - -static uint32_t re_map_to_pos(uint32_t value_to_unmap) -{ - if (value_to_unmap & 0x1) { /* if uneven */ - if (value_to_unmap == 0xFFFFFFFF) /* catch overflow */ - return 0x80000000; - return -((value_to_unmap + 1) / 2); - } else { - return value_to_unmap / 2; - } -} - - -/** - * @brief decompress the next code word in the bitstream and decorate it with - * the model - * - * @param decoded_value pointer to the decoded value - * @param model model of the decoded_value (0 if not used) - * @param stream_pos start bit position code word to be decoded in the bitstream - * @param setup pointer to the decoder setup - * - * @returns bit index of the next code word in the bitstream on success; returns - * negative in case of erroneous input; returns CMP_ERROR_SMALL_BUF if the - * bitstream buffer is too small to read the value from the bitstream - */ - -static int decode_value(uint32_t *decoded_value, uint32_t model, - int stream_pos, const struct decoder_setup *setup) -{ - uint32_t mask = (~0U >> (32 - setup->max_data_bits)); /* mask the used bits */ - - /* decode the next value from the bitstream */ - stream_pos = setup->decode_method_f(decoded_value, stream_pos, setup); - if (stream_pos <= 0) - return stream_pos; - - if (setup->decode_method_f == decode_none) - /* we are done here in stuff mode */ - return stream_pos; - - /* map the unsigned decode value back to a signed value */ - *decoded_value = re_map_to_pos(*decoded_value); - - /* decorate data the data with the model */ - *decoded_value += round_fwd(model, setup->lossy_par); - - /* we mask only the used bits in case there is an overflow when adding the model */ - *decoded_value &= mask; - - /* inverse step of the lossy compression */ - *decoded_value = round_inv(*decoded_value, setup->lossy_par); - - return stream_pos; -} - - -/** - * @brief configure a decoder setup structure to have a setup to decode a vale - * - * @param setup pointer to the decoder setup - * @param cmp_par compression parameter - * @param spillover spillover_par parameter - * @param lossy_par lossy compression parameter - * @param max_data_bits how many bits are needed to represent the highest possible value - * @param cfg pointer to the compression configuration structure - * - * @returns 0 on success; otherwise error - */ - -static int configure_decoder_setup(struct decoder_setup *setup, - uint32_t cmp_par, uint32_t spillover, - uint32_t lossy_par, uint32_t max_data_bits, - const struct cmp_cfg *cfg) -{ - if (multi_escape_mech_is_used(cfg->cmp_mode)) - setup->decode_method_f = &decode_multi; - else if (zero_escape_mech_is_used(cfg->cmp_mode)) - setup->decode_method_f = &decode_zero; - else if (cfg->cmp_mode == CMP_MODE_STUFF) - setup->decode_method_f = &decode_none; - else { - setup->decode_method_f = NULL; - debug_print("Error: Compression mode not supported.\n"); - return -1; - } - - setup->bitstream_adr = cfg->icu_output_buf; /* start address of the compressed data bitstream */ - if (cfg->buffer_length & 0x3) { - debug_print("Error: The length of the compressed data is not a multiple of 4 bytes."); - return -1; - } - setup->max_stream_len = (cfg->buffer_length) * CHAR_BIT; /* maximum length of the bitstream/icu_output_buf in bits */ - setup->encoder_par1 = cmp_par; /* encoding parameter 1 */ - if (ilog_2(cmp_par) < 0) - return -1; - setup->encoder_par2 = ilog_2(cmp_par); /* encoding parameter 2 */ - setup->outlier_par = spillover; /* outlier parameter */ - setup->lossy_par = lossy_par; /* lossy compression parameter */ - setup->model_value = cfg->model_value; /* model value parameter */ - setup->max_data_bits = max_data_bits; /* how many bits are needed to represent the highest possible value */ - setup->decode_cw_f = select_decoder(cmp_par); - - return 0; -} - - -/** - * @brief decompress imagette data - * - * @param cfg pointer to the compression configuration structure - * - * @returns bit position of the last read bit in the bitstream on success; - * returns negative on error, returns CMP_ERROR_SMALL_BUF if the bitstream - * buffer is too small to read the value from the bitstream - */ - -static int decompress_imagette(struct cmp_cfg *cfg) -{ - int err; - size_t i; - int stream_pos = 0; - struct decoder_setup setup; - uint16_t *decompressed_data = cfg->input_buf; - uint16_t *model_buf = cfg->model_buf; - uint16_t *up_model_buf = cfg->icu_new_model_buf; - uint32_t decoded_value = 0; - uint16_t model; - - err = configure_decoder_setup(&setup, cfg->golomb_par, cfg->spill, - cfg->round, cfg->max_used_bits->nc_imagette, cfg); - if (err) - return -1; - - - for (i = 0; i < cfg->samples; i++) { - if (model_mode_is_used(cfg->cmp_mode)) - model = model_buf[i]; - else - model = decoded_value; - - stream_pos = decode_value(&decoded_value, model, stream_pos, &setup); - if (stream_pos <= 0) - return stream_pos; - decompressed_data[i] = decoded_value; - - if (up_model_buf) { - up_model_buf[i] = cmp_up_model(decoded_value, model, - cfg->model_value, setup.lossy_par); - } - } - - return stream_pos; -} - - -/** - * @brief decompress the multi-entry packet header structure and sets the data, - * model and up_model pointers to the data after the header - * - * @param data pointer to a pointer pointing to the data to be compressed - * @param model pointer to a pointer pointing to the model of the data - * @param up_model pointer to a pointer pointing to the updated model buffer - * @param cfg pointer to the compression configuration structure - * - * @returns the bit length of the bitstream on success - * - * @note the (void **) cast relies on all pointer types having the same internal - * representation which is common, but not universal; http://www.c-faq.com/ptrs/genericpp.html - */ - -static int decompress_multi_entry_hdr(void **data, void **model, void **up_model, - const struct cmp_cfg *cfg) -{ - if (cfg->buffer_length < MULTI_ENTRY_HDR_SIZE) - return -1; - - if (*data) { - if (cfg->icu_output_buf) - memcpy(*data, cfg->icu_output_buf, MULTI_ENTRY_HDR_SIZE); - *data = (uint8_t *)*data + MULTI_ENTRY_HDR_SIZE; - } - - if (*model) { - if (cfg->icu_output_buf) - memcpy(*model, cfg->icu_output_buf, MULTI_ENTRY_HDR_SIZE); - *model = (uint8_t *)*model + MULTI_ENTRY_HDR_SIZE; - } - - if (*up_model) { - if (cfg->icu_output_buf) - memcpy(*up_model, cfg->icu_output_buf, MULTI_ENTRY_HDR_SIZE); - *up_model = (uint8_t *)*up_model + MULTI_ENTRY_HDR_SIZE; - } - - return MULTI_ENTRY_HDR_SIZE * CHAR_BIT; -} - - -/** - * @brief decompress short normal light flux (S_FX) data - * - * @param cfg pointer to the compression configuration structure - * - * @returns bit position of the last read bit in the bitstream on success; - * returns negative on error, returns CMP_ERROR_SMALL_BUF if the bitstream - * buffer is too small to read the value from the bitstream - */ - -static int decompress_s_fx(const struct cmp_cfg *cfg) -{ - size_t i; - int stream_pos = 0; - uint32_t decoded_value; - struct decoder_setup setup_exp_flags, setup_fx; - struct s_fx *data_buf = cfg->input_buf; - struct s_fx *model_buf = cfg->model_buf; - struct s_fx *up_model_buf = NULL; - struct s_fx *next_model_p; - struct s_fx model; - - if (model_mode_is_used(cfg->cmp_mode)) - up_model_buf = cfg->icu_new_model_buf; - - stream_pos = decompress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf, - (void **)&up_model_buf, cfg); - - if (model_mode_is_used(cfg->cmp_mode)) { - model = model_buf[0]; - next_model_p = &model_buf[1]; - } else { - memset(&model, 0, sizeof(model)); - next_model_p = data_buf; - } - - if (configure_decoder_setup(&setup_exp_flags, cfg->cmp_par_exp_flags, cfg->spill_exp_flags, - cfg->round, cfg->max_used_bits->s_exp_flags, cfg)) - return -1; - if (configure_decoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, - cfg->round, cfg->max_used_bits->s_fx, cfg)) - return -1; - - for (i = 0; ; i++) { - stream_pos = decode_value(&decoded_value, model.exp_flags, - stream_pos, &setup_exp_flags); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].exp_flags = decoded_value; - - stream_pos = decode_value(&decoded_value, model.fx, stream_pos, - &setup_fx); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].fx = decoded_value; - - if (up_model_buf) { - up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags, - cfg->model_value, setup_exp_flags.lossy_par); - up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx, - cfg->model_value, setup_fx.lossy_par); - } - - if (i >= cfg->samples-1) - break; - - model = next_model_p[i]; - } - return stream_pos; -} - - -/** - * @brief decompress S_FX_EFX data - * - * @param cfg pointer to the compression configuration structure - * - * @returns bit position of the last read bit in the bitstream on success; - * returns negative on error, returns CMP_ERROR_SMALL_BUF if the bitstream - * buffer is too small to read the value from the bitstream - */ - -static int decompress_s_fx_efx(const struct cmp_cfg *cfg) -{ - size_t i; - int stream_pos = 0; - uint32_t decoded_value; - struct decoder_setup setup_exp_flags, setup_fx, setup_efx; - struct s_fx_efx *data_buf = cfg->input_buf; - struct s_fx_efx *model_buf = cfg->model_buf; - struct s_fx_efx *up_model_buf = NULL; - struct s_fx_efx *next_model_p; - struct s_fx_efx model; - - if (model_mode_is_used(cfg->cmp_mode)) - up_model_buf = cfg->icu_new_model_buf; - - stream_pos = decompress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf, - (void **)&up_model_buf, cfg); - - if (model_mode_is_used(cfg->cmp_mode)) { - model = model_buf[0]; - next_model_p = &model_buf[1]; - } else { - memset(&model, 0, sizeof(model)); - next_model_p = data_buf; - } - - if (configure_decoder_setup(&setup_exp_flags, cfg->cmp_par_exp_flags, cfg->spill_exp_flags, - cfg->round, cfg->max_used_bits->s_exp_flags, cfg)) - return -1; - if (configure_decoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, - cfg->round, cfg->max_used_bits->s_fx, cfg)) - return -1; - if (configure_decoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx, - cfg->round, cfg->max_used_bits->s_efx, cfg)) - return -1; - - for (i = 0; ; i++) { - stream_pos = decode_value(&decoded_value, model.exp_flags, - stream_pos, &setup_exp_flags); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].exp_flags = decoded_value; - - stream_pos = decode_value(&decoded_value, model.fx, stream_pos, - &setup_fx); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].fx = decoded_value; - - stream_pos = decode_value(&decoded_value, model.efx, stream_pos, - &setup_efx); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].efx = decoded_value; - - if (up_model_buf) { - up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags, - cfg->model_value, setup_exp_flags.lossy_par); - up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx, - cfg->model_value, setup_fx.lossy_par); - up_model_buf[i].efx = cmp_up_model(data_buf[i].efx, model.efx, - cfg->model_value, setup_efx.lossy_par); - } - - if (i >= cfg->samples-1) - break; - - model = next_model_p[i]; - } - return stream_pos; -} - - -/** - * @brief decompress short S_FX_NCOB data - * - * @param cfg pointer to the compression configuration structure - * - * @returns bit position of the last read bit in the bitstream on success; - * returns negative on error, returns CMP_ERROR_SMALL_BUF if the bitstream - * buffer is too small to read the value from the bitstream - */ - -static int decompress_s_fx_ncob(const struct cmp_cfg *cfg) -{ - size_t i; - int stream_pos = 0; - uint32_t decoded_value; - struct decoder_setup setup_exp_flags, setup_fx, setup_ncob; - struct s_fx_ncob *data_buf = cfg->input_buf; - struct s_fx_ncob *model_buf = cfg->model_buf; - struct s_fx_ncob *up_model_buf = NULL; - struct s_fx_ncob *next_model_p; - struct s_fx_ncob model; - - if (model_mode_is_used(cfg->cmp_mode)) - up_model_buf = cfg->icu_new_model_buf; - - stream_pos = decompress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf, - (void **)&up_model_buf, cfg); - - if (model_mode_is_used(cfg->cmp_mode)) { - model = model_buf[0]; - next_model_p = &model_buf[1]; - } else { - memset(&model, 0, sizeof(model)); - next_model_p = data_buf; - } - - if (configure_decoder_setup(&setup_exp_flags, cfg->cmp_par_exp_flags, cfg->spill_exp_flags, - cfg->round, cfg->max_used_bits->s_exp_flags, cfg)) - return -1; - if (configure_decoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, - cfg->round, cfg->max_used_bits->s_fx, cfg)) - return -1; - if (configure_decoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob, - cfg->round, cfg->max_used_bits->s_ncob, cfg)) - return -1; - - for (i = 0; ; i++) { - stream_pos = decode_value(&decoded_value, model.exp_flags, - stream_pos, &setup_exp_flags); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].exp_flags = decoded_value; - - stream_pos = decode_value(&decoded_value, model.fx, stream_pos, - &setup_fx); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].fx = decoded_value; - - stream_pos = decode_value(&decoded_value, model.ncob_x, stream_pos, - &setup_ncob); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].ncob_x = decoded_value; - - stream_pos = decode_value(&decoded_value, model.ncob_y, stream_pos, - &setup_ncob); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].ncob_y = decoded_value; - - if (up_model_buf) { - up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags, - cfg->model_value, setup_exp_flags.lossy_par); - up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx, - cfg->model_value, setup_fx.lossy_par); - up_model_buf[i].ncob_x = cmp_up_model(data_buf[i].ncob_x, model.ncob_x, - cfg->model_value, setup_ncob.lossy_par); - up_model_buf[i].ncob_y = cmp_up_model(data_buf[i].ncob_y, model.ncob_y, - cfg->model_value, setup_ncob.lossy_par); - } - - if (i >= cfg->samples-1) - break; - - model = next_model_p[i]; - } - return stream_pos; -} - - -/** - * @brief decompress short S_FX_NCOB_ECOB data - * - * @param cfg pointer to the compression configuration structure - * - * @returns bit position of the last read bit in the bitstream on success; - * returns negative on error, returns CMP_ERROR_SMALL_BUF if the bitstream - * buffer is too small to read the value from the bitstream - */ - -static int decompress_s_fx_efx_ncob_ecob(const struct cmp_cfg *cfg) -{ - size_t i; - int stream_pos = 0; - uint32_t decoded_value; - struct decoder_setup setup_exp_flags, setup_fx, setup_ncob, setup_efx, setup_ecob; - struct s_fx_efx_ncob_ecob *data_buf = cfg->input_buf; - struct s_fx_efx_ncob_ecob *model_buf = cfg->model_buf; - struct s_fx_efx_ncob_ecob *up_model_buf = NULL; - struct s_fx_efx_ncob_ecob *next_model_p; - struct s_fx_efx_ncob_ecob model; - - if (model_mode_is_used(cfg->cmp_mode)) - up_model_buf = cfg->icu_new_model_buf; - - stream_pos = decompress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf, - (void **)&up_model_buf, cfg); - - if (model_mode_is_used(cfg->cmp_mode)) { - model = model_buf[0]; - next_model_p = &model_buf[1]; - } else { - memset(&model, 0, sizeof(model)); - next_model_p = data_buf; - } - - if (configure_decoder_setup(&setup_exp_flags, cfg->cmp_par_exp_flags, cfg->spill_exp_flags, - cfg->round, cfg->max_used_bits->s_exp_flags, cfg)) - return -1; - if (configure_decoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, - cfg->round, cfg->max_used_bits->s_fx, cfg)) - return -1; - if (configure_decoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob, - cfg->round, cfg->max_used_bits->s_ncob, cfg)) - return -1; - if (configure_decoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx, - cfg->round, cfg->max_used_bits->s_efx, cfg)) - return -1; - if (configure_decoder_setup(&setup_ecob, cfg->cmp_par_ecob, cfg->spill_ecob, - cfg->round, cfg->max_used_bits->s_ecob, cfg)) - return -1; - - for (i = 0; ; i++) { - stream_pos = decode_value(&decoded_value, model.exp_flags, - stream_pos, &setup_exp_flags); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].exp_flags = decoded_value; - - stream_pos = decode_value(&decoded_value, model.fx, stream_pos, - &setup_fx); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].fx = decoded_value; - - stream_pos = decode_value(&decoded_value, model.ncob_x, stream_pos, - &setup_ncob); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].ncob_x = decoded_value; - - stream_pos = decode_value(&decoded_value, model.ncob_y, stream_pos, - &setup_ncob); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].ncob_y = decoded_value; - - stream_pos = decode_value(&decoded_value, model.efx, stream_pos, - &setup_efx); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].efx = decoded_value; - - stream_pos = decode_value(&decoded_value, model.ecob_x, stream_pos, - &setup_ecob); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].ecob_x = decoded_value; - - stream_pos = decode_value(&decoded_value, model.ecob_y, stream_pos, - &setup_ecob); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].ecob_y = decoded_value; - - if (up_model_buf) { - up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags, - cfg->model_value, setup_exp_flags.lossy_par); - up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx, - cfg->model_value, setup_fx.lossy_par); - up_model_buf[i].ncob_x = cmp_up_model(data_buf[i].ncob_x, model.ncob_x, - cfg->model_value, setup_ncob.lossy_par); - up_model_buf[i].ncob_y = cmp_up_model(data_buf[i].ncob_y, model.ncob_y, - cfg->model_value, setup_ncob.lossy_par); - up_model_buf[i].efx = cmp_up_model(data_buf[i].efx, model.efx, - cfg->model_value, setup_efx.lossy_par); - up_model_buf[i].ecob_x = cmp_up_model(data_buf[i].ecob_x, model.ecob_x, - cfg->model_value, setup_ecob.lossy_par); - up_model_buf[i].ecob_y = cmp_up_model(data_buf[i].ecob_y, model.ecob_y, - cfg->model_value, setup_ecob.lossy_par); - } - - if (i >= cfg->samples-1) - break; - - model = next_model_p[i]; - } - return stream_pos; -} - - -/** - * @brief decompress fast normal light flux (F_FX) data - * - * @param cfg pointer to the compression configuration structure - * - * @returns bit position of the last read bit in the bitstream on success; - * returns negative on error, returns CMP_ERROR_SMALL_BUF if the bitstream - * buffer is too small to read the value from the bitstream - */ - -static int decompress_f_fx(const struct cmp_cfg *cfg) -{ - size_t i; - int stream_pos = 0; - uint32_t decoded_value; - struct decoder_setup setup_fx; - struct f_fx *data_buf = cfg->input_buf; - struct f_fx *model_buf = cfg->model_buf; - struct f_fx *up_model_buf = NULL; - struct f_fx *next_model_p; - struct f_fx model; - - if (model_mode_is_used(cfg->cmp_mode)) - up_model_buf = cfg->icu_new_model_buf; - - stream_pos = decompress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf, - (void **)&up_model_buf, cfg); - - if (model_mode_is_used(cfg->cmp_mode)) { - model = model_buf[0]; - next_model_p = &model_buf[1]; - } else { - memset(&model, 0, sizeof(model)); - next_model_p = data_buf; - } - - if (configure_decoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, - cfg->round, cfg->max_used_bits->f_fx, cfg)) - return -1; - - for (i = 0; ; i++) { - stream_pos = decode_value(&decoded_value, model.fx, stream_pos, - &setup_fx); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].fx = decoded_value; - - if (up_model_buf) - up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx, - cfg->model_value, setup_fx.lossy_par); - - if (i >= cfg->samples-1) - break; - - model = next_model_p[i]; - } - return stream_pos; -} - - -/** - * @brief decompress F_FX_EFX data - * - * @param cfg pointer to the compression configuration structure - * - * @returns bit position of the last read bit in the bitstream on success; - * returns negative on error, returns CMP_ERROR_SMALL_BUF if the bitstream - * buffer is too small to read the value from the bitstream - */ - -static int decompress_f_fx_efx(const struct cmp_cfg *cfg) -{ - size_t i; - int stream_pos = 0; - uint32_t decoded_value; - struct decoder_setup setup_fx, setup_efx; - struct f_fx_efx *data_buf = cfg->input_buf; - struct f_fx_efx *model_buf = cfg->model_buf; - struct f_fx_efx *up_model_buf = NULL; - struct f_fx_efx *next_model_p; - struct f_fx_efx model; - - if (model_mode_is_used(cfg->cmp_mode)) - up_model_buf = cfg->icu_new_model_buf; - - stream_pos = decompress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf, - (void **)&up_model_buf, cfg); - - if (model_mode_is_used(cfg->cmp_mode)) { - model = model_buf[0]; - next_model_p = &model_buf[1]; - } else { - memset(&model, 0, sizeof(model)); - next_model_p = data_buf; - } - - if (configure_decoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, - cfg->round, cfg->max_used_bits->f_fx, cfg)) - return -1; - if (configure_decoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx, - cfg->round, cfg->max_used_bits->f_efx, cfg)) - return -1; - - for (i = 0; ; i++) { - stream_pos = decode_value(&decoded_value, model.fx, stream_pos, - &setup_fx); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].fx = decoded_value; - - stream_pos = decode_value(&decoded_value, model.efx, stream_pos, - &setup_efx); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].efx = decoded_value; - - if (up_model_buf) { - up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx, - cfg->model_value, setup_fx.lossy_par); - up_model_buf[i].efx = cmp_up_model(data_buf[i].efx, model.efx, - cfg->model_value, setup_efx.lossy_par); - } - - if (i >= cfg->samples-1) - break; - - model = next_model_p[i]; - } - return stream_pos; -} - - -/** - * @brief decompress short F_FX_NCOB data - * - * @param cfg pointer to the compression configuration structure - * - * @returns bit position of the last read bit in the bitstream on success; - * returns negative on error, returns CMP_ERROR_SMALL_BUF if the bitstream - * buffer is too small to read the value from the bitstream - */ - -static int decompress_f_fx_ncob(const struct cmp_cfg *cfg) -{ - size_t i; - int stream_pos = 0; - uint32_t decoded_value; - struct decoder_setup setup_fx, setup_ncob; - struct f_fx_ncob *data_buf = cfg->input_buf; - struct f_fx_ncob *model_buf = cfg->model_buf; - struct f_fx_ncob *up_model_buf = NULL; - struct f_fx_ncob *next_model_p; - struct f_fx_ncob model; - - if (model_mode_is_used(cfg->cmp_mode)) - up_model_buf = cfg->icu_new_model_buf; - - stream_pos = decompress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf, - (void **)&up_model_buf, cfg); - - if (model_mode_is_used(cfg->cmp_mode)) { - model = model_buf[0]; - next_model_p = &model_buf[1]; - } else { - memset(&model, 0, sizeof(model)); - next_model_p = data_buf; - } - - if (configure_decoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, - cfg->round, cfg->max_used_bits->f_fx, cfg)) - return -1; - if (configure_decoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob, - cfg->round, cfg->max_used_bits->f_ncob, cfg)) - return -1; - - for (i = 0; ; i++) { - stream_pos = decode_value(&decoded_value, model.fx, stream_pos, - &setup_fx); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].fx = decoded_value; - - stream_pos = decode_value(&decoded_value, model.ncob_x, stream_pos, - &setup_ncob); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].ncob_x = decoded_value; - - stream_pos = decode_value(&decoded_value, model.ncob_y, stream_pos, - &setup_ncob); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].ncob_y = decoded_value; - - if (up_model_buf) { - up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx, - cfg->model_value, setup_fx.lossy_par); - up_model_buf[i].ncob_x = cmp_up_model(data_buf[i].ncob_x, model.ncob_x, - cfg->model_value, setup_ncob.lossy_par); - up_model_buf[i].ncob_y = cmp_up_model(data_buf[i].ncob_y, model.ncob_y, - cfg->model_value, setup_ncob.lossy_par); - } - - if (i >= cfg->samples-1) - break; - - model = next_model_p[i]; - } - return stream_pos; -} - - -/** - * @brief decompress short F_FX_NCOB_ECOB data - * - * @param cfg pointer to the compression configuration structure - * - * @returns bit position of the last read bit in the bitstream on success; - * returns negative on error, returns CMP_ERROR_SMALL_BUF if the bitstream - * buffer is too small to read the value from the bitstream - */ - -static int decompress_f_fx_efx_ncob_ecob(const struct cmp_cfg *cfg) -{ - size_t i; - int stream_pos = 0; - uint32_t decoded_value; - struct decoder_setup setup_fx, setup_ncob, setup_efx, setup_ecob; - struct f_fx_efx_ncob_ecob *data_buf = cfg->input_buf; - struct f_fx_efx_ncob_ecob *model_buf = cfg->model_buf; - struct f_fx_efx_ncob_ecob *up_model_buf = NULL; - struct f_fx_efx_ncob_ecob *next_model_p; - struct f_fx_efx_ncob_ecob model; - - if (model_mode_is_used(cfg->cmp_mode)) - up_model_buf = cfg->icu_new_model_buf; - - stream_pos = decompress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf, - (void **)&up_model_buf, cfg); - - if (model_mode_is_used(cfg->cmp_mode)) { - model = model_buf[0]; - next_model_p = &model_buf[1]; - } else { - memset(&model, 0, sizeof(model)); - next_model_p = data_buf; - } - - if (configure_decoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, - cfg->round, cfg->max_used_bits->f_fx, cfg)) - return -1; - if (configure_decoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob, - cfg->round, cfg->max_used_bits->f_ncob, cfg)) - return -1; - if (configure_decoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx, - cfg->round, cfg->max_used_bits->f_efx, cfg)) - return -1; - if (configure_decoder_setup(&setup_ecob, cfg->cmp_par_ecob, cfg->spill_ecob, - cfg->round, cfg->max_used_bits->f_ecob, cfg)) - return -1; - - for (i = 0; ; i++) { - stream_pos = decode_value(&decoded_value, model.fx, stream_pos, - &setup_fx); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].fx = decoded_value; - - stream_pos = decode_value(&decoded_value, model.ncob_x, stream_pos, - &setup_ncob); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].ncob_x = decoded_value; - - stream_pos = decode_value(&decoded_value, model.ncob_y, stream_pos, - &setup_ncob); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].ncob_y = decoded_value; - - stream_pos = decode_value(&decoded_value, model.efx, stream_pos, - &setup_efx); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].efx = decoded_value; - - stream_pos = decode_value(&decoded_value, model.ecob_x, stream_pos, - &setup_ecob); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].ecob_x = decoded_value; - - stream_pos = decode_value(&decoded_value, model.ecob_y, stream_pos, - &setup_ecob); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].ecob_y = decoded_value; - - if (up_model_buf) { - up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx, - cfg->model_value, setup_fx.lossy_par); - up_model_buf[i].ncob_x = cmp_up_model(data_buf[i].ncob_x, model.ncob_x, - cfg->model_value, setup_ncob.lossy_par); - up_model_buf[i].ncob_y = cmp_up_model(data_buf[i].ncob_y, model.ncob_y, - cfg->model_value, setup_ncob.lossy_par); - up_model_buf[i].efx = cmp_up_model(data_buf[i].efx, model.efx, - cfg->model_value, setup_efx.lossy_par); - up_model_buf[i].ecob_x = cmp_up_model(data_buf[i].ecob_x, model.ecob_x, - cfg->model_value, setup_ecob.lossy_par); - up_model_buf[i].ecob_y = cmp_up_model(data_buf[i].ecob_y, model.ecob_y, - cfg->model_value, setup_ecob.lossy_par); - } - - if (i >= cfg->samples-1) - break; - - model = next_model_p[i]; - } - return stream_pos; -} - - -/** - * @brief decompress long normal light flux (L_FX) data - * - * @param cfg pointer to the compression configuration structure - * - * @returns bit position of the last read bit in the bitstream on success; - * returns negative on error, returns CMP_ERROR_SMALL_BUF if the bitstream - * buffer is too small to read the value from the bitstream - */ - -static int decompress_l_fx(const struct cmp_cfg *cfg) -{ - size_t i; - int stream_pos = 0; - uint32_t decoded_value; - struct decoder_setup setup_exp_flags, setup_fx, setup_fx_var; - struct l_fx *data_buf = cfg->input_buf; - struct l_fx *model_buf = cfg->model_buf; - struct l_fx *up_model_buf = NULL; - struct l_fx *next_model_p; - struct l_fx model; - - if (model_mode_is_used(cfg->cmp_mode)) - up_model_buf = cfg->icu_new_model_buf; - - stream_pos = decompress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf, - (void **)&up_model_buf, cfg); - - if (model_mode_is_used(cfg->cmp_mode)) { - model = model_buf[0]; - next_model_p = &model_buf[1]; - } else { - memset(&model, 0, sizeof(model)); - next_model_p = data_buf; - } - - if (configure_decoder_setup(&setup_exp_flags, cfg->cmp_par_exp_flags, cfg->spill_exp_flags, - cfg->round, cfg->max_used_bits->l_exp_flags, cfg)) - return -1; - if (configure_decoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, - cfg->round, cfg->max_used_bits->l_fx, cfg)) - return -1; - if (configure_decoder_setup(&setup_fx_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance, - cfg->round, cfg->max_used_bits->l_fx_variance, cfg)) - return -1; - - for (i = 0; ; i++) { - stream_pos = decode_value(&decoded_value, model.exp_flags, - stream_pos, &setup_exp_flags); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].exp_flags = decoded_value; - - stream_pos = decode_value(&decoded_value, model.fx, stream_pos, - &setup_fx); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].fx = decoded_value; - - stream_pos = decode_value(&decoded_value, model.fx_variance, stream_pos, - &setup_fx_var); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].fx_variance = decoded_value; - - if (up_model_buf) { - up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags, - cfg->model_value, setup_exp_flags.lossy_par); - up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx, - cfg->model_value, setup_fx.lossy_par); - up_model_buf[i].fx_variance = cmp_up_model(data_buf[i].fx_variance, model.fx_variance, - cfg->model_value, setup_fx_var.lossy_par); - } - - if (i >= cfg->samples-1) - break; - - model = next_model_p[i]; - } - return stream_pos; -} - - -/** - * @brief decompress L_FX_EFX data - * - * @param cfg pointer to the compression configuration structure - * - * @returns bit position of the last read bit in the bitstream on success; - * returns negative on error, returns CMP_ERROR_SMALL_BUF if the bitstream - * buffer is too small to read the value from the bitstream - */ - -static int decompress_l_fx_efx(const struct cmp_cfg *cfg) -{ - size_t i; - int stream_pos = 0; - uint32_t decoded_value; - struct decoder_setup setup_exp_flags, setup_fx, setup_efx, setup_fx_var; - struct l_fx_efx *data_buf = cfg->input_buf; - struct l_fx_efx *model_buf = cfg->model_buf; - struct l_fx_efx *up_model_buf = NULL; - struct l_fx_efx *next_model_p; - struct l_fx_efx model; - - if (model_mode_is_used(cfg->cmp_mode)) - up_model_buf = cfg->icu_new_model_buf; - - stream_pos = decompress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf, - (void **)&up_model_buf, cfg); - - if (model_mode_is_used(cfg->cmp_mode)) { - model = model_buf[0]; - next_model_p = &model_buf[1]; - } else { - memset(&model, 0, sizeof(model)); - next_model_p = data_buf; - } - - if (configure_decoder_setup(&setup_exp_flags, cfg->cmp_par_exp_flags, cfg->spill_exp_flags, - cfg->round, cfg->max_used_bits->l_exp_flags, cfg)) - return -1; - if (configure_decoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, - cfg->round, cfg->max_used_bits->l_fx, cfg)) - return -1; - if (configure_decoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx, - cfg->round, cfg->max_used_bits->l_efx, cfg)) - return -1; - if (configure_decoder_setup(&setup_fx_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance, - cfg->round, cfg->max_used_bits->l_fx_variance, cfg)) - return -1; - - for (i = 0; ; i++) { - stream_pos = decode_value(&decoded_value, model.exp_flags, - stream_pos, &setup_exp_flags); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].exp_flags = decoded_value; - - stream_pos = decode_value(&decoded_value, model.fx, stream_pos, - &setup_fx); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].fx = decoded_value; - - stream_pos = decode_value(&decoded_value, model.efx, stream_pos, - &setup_efx); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].efx = decoded_value; - - stream_pos = decode_value(&decoded_value, model.fx_variance, stream_pos, - &setup_fx_var); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].fx_variance = decoded_value; - - if (up_model_buf) { - up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags, - cfg->model_value, setup_exp_flags.lossy_par); - up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx, - cfg->model_value, setup_fx.lossy_par); - up_model_buf[i].efx = cmp_up_model(data_buf[i].efx, model.efx, - cfg->model_value, setup_efx.lossy_par); - up_model_buf[i].fx_variance = cmp_up_model(data_buf[i].fx_variance, model.fx_variance, - cfg->model_value, setup_fx_var.lossy_par); - } - - if (i >= cfg->samples-1) - break; - - model = next_model_p[i]; - } - return stream_pos; -} - - -/** - * @brief decompress L_FX_NCOB data - * - * @param cfg pointer to the compression configuration structure - * - * @returns bit position of the last read bit in the bitstream on success; - * returns negative on error, returns CMP_ERROR_SMALL_BUF if the bitstream - * buffer is too small to read the value from the bitstream - */ - -static int decompress_l_fx_ncob(const struct cmp_cfg *cfg) -{ - size_t i; - int stream_pos = 0; - uint32_t decoded_value; - struct decoder_setup setup_exp_flags, setup_fx, setup_ncob, - setup_fx_var, setup_cob_var; - struct l_fx_ncob *data_buf = cfg->input_buf; - struct l_fx_ncob *model_buf = cfg->model_buf; - struct l_fx_ncob *up_model_buf = NULL; - struct l_fx_ncob *next_model_p; - struct l_fx_ncob model; - - if (model_mode_is_used(cfg->cmp_mode)) - up_model_buf = cfg->icu_new_model_buf; - - stream_pos = decompress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf, - (void **)&up_model_buf, cfg); - - if (model_mode_is_used(cfg->cmp_mode)) { - model = model_buf[0]; - next_model_p = &model_buf[1]; - } else { - memset(&model, 0, sizeof(model)); - next_model_p = data_buf; - } - - if (configure_decoder_setup(&setup_exp_flags, cfg->cmp_par_exp_flags, cfg->spill_exp_flags, - cfg->round, cfg->max_used_bits->l_exp_flags, cfg)) - return -1; - if (configure_decoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, - cfg->round, cfg->max_used_bits->l_fx, cfg)) - return -1; - if (configure_decoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob, - cfg->round, cfg->max_used_bits->l_ncob, cfg)) - return -1; - if (configure_decoder_setup(&setup_fx_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance, - cfg->round, cfg->max_used_bits->l_fx_variance, cfg)) - return -1; - if (configure_decoder_setup(&setup_cob_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance, - cfg->round, cfg->max_used_bits->l_cob_variance, cfg)) - return -1; - - for (i = 0; ; i++) { - stream_pos = decode_value(&decoded_value, model.exp_flags, - stream_pos, &setup_exp_flags); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].exp_flags = decoded_value; - - stream_pos = decode_value(&decoded_value, model.fx, stream_pos, - &setup_fx); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].fx = decoded_value; - - stream_pos = decode_value(&decoded_value, model.ncob_x, - stream_pos, &setup_ncob); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].ncob_x = decoded_value; - - stream_pos = decode_value(&decoded_value, model.ncob_y, - stream_pos, &setup_ncob); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].ncob_y = decoded_value; - - stream_pos = decode_value(&decoded_value, model.fx_variance, - stream_pos, &setup_fx_var); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].fx_variance = decoded_value; - - stream_pos = decode_value(&decoded_value, model.cob_x_variance, - stream_pos, &setup_cob_var); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].cob_x_variance = decoded_value; - - stream_pos = decode_value(&decoded_value, model.cob_y_variance, - stream_pos, &setup_cob_var); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].cob_y_variance = decoded_value; - - if (up_model_buf) { - up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags, - cfg->model_value, setup_exp_flags.lossy_par); - up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx, - cfg->model_value, setup_fx.lossy_par); - up_model_buf[i].ncob_x = cmp_up_model(data_buf[i].ncob_x, model.ncob_x, - cfg->model_value, setup_ncob.lossy_par); - up_model_buf[i].ncob_y = cmp_up_model(data_buf[i].ncob_y, model.ncob_y, - cfg->model_value, setup_ncob.lossy_par); - up_model_buf[i].fx_variance = cmp_up_model(data_buf[i].fx_variance, model.fx_variance, - cfg->model_value, setup_fx_var.lossy_par); - up_model_buf[i].cob_x_variance = cmp_up_model(data_buf[i].cob_x_variance, model.cob_x_variance, - cfg->model_value, setup_cob_var.lossy_par); - up_model_buf[i].cob_y_variance = cmp_up_model(data_buf[i].cob_y_variance, model.cob_y_variance, - cfg->model_value, setup_cob_var.lossy_par); - } - - if (i >= cfg->samples-1) - break; - - model = next_model_p[i]; - } - return stream_pos; -} - - -/** - * @brief decompress L_FX_EFX_NCOB_ECOB data - * - * @param cfg pointer to the compression configuration structure - * - * @returns bit position of the last read bit in the bitstream on success; - * returns negative on error, returns CMP_ERROR_SMALL_BUF if the bitstream - * buffer is too small to read the value from the bitstream - */ - -static int decompress_l_fx_efx_ncob_ecob(const struct cmp_cfg *cfg) -{ - size_t i; - int stream_pos = 0; - uint32_t decoded_value; - struct decoder_setup setup_exp_flags, setup_fx, setup_ncob, setup_efx, - setup_ecob, setup_fx_var, setup_cob_var; - struct l_fx_efx_ncob_ecob *data_buf = cfg->input_buf; - struct l_fx_efx_ncob_ecob *model_buf = cfg->model_buf; - struct l_fx_efx_ncob_ecob *up_model_buf = NULL; - struct l_fx_efx_ncob_ecob *next_model_p; - struct l_fx_efx_ncob_ecob model; - - if (model_mode_is_used(cfg->cmp_mode)) - up_model_buf = cfg->icu_new_model_buf; - - stream_pos = decompress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf, - (void **)&up_model_buf, cfg); - - if (model_mode_is_used(cfg->cmp_mode)) { - model = model_buf[0]; - next_model_p = &model_buf[1]; - } else { - memset(&model, 0, sizeof(model)); - next_model_p = data_buf; - } - - if (configure_decoder_setup(&setup_exp_flags, cfg->cmp_par_exp_flags, cfg->spill_exp_flags, - cfg->round, cfg->max_used_bits->l_exp_flags, cfg)) - return -1; - if (configure_decoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, - cfg->round, cfg->max_used_bits->l_fx, cfg)) - return -1; - if (configure_decoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob, - cfg->round, cfg->max_used_bits->l_ncob, cfg)) - return -1; - if (configure_decoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx, - cfg->round, cfg->max_used_bits->l_efx, cfg)) - return -1; - if (configure_decoder_setup(&setup_ecob, cfg->cmp_par_ecob, cfg->spill_ecob, - cfg->round, cfg->max_used_bits->l_ecob, cfg)) - return -1; - if (configure_decoder_setup(&setup_fx_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance, - cfg->round, cfg->max_used_bits->l_fx_variance, cfg)) - return -1; - if (configure_decoder_setup(&setup_cob_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance, - cfg->round, cfg->max_used_bits->l_cob_variance, cfg)) - return -1; - - for (i = 0; ; i++) { - stream_pos = decode_value(&decoded_value, model.exp_flags, - stream_pos, &setup_exp_flags); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].exp_flags = decoded_value; - - stream_pos = decode_value(&decoded_value, model.fx, stream_pos, - &setup_fx); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].fx = decoded_value; - - stream_pos = decode_value(&decoded_value, model.ncob_x, - stream_pos, &setup_ncob); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].ncob_x = decoded_value; - - stream_pos = decode_value(&decoded_value, model.ncob_y, - stream_pos, &setup_ncob); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].ncob_y = decoded_value; - - stream_pos = decode_value(&decoded_value, model.efx, stream_pos, - &setup_efx); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].efx = decoded_value; - - stream_pos = decode_value(&decoded_value, model.ecob_x, - stream_pos, &setup_ecob); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].ecob_x = decoded_value; - - stream_pos = decode_value(&decoded_value, model.ecob_y, - stream_pos, &setup_ecob); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].ecob_y = decoded_value; - - stream_pos = decode_value(&decoded_value, model.fx_variance, - stream_pos, &setup_fx_var); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].fx_variance = decoded_value; - - stream_pos = decode_value(&decoded_value, model.cob_x_variance, - stream_pos, &setup_cob_var); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].cob_x_variance = decoded_value; - - stream_pos = decode_value(&decoded_value, model.cob_y_variance, - stream_pos, &setup_cob_var); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].cob_y_variance = decoded_value; - - if (up_model_buf) { - up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags, - cfg->model_value, setup_exp_flags.lossy_par); - up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx, - cfg->model_value, setup_fx.lossy_par); - up_model_buf[i].ncob_x = cmp_up_model(data_buf[i].ncob_x, model.ncob_x, - cfg->model_value, setup_ncob.lossy_par); - up_model_buf[i].ncob_y = cmp_up_model(data_buf[i].ncob_y, model.ncob_y, - cfg->model_value, setup_ncob.lossy_par); - up_model_buf[i].efx = cmp_up_model(data_buf[i].efx, model.efx, - cfg->model_value, setup_efx.lossy_par); - up_model_buf[i].ecob_x = cmp_up_model(data_buf[i].ecob_x, model.ecob_x, - cfg->model_value, setup_ecob.lossy_par); - up_model_buf[i].ecob_y = cmp_up_model(data_buf[i].ecob_y, model.ecob_y, - cfg->model_value, setup_ecob.lossy_par); - up_model_buf[i].fx_variance = cmp_up_model(data_buf[i].fx_variance, model.fx_variance, - cfg->model_value, setup_fx_var.lossy_par); - up_model_buf[i].cob_x_variance = cmp_up_model(data_buf[i].cob_x_variance, model.cob_x_variance, - cfg->model_value, setup_cob_var.lossy_par); - up_model_buf[i].cob_y_variance = cmp_up_model(data_buf[i].cob_y_variance, model.cob_y_variance, - cfg->model_value, setup_cob_var.lossy_par); - } - - if (i >= cfg->samples-1) - break; - - model = next_model_p[i]; - } - return stream_pos; -} - - -/** - * @brief decompress N-CAM offset data - * - * @param cfg pointer to the compression configuration structure - * - * @returns bit position of the last read bit in the bitstream on success; - * returns negative on error, returns CMP_ERROR_SMALL_BUF if the bitstream - * buffer is too small to read the value from the bitstream - */ - -static int decompress_nc_offset(const struct cmp_cfg *cfg) -{ - size_t i; - int stream_pos = 0; - uint32_t decoded_value; - struct decoder_setup setup_mean, setup_var; - struct nc_offset *data_buf = cfg->input_buf; - struct nc_offset *model_buf = cfg->model_buf; - struct nc_offset *up_model_buf = NULL; - struct nc_offset *next_model_p; - struct nc_offset model; - - if (model_mode_is_used(cfg->cmp_mode)) - up_model_buf = cfg->icu_new_model_buf; - - stream_pos = decompress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf, - (void **)&up_model_buf, cfg); - - if (model_mode_is_used(cfg->cmp_mode)) { - model = model_buf[0]; - next_model_p = &model_buf[1]; - } else { - memset(&model, 0, sizeof(model)); - next_model_p = data_buf; - } - - if (configure_decoder_setup(&setup_mean, cfg->cmp_par_mean, cfg->spill_mean, - cfg->round, cfg->max_used_bits->nc_offset_mean, cfg)) - return -1; - if (configure_decoder_setup(&setup_var, cfg->cmp_par_variance, cfg->spill_variance, - cfg->round, cfg->max_used_bits->nc_offset_variance, cfg)) - return -1; - - for (i = 0; ; i++) { - stream_pos = decode_value(&decoded_value, model.mean, stream_pos, - &setup_mean); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].mean = decoded_value; - - stream_pos = decode_value(&decoded_value, model.variance, stream_pos, - &setup_var); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].variance = decoded_value; - - if (up_model_buf) { - up_model_buf[i].mean = cmp_up_model(data_buf[i].mean, - model.mean, cfg->model_value, setup_mean.lossy_par); - up_model_buf[i].variance = cmp_up_model(data_buf[i].variance, - model.variance, cfg->model_value, setup_var.lossy_par); - } - - if (i >= cfg->samples-1) - break; - - model = next_model_p[i]; - } - return stream_pos; -} - - -/** - * @brief decompress N-CAM background data - * - * @param cfg pointer to the compression configuration structure - * - * @returns bit position of the last read bit in the bitstream on success; - * returns negative on error, returns CMP_ERROR_SMALL_BUF if the bitstream - * buffer is too small to read the value from the bitstream - */ - -static int decompress_nc_background(const struct cmp_cfg *cfg) -{ - size_t i; - int stream_pos = 0; - uint32_t decoded_value; - struct decoder_setup setup_mean, setup_var, setup_pix; - struct nc_background *data_buf = cfg->input_buf; - struct nc_background *model_buf = cfg->model_buf; - struct nc_background *up_model_buf = NULL; - struct nc_background *next_model_p; - struct nc_background model; - - if (model_mode_is_used(cfg->cmp_mode)) - up_model_buf = cfg->icu_new_model_buf; - - stream_pos = decompress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf, - (void **)&up_model_buf, cfg); - - if (model_mode_is_used(cfg->cmp_mode)) { - model = model_buf[0]; - next_model_p = &model_buf[1]; - } else { - memset(&model, 0, sizeof(model)); - next_model_p = data_buf; - } - - if (configure_decoder_setup(&setup_mean, cfg->cmp_par_mean, cfg->spill_mean, - cfg->round, cfg->max_used_bits->nc_background_mean, cfg)) - return -1; - if (configure_decoder_setup(&setup_var, cfg->cmp_par_variance, cfg->spill_variance, - cfg->round, cfg->max_used_bits->nc_background_variance, cfg)) - return -1; - if (configure_decoder_setup(&setup_pix, cfg->cmp_par_pixels_error, cfg->spill_pixels_error, - cfg->round, cfg->max_used_bits->nc_background_outlier_pixels, cfg)) - return -1; - - for (i = 0; ; i++) { - stream_pos = decode_value(&decoded_value, model.mean, stream_pos, - &setup_mean); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].mean = decoded_value; - - stream_pos = decode_value(&decoded_value, model.variance, stream_pos, - &setup_var); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].variance = decoded_value; - - stream_pos = decode_value(&decoded_value, model.outlier_pixels, stream_pos, - &setup_pix); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].outlier_pixels = decoded_value; - - if (up_model_buf) { - up_model_buf[i].mean = cmp_up_model(data_buf[i].mean, - model.mean, cfg->model_value, setup_mean.lossy_par); - up_model_buf[i].variance = cmp_up_model(data_buf[i].variance, - model.variance, cfg->model_value, setup_var.lossy_par); - up_model_buf[i].outlier_pixels = cmp_up_model(data_buf[i].outlier_pixels, - model.outlier_pixels, cfg->model_value, setup_pix.lossy_par); - } - - if (i >= cfg->samples-1) - break; - - model = next_model_p[i]; - } - return stream_pos; -} - - -/** - * @brief decompress N-CAM smearing data - * - * @param cfg pointer to the compression configuration structure - * - * @returns bit position of the last read bit in the bitstream on success; - * returns negative on error, returns CMP_ERROR_SMALL_BUF if the bitstream - * buffer is too small to read the value from the bitstream - */ - -static int decompress_smearing(const struct cmp_cfg *cfg) -{ - size_t i; - int stream_pos = 0; - uint32_t decoded_value; - struct decoder_setup setup_mean, setup_var, setup_pix; - struct smearing *data_buf = cfg->input_buf; - struct smearing *model_buf = cfg->model_buf; - struct smearing *up_model_buf = NULL; - struct smearing *next_model_p; - struct smearing model; - - if (model_mode_is_used(cfg->cmp_mode)) - up_model_buf = cfg->icu_new_model_buf; - - stream_pos = decompress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf, - (void **)&up_model_buf, cfg); - - if (model_mode_is_used(cfg->cmp_mode)) { - model = model_buf[0]; - next_model_p = &model_buf[1]; - } else { - memset(&model, 0, sizeof(model)); - next_model_p = data_buf; - } - - if (configure_decoder_setup(&setup_mean, cfg->cmp_par_mean, cfg->spill_mean, - cfg->round, cfg->max_used_bits->smearing_mean, cfg)) - return -1; - if (configure_decoder_setup(&setup_var, cfg->cmp_par_variance, cfg->spill_variance, - cfg->round, cfg->max_used_bits->smearing_variance_mean, cfg)) - return -1; - if (configure_decoder_setup(&setup_pix, cfg->cmp_par_pixels_error, cfg->spill_pixels_error, - cfg->round, cfg->max_used_bits->smearing_outlier_pixels, cfg)) - return -1; - - for (i = 0; ; i++) { - stream_pos = decode_value(&decoded_value, model.mean, stream_pos, - &setup_mean); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].mean = decoded_value; - - stream_pos = decode_value(&decoded_value, model.variance_mean, stream_pos, - &setup_var); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].variance_mean = decoded_value; - - stream_pos = decode_value(&decoded_value, model.outlier_pixels, stream_pos, - &setup_pix); - if (stream_pos <= 0) - return stream_pos; - data_buf[i].outlier_pixels = decoded_value; - - if (up_model_buf) { - up_model_buf[i].mean = cmp_up_model(data_buf[i].mean, - model.mean, cfg->model_value, setup_mean.lossy_par); - up_model_buf[i].variance_mean = cmp_up_model(data_buf[i].variance_mean, - model.variance_mean, cfg->model_value, setup_var.lossy_par); - up_model_buf[i].outlier_pixels = cmp_up_model(data_buf[i].outlier_pixels, - model.outlier_pixels, cfg->model_value, setup_pix.lossy_par); - } - - if (i >= cfg->samples-1) - break; - - model = next_model_p[i]; - } - return stream_pos; -} - - -/** - * @brief decompress the data based on a compression configuration - * - * @param cfg pointer to a compression configuration - * - * @note cfg->buffer_length is measured in bytes (instead of samples as by the - * compression) - * - * @returns the size of the decompressed data on success; returns negative on failure - * TODO: change return type to int32_t - */ - -static int decompressed_data_internal(struct cmp_cfg *cfg) -{ - int data_size, strem_len_bit = -1; - - if (!cfg) - return -1; - - if (!cfg->icu_output_buf) - return -1; - - if (!cfg->max_used_bits) - return -1; - - data_size = cmp_cal_size_of_data(cfg->samples, cfg->data_type); - if (!cfg->input_buf || !data_size) - return data_size; - - if (model_mode_is_used(cfg->cmp_mode)) - if (!cfg->model_buf) - return -1; - - if (cfg->cmp_mode == CMP_MODE_RAW) { - - if ((unsigned int)data_size < cfg->buffer_length/CHAR_BIT) - return -1; - - if (cfg->input_buf) { - memcpy(cfg->input_buf, cfg->icu_output_buf, data_size); - if (cmp_input_big_to_cpu_endianness(cfg->input_buf, data_size, cfg->data_type)) - return -1; - strem_len_bit = data_size * CHAR_BIT; - } - - } else { - switch (cfg->data_type) { - case DATA_TYPE_IMAGETTE: - case DATA_TYPE_IMAGETTE_ADAPTIVE: - case DATA_TYPE_SAT_IMAGETTE: - case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE: - case DATA_TYPE_F_CAM_IMAGETTE: - case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE: - strem_len_bit = decompress_imagette(cfg); - break; - case DATA_TYPE_S_FX: - strem_len_bit = decompress_s_fx(cfg); - break; - case DATA_TYPE_S_FX_EFX: - strem_len_bit = decompress_s_fx_efx(cfg); - break; - case DATA_TYPE_S_FX_NCOB: - strem_len_bit = decompress_s_fx_ncob(cfg); - break; - case DATA_TYPE_S_FX_EFX_NCOB_ECOB: - strem_len_bit = decompress_s_fx_efx_ncob_ecob(cfg); - break; - - case DATA_TYPE_F_FX: - strem_len_bit = decompress_f_fx(cfg); - break; - case DATA_TYPE_F_FX_EFX: - strem_len_bit = decompress_f_fx_efx(cfg); - break; - case DATA_TYPE_F_FX_NCOB: - strem_len_bit = decompress_f_fx_ncob(cfg); - break; - case DATA_TYPE_F_FX_EFX_NCOB_ECOB: - strem_len_bit = decompress_f_fx_efx_ncob_ecob(cfg); - break; - - case DATA_TYPE_L_FX: - strem_len_bit = decompress_l_fx(cfg); - break; - case DATA_TYPE_L_FX_EFX: - strem_len_bit = decompress_l_fx_efx(cfg); - break; - case DATA_TYPE_L_FX_NCOB: - strem_len_bit = decompress_l_fx_ncob(cfg); - break; - case DATA_TYPE_L_FX_EFX_NCOB_ECOB: - strem_len_bit = decompress_l_fx_efx_ncob_ecob(cfg); - break; - - case DATA_TYPE_OFFSET: - strem_len_bit = decompress_nc_offset(cfg); - break; - case DATA_TYPE_BACKGROUND: - strem_len_bit = decompress_nc_background(cfg); - break; - case DATA_TYPE_SMEARING: - strem_len_bit = decompress_smearing(cfg); - break; - - case DATA_TYPE_F_CAM_OFFSET: - case DATA_TYPE_F_CAM_BACKGROUND: - case DATA_TYPE_UNKNOWN: - default: - strem_len_bit = -1; - debug_print("Error: Compressed data type not supported.\n"); - break; - } - } - if (strem_len_bit <= 0) - return -1; - - return data_size; -} - - -/** - * @brief read in an imagette compression entity header to a - * compression configuration - * - * @param ent pointer to a compression entity - * @param cfg pointer to a compression configuration - * - * @returns 0 on success; otherwise error - */ - -static int cmp_ent_read_header(struct cmp_entity *ent, struct cmp_cfg *cfg) -{ - int32_t samples; - - if (!cfg) - return -1; - - cfg->data_type = cmp_ent_get_data_type(ent); - if (cmp_data_type_is_invalid(cfg->data_type)) { - debug_print("Error: Compression data type not supported.\n"); - return -1; - } - - cfg->cmp_mode = cmp_ent_get_cmp_mode(ent); - if (cmp_ent_get_data_type_raw_bit(ent) != (cfg->cmp_mode == CMP_MODE_RAW)) { - debug_print("Error: The entity's raw data bit does not match up with the compression mode.\n"); - return -1; - } - cfg->model_value = cmp_ent_get_model_value(ent); - cfg->round = cmp_ent_get_lossy_cmp_par(ent); - cfg->buffer_length = cmp_ent_get_cmp_data_size(ent); - - samples = cmp_input_size_to_samples(cmp_ent_get_original_size(ent), cfg->data_type); - if (samples < 0) { - debug_print("Error: original_size and data product type in the compression header are not compatible.\n"); - cfg->samples = 0; - return -1; - } - - cfg->samples = (uint32_t)samples; - - cfg->icu_output_buf = cmp_ent_get_data_buf(ent); - - cfg->max_used_bits = cmp_max_used_bits_list_get(cmp_ent_get_max_used_bits_version(ent)); - if (!cfg->max_used_bits) { - debug_print("Error: The Max. Used Bits Registry Version in the compression header is unknown.\n"); - return -1; - } - - if (cfg->cmp_mode == CMP_MODE_RAW) - /* no specific header is used for raw data we are done */ - return 0; - - switch (cfg->data_type) { - case DATA_TYPE_IMAGETTE_ADAPTIVE: - case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE: - case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE: - cfg->ap1_golomb_par = cmp_ent_get_ima_ap1_golomb_par(ent); - cfg->ap1_spill = cmp_ent_get_ima_ap1_spill(ent); - cfg->ap2_golomb_par = cmp_ent_get_ima_ap2_golomb_par(ent); - cfg->ap2_spill = cmp_ent_get_ima_ap2_spill(ent); - /* fall through */ - case DATA_TYPE_IMAGETTE: - case DATA_TYPE_SAT_IMAGETTE: - case DATA_TYPE_F_CAM_IMAGETTE: - cfg->spill = cmp_ent_get_ima_spill(ent); - cfg->golomb_par = cmp_ent_get_ima_golomb_par(ent); - break; - case DATA_TYPE_OFFSET: - case DATA_TYPE_BACKGROUND: - case DATA_TYPE_SMEARING: - cfg->cmp_par_mean = cmp_ent_get_non_ima_cmp_par1(ent); - cfg->spill_mean = cmp_ent_get_non_ima_spill1(ent); - cfg->cmp_par_variance = cmp_ent_get_non_ima_cmp_par2(ent); - cfg->spill_variance = cmp_ent_get_non_ima_spill2(ent); - cfg->cmp_par_pixels_error = cmp_ent_get_non_ima_cmp_par3(ent); - cfg->spill_pixels_error = cmp_ent_get_non_ima_spill3(ent); - break; - case DATA_TYPE_S_FX: - case DATA_TYPE_S_FX_EFX: - case DATA_TYPE_S_FX_NCOB: - case DATA_TYPE_S_FX_EFX_NCOB_ECOB: - case DATA_TYPE_L_FX: - case DATA_TYPE_L_FX_EFX: - case DATA_TYPE_L_FX_NCOB: - case DATA_TYPE_L_FX_EFX_NCOB_ECOB: - case DATA_TYPE_F_FX: - case DATA_TYPE_F_FX_EFX: - case DATA_TYPE_F_FX_NCOB: - case DATA_TYPE_F_FX_EFX_NCOB_ECOB: - cfg->cmp_par_exp_flags = cmp_ent_get_non_ima_cmp_par1(ent); - cfg->spill_exp_flags = cmp_ent_get_non_ima_spill1(ent); - cfg->cmp_par_fx = cmp_ent_get_non_ima_cmp_par2(ent); - cfg->spill_fx = cmp_ent_get_non_ima_spill2(ent); - cfg->cmp_par_ncob = cmp_ent_get_non_ima_cmp_par3(ent); - cfg->spill_ncob = cmp_ent_get_non_ima_spill3(ent); - cfg->cmp_par_efx = cmp_ent_get_non_ima_cmp_par4(ent); - cfg->spill_efx = cmp_ent_get_non_ima_spill4(ent); - cfg->cmp_par_ecob = cmp_ent_get_non_ima_cmp_par5(ent); - cfg->spill_ecob = cmp_ent_get_non_ima_spill5(ent); - cfg->cmp_par_fx_cob_variance = cmp_ent_get_non_ima_cmp_par6(ent); - cfg->spill_fx_cob_variance = cmp_ent_get_non_ima_spill6(ent); - break; - case DATA_TYPE_F_CAM_OFFSET: - case DATA_TYPE_F_CAM_BACKGROUND: - /* LCOV_EXCL_START */ - case DATA_TYPE_UNKNOWN: - default: - return -1; - /* LCOV_EXCL_STOP */ - } - - return 0; -} - - -/** - * @brief decompress a compression entity - * - * @param ent pointer to the compression entity to be decompressed - * @param model_of_data pointer to model data buffer (can be NULL if no - * model compression mode is used) - * @param up_model_buf pointer to store the updated model for the next model - * mode compression (can be the same as the model_of_data - * buffer for in-place update or NULL if updated model is not needed) - * @param decompressed_data pointer to the decompressed data buffer (can be NULL) - * - * @returns the size of the decompressed data on success; returns negative on failure - */ - -int decompress_cmp_entiy(struct cmp_entity *ent, void *model_of_data, - void *up_model_buf, void *decompressed_data) -{ - int err; - struct cmp_cfg cfg = {0}; - - cfg.model_buf = model_of_data; - cfg.icu_new_model_buf = up_model_buf; - cfg.input_buf = decompressed_data; - - if (!ent) - return -1; - - err = cmp_ent_read_header(ent, &cfg); - if (err) - return -1; - - return decompressed_data_internal(&cfg); -} - - -/** - * @brief decompress RDCU compressed data without a compression entity header - * - * @param compressed_data pointer to the RDCU compressed data (without a - * compression entity header) - * @param info pointer to a decompression information structure - * consisting the metadata of the compression - * @param model_of_data pointer to model data buffer (can be NULL if no - * model compression mode is used) - * @param up_model_buf pointer to store the updated model for the next model - * mode compression (can be the same as the model_of_data - * buffer for in-place update or NULL if updated model is not needed) - * @param decompressed_data pointer to the decompressed data buffer (can be NULL) - * - * @returns the size of the decompressed data on success; returns negative on failure - */ - -int decompress_rdcu_data(uint32_t *compressed_data, const struct cmp_info *info, - uint16_t *model_of_data, uint16_t *up_model_buf, - uint16_t *decompressed_data) - -{ - struct cmp_cfg cfg = {0}; - - if (!compressed_data) - return -1; - - if (!info) - return -1; - - if (info->cmp_err) - return -1; - - cfg.data_type = DATA_TYPE_IMAGETTE; - cfg.model_buf = model_of_data; - cfg.icu_new_model_buf = up_model_buf; - cfg.input_buf = decompressed_data; - - cfg.cmp_mode = info->cmp_mode_used; - cfg.model_value = info->model_value_used; - cfg.round = info->round_used; - cfg.spill = info->spill_used; - cfg.golomb_par = info->golomb_par_used; - cfg.samples = info->samples_used; - cfg.icu_output_buf = compressed_data; - cfg.buffer_length = cmp_bit_to_4byte(info->cmp_size); - cfg.max_used_bits = &MAX_USED_BITS_SAFE; - - return decompressed_data_internal(&cfg); -} diff --git a/include/decmp.h b/lib/decmp.h similarity index 88% rename from include/decmp.h rename to lib/decmp.h index c09da34a72f1d1e3001c7ffce786ff4cd57bc8b8..f39cb37d4e46d6eb32a1f5e8e6d6966a0b9df4aa 100644 --- a/include/decmp.h +++ b/lib/decmp.h @@ -16,11 +16,11 @@ * @brief software decompression library */ -#ifndef DECMP_H_ -#define DECMP_H_ +#ifndef DECMP_H +#define DECMP_H -#include <cmp_entity.h> -#include <cmp_support.h> +#include "common/cmp_entity.h" +#include "common/cmp_support.h" int decompress_cmp_entiy(struct cmp_entity *ent, void *model_of_data, void *up_model_buf, void *decompressed_data); @@ -29,4 +29,4 @@ int decompress_rdcu_data(uint32_t *compressed_data, const struct cmp_info *info, uint16_t *model_of_data, uint16_t *up_model_buf, uint16_t *decompressed_data); -#endif /* DECMP_H_ */ +#endif /* DECMP_H */ diff --git a/lib/cmp_max_used_bits_list.c b/lib/decompress/cmp_max_used_bits_list.c similarity index 88% rename from lib/cmp_max_used_bits_list.c rename to lib/decompress/cmp_max_used_bits_list.c index 28fe3126678adbcdadc8c118b224777dc9f2263e..f4844ffc58da55b555523afe7281315fd0ae9491 100644 --- a/lib/cmp_max_used_bits_list.c +++ b/lib/decompress/cmp_max_used_bits_list.c @@ -21,10 +21,9 @@ #include <stdlib.h> -#include <assert.h> -#include <list.h> -#include <cmp_max_used_bits.h> +#include "../common/list.h" +#include "../common/cmp_max_used_bits.h" struct list_item { @@ -32,7 +31,7 @@ struct list_item { struct cmp_max_used_bits data; }; -LIST_HEAD(max_used_bits_list); +static LIST_HEAD(max_used_bits_list); /** @@ -77,17 +76,18 @@ const struct cmp_max_used_bits *cmp_max_used_bits_list_get(uint8_t version) int cmp_max_used_bits_list_add(struct cmp_max_used_bits const *item) { struct list_item *item_ptr = NULL; - struct cmp_max_used_bits *p; if (!item) return -1; - if (item->version <= 16) + if (item->version < CMP_MAX_USED_BITS_RESERVED_VERSIONS) return -1; - p = (struct cmp_max_used_bits *)cmp_max_used_bits_list_get(item->version); - if (p) { - *p = *item; /* replace existing list entry */ - return 1; + /* check for an existing entry */ + list_for_each_entry(item_ptr, &max_used_bits_list, list) { + if (item_ptr->data.version == item->version) { + item_ptr->data = *item; /* replace existing list entry */ + return 1; + } } item_ptr = (struct list_item *)malloc(sizeof(struct list_item)); diff --git a/include/cmp_max_used_bits_list.h b/lib/decompress/cmp_max_used_bits_list.h similarity index 77% rename from include/cmp_max_used_bits_list.h rename to lib/decompress/cmp_max_used_bits_list.h index 82a4cce42f7122bfdf4a879a00e19ed4d526e099..317c7163fab7894654fb3d06e9911c9d64d63da2 100644 --- a/include/cmp_max_used_bits_list.h +++ b/lib/decompress/cmp_max_used_bits_list.h @@ -20,20 +20,20 @@ */ -#ifndef _CMP_MAX_USED_LIST_H_ -#define _CMP_MAX_USED_LIST_H_ +#ifndef CMP_MAX_USED_LIST_H +#define CMP_MAX_USED_LIST_H #include <stdint.h> -#include <cmp_data_types.h> +#include "../common/cmp_data_types.h" -struct cmp_max_used_bits *cmp_max_used_bits_list_get(uint8_t version); +const struct cmp_max_used_bits *cmp_max_used_bits_list_get(uint8_t version); int cmp_max_used_bits_list_add(struct cmp_max_used_bits const *item); -int cmp_max_used_bits_list_delet(uint8_t version); +void cmp_max_used_bits_list_delet(uint8_t version); void cmp_max_used_bits_list_empty(void); -#endif /* _CMP_MAX_USED_LIST_H_ */ +#endif /* CMP_MAX_USED_LIST_H */ diff --git a/lib/decompress/decmp.c b/lib/decompress/decmp.c new file mode 100644 index 0000000000000000000000000000000000000000..3c26fbd4ad400e7ebf4641edf3985e5eaa3979f3 --- /dev/null +++ b/lib/decompress/decmp.c @@ -0,0 +1,2413 @@ +/** + * @file decmp.c + * @author Dominik Loidolt (dominik.loidolt@univie.ac.at) + * @date 2020 + * + * @copyright GPLv2 + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * @brief software decompression library + * @see Data Compression User Manual PLATO-UVIE-PL-UM-0001 + * + * To decompress a compression entity (consisting of a compression entity header + * and the compressed data) use the decompress_cmp_entiy() function. + * + * @warning not intended for use with the flight software + */ + + +#include <stdint.h> +#include <limits.h> +#include <string.h> +#include <assert.h> + +#include "../common/byteorder.h" +#include "../common/compiler.h" + +#include "read_bitstream.h" +#include "cmp_max_used_bits_list.h" +#include "../common/cmp_debug.h" +#include "../common/cmp_support.h" +#include "../common/cmp_entity.h" +#include "../common/cmp_max_used_bits.h" + + +#define CORRUPTION_DETECTED -1 + + +MAYBE_UNUSED static const char *please_check_str = + "Please check that the compression parameters match those used to compress the data and that the compressed data are not corrupted."; + + +/** + * @brief function pointer to a code word decoder function + */ + +typedef uint32_t(*decoder_ptr)(struct bit_decoder *, uint32_t, uint32_t); + + +/** + * @brief structure to hold all parameters to decode a value + */ + +struct decoder_setup { + int (*decode_method_f)(const struct decoder_setup *setup, + uint32_t *decoded_value); /* pointer to the decoding function with escape mechanism */ + decoder_ptr decode_cw_f; /* pointer to the code word decoder function (Golomb/Rice/unary) */ + struct bit_decoder *dec; /* pointer to a bit_decoder context */ + uint32_t encoder_par1; /* encoding parameter 1 */ + uint32_t encoder_par2; /* encoding parameter 2 */ + uint32_t outlier_par; /* outlier parameter */ + uint32_t lossy_par; /* lossy compression parameter */ + uint32_t max_data_bits; /* bit length of the decoded value */ +}; + + +enum decmp_type {ICU_DECOMRESSION, RDCU_DECOMPRESSION}; + + +/** + * @brief decode the next unary code word in the bitstream + * + * @param dec a pointer to a bit_decoder context + * @param m this parameter is not used + * @param log2_m this parameter is not used + * @note: Can be used to decode a code word with compression parameter m = 1 (log2_m = 0) + * + * @returns the decoded value + */ + +static __inline uint32_t unary_decoder(struct bit_decoder *dec, uint32_t m UNUSED, + uint32_t log2_m UNUSED) +{ + uint32_t const decoded_cw = bit_peek_leading_ones(dec); /* decode unary coding */ + uint32_t const cw_len = decoded_cw + 1; /* Number of 1's + following 0 */ + + bit_consume_bits(dec, cw_len); + + return decoded_cw; +} + + +/** + * @brief decode the next Rice code word in the bitstream + * + * @param dec a pointer to a bit_decoder context + * @param m Golomb parameter, must be the same used for encoding + * @param log2_m Rice parameter, is ilog_2(m), must be larger than 0 + * @note the Golomb parameter (m) must be a power of 2 + * @warning the Rice parameter (log2_m) must be greater than 0! If you want to + * use a Rice parameter equal to 0, use the unary_decoder instead. + * + * @returns the decoded value + */ + +static uint32_t rice_decoder(struct bit_decoder *dec, uint32_t m, uint32_t log2_m) +{ + uint32_t q; /* quotient */ + uint32_t r; /* remainder */ + + assert(log2_m > 0 && log2_m < 32); + + q = unary_decoder(dec, m, log2_m); /* decode quotient unary code part */ + r = bit_read_bits32(dec, log2_m); /* get remainder */ + + return (q << log2_m) + r; /* calculate decoded value (q*m+r) */ +} + + +/** + * @brief decode the next Golomb code word in the bitstream + * + * @param dec a pointer to a bit_decoder context + * @param m Golomb parameter (has to be bigger than 0) + * @param log2_m is ilog_2(m) calculate outside function for better + * performance + * + * @returns the decoded value + */ + +static uint32_t golomb_decoder(struct bit_decoder *dec, uint32_t m, uint32_t log2_m) +{ + uint32_t q; /* quotient */ + uint32_t r1; /* remainder case 1 */ + uint32_t r2; /* remainder case 2 */ + uint32_t r; /* remainder */ + uint32_t cutoff; /* cutoff between group 1 and 2 */ + + assert(m > 0); + assert(log2_m == ilog_2(m)); + + /* decode quotient unary code part */ + q = unary_decoder(dec, m, log2_m); + + /* get the remainder code for both cases */ + r2 = (uint32_t)bit_peek_bits(dec, log2_m+1); + r1 = r2 >> 1; + + /* calculate cutoff between case 1 and 2 */ + cutoff = (0x2U << log2_m) - m; /* = 2^(log2_m+1)-m */ + + if (r1 < cutoff) { /* remainder case 1: remainder length=log2_m */ + bit_consume_bits(dec, log2_m); + r = r1; + } else { /* remainder case 2: remainder length = log2_m+1 */ + bit_consume_bits(dec, log2_m+1); + r = r2 - cutoff; + } + + return q*m + r; +} + + +/** + * @brief select the decoder based on the used Golomb parameter + * + * @param golomb_par Golomb parameter, has to be bigger than 0 + * + * @note if the Golomb parameter is a power of 2 we can use the faster Rice decoder + * @note if the Golomb parameter is 1 we can use the even faster unary decoder + * + * @returns function pointer to the select code word decoder function + */ + +static decoder_ptr select_decoder(uint32_t golomb_par) +{ + assert(golomb_par > 0); + + if (golomb_par == 1) + return &unary_decoder; + + if (is_a_pow_of_2(golomb_par)) + return &rice_decoder; + else + return &golomb_decoder; +} + + +/** + * @brief decode the next code word with zero escape system mechanism from the bitstream + * + * @param setup pointer to the decoder setup + * @param decoded_value points to the location where the decoded value is stored + * + * @returns 0 on success; otherwise error + */ + +static int decode_zero(const struct decoder_setup *setup, uint32_t *decoded_value) +{ + /* Decode the next value in the bitstream with the Golomb/Rice/unary decoder */ + *decoded_value = setup->decode_cw_f(setup->dec, setup->encoder_par1, setup->encoder_par2); + + if (*decoded_value != 0) { /* no escape symbol detected */ + if (*decoded_value >= setup->outlier_par) { + debug_print("Error: Data consistency check failed. Non-outlier decoded value greater or equal than the outlier parameter. %s", please_check_str); + return CORRUPTION_DETECTED; + } + *decoded_value -= 1; + } else { + /* the zero escape symbol mechanism was used; read unencoded value */ + bit_refill(setup->dec); + *decoded_value = bit_read_bits32_sub_1(setup->dec, setup->max_data_bits); + + if (*decoded_value < setup->outlier_par - 1) { /* -1 because we subtract -1 from the *decoded_value */ + if (bit_refill(setup->dec) != BIT_OVERFLOW) + debug_print("Error: Data consistency check failed. Outlier small than the outlier parameter. %s", please_check_str); + return CORRUPTION_DETECTED; + } + } + return bit_refill(setup->dec) == BIT_OVERFLOW; +} + + +/** + * @brief decode the next code word with the multi escape mechanism from the bitstream + * + * @param setup pointer to the decoder setup + * @param decoded_value points to the location where the decoded value is stored + * + * @returns 0 on success; otherwise error + */ + +static int decode_multi(const struct decoder_setup *setup, uint32_t *decoded_value) +{ + /* Decode the next value in the bitstream with the Golomb/Rice/unary decoder */ + *decoded_value = setup->decode_cw_f(setup->dec, setup->encoder_par1, setup->encoder_par2); + + if (*decoded_value >= setup->outlier_par) { /* escape symbol mechanism detected */ + uint32_t const unencoded_len = (*decoded_value - setup->outlier_par + 1) << 1; + + if (unencoded_len > ((setup->max_data_bits+1) & -2U)) { /* round up max_data_bits to the nearest multiple of 2 */ + debug_print("Error: Data consistency check failed. Multi escape symbol higher than expected. %s", please_check_str); + return CORRUPTION_DETECTED; + } + + /* read unencoded value */ + bit_refill(setup->dec); + *decoded_value = bit_read_bits32(setup->dec, unencoded_len); + + if (*decoded_value >> (unencoded_len-2) == 0) { /* check if at least one bit of the two highest is set. */ + if (unencoded_len > 2) { /* Exception: if we code outlier_par as outlier, no set bit is expected */ + if (bit_refill(setup->dec) != BIT_OVERFLOW) + debug_print("Error: Data consistency check failed. Unencoded data after multi escape symbol to small. %s", please_check_str); + return CORRUPTION_DETECTED; + } + } + + *decoded_value += setup->outlier_par; + + if ((*decoded_value & BIT_MASK[setup->max_data_bits]) < setup->outlier_par) { /* check for overflow in addition */ + if (bit_refill(setup->dec) != BIT_OVERFLOW) + debug_print("Error: Data consistency check failed. Outlier small than the outlier parameter. %s", please_check_str); + return CORRUPTION_DETECTED; + } + } + return bit_refill(setup->dec) == BIT_OVERFLOW; +} + + +/** + * @brief get the value unencoded with setup->cmp_par_1 bits without any + * additional changes from the bitstream + * + * @param setup pointer to the decoder setup + * @param decoded_value points to the location where the decoded value is stored + * + * @returns 0 on success; otherwise error + */ + +static int decode_none(const struct decoder_setup *setup, uint32_t *decoded_value) +{ + *decoded_value = bit_read_bits32(setup->dec, setup->encoder_par1); + + return bit_refill(setup->dec) == BIT_OVERFLOW; +} + + +/** + * @brief remap an unsigned value back to a signed value + * @note this is the reverse function of map_to_pos() + * + * @param value_to_unmap unsigned value to remap + * + * @returns the signed remapped value + */ + +static __inline uint32_t re_map_to_pos(uint32_t value_to_unmap) +{ + if (value_to_unmap & 0x1) { /* if uneven */ + /* uint64_t to prevent overflow if value_to_unmap == 0xFFFFFFFF */ + uint64_t tmp64 = value_to_unmap; + + return (uint32_t)(-((tmp64 + 1) / 2)); + } else { + return value_to_unmap / 2; + } +} + + +/** + * @brief decompress the next code word in the bitstream and decorate it with + * the model + * + * @param setup pointer to the decoder setup + * @param decoded_value points to the location where the decoded value is stored + * @param model model of the decoded_value (0 if not used) + * + * @returns 0 on success; otherwise error + */ + +static int decode_value(const struct decoder_setup *setup, uint32_t *decoded_value, + uint32_t model) +{ + /* decode the next value from the bitstream */ + int err = setup->decode_method_f(setup, decoded_value); + + if (setup->decode_method_f == decode_none) + /* we are done here in stuff mode */ + return err; + + /* map the unsigned decode value back to a signed value */ + *decoded_value = re_map_to_pos(*decoded_value); + + /* decorate data the data with the model */ + *decoded_value += round_fwd(model, setup->lossy_par); + + /* we mask only the used bits in case there is an overflow when adding the model */ + *decoded_value &= BIT_MASK[setup->max_data_bits]; + + /* inverse step of the lossy compression */ + *decoded_value = round_inv(*decoded_value, setup->lossy_par); + + return err; +} + + +/** + * @brief configure a decoder setup structure to have a setup to decode a vale + * + * @param setup pointer to the decoder setup + * @param dec pointer to a bit_decoder context + * @param cmp_mode compression mode + * @param cmp_par compression parameter + * @param spillover spillover_par parameter + * @param lossy_par lossy compression parameter + * @param max_data_bits how many bits are needed to represent the highest possible value + */ + +static void configure_decoder_setup(struct decoder_setup *setup, struct bit_decoder *dec, + enum cmp_mode cmp_mode, uint32_t cmp_par, + uint32_t spillover, uint32_t lossy_par, + uint32_t max_data_bits) +{ + assert(setup != NULL); + assert(dec != NULL); + assert(cmp_par != 0); + assert(max_data_bits > 0 && max_data_bits <= 32); + + if (multi_escape_mech_is_used(cmp_mode)) + setup->decode_method_f = &decode_multi; + else if (zero_escape_mech_is_used(cmp_mode)) + setup->decode_method_f = &decode_zero; + else if (cmp_mode == CMP_MODE_STUFF) + setup->decode_method_f = &decode_none; + else { + debug_print("Error: Compression mode not supported."); + assert(0); + } + setup->decode_cw_f = select_decoder(cmp_par); + setup->dec = dec; + setup->encoder_par1 = cmp_par; /* encoding parameter 1 */ + setup->encoder_par2 = ilog_2(cmp_par); /* encoding parameter 2 */ + setup->outlier_par = spillover; /* outlier parameter */ + setup->lossy_par = lossy_par; /* lossy compression parameter */ + setup->max_data_bits = max_data_bits; /* how many bits are needed to represent the highest possible value */ +} + + +/** + * @brief return a pointer of the data of a collection + * + * @param col pointer to a collection header (can be NULL) + * + * @returns pointer to the collection data; NULL if col is NULL + */ + +void *get_collection_data(void *col) +{ + if (col) + col = (uint8_t *)col + COLLECTION_HDR_SIZE; + return col; +} + + +/** + * @brief decompress imagette data + * + * @param cfg pointer to the compression configuration structure + * @param dec a pointer to a bit_decoder context + * + * @returns 0 on success; otherwise error + */ + +static int decompress_imagette(const struct cmp_cfg *cfg, struct bit_decoder *dec, enum decmp_type decmp_type) +{ + size_t i; + int err; + uint32_t decoded_value; + uint32_t max_data_bits; + struct decoder_setup setup; + uint16_t *data_buf; + uint16_t *model_buf; + uint16_t *up_model_buf; + uint16_t *next_model_p; + uint16_t model; + + switch (decmp_type) { + case RDCU_DECOMPRESSION: /* RDCU compresses the header like data */ + data_buf = cfg->input_buf; + model_buf = cfg->model_buf; + up_model_buf = cfg->icu_new_model_buf; + break; + case ICU_DECOMRESSION: + data_buf = get_collection_data(cfg->input_buf); + model_buf = get_collection_data(cfg->model_buf); + up_model_buf = get_collection_data(cfg->icu_new_model_buf); + break; + } + + if (model_mode_is_used(cfg->cmp_mode)) { + model = model_buf[0]; + next_model_p = &model_buf[1]; + } else { + up_model_buf = NULL; + memset(&model, 0, sizeof(model)); + next_model_p = data_buf; + } + + switch (cfg->data_type) { + case DATA_TYPE_IMAGETTE: + case DATA_TYPE_IMAGETTE_ADAPTIVE: + max_data_bits = cfg->max_used_bits->nc_imagette; + break; + case DATA_TYPE_SAT_IMAGETTE: + case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE: + max_data_bits = cfg->max_used_bits->saturated_imagette; + break; + default: + case DATA_TYPE_F_CAM_IMAGETTE: + case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE: + max_data_bits = cfg->max_used_bits->fc_imagette; + break; + } + + configure_decoder_setup(&setup, dec, cfg->cmp_mode, cfg->golomb_par, + cfg->spill, cfg->round, max_data_bits); + + for (i = 0; ; i++) { + err = decode_value(&setup, &decoded_value, model); + if (err) + break; + data_buf[i] = (__typeof__(data_buf[i]))decoded_value; + + if (up_model_buf) + up_model_buf[i] = cmp_up_model(data_buf[i], model, cfg->model_value, + setup.lossy_par); + + if (i >= cfg->samples-1) + break; + + model = next_model_p[i]; + } + return err; +} + + +#if 0 +/** + * @brief decompress the multi-entry packet header structure and sets the data, + * model and up_model pointers to the data after the header + * + * @param data pointer to a pointer pointing to the data to be compressed + * @param model pointer to a pointer pointing to the model of the data + * @param up_model pointer to a pointer pointing to the updated model buffer + * @param cfg pointer to the compression configuration structure + * + * @returns the bit length of the bitstream on success + * + * @note the (void **) cast relies on all pointer types having the same internal + * representation which is common, but not universal; http://www.c-faq.com/ptrs/genericpp.html + */ + +static int decompress_multi_entry_hdr(void **data, void **model, void **up_model, + const struct cmp_cfg *cfg) +{ + if (cfg->buffer_length < COLLECTION_HDR_SIZE) + return -1; + + if (*data) { + if (cfg->icu_output_buf) + memcpy(*data, cfg->icu_output_buf, COLLECTION_HDR_SIZE); + *data = (uint8_t *)*data + COLLECTION_HDR_SIZE; + } + + if (*model) { + if (cfg->icu_output_buf) + memcpy(*model, cfg->icu_output_buf, COLLECTION_HDR_SIZE); + *model = (uint8_t *)*model + COLLECTION_HDR_SIZE; + } + + if (*up_model) { + if (cfg->icu_output_buf) + memcpy(*up_model, cfg->icu_output_buf, COLLECTION_HDR_SIZE); + *up_model = (uint8_t *)*up_model + COLLECTION_HDR_SIZE; + } + + return COLLECTION_HDR_SIZE * CHAR_BIT; +} +#endif + + +/** + * @brief decompress short normal light flux (S_FX) data + * + * @param cfg pointer to the compression configuration structure + * @param dec a pointer to a bit_decoder context + * + * @returns 0 on success; otherwise error + */ + +static int decompress_s_fx(const struct cmp_cfg *cfg, struct bit_decoder *dec) +{ + size_t i; + int err; + uint32_t decoded_value; + struct decoder_setup setup_exp_flags, setup_fx; + struct s_fx *data_buf = get_collection_data(cfg->input_buf); + struct s_fx *model_buf = get_collection_data(cfg->model_buf); + struct s_fx *up_model_buf; + struct s_fx *next_model_p; + struct s_fx model; + + if (model_mode_is_used(cfg->cmp_mode)) { + model = model_buf[0]; + next_model_p = &model_buf[1]; + up_model_buf = get_collection_data(cfg->icu_new_model_buf); + } else { + memset(&model, 0, sizeof(model)); + next_model_p = data_buf; + up_model_buf = NULL; + } + + configure_decoder_setup(&setup_exp_flags, dec, cfg->cmp_mode, cfg->cmp_par_exp_flags, + cfg->spill_exp_flags, cfg->round, cfg->max_used_bits->s_exp_flags); + configure_decoder_setup(&setup_fx, dec, cfg->cmp_mode, cfg->cmp_par_fx, + cfg->spill_fx, cfg->round, cfg->max_used_bits->s_fx); + + for (i = 0; ; i++) { + err = decode_value(&setup_exp_flags, &decoded_value, model.exp_flags); + if (err) + break; + data_buf[i].exp_flags = (__typeof__(data_buf[i].exp_flags))decoded_value; + + err = decode_value(&setup_fx, &decoded_value, model.fx); + if (err) + break; + data_buf[i].fx = decoded_value; + + if (up_model_buf) { + up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags, + cfg->model_value, setup_exp_flags.lossy_par); + up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx, + cfg->model_value, setup_fx.lossy_par); + } + + if (i >= cfg->samples-1) + break; + + model = next_model_p[i]; + } + return err; +} + + +/** + * @brief decompress S_FX_EFX data + * + * @param cfg pointer to the compression configuration structure + * @param dec a pointer to a bit_decoder context + * + * @returns 0 on success; otherwise error + */ + +static int decompress_s_fx_efx(const struct cmp_cfg *cfg, struct bit_decoder *dec) +{ + size_t i; + int err; + uint32_t decoded_value; + struct decoder_setup setup_exp_flags, setup_fx, setup_efx; + struct s_fx_efx *data_buf = get_collection_data(cfg->input_buf); + struct s_fx_efx *model_buf = get_collection_data(cfg->model_buf); + struct s_fx_efx *up_model_buf; + struct s_fx_efx *next_model_p; + struct s_fx_efx model; + + if (model_mode_is_used(cfg->cmp_mode)) { + up_model_buf = get_collection_data(cfg->icu_new_model_buf); + model = model_buf[0]; + next_model_p = &model_buf[1]; + } else { + up_model_buf = NULL; + memset(&model, 0, sizeof(model)); + next_model_p = data_buf; + } + + configure_decoder_setup(&setup_exp_flags, dec, cfg->cmp_mode, cfg->cmp_par_exp_flags, + cfg->spill_exp_flags, cfg->round, cfg->max_used_bits->s_exp_flags); + configure_decoder_setup(&setup_fx, dec, cfg->cmp_mode, cfg->cmp_par_fx, + cfg->spill_fx, cfg->round, cfg->max_used_bits->s_fx); + configure_decoder_setup(&setup_efx, dec, cfg->cmp_mode, cfg->cmp_par_efx, + cfg->spill_efx, cfg->round, cfg->max_used_bits->s_efx); + + for (i = 0; ; i++) { + err = decode_value(&setup_exp_flags, &decoded_value, model.exp_flags); + if (err) + break; + data_buf[i].exp_flags = (__typeof__(data_buf[i].exp_flags)) decoded_value; + + err = decode_value(&setup_fx, &decoded_value, model.fx); + if (err) + break; + data_buf[i].fx = decoded_value; + + err = decode_value(&setup_efx, &decoded_value, model.efx); + if (err) + break; + data_buf[i].efx = decoded_value; + + if (up_model_buf) { + up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags, + cfg->model_value, setup_exp_flags.lossy_par); + up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx, + cfg->model_value, setup_fx.lossy_par); + up_model_buf[i].efx = cmp_up_model(data_buf[i].efx, model.efx, + cfg->model_value, setup_efx.lossy_par); + } + + if (i >= cfg->samples-1) + break; + + model = next_model_p[i]; + } + return err; +} + + +/** + * @brief decompress short S_FX_NCOB data + * + * @param cfg pointer to the compression configuration structure + * @param dec a pointer to a bit_decoder context + * + * @returns 0 on success; otherwise error + */ + +static int decompress_s_fx_ncob(const struct cmp_cfg *cfg, struct bit_decoder *dec) +{ + size_t i; + int err; + uint32_t decoded_value; + struct decoder_setup setup_exp_flags, setup_fx, setup_ncob; + struct s_fx_ncob *data_buf = get_collection_data(cfg->input_buf); + struct s_fx_ncob *model_buf = get_collection_data(cfg->model_buf); + struct s_fx_ncob *up_model_buf; + struct s_fx_ncob *next_model_p; + struct s_fx_ncob model; + + if (model_mode_is_used(cfg->cmp_mode)) { + up_model_buf = get_collection_data(cfg->icu_new_model_buf); + model = model_buf[0]; + next_model_p = &model_buf[1]; + } else { + up_model_buf = NULL; + memset(&model, 0, sizeof(model)); + next_model_p = data_buf; + } + + configure_decoder_setup(&setup_exp_flags, dec, cfg->cmp_mode, cfg->cmp_par_exp_flags, + cfg->spill_exp_flags, cfg->round, cfg->max_used_bits->s_exp_flags); + configure_decoder_setup(&setup_fx, dec, cfg->cmp_mode, cfg->cmp_par_fx, + cfg->spill_fx, cfg->round, cfg->max_used_bits->s_fx); + configure_decoder_setup(&setup_ncob, dec, cfg->cmp_mode, cfg->cmp_par_ncob, + cfg->spill_ncob, cfg->round, cfg->max_used_bits->s_ncob); + + for (i = 0; ; i++) { + err = decode_value(&setup_exp_flags, &decoded_value, model.exp_flags); + if (err) + break; + data_buf[i].exp_flags = (__typeof__(data_buf[i].exp_flags)) decoded_value; + + err = decode_value(&setup_fx, &decoded_value, model.fx); + if (err) + break; + data_buf[i].fx = decoded_value; + + err = decode_value(&setup_ncob, &decoded_value, model.ncob_x); + if (err) + break; + data_buf[i].ncob_x = decoded_value; + + err = decode_value(&setup_ncob, &decoded_value, model.ncob_y); + if (err) + break; + data_buf[i].ncob_y = decoded_value; + + if (up_model_buf) { + up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags, + cfg->model_value, setup_exp_flags.lossy_par); + up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx, + cfg->model_value, setup_fx.lossy_par); + up_model_buf[i].ncob_x = cmp_up_model(data_buf[i].ncob_x, model.ncob_x, + cfg->model_value, setup_ncob.lossy_par); + up_model_buf[i].ncob_y = cmp_up_model(data_buf[i].ncob_y, model.ncob_y, + cfg->model_value, setup_ncob.lossy_par); + } + + if (i >= cfg->samples-1) + break; + + model = next_model_p[i]; + } + return err; +} + + +/** + * @brief decompress short S_FX_NCOB_ECOB data + * + * @param cfg pointer to the compression configuration structure + * @param dec a pointer to a bit_decoder context + * + * @returns 0 on success; otherwise error + */ + +static int decompress_s_fx_efx_ncob_ecob(const struct cmp_cfg *cfg, struct bit_decoder *dec) +{ + size_t i; + int err; + uint32_t decoded_value; + struct decoder_setup setup_exp_flags, setup_fx, setup_ncob, setup_efx, setup_ecob; + struct s_fx_efx_ncob_ecob *data_buf = get_collection_data(cfg->input_buf); + struct s_fx_efx_ncob_ecob *model_buf = get_collection_data(cfg->model_buf); + struct s_fx_efx_ncob_ecob *up_model_buf; + struct s_fx_efx_ncob_ecob *next_model_p; + struct s_fx_efx_ncob_ecob model; + + if (model_mode_is_used(cfg->cmp_mode)) { + up_model_buf = get_collection_data(cfg->icu_new_model_buf); + model = model_buf[0]; + next_model_p = &model_buf[1]; + } else { + up_model_buf = NULL; + memset(&model, 0, sizeof(model)); + next_model_p = data_buf; + } + + configure_decoder_setup(&setup_exp_flags, dec, cfg->cmp_mode, cfg->cmp_par_exp_flags, + cfg->spill_exp_flags, cfg->round, cfg->max_used_bits->s_exp_flags); + configure_decoder_setup(&setup_fx, dec, cfg->cmp_mode, cfg->cmp_par_fx, cfg->spill_fx, + cfg->round, cfg->max_used_bits->s_fx); + configure_decoder_setup(&setup_ncob, dec, cfg->cmp_mode, cfg->cmp_par_ncob, cfg->spill_ncob, + cfg->round, cfg->max_used_bits->s_ncob); + configure_decoder_setup(&setup_efx, dec, cfg->cmp_mode, cfg->cmp_par_efx, cfg->spill_efx, + cfg->round, cfg->max_used_bits->s_efx); + configure_decoder_setup(&setup_ecob, dec, cfg->cmp_mode, cfg->cmp_par_ecob, cfg->spill_ecob, + cfg->round, cfg->max_used_bits->s_ecob); + + for (i = 0; ; i++) { + err = decode_value(&setup_exp_flags, &decoded_value, model.exp_flags); + if (err) + break; + data_buf[i].exp_flags = (__typeof__(data_buf[i].exp_flags)) decoded_value; + + err = decode_value(&setup_fx, &decoded_value, model.fx); + if (err) + break; + data_buf[i].fx = decoded_value; + + err = decode_value(&setup_ncob, &decoded_value, model.ncob_x); + if (err) + break; + data_buf[i].ncob_x = decoded_value; + + err = decode_value(&setup_ncob, &decoded_value, model.ncob_y); + if (err) + break; + data_buf[i].ncob_y = decoded_value; + + err = decode_value(&setup_efx, &decoded_value, model.efx); + if (err) + break; + data_buf[i].efx = decoded_value; + + err = decode_value(&setup_ecob, &decoded_value, model.ecob_x); + if (err) + break; + data_buf[i].ecob_x = decoded_value; + + err = decode_value(&setup_ecob, &decoded_value, model.ecob_y); + if (err) + break; + data_buf[i].ecob_y = decoded_value; + + if (up_model_buf) { + up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags, + cfg->model_value, setup_exp_flags.lossy_par); + up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx, + cfg->model_value, setup_fx.lossy_par); + up_model_buf[i].ncob_x = cmp_up_model(data_buf[i].ncob_x, model.ncob_x, + cfg->model_value, setup_ncob.lossy_par); + up_model_buf[i].ncob_y = cmp_up_model(data_buf[i].ncob_y, model.ncob_y, + cfg->model_value, setup_ncob.lossy_par); + up_model_buf[i].efx = cmp_up_model(data_buf[i].efx, model.efx, + cfg->model_value, setup_efx.lossy_par); + up_model_buf[i].ecob_x = cmp_up_model(data_buf[i].ecob_x, model.ecob_x, + cfg->model_value, setup_ecob.lossy_par); + up_model_buf[i].ecob_y = cmp_up_model(data_buf[i].ecob_y, model.ecob_y, + cfg->model_value, setup_ecob.lossy_par); + } + + if (i >= cfg->samples-1) + break; + + model = next_model_p[i]; + } + return err; +} + + +/** + * @brief decompress fast normal light flux (F_FX) data + * + * @param cfg pointer to the compression configuration structure + * @param dec a pointer to a bit_decoder context + * + * @returns 0 on success; otherwise error + */ + +static int decompress_f_fx(const struct cmp_cfg *cfg, struct bit_decoder *dec) +{ + size_t i; + int err; + uint32_t decoded_value; + struct decoder_setup setup_fx; + struct f_fx *data_buf = get_collection_data(cfg->input_buf); + struct f_fx *model_buf = get_collection_data(cfg->model_buf); + struct f_fx *up_model_buf; + struct f_fx *next_model_p; + struct f_fx model; + + if (model_mode_is_used(cfg->cmp_mode)) { + up_model_buf = get_collection_data(cfg->icu_new_model_buf); + model = model_buf[0]; + next_model_p = &model_buf[1]; + } else { + up_model_buf = NULL; + memset(&model, 0, sizeof(model)); + next_model_p = data_buf; + } + + configure_decoder_setup(&setup_fx, dec, cfg->cmp_mode, cfg->cmp_par_fx, cfg->spill_fx, + cfg->round, cfg->max_used_bits->f_fx); + + for (i = 0; ; i++) { + err = decode_value(&setup_fx, &decoded_value, model.fx); + if (err) + break; + data_buf[i].fx = decoded_value; + + if (up_model_buf) + up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx, + cfg->model_value, setup_fx.lossy_par); + + if (i >= cfg->samples-1) + break; + + model = next_model_p[i]; + } + return err; +} + + +/** + * @brief decompress F_FX_EFX data + * + * @param cfg pointer to the compression configuration structure + * @param dec a pointer to a bit_decoder context + * + * @returns 0 on success; otherwise error + */ + +static int decompress_f_fx_efx(const struct cmp_cfg *cfg, struct bit_decoder *dec) +{ + size_t i; + int err; + uint32_t decoded_value; + struct decoder_setup setup_fx, setup_efx; + struct f_fx_efx *data_buf = get_collection_data(cfg->input_buf); + struct f_fx_efx *model_buf = get_collection_data(cfg->model_buf); + struct f_fx_efx *up_model_buf; + struct f_fx_efx *next_model_p; + struct f_fx_efx model; + + if (model_mode_is_used(cfg->cmp_mode)) { + up_model_buf = get_collection_data(cfg->icu_new_model_buf); + model = model_buf[0]; + next_model_p = &model_buf[1]; + } else { + up_model_buf = NULL; + memset(&model, 0, sizeof(model)); + next_model_p = data_buf; + } + + configure_decoder_setup(&setup_fx, dec, cfg->cmp_mode, cfg->cmp_par_fx, cfg->spill_fx, + cfg->round, cfg->max_used_bits->f_fx); + configure_decoder_setup(&setup_efx, dec, cfg->cmp_mode, cfg->cmp_par_efx, cfg->spill_efx, + cfg->round, cfg->max_used_bits->f_efx); + + for (i = 0; ; i++) { + err = decode_value(&setup_fx, &decoded_value, model.fx); + if (err) + break; + data_buf[i].fx = decoded_value; + + err = decode_value(&setup_efx, &decoded_value, model.efx); + if (err) + break; + data_buf[i].efx = decoded_value; + + if (up_model_buf) { + up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx, + cfg->model_value, setup_fx.lossy_par); + up_model_buf[i].efx = cmp_up_model(data_buf[i].efx, model.efx, + cfg->model_value, setup_efx.lossy_par); + } + + if (i >= cfg->samples-1) + break; + + model = next_model_p[i]; + } + return err; +} + + +/** + * @brief decompress short F_FX_NCOB data + * + * @param cfg pointer to the compression configuration structure + * @param dec a pointer to a bit_decoder context + * + * @returns 0 on success; otherwise error + */ + +static int decompress_f_fx_ncob(const struct cmp_cfg *cfg, struct bit_decoder *dec) +{ + size_t i; + int err; + uint32_t decoded_value; + struct decoder_setup setup_fx, setup_ncob; + struct f_fx_ncob *data_buf = get_collection_data(cfg->input_buf); + struct f_fx_ncob *model_buf = get_collection_data(cfg->model_buf); + struct f_fx_ncob *up_model_buf; + struct f_fx_ncob *next_model_p; + struct f_fx_ncob model; + + if (model_mode_is_used(cfg->cmp_mode)) { + up_model_buf = get_collection_data(cfg->icu_new_model_buf); + model = model_buf[0]; + next_model_p = &model_buf[1]; + } else { + up_model_buf = NULL; + memset(&model, 0, sizeof(model)); + next_model_p = data_buf; + } + + configure_decoder_setup(&setup_fx, dec, cfg->cmp_mode, cfg->cmp_par_fx, cfg->spill_fx, + cfg->round, cfg->max_used_bits->f_fx); + configure_decoder_setup(&setup_ncob, dec, cfg->cmp_mode, cfg->cmp_par_ncob, cfg->spill_ncob, + cfg->round, cfg->max_used_bits->f_ncob); + + for (i = 0; ; i++) { + err = decode_value(&setup_fx, &decoded_value, model.fx); + if (err) + break; + data_buf[i].fx = decoded_value; + + err = decode_value(&setup_ncob, &decoded_value, model.ncob_x); + if (err) + break; + data_buf[i].ncob_x = decoded_value; + + err = decode_value(&setup_ncob, &decoded_value, model.ncob_y); + if (err) + break; + data_buf[i].ncob_y = decoded_value; + + if (up_model_buf) { + up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx, + cfg->model_value, setup_fx.lossy_par); + up_model_buf[i].ncob_x = cmp_up_model(data_buf[i].ncob_x, model.ncob_x, + cfg->model_value, setup_ncob.lossy_par); + up_model_buf[i].ncob_y = cmp_up_model(data_buf[i].ncob_y, model.ncob_y, + cfg->model_value, setup_ncob.lossy_par); + } + + if (i >= cfg->samples-1) + break; + + model = next_model_p[i]; + } + return err; +} + + +/** + * @brief decompress short F_FX_NCOB_ECOB data + * + * @param cfg pointer to the compression configuration structure + * @param dec a pointer to a bit_decoder context + * + * @returns 0 on success; otherwise error + */ + +static int decompress_f_fx_efx_ncob_ecob(const struct cmp_cfg *cfg, struct bit_decoder *dec) +{ + size_t i; + int err; + uint32_t decoded_value; + struct decoder_setup setup_fx, setup_ncob, setup_efx, setup_ecob; + struct f_fx_efx_ncob_ecob *data_buf = get_collection_data(cfg->input_buf); + struct f_fx_efx_ncob_ecob *model_buf = get_collection_data(cfg->model_buf); + struct f_fx_efx_ncob_ecob *up_model_buf; + struct f_fx_efx_ncob_ecob *next_model_p; + struct f_fx_efx_ncob_ecob model; + + if (model_mode_is_used(cfg->cmp_mode)) { + up_model_buf = get_collection_data(cfg->icu_new_model_buf); + model = model_buf[0]; + next_model_p = &model_buf[1]; + } else { + up_model_buf = NULL; + memset(&model, 0, sizeof(model)); + next_model_p = data_buf; + } + + configure_decoder_setup(&setup_fx, dec, cfg->cmp_mode, cfg->cmp_par_fx, cfg->spill_fx, + cfg->round, cfg->max_used_bits->f_fx); + configure_decoder_setup(&setup_ncob, dec, cfg->cmp_mode, cfg->cmp_par_ncob, cfg->spill_ncob, + cfg->round, cfg->max_used_bits->f_ncob); + configure_decoder_setup(&setup_efx, dec, cfg->cmp_mode, cfg->cmp_par_efx, cfg->spill_efx, + cfg->round, cfg->max_used_bits->f_efx); + configure_decoder_setup(&setup_ecob, dec, cfg->cmp_mode, cfg->cmp_par_ecob, cfg->spill_ecob, + cfg->round, cfg->max_used_bits->f_ecob); + + for (i = 0; ; i++) { + err = decode_value(&setup_fx, &decoded_value, model.fx); + if (err) + break; + data_buf[i].fx = decoded_value; + + err = decode_value(&setup_ncob, &decoded_value, model.ncob_x); + if (err) + break; + data_buf[i].ncob_x = decoded_value; + + err = decode_value(&setup_ncob, &decoded_value, model.ncob_y); + if (err) + break; + data_buf[i].ncob_y = decoded_value; + + err = decode_value(&setup_efx, &decoded_value, model.efx); + if (err) + break; + data_buf[i].efx = decoded_value; + + err = decode_value(&setup_ecob, &decoded_value, model.ecob_x); + if (err) + break; + data_buf[i].ecob_x = decoded_value; + + err = decode_value(&setup_ecob, &decoded_value, model.ecob_y); + if (err) + break; + data_buf[i].ecob_y = decoded_value; + + if (up_model_buf) { + up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx, + cfg->model_value, setup_fx.lossy_par); + up_model_buf[i].ncob_x = cmp_up_model(data_buf[i].ncob_x, model.ncob_x, + cfg->model_value, setup_ncob.lossy_par); + up_model_buf[i].ncob_y = cmp_up_model(data_buf[i].ncob_y, model.ncob_y, + cfg->model_value, setup_ncob.lossy_par); + up_model_buf[i].efx = cmp_up_model(data_buf[i].efx, model.efx, + cfg->model_value, setup_efx.lossy_par); + up_model_buf[i].ecob_x = cmp_up_model(data_buf[i].ecob_x, model.ecob_x, + cfg->model_value, setup_ecob.lossy_par); + up_model_buf[i].ecob_y = cmp_up_model(data_buf[i].ecob_y, model.ecob_y, + cfg->model_value, setup_ecob.lossy_par); + } + + if (i >= cfg->samples-1) + break; + + model = next_model_p[i]; + } + return err; +} + + +/** + * @brief decompress long normal light flux (L_FX) data + * + * @param cfg pointer to the compression configuration structure + * @param dec a pointer to a bit_decoder context + * + * @returns 0 on success; otherwise error + */ + +static int decompress_l_fx(const struct cmp_cfg *cfg, struct bit_decoder *dec) +{ + size_t i; + int err; + uint32_t decoded_value; + struct decoder_setup setup_exp_flags, setup_fx, setup_fx_var; + struct l_fx *data_buf = get_collection_data(cfg->input_buf); + struct l_fx *model_buf = get_collection_data(cfg->model_buf); + struct l_fx *up_model_buf; + struct l_fx *next_model_p; + struct l_fx model; + + if (model_mode_is_used(cfg->cmp_mode)) { + up_model_buf = get_collection_data(cfg->icu_new_model_buf); + model = model_buf[0]; + next_model_p = &model_buf[1]; + } else { + up_model_buf = NULL; + memset(&model, 0, sizeof(model)); + next_model_p = data_buf; + } + + configure_decoder_setup(&setup_exp_flags, dec, cfg->cmp_mode, cfg->cmp_par_exp_flags, cfg->spill_exp_flags, + cfg->round, cfg->max_used_bits->l_exp_flags); + configure_decoder_setup(&setup_fx, dec, cfg->cmp_mode, cfg->cmp_par_fx, cfg->spill_fx, + cfg->round, cfg->max_used_bits->l_fx); + configure_decoder_setup(&setup_fx_var, dec, cfg->cmp_mode, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance, + cfg->round, cfg->max_used_bits->l_fx_variance); + + for (i = 0; ; i++) { + err = decode_value(&setup_exp_flags, &decoded_value, model.exp_flags); + if (err) + break; + data_buf[i].exp_flags = decoded_value; + + err = decode_value(&setup_fx, &decoded_value, model.fx); + if (err) + break; + data_buf[i].fx = decoded_value; + + err = decode_value(&setup_fx_var, &decoded_value, model.fx_variance); + if (err) + break; + data_buf[i].fx_variance = decoded_value; + + if (up_model_buf) { + up_model_buf[i].exp_flags = cmp_up_model32(data_buf[i].exp_flags, model.exp_flags, + cfg->model_value, setup_exp_flags.lossy_par); + up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx, + cfg->model_value, setup_fx.lossy_par); + up_model_buf[i].fx_variance = cmp_up_model(data_buf[i].fx_variance, model.fx_variance, + cfg->model_value, setup_fx_var.lossy_par); + } + + if (i >= cfg->samples-1) + break; + + model = next_model_p[i]; + } + return err; +} + + +/** + * @brief decompress L_FX_EFX data + * + * @param cfg pointer to the compression configuration structure + * @param dec a pointer to a bit_decoder context + * + * @returns 0 on success; otherwise error + */ + +static int decompress_l_fx_efx(const struct cmp_cfg *cfg, struct bit_decoder *dec) +{ + size_t i; + int err; + uint32_t decoded_value; + struct decoder_setup setup_exp_flags, setup_fx, setup_efx, setup_fx_var; + struct l_fx_efx *data_buf = get_collection_data(cfg->input_buf); + struct l_fx_efx *model_buf = get_collection_data(cfg->model_buf); + struct l_fx_efx *up_model_buf; + struct l_fx_efx *next_model_p; + struct l_fx_efx model; + + if (model_mode_is_used(cfg->cmp_mode)) { + up_model_buf = get_collection_data(cfg->icu_new_model_buf); + model = model_buf[0]; + next_model_p = &model_buf[1]; + } else { + up_model_buf = NULL; + memset(&model, 0, sizeof(model)); + next_model_p = data_buf; + } + + configure_decoder_setup(&setup_exp_flags, dec, cfg->cmp_mode, cfg->cmp_par_exp_flags, cfg->spill_exp_flags, + cfg->round, cfg->max_used_bits->l_exp_flags); + configure_decoder_setup(&setup_fx, dec, cfg->cmp_mode, cfg->cmp_par_fx, cfg->spill_fx, + cfg->round, cfg->max_used_bits->l_fx); + configure_decoder_setup(&setup_efx, dec, cfg->cmp_mode, cfg->cmp_par_efx, cfg->spill_efx, + cfg->round, cfg->max_used_bits->l_efx); + configure_decoder_setup(&setup_fx_var, dec, cfg->cmp_mode, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance, + cfg->round, cfg->max_used_bits->l_fx_variance); + + for (i = 0; ; i++) { + err = decode_value(&setup_exp_flags, &decoded_value, model.exp_flags); + if (err) + break; + data_buf[i].exp_flags = decoded_value; + + err = decode_value(&setup_fx, &decoded_value, model.fx); + if (err) + break; + data_buf[i].fx = decoded_value; + + err = decode_value(&setup_efx, &decoded_value, model.efx); + if (err) + break; + data_buf[i].efx = decoded_value; + + err = decode_value(&setup_fx_var, &decoded_value, model.fx_variance); + if (err) + break; + data_buf[i].fx_variance = decoded_value; + + if (up_model_buf) { + up_model_buf[i].exp_flags = cmp_up_model32(data_buf[i].exp_flags, model.exp_flags, + cfg->model_value, setup_exp_flags.lossy_par); + up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx, + cfg->model_value, setup_fx.lossy_par); + up_model_buf[i].efx = cmp_up_model(data_buf[i].efx, model.efx, + cfg->model_value, setup_efx.lossy_par); + up_model_buf[i].fx_variance = cmp_up_model(data_buf[i].fx_variance, model.fx_variance, + cfg->model_value, setup_fx_var.lossy_par); + } + + if (i >= cfg->samples-1) + break; + + model = next_model_p[i]; + } + return err; +} + + +/** + * @brief decompress L_FX_NCOB data + * + * @param cfg pointer to the compression configuration structure + * @param dec a pointer to a bit_decoder context + * + * @returns 0 on success; otherwise error + */ + +static int decompress_l_fx_ncob(const struct cmp_cfg *cfg, struct bit_decoder *dec) +{ + size_t i; + int err; + uint32_t decoded_value; + struct decoder_setup setup_exp_flags, setup_fx, setup_ncob, + setup_fx_var, setup_cob_var; + struct l_fx_ncob *data_buf = get_collection_data(cfg->input_buf); + struct l_fx_ncob *model_buf = get_collection_data(cfg->model_buf); + struct l_fx_ncob *up_model_buf; + struct l_fx_ncob *next_model_p; + struct l_fx_ncob model; + + if (model_mode_is_used(cfg->cmp_mode)) { + up_model_buf = get_collection_data(cfg->icu_new_model_buf); + model = model_buf[0]; + next_model_p = &model_buf[1]; + } else { + up_model_buf = NULL; + memset(&model, 0, sizeof(model)); + next_model_p = data_buf; + } + + configure_decoder_setup(&setup_exp_flags, dec, cfg->cmp_mode, cfg->cmp_par_exp_flags, cfg->spill_exp_flags, + cfg->round, cfg->max_used_bits->l_exp_flags); + configure_decoder_setup(&setup_fx, dec, cfg->cmp_mode, cfg->cmp_par_fx, cfg->spill_fx, + cfg->round, cfg->max_used_bits->l_fx); + configure_decoder_setup(&setup_ncob, dec, cfg->cmp_mode, cfg->cmp_par_ncob, cfg->spill_ncob, + cfg->round, cfg->max_used_bits->l_ncob); + configure_decoder_setup(&setup_fx_var, dec, cfg->cmp_mode, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance, + cfg->round, cfg->max_used_bits->l_fx_variance); + configure_decoder_setup(&setup_cob_var, dec, cfg->cmp_mode, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance, + cfg->round, cfg->max_used_bits->l_cob_variance); + + for (i = 0; ; i++) { + err = decode_value(&setup_exp_flags, &decoded_value, model.exp_flags); + if (err) + break; + data_buf[i].exp_flags = decoded_value; + + err = decode_value(&setup_fx, &decoded_value, model.fx); + if (err) + break; + data_buf[i].fx = decoded_value; + + err = decode_value(&setup_ncob, &decoded_value, model.ncob_x); + if (err) + break; + data_buf[i].ncob_x = decoded_value; + + err = decode_value(&setup_ncob, &decoded_value, model.ncob_y); + if (err) + break; + data_buf[i].ncob_y = decoded_value; + + err = decode_value(&setup_fx_var, &decoded_value, model.fx_variance); + if (err) + break; + data_buf[i].fx_variance = decoded_value; + + err = decode_value(&setup_cob_var, &decoded_value, model.cob_x_variance); + if (err) + break; + data_buf[i].cob_x_variance = decoded_value; + + err = decode_value(&setup_cob_var, &decoded_value, model.cob_y_variance); + if (err) + break; + data_buf[i].cob_y_variance = decoded_value; + + if (up_model_buf) { + up_model_buf[i].exp_flags = cmp_up_model32(data_buf[i].exp_flags, model.exp_flags, + cfg->model_value, setup_exp_flags.lossy_par); + up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx, + cfg->model_value, setup_fx.lossy_par); + up_model_buf[i].ncob_x = cmp_up_model(data_buf[i].ncob_x, model.ncob_x, + cfg->model_value, setup_ncob.lossy_par); + up_model_buf[i].ncob_y = cmp_up_model(data_buf[i].ncob_y, model.ncob_y, + cfg->model_value, setup_ncob.lossy_par); + up_model_buf[i].fx_variance = cmp_up_model(data_buf[i].fx_variance, model.fx_variance, + cfg->model_value, setup_fx_var.lossy_par); + up_model_buf[i].cob_x_variance = cmp_up_model(data_buf[i].cob_x_variance, model.cob_x_variance, + cfg->model_value, setup_cob_var.lossy_par); + up_model_buf[i].cob_y_variance = cmp_up_model(data_buf[i].cob_y_variance, model.cob_y_variance, + cfg->model_value, setup_cob_var.lossy_par); + } + + if (i >= cfg->samples-1) + break; + + model = next_model_p[i]; + } + return err; +} + + +/** + * @brief decompress L_FX_EFX_NCOB_ECOB data + * + * @param cfg pointer to the compression configuration structure + * @param dec a pointer to a bit_decoder context + * + * @returns 0 on success; otherwise error + */ + +static int decompress_l_fx_efx_ncob_ecob(const struct cmp_cfg *cfg, struct bit_decoder *dec) +{ + size_t i; + int err; + uint32_t decoded_value; + struct decoder_setup setup_exp_flags, setup_fx, setup_ncob, setup_efx, + setup_ecob, setup_fx_var, setup_cob_var; + struct l_fx_efx_ncob_ecob *data_buf = get_collection_data(cfg->input_buf); + struct l_fx_efx_ncob_ecob *model_buf = get_collection_data(cfg->model_buf); + struct l_fx_efx_ncob_ecob *up_model_buf; + struct l_fx_efx_ncob_ecob *next_model_p; + struct l_fx_efx_ncob_ecob model; + + if (model_mode_is_used(cfg->cmp_mode)) { + up_model_buf = get_collection_data(cfg->icu_new_model_buf); + model = model_buf[0]; + next_model_p = &model_buf[1]; + } else { + up_model_buf = NULL; + memset(&model, 0, sizeof(model)); + next_model_p = data_buf; + } + + configure_decoder_setup(&setup_exp_flags, dec, cfg->cmp_mode, cfg->cmp_par_exp_flags, cfg->spill_exp_flags, + cfg->round, cfg->max_used_bits->l_exp_flags); + configure_decoder_setup(&setup_fx, dec, cfg->cmp_mode, cfg->cmp_par_fx, cfg->spill_fx, + cfg->round, cfg->max_used_bits->l_fx); + configure_decoder_setup(&setup_ncob, dec, cfg->cmp_mode, cfg->cmp_par_ncob, cfg->spill_ncob, + cfg->round, cfg->max_used_bits->l_ncob); + configure_decoder_setup(&setup_efx, dec, cfg->cmp_mode, cfg->cmp_par_efx, cfg->spill_efx, + cfg->round, cfg->max_used_bits->l_efx); + configure_decoder_setup(&setup_ecob, dec, cfg->cmp_mode, cfg->cmp_par_ecob, cfg->spill_ecob, + cfg->round, cfg->max_used_bits->l_ecob); + configure_decoder_setup(&setup_fx_var, dec, cfg->cmp_mode, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance, + cfg->round, cfg->max_used_bits->l_fx_variance); + configure_decoder_setup(&setup_cob_var, dec, cfg->cmp_mode, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance, + cfg->round, cfg->max_used_bits->l_cob_variance); + + for (i = 0; ; i++) { + err = decode_value(&setup_exp_flags, &decoded_value, model.exp_flags); + if (err) + break; + data_buf[i].exp_flags = decoded_value; + + err = decode_value(&setup_fx, &decoded_value, model.fx); + if (err) + break; + data_buf[i].fx = decoded_value; + + err = decode_value(&setup_ncob, &decoded_value, model.ncob_x); + if (err) + break; + data_buf[i].ncob_x = decoded_value; + + err = decode_value(&setup_ncob, &decoded_value, model.ncob_y); + if (err) + break; + data_buf[i].ncob_y = decoded_value; + + err = decode_value(&setup_efx, &decoded_value, model.efx); + if (err) + break; + data_buf[i].efx = decoded_value; + + err = decode_value(&setup_ecob, &decoded_value, model.ecob_x); + if (err) + break; + data_buf[i].ecob_x = decoded_value; + + err = decode_value(&setup_ecob, &decoded_value, model.ecob_y); + if (err) + break; + data_buf[i].ecob_y = decoded_value; + + err = decode_value(&setup_fx_var, &decoded_value, model.fx_variance); + if (err) + break; + data_buf[i].fx_variance = decoded_value; + + err = decode_value(&setup_cob_var, &decoded_value, model.cob_x_variance); + if (err) + break; + data_buf[i].cob_x_variance = decoded_value; + + err = decode_value(&setup_cob_var, &decoded_value, model.cob_y_variance); + if (err) + break; + data_buf[i].cob_y_variance = decoded_value; + + if (up_model_buf) { + up_model_buf[i].exp_flags = cmp_up_model32(data_buf[i].exp_flags, model.exp_flags, + cfg->model_value, setup_exp_flags.lossy_par); + up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx, + cfg->model_value, setup_fx.lossy_par); + up_model_buf[i].ncob_x = cmp_up_model(data_buf[i].ncob_x, model.ncob_x, + cfg->model_value, setup_ncob.lossy_par); + up_model_buf[i].ncob_y = cmp_up_model(data_buf[i].ncob_y, model.ncob_y, + cfg->model_value, setup_ncob.lossy_par); + up_model_buf[i].efx = cmp_up_model(data_buf[i].efx, model.efx, + cfg->model_value, setup_efx.lossy_par); + up_model_buf[i].ecob_x = cmp_up_model(data_buf[i].ecob_x, model.ecob_x, + cfg->model_value, setup_ecob.lossy_par); + up_model_buf[i].ecob_y = cmp_up_model(data_buf[i].ecob_y, model.ecob_y, + cfg->model_value, setup_ecob.lossy_par); + up_model_buf[i].fx_variance = cmp_up_model(data_buf[i].fx_variance, model.fx_variance, + cfg->model_value, setup_fx_var.lossy_par); + up_model_buf[i].cob_x_variance = cmp_up_model(data_buf[i].cob_x_variance, model.cob_x_variance, + cfg->model_value, setup_cob_var.lossy_par); + up_model_buf[i].cob_y_variance = cmp_up_model(data_buf[i].cob_y_variance, model.cob_y_variance, + cfg->model_value, setup_cob_var.lossy_par); + } + + if (i >= cfg->samples-1) + break; + + model = next_model_p[i]; + } + return err; +} + + +/** + * @brief decompress N-CAM and F-CAM offset data + * + * @param cfg pointer to the compression configuration structure + * @param dec a pointer to a bit_decoder context + * + * @returns 0 on success; otherwise error + */ + +static int decompress_offset(const struct cmp_cfg *cfg, struct bit_decoder *dec) +{ + size_t i; + int err; + uint32_t decoded_value; + struct decoder_setup setup_mean, setup_var; + struct offset *data_buf = get_collection_data(cfg->input_buf); + struct offset *model_buf = get_collection_data(cfg->model_buf); + struct offset *up_model_buf; + struct offset *next_model_p; + struct offset model; + + if (model_mode_is_used(cfg->cmp_mode)) { + up_model_buf = get_collection_data(cfg->icu_new_model_buf); + model = model_buf[0]; + next_model_p = &model_buf[1]; + } else { + up_model_buf = NULL; + memset(&model, 0, sizeof(model)); + next_model_p = data_buf; + } + + { + unsigned int mean_bits_used, variance_bits_used; + + switch (cfg->data_type) { + case DATA_TYPE_F_CAM_OFFSET: + mean_bits_used = cfg->max_used_bits->fc_offset_mean; + variance_bits_used = cfg->max_used_bits->fc_offset_variance; + break; + case DATA_TYPE_OFFSET: + default: + mean_bits_used = cfg->max_used_bits->nc_offset_mean; + variance_bits_used = cfg->max_used_bits->nc_offset_variance; + break; + } + configure_decoder_setup(&setup_mean, dec, cfg->cmp_mode, cfg->cmp_par_offset_mean, cfg->spill_offset_mean, + cfg->round, mean_bits_used); + + configure_decoder_setup(&setup_var, dec, cfg->cmp_mode, cfg->cmp_par_offset_variance, cfg->spill_offset_variance, + cfg->round, variance_bits_used); + + } + + for (i = 0; ; i++) { + err = decode_value(&setup_mean, &decoded_value, model.mean); + if (err) + break; + data_buf[i].mean = decoded_value; + + err = decode_value(&setup_var, &decoded_value, model.variance); + if (err) + break; + data_buf[i].variance = decoded_value; + + if (up_model_buf) { + up_model_buf[i].mean = cmp_up_model(data_buf[i].mean, + model.mean, cfg->model_value, setup_mean.lossy_par); + up_model_buf[i].variance = cmp_up_model(data_buf[i].variance, + model.variance, cfg->model_value, setup_var.lossy_par); + } + + if (i >= cfg->samples-1) + break; + + model = next_model_p[i]; + } + return err; +} + + +/** + * @brief decompress N-CAM background data + * + * @param cfg pointer to the compression configuration structure + * @param dec a pointer to a bit_decoder context + * + * @returns 0 on success; otherwise error + */ + +static int decompress_background(const struct cmp_cfg *cfg, struct bit_decoder *dec) +{ + size_t i; + int err; + uint32_t decoded_value; + struct decoder_setup setup_mean, setup_var, setup_pix; + struct background *data_buf = get_collection_data(cfg->input_buf); + struct background *model_buf = get_collection_data(cfg->model_buf); + struct background *up_model_buf; + struct background *next_model_p; + struct background model; + + if (model_mode_is_used(cfg->cmp_mode)) { + up_model_buf = get_collection_data(cfg->icu_new_model_buf); + model = model_buf[0]; + next_model_p = &model_buf[1]; + } else { + up_model_buf = NULL; + memset(&model, 0, sizeof(model)); + next_model_p = data_buf; + } + { + unsigned int mean_used_bits, variance_used_bits, outlier_pixels_used_bits; + + switch (cfg->data_type) { + case DATA_TYPE_F_CAM_BACKGROUND: + mean_used_bits = cfg->max_used_bits->fc_background_mean; + variance_used_bits = cfg->max_used_bits->fc_background_variance; + outlier_pixels_used_bits = cfg->max_used_bits->fc_background_outlier_pixels; + break; + case DATA_TYPE_BACKGROUND: + default: + mean_used_bits = cfg->max_used_bits->nc_background_mean; + variance_used_bits = cfg->max_used_bits->nc_background_variance; + outlier_pixels_used_bits = cfg->max_used_bits->nc_background_outlier_pixels; + break; + } + + configure_decoder_setup(&setup_mean, dec, cfg->cmp_mode, cfg->cmp_par_background_mean, cfg->spill_background_mean, + cfg->round, mean_used_bits); + + configure_decoder_setup(&setup_var, dec, cfg->cmp_mode, cfg->cmp_par_background_variance, cfg->spill_background_variance, + cfg->round, variance_used_bits); + + configure_decoder_setup(&setup_pix, dec, cfg->cmp_mode, cfg->cmp_par_background_pixels_error, cfg->spill_background_pixels_error, + cfg->round, outlier_pixels_used_bits); + + } + + for (i = 0; ; i++) { + err = decode_value(&setup_mean, &decoded_value, model.mean); + if (err) + break; + data_buf[i].mean = decoded_value; + + err = decode_value(&setup_var, &decoded_value, model.variance); + if (err) + break; + data_buf[i].variance = decoded_value; + + err = decode_value(&setup_pix, &decoded_value, model.outlier_pixels); + if (err) + break; + data_buf[i].outlier_pixels = (__typeof__(data_buf[i].outlier_pixels))decoded_value; + + if (up_model_buf) { + up_model_buf[i].mean = cmp_up_model(data_buf[i].mean, + model.mean, cfg->model_value, setup_mean.lossy_par); + up_model_buf[i].variance = cmp_up_model(data_buf[i].variance, + model.variance, cfg->model_value, setup_var.lossy_par); + up_model_buf[i].outlier_pixels = cmp_up_model(data_buf[i].outlier_pixels, + model.outlier_pixels, cfg->model_value, setup_pix.lossy_par); + } + + if (i >= cfg->samples-1) + break; + + model = next_model_p[i]; + } + return err; +} + + +/** + * @brief decompress N-CAM smearing data + * + * @param cfg pointer to the compression configuration structure + * @param dec a pointer to a bit_decoder context + * + * @returns 0 on success; otherwise error + */ + +static int decompress_smearing(const struct cmp_cfg *cfg, struct bit_decoder *dec) +{ + size_t i; + int err; + uint32_t decoded_value; + struct decoder_setup setup_mean, setup_var, setup_pix; + struct smearing *data_buf = get_collection_data(cfg->input_buf); + struct smearing *model_buf = get_collection_data(cfg->model_buf); + struct smearing *up_model_buf; + struct smearing *next_model_p; + struct smearing model; + + if (model_mode_is_used(cfg->cmp_mode)) { + up_model_buf = get_collection_data(cfg->icu_new_model_buf); + model = model_buf[0]; + next_model_p = &model_buf[1]; + } else { + up_model_buf = NULL; + memset(&model, 0, sizeof(model)); + next_model_p = data_buf; + } + + configure_decoder_setup(&setup_mean, dec, cfg->cmp_mode, cfg->cmp_par_smearing_mean, cfg->spill_smearing_mean, + cfg->round, cfg->max_used_bits->smearing_mean); + configure_decoder_setup(&setup_var, dec, cfg->cmp_mode, cfg->cmp_par_smearing_variance, cfg->spill_smearing_variance, + cfg->round, cfg->max_used_bits->smearing_variance_mean); + configure_decoder_setup(&setup_pix, dec, cfg->cmp_mode, cfg->cmp_par_smearing_pixels_error, cfg->spill_smearing_pixels_error, + cfg->round, cfg->max_used_bits->smearing_outlier_pixels); + + for (i = 0; ; i++) { + err = decode_value(&setup_mean, &decoded_value, model.mean); + if (err) + break; + data_buf[i].mean = decoded_value; + + err = decode_value(&setup_var, &decoded_value, model.variance_mean); + if (err) + break; + data_buf[i].variance_mean = (__typeof__(data_buf[i].variance_mean))decoded_value; + + err = decode_value(&setup_pix, &decoded_value, model.outlier_pixels); + if (err) + break; + data_buf[i].outlier_pixels = (__typeof__(data_buf[i].outlier_pixels))decoded_value; + + if (up_model_buf) { + up_model_buf[i].mean = cmp_up_model(data_buf[i].mean, + model.mean, cfg->model_value, setup_mean.lossy_par); + up_model_buf[i].variance_mean = cmp_up_model(data_buf[i].variance_mean, + model.variance_mean, cfg->model_value, setup_var.lossy_par); + up_model_buf[i].outlier_pixels = cmp_up_model(data_buf[i].outlier_pixels, + model.outlier_pixels, cfg->model_value, setup_pix.lossy_par); + } + + if (i >= cfg->samples-1) + break; + + model = next_model_p[i]; + } + return err; +} + + +/** + * @brief Decompresses the collection header. + * + * @param cfg pointer to the compression configuration structure + * + * @note the collection header is not truly compressed; it is simply copied into + * the compressed data. + * + * @return The size of the decompressed collection header on success, + * or -1 if the buffer length is insufficient + */ + +static int decompress_collection_hdr(const struct cmp_cfg *cfg) +{ + if (cfg->buffer_length < COLLECTION_HDR_SIZE) + return -1; + + if (cfg->icu_output_buf) { + if (cfg->input_buf) + memcpy(cfg->input_buf, cfg->icu_output_buf, COLLECTION_HDR_SIZE); + + if (model_mode_is_used(cfg->cmp_mode) && cfg->icu_new_model_buf) + memcpy(cfg->icu_new_model_buf, cfg->icu_output_buf, COLLECTION_HDR_SIZE); + } + return COLLECTION_HDR_SIZE; +} + + +/** + * @brief decompress the data based on a compression configuration + * + * @param cfg pointer to a compression configuration + * @param decmp_type type of decompression: ICU chunk or RDCU decompression + * + * @note cfg->buffer_length is measured in bytes + * + * @returns the size of the decompressed data on success; returns negative on failure + */ + +static int decompressed_data_internal(const struct cmp_cfg *cfg, enum decmp_type decmp_type) +{ + int err; + uint32_t data_size; + + assert(decmp_type == ICU_DECOMRESSION || decmp_type == RDCU_DECOMPRESSION); + + if (!cfg) + return -1; + + if (!cfg->icu_output_buf) + return -1; + + if (!cfg->max_used_bits) + return -1; + + if (cmp_imagette_data_type_is_used(cfg->data_type)) { + if (cmp_cfg_imagette_is_invalid(cfg, ICU_CHECK)) + return -1; + } else if (cmp_fx_cob_data_type_is_used(cfg->data_type)) { + if (cmp_cfg_fx_cob_is_invalid(cfg)) + return -1; + } else if (cmp_aux_data_type_is_used(cfg->data_type)) { + if (cmp_cfg_aux_is_invalid(cfg)) + return -1; + } else { + return -1; + } + + if (model_mode_is_used(cfg->cmp_mode)) + if (!cfg->model_buf) /* we need a model for model compression */ + return -1; + + data_size = cfg->samples * (uint32_t)size_of_a_sample(cfg->data_type); + if (decmp_type == ICU_DECOMRESSION) + data_size += COLLECTION_HDR_SIZE; + /* data_size = cmp_cal_size_of_data(cfg->samples, cfg->data_type); */ + /* if (!cfg->input_buf || !data_size) */ + /* return (int)data_size; */ + + if (cfg->cmp_mode == CMP_MODE_RAW) { + /* if (data_size < cfg->buffer_length/CHAR_BIT) */ + /* return -1; */ + + if (cfg->input_buf) { + /* uint32_t s = cmp_col_get_size(cfg->icu_output_buf); */ + /* assert(s==data_size); */ + memcpy(cfg->input_buf, cfg->icu_output_buf, data_size); + switch (decmp_type) { + case ICU_DECOMRESSION: + if (be_to_cpu_chunk(cfg->input_buf, data_size)) + return -1; + break; + case RDCU_DECOMPRESSION: + if (be_to_cpu_data_type(cfg->input_buf, data_size, + cfg->data_type)) + return -1; + break; + } + } + err = 0; + + } else { + struct bit_decoder dec; + int hdr_size = 0; + + if (!cfg->input_buf) + return (int)data_size; + + if (decmp_type == ICU_DECOMRESSION) { + hdr_size = decompress_collection_hdr(cfg); + if (hdr_size < 0) + return -1; + } + + bit_init_decoder(&dec, (uint8_t *)cfg->icu_output_buf+hdr_size, + cfg->buffer_length-(uint32_t)hdr_size); + + switch (cfg->data_type) { + case DATA_TYPE_IMAGETTE: + case DATA_TYPE_IMAGETTE_ADAPTIVE: + case DATA_TYPE_SAT_IMAGETTE: + case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE: + case DATA_TYPE_F_CAM_IMAGETTE: + case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE: + err = decompress_imagette(cfg, &dec, decmp_type); + break; + case DATA_TYPE_S_FX: + err = decompress_s_fx(cfg, &dec); + break; + case DATA_TYPE_S_FX_EFX: + err = decompress_s_fx_efx(cfg, &dec); + break; + case DATA_TYPE_S_FX_NCOB: + err = decompress_s_fx_ncob(cfg, &dec); + break; + case DATA_TYPE_S_FX_EFX_NCOB_ECOB: + err = decompress_s_fx_efx_ncob_ecob(cfg, &dec); + break; + + case DATA_TYPE_F_FX: + err = decompress_f_fx(cfg, &dec); + break; + case DATA_TYPE_F_FX_EFX: + err = decompress_f_fx_efx(cfg, &dec); + break; + case DATA_TYPE_F_FX_NCOB: + err = decompress_f_fx_ncob(cfg, &dec); + break; + case DATA_TYPE_F_FX_EFX_NCOB_ECOB: + err = decompress_f_fx_efx_ncob_ecob(cfg, &dec); + break; + + case DATA_TYPE_L_FX: + err = decompress_l_fx(cfg, &dec); + break; + case DATA_TYPE_L_FX_EFX: + err = decompress_l_fx_efx(cfg, &dec); + break; + case DATA_TYPE_L_FX_NCOB: + err = decompress_l_fx_ncob(cfg, &dec); + break; + case DATA_TYPE_L_FX_EFX_NCOB_ECOB: + err = decompress_l_fx_efx_ncob_ecob(cfg, &dec); + break; + + case DATA_TYPE_OFFSET: + case DATA_TYPE_F_CAM_OFFSET: + err = decompress_offset(cfg, &dec); + break; + case DATA_TYPE_BACKGROUND: + case DATA_TYPE_F_CAM_BACKGROUND: + err = decompress_background(cfg, &dec); + break; + case DATA_TYPE_SMEARING: + err = decompress_smearing(cfg, &dec); + break; + + case DATA_TYPE_UNKNOWN: + default: + err = -1; + debug_print("Error: Compressed data type not supported."); + break; + } + + switch (bit_refill(&dec)) { + case BIT_OVERFLOW: + if (dec.cursor == dec.limit_ptr) + debug_print("Error: The end of the compressed bit stream has been exceeded. Please check that the compression parameters match those used to compress the data and that the compressed data are not corrupted."); + else + debug_print("Error: Data consistency check failed. %s", please_check_str); + break; + case BIT_END_OF_BUFFER: + /* check if non consumed bits are zero */ + if (bit_read_bits(&dec, sizeof(dec.bit_container)*8 - dec.bits_consumed) == 0) + break; + /* fall through */ + case BIT_UNFINISHED: + debug_print("Warning: Not all compressed data are processed."); + break; + } + } + if (err) + return -1; + + return (int)data_size; +} + + +/** + * @brief read in an imagette compression entity header to a + * compression configuration + * + * @param ent pointer to a compression entity + * @param cfg pointer to a compression configuration + * + * @returns 0 on success; otherwise error + */ + +static int cmp_ent_read_header(struct cmp_entity *ent, struct cmp_cfg *cfg) +{ + if (!cfg) + return -1; + + cfg->data_type = cmp_ent_get_data_type(ent); + if (cmp_data_type_is_invalid(cfg->data_type)) { + debug_print("Error: Compression data type not supported."); + return -1; + } + + cfg->cmp_mode = cmp_ent_get_cmp_mode(ent); + if (cmp_ent_get_data_type_raw_bit(ent) != (cfg->cmp_mode == CMP_MODE_RAW)) { + debug_print("Error: The entity's raw data bit does not match up with the compression mode."); + return -1; + } + cfg->model_value = cmp_ent_get_model_value(ent); + cfg->round = cmp_ent_get_lossy_cmp_par(ent); + cfg->buffer_length = cmp_ent_get_cmp_data_size(ent); + + if (cfg->data_type == DATA_TYPE_CHUNK) { + cfg->samples = 0; + if ((cfg->buffer_length < (COLLECTION_HDR_SIZE + CMP_COLLECTION_FILD_SIZE) && (cfg->cmp_mode != CMP_MODE_RAW)) || + (cfg->buffer_length < COLLECTION_HDR_SIZE && (cfg->cmp_mode == CMP_MODE_RAW))) { + debug_print("Error: The compressed data size in the compression header is smaller than a collection header."); + return -1; + } + } else { + int32_t samples = cmp_input_size_to_samples(cmp_ent_get_original_size(ent), cfg->data_type); + + if (samples < 0) { + debug_print("Error: original_size and data product type in the compression header are not compatible."); + cfg->samples = 0; + return -1; + } + cfg->samples = (uint32_t)samples; + } + + cfg->icu_output_buf = cmp_ent_get_data_buf(ent); + + cfg->max_used_bits = cmp_max_used_bits_list_get(cmp_ent_get_max_used_bits_version(ent)); + if (!cfg->max_used_bits) { + debug_print("Error: The Max. Used Bits Registry Version in the compression header is unknown."); + return -1; + } + + if (cfg->cmp_mode == CMP_MODE_RAW) { + if (cmp_ent_get_original_size(ent) != cmp_ent_get_cmp_data_size(ent)) { + debug_print("Error: The compressed data size and the decompressed original data size in the compression header should be the same in raw mode."); + return -1; + } + /* no specific header is used for raw data we are done */ + return 0; + } + + switch (cfg->data_type) { + case DATA_TYPE_IMAGETTE_ADAPTIVE: + case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE: + case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE: + cfg->ap1_golomb_par = cmp_ent_get_ima_ap1_golomb_par(ent); + cfg->ap1_spill = cmp_ent_get_ima_ap1_spill(ent); + cfg->ap2_golomb_par = cmp_ent_get_ima_ap2_golomb_par(ent); + cfg->ap2_spill = cmp_ent_get_ima_ap2_spill(ent); + /* fall through */ + case DATA_TYPE_IMAGETTE: + case DATA_TYPE_SAT_IMAGETTE: + case DATA_TYPE_F_CAM_IMAGETTE: + cfg->spill = cmp_ent_get_ima_spill(ent); + cfg->golomb_par = cmp_ent_get_ima_golomb_par(ent); + break; + case DATA_TYPE_OFFSET: + case DATA_TYPE_F_CAM_OFFSET: + case DATA_TYPE_BACKGROUND: + case DATA_TYPE_F_CAM_BACKGROUND: + case DATA_TYPE_SMEARING: + case DATA_TYPE_S_FX: + case DATA_TYPE_S_FX_EFX: + case DATA_TYPE_S_FX_NCOB: + case DATA_TYPE_S_FX_EFX_NCOB_ECOB: + case DATA_TYPE_L_FX: + case DATA_TYPE_L_FX_EFX: + case DATA_TYPE_L_FX_NCOB: + case DATA_TYPE_L_FX_EFX_NCOB_ECOB: + case DATA_TYPE_F_FX: + case DATA_TYPE_F_FX_EFX: + case DATA_TYPE_F_FX_NCOB: + case DATA_TYPE_F_FX_EFX_NCOB_ECOB: + case DATA_TYPE_CHUNK: + cfg->cmp_par_exp_flags = cmp_ent_get_non_ima_cmp_par1(ent); + cfg->spill_exp_flags = cmp_ent_get_non_ima_spill1(ent); + cfg->cmp_par_fx = cmp_ent_get_non_ima_cmp_par2(ent); + cfg->spill_fx = cmp_ent_get_non_ima_spill2(ent); + cfg->cmp_par_ncob = cmp_ent_get_non_ima_cmp_par3(ent); + cfg->spill_ncob = cmp_ent_get_non_ima_spill3(ent); + cfg->cmp_par_efx = cmp_ent_get_non_ima_cmp_par4(ent); + cfg->spill_efx = cmp_ent_get_non_ima_spill4(ent); + cfg->cmp_par_ecob = cmp_ent_get_non_ima_cmp_par5(ent); + cfg->spill_ecob = cmp_ent_get_non_ima_spill5(ent); + cfg->cmp_par_fx_cob_variance = cmp_ent_get_non_ima_cmp_par6(ent); + cfg->spill_fx_cob_variance = cmp_ent_get_non_ima_spill6(ent); + break; + /* LCOV_EXCL_START */ + case DATA_TYPE_UNKNOWN: + default: + return -1; + /* LCOV_EXCL_STOP */ + } + + return 0; +} + + +/** + * @brief Get the size of the compressed collection data + * + * @param cmp_col pointer to a compressed collection + * + * @return The size of the compressed collection data in bytes + */ + +static uint16_t get_cmp_collection_data_length(uint8_t *cmp_col) +{ + uint16_t cmp_data_size; + /* If a non-raw mode is used to compress all collections, a + * 2-byte big endian field with the size of the compressed data + * is prefixed (without the size of the file itself and without + * the size of the collection header). This is followed by a + * collection header, followed by the compressed data. + * |---------------------| - cmp_col + * |compressed collection| + * | data size | 2 bytes + * |---------------------|- + * | COLLECTION HDR | + * | | 12 bytes + * |---------------------|- + * | compressed data | (variable) data size + * | *-*-* | + * | *-*-* | + * |---------------------|- next cmp_col + * Fields not scaled correctly + */ + + memcpy(&cmp_data_size, cmp_col, sizeof(cmp_data_size)); + be16_to_cpus(&cmp_data_size); + + return cmp_data_size; +} + + +/** + * @brief get the total size of the compressed collection + * j + * This function returns the total size of the compressed collection in bytes, + * including the size of the compressed size field itself, the collection header, + * and the compressed collection data. + * + * @param cmp_col pointer to a compressed collection + * + * @return The total size of the compressed collection in bytes + */ + +static uint32_t get_cmp_collection_size(uint8_t *cmp_col) +{ + return CMP_COLLECTION_FILD_SIZE + COLLECTION_HDR_SIZE + + get_cmp_collection_data_length(cmp_col); +} + + +/** + * @brief get the number of compressed collections in a compression entity + * + * This function returns the number of compressed collections in a compression + * entity, by iterating over the compressed collection data + * + * @param ent pointer to the compression entity + * + * @return the number of compressed collections in the compressed entity, or -1 + * on error + */ + +static int get_num_of_chunks(struct cmp_entity *ent) +{ + uint8_t *cmp_data_p = cmp_ent_get_data_buf(ent); + long cmp_data_size = cmp_ent_get_cmp_data_size(ent); + int n = 0; + uint8_t *p = cmp_data_p; + /* highest plausible address of compressed collection */ + const uint8_t *limit_ptr = cmp_data_p + cmp_data_size - COLLECTION_HDR_SIZE; + + while (p < limit_ptr) { + p += get_cmp_collection_size(p); + n++; + } + + if (p-cmp_data_p != cmp_data_size) { + debug_print("Error: The sum of the compressed collection does not match the size of the data in the compression header."); + return -1; + } + return n; +} + + +/** + * @brief Parse n'th compressed collection and set configuration parameters + * for decompression it + * + * @param cmp_col pointer to a compressed collection to parse + * @param n the number of the compressed collection to + * parse, starting from 1 + * @param cfg pointer to the configuration structure + * @param coll_uncompressed pointer to store whether the collection is + * uncompressed or not + * + * @return the byte offset where to put the uncompressed result in the + * decompressed data, or -1 on error. + */ + +static long parse_cmp_collection(uint8_t *cmp_col, int n, struct cmp_cfg *cfg, int *coll_uncompressed) +{ + int i; + long decmp_pos = 0; /* position where to put the uncompressed result */ + /* pointer to the collection header */ + struct collection_hdr *col_hdr = (struct collection_hdr *)(cmp_col + CMP_COLLECTION_FILD_SIZE); + uint32_t cmp_data_size; /* size of the compressed data in the collection (not including the header) */ + uint16_t original_col_size; /* size of the decompressed collection data (not including the header) */ + size_t sample_size; + + /* get to the collection we want to decompress */ + for (i = 0; i < n; i++) { + decmp_pos += cmp_col_get_size(col_hdr); + cmp_col += get_cmp_collection_size(cmp_col); + col_hdr = (struct collection_hdr *)(cmp_col + CMP_COLLECTION_FILD_SIZE); + } + + cmp_data_size = get_cmp_collection_data_length(cmp_col); + original_col_size = cmp_col_get_data_length(col_hdr); + + if (cmp_data_size > original_col_size) { + debug_print("Error: Collection %i, the size of the compressed collection is larger than that of the uncompressed collection.", i); + return -1; + } + + /* if the compressed data size == original_col_size the collection data + * was put uncompressed into the bitstream */ + if (cmp_data_size == original_col_size) + *coll_uncompressed = 1; + else + *coll_uncompressed = 0; + + cfg->icu_output_buf = (void *)(col_hdr); /* unaligned cast -> reading compressed data as uint8_t * */ + cfg->buffer_length = cmp_data_size + COLLECTION_HDR_SIZE; + + cfg->data_type = convert_subservice_to_cmp_data_type(cmp_col_get_subservice(col_hdr)); + sample_size = size_of_a_sample(cfg->data_type); + if (!sample_size) + return -1; + + if (original_col_size % sample_size) { + debug_print("Error: The size of the collection is not a multiple of a collection entry."); + return -1; + } + cfg->samples = original_col_size / sample_size; + + return decmp_pos; +} + + +/** + * @brief decompress a compression entity + * + * @note this function assumes that the entity size in the ent header is correct + * @param ent pointer to the compression entity to be decompressed + * @param model_of_data pointer to model data buffer (can be NULL if no + * model compression mode is used) + * @param up_model_buf pointer to store the updated model for the next model + * mode compression (can be the same as the model_of_data + * buffer for an in-place update or NULL if the updated model is not needed) + * @param decompressed_data pointer to the decompressed data buffer (can be NULL) + * + * @returns the size of the decompressed data on success; returns negative on failure + */ + +int decompress_cmp_entiy(struct cmp_entity *ent, void *model_of_data, + void *up_model_buf, void *decompressed_data) +{ + struct cmp_cfg cfg; + int decmp_size; + int i, n_chunks; + + memset(&cfg, 0, sizeof(struct cmp_cfg)); + + if (!ent) + return -1; + + decmp_size = (int)cmp_ent_get_original_size(ent); + if (decmp_size < 0) + return -1; + if (decmp_size == 0) + return 0; + + if (cmp_ent_read_header(ent, &cfg)) + return -1; + + if (cfg.data_type != DATA_TYPE_CHUNK) { /* perform a non-chunk decompression */ + if (cfg.cmp_mode == CMP_MODE_RAW) { + uint32_t data_size = cmp_cal_size_of_data(cfg.samples, cfg.data_type); + + if (decompressed_data) { + memcpy(decompressed_data, cmp_ent_get_data_buf(ent), data_size); + if (cmp_input_big_to_cpu_endianness(decompressed_data, data_size, cfg.data_type)) + return -1; + } + return (int)data_size; + } + + cfg.model_buf = model_of_data; + cfg.icu_new_model_buf = up_model_buf; + cfg.input_buf = decompressed_data; + + return decompressed_data_internal(&cfg, RDCU_DECOMPRESSION); + } + + /* perform a chunk decompression */ + + if (cfg.cmp_mode == CMP_MODE_RAW) { + if (decompressed_data) { + memcpy(decompressed_data, cfg.icu_output_buf, cfg.buffer_length); + cpu_to_be_chunk(decompressed_data, cfg.buffer_length); + } + /* if (up_model_buf) { /1* TODO: if diff non model mode? *1/ */ + /* memcpy(up_model_buf, cfg.icu_output_buf, cfg.buffer_length); */ + /* cpu_to_be_chunk(up_model_buf, cfg.buffer_length); */ + /* } */ + return (int)cfg.buffer_length; + } + + n_chunks = get_num_of_chunks(ent); + if (n_chunks <= 0) + return -1; + + for (i = 0; i < n_chunks; i++) { + int decmp_chunk_size; + int col_uncompressed; + struct cmp_cfg cmp_cpy = cfg; + long offset = parse_cmp_collection(cmp_ent_get_data_buf(ent), i, + &cmp_cpy, &col_uncompressed); + if (offset < 0) + return -1; + + if (decompressed_data) + cmp_cpy.input_buf = (uint8_t *)decompressed_data + offset; + if (model_of_data) + cmp_cpy.model_buf = (uint8_t *)model_of_data + offset; + if (up_model_buf) + cmp_cpy.icu_new_model_buf = (uint8_t *)up_model_buf + offset; + + if (col_uncompressed) { + if (cmp_cpy.icu_new_model_buf && model_mode_is_used(cmp_cpy.cmp_mode)) { + uint32_t s = cmp_cpy.buffer_length; + memcpy(cmp_cpy.icu_new_model_buf, cmp_cpy.icu_output_buf, s); + if (be_to_cpu_chunk(cmp_cpy.icu_new_model_buf, s)) + return -1; + } + cmp_cpy.cmp_mode = CMP_MODE_RAW; + } + + decmp_chunk_size = decompressed_data_internal(&cmp_cpy, ICU_DECOMRESSION); + if (decmp_chunk_size < 0) + return decmp_chunk_size; + } + return decmp_size; +} + + +/** + * @brief decompress RDCU compressed data without a compression entity header + * + * @param compressed_data pointer to the RDCU compressed data (without a + * compression entity header) + * @param info pointer to a decompression information structure + * consisting of the metadata of the compression + * @param model_of_data pointer to model data buffer (can be NULL if no + * model compression mode is used) + * @param up_model_buf pointer to store the updated model for the next model + * mode compression (can be the same as the model_of_data + * buffer for an in-place update or NULL if the + * updated model is not needed) + * @param decompressed_data pointer to the decompressed data buffer (can be NULL) + * + * @returns the size of the decompressed data on success; returns negative on failure + */ + +int decompress_rdcu_data(uint32_t *compressed_data, const struct cmp_info *info, + uint16_t *model_of_data, uint16_t *up_model_buf, + uint16_t *decompressed_data) + +{ + struct cmp_cfg cfg; + + if (!compressed_data) + return -1; + + if (!info) + return -1; + + if (info->cmp_err) + return -1; + + memset(&cfg, 0, sizeof(struct cmp_cfg)); + + cfg.data_type = DATA_TYPE_IMAGETTE; + cfg.model_buf = model_of_data; + cfg.icu_new_model_buf = up_model_buf; + cfg.input_buf = decompressed_data; + + cfg.cmp_mode = info->cmp_mode_used; + cfg.model_value = info->model_value_used; + cfg.round = info->round_used; + cfg.spill = info->spill_used; + cfg.golomb_par = info->golomb_par_used; + cfg.samples = info->samples_used; + cfg.icu_output_buf = compressed_data; + cfg.buffer_length = (info->cmp_size+7)/8; + cfg.max_used_bits = &MAX_USED_BITS_SAFE; + + return decompressed_data_internal(&cfg, RDCU_DECOMPRESSION); +} diff --git a/lib/decompress/meson.build b/lib/decompress/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..08da610cfc6ae1e4af843f77c64ed70254d884c0 --- /dev/null +++ b/lib/decompress/meson.build @@ -0,0 +1,4 @@ +decompress_sources = files([ + 'cmp_max_used_bits_list.c', + 'decmp.c' +]) diff --git a/lib/decompress/read_bitstream.h b/lib/decompress/read_bitstream.h new file mode 100644 index 0000000000000000000000000000000000000000..c65090eac4074d12fcd087fa43d193c3c4ade4fa --- /dev/null +++ b/lib/decompress/read_bitstream.h @@ -0,0 +1,373 @@ +/** + * @file read_bitstream.h + * @author Dominik Loidolt (dominik.loidolt@univie.ac.at) + * @date 2023 + * + * @copyright GPLv2 + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * @brief this library handles the reading from an MSB-first bitstream + * + * This API consists of small unitary functions, which must be inlined for best performance. + * Since link-time-optimization is not available for all compilers, these + * functions are defined into a .h to be included. + * + * Start by invoking bit_init_decoder(). A chunk of the bitstream is then stored + * into a local register. The local register size is 64 bits. You can then retrieve + * bit-fields stored into the local register. The local register is explicitly + * reloaded from the memory with the bit_refill() function. + * A reload guarantees a minimum of 57 bits in the local register if the + * returned status is BIT_UNFINISHED. + * Otherwise, it can be less than that, so proceed accordingly. + * Checking if bit_decoder has reached its end can be performed with bit_end_of_stream(). + * + * This is based on the bitstream part of the FiniteStateEntropy library, see: + * https://github.com/Cyan4973/FiniteStateEntropy/blob/dev/lib/bitstream.h + * by @author Yann Collet + * As well as some ideas from this blog post: + * https://fgiesen.wordpress.com/2018/02/20/reading-bits-in-far-too-many-ways-part-2/ + * by @author Fabian Giesen + */ + +#ifndef READ_BITSTREAM_H +#define READ_BITSTREAM_H + +#include <stdint.h> +#include <stddef.h> +#include <assert.h> +#include <string.h> + +#include "../common/byteorder.h" +#include "../common/compiler.h" + + + +/** + * @brief bitstream decoder context type + */ + +struct bit_decoder { + uint64_t bit_container; + unsigned int bits_consumed; + const uint8_t *cursor; + const uint8_t *limit_ptr; +}; + + +/** + * @brief bitstream decoder status, return type of bit_refill() + */ + +enum bit_status {BIT_OVERFLOW, BIT_END_OF_BUFFER, BIT_ALL_READ_IN, BIT_UNFINISHED}; + + +/* + * bitstream decoder API + */ + +static __inline size_t bit_init_decoder(struct bit_decoder *dec, const void *buf, size_t buf_size); +static __inline uint64_t bit_peek_bits(const struct bit_decoder *dec, unsigned int nb_bits); +static __inline void bit_consume_bits(struct bit_decoder *dec, unsigned int nb_bits); +static __inline uint64_t bit_read_bits(struct bit_decoder *dec, unsigned int nb_bits); +static __inline uint32_t bit_read_bits32(struct bit_decoder *dec, unsigned int nb_bits); +static __inline uint32_t bit_read_bits32_sub_1(struct bit_decoder *dec, unsigned int nb_bits); +static __inline unsigned int bit_end_of_stream(const struct bit_decoder *dec); +static __inline int bit_refill(struct bit_decoder *dec); + + +/* + * internal implementation + */ + +static const uint32_t BIT_MASK[] = { + 0, 1, 3, 7, 0xF, 0x1F, + 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, + 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, 0x1FFFF, + 0x3FFFF, 0x7FFFF, 0xFFFFF, 0x1FFFFF, 0x3FFFFF, 0x7FFFFF, + 0xFFFFFF, 0x1FFFFFF, 0x3FFFFFF, 0x7FFFFFF, 0xFFFFFFF, 0x1FFFFFFF, + 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF}; /* up to 32 bits */ +#define BIT_MASK_SIZE ARRAY_SIZE(BIT_mask) + + +/** + * @brief read 8 bytes of big-endian data from an unaligned address + * + * @param ptr pointer to the data (can be unaligned) + * + * @returns 64 bit data at mem_ptr address in big-endian byte order + */ + +static __inline uint64_t bit_read_unaligned_64be(const void *ptr) +{ + typedef __attribute__((aligned(1))) uint64_t unalign64; + return cpu_to_be64(*(const unalign64*)ptr); +} + + +/** + * @brief initialize a bit_decoder + * + * @param dec a pointer to an already allocated bit_decoder structure + * @param buf start address of the bitstream buffer + * @param buf_size size of the bitstream in bytes + * + * @returns size of stream (== src_size), or zero if a problem is detected + */ + +static __inline size_t bit_init_decoder(struct bit_decoder *dec, const void *buf, + size_t buf_size) +{ + assert(dec != NULL); + assert(buf != NULL); + + dec->cursor = (const uint8_t *)buf; + + if (buf_size < 1) { + dec->bits_consumed = sizeof(dec->bit_container)*8; + dec->bit_container = 0; + dec->limit_ptr = (const uint8_t *)buf; + return 0; + } + + if (buf_size >= sizeof(dec->bit_container)) { /* normal case */ + dec->bits_consumed = 0; + dec->bit_container = bit_read_unaligned_64be(dec->cursor); + dec->limit_ptr = dec->cursor + buf_size - sizeof(dec->bit_container); + } else { + const uint8_t *ui8_p = (const uint8_t *)(buf); + + dec->bits_consumed = (unsigned int)(sizeof(dec->bit_container) - buf_size) * 8; + + dec->bit_container = (uint64_t)ui8_p[0] << 56; + switch (buf_size) { + case 7: + dec->bit_container += (uint64_t)ui8_p[6] << 8; + /* fall-through */ + case 6: + dec->bit_container += (uint64_t)ui8_p[5] << 16; + /* fall-through */ + case 5: + dec->bit_container += (uint64_t)ui8_p[4] << 24; + /* fall-through */ + case 4: + dec->bit_container += (uint64_t)ui8_p[3] << 32; + /* fall-through */ + case 3: + dec->bit_container += (uint64_t)ui8_p[2] << 40; + /* fall-through */ + case 2: + dec->bit_container += (uint64_t)ui8_p[1] << 48; + /* fall-through */ + default: + break; + } + dec->bit_container >>= dec->bits_consumed; + + dec->limit_ptr = dec->cursor; + } + return buf_size; +} + + +/** + * @brief provides next n bits from local register; local register is not modified + * + * @param dec a pointer to a bit_decoder context + * @param nb_bits number of bits to look; only works if 1 <= nb_bits <= 56 + * + * @returns extracted value + */ + +static __inline uint64_t bit_peek_bits(const struct bit_decoder *dec, unsigned int nb_bits) +{ + /* mask for the shift value register to prevent undefined behaviour */ + uint32_t const reg_mask = 0x3F; + + assert(nb_bits >= 1 && nb_bits <= (64 - 7)); + /* why -7: worst case refill can only put 56 bit in the bit_container */ + + /* shift out consumed bits; return the top nb_bits bits we want to peek */ + return (dec->bit_container << (dec->bits_consumed & reg_mask)) >> (64-nb_bits); +} + + +/** + * @brief count the leading ones in the local register; local register is not modified + * + * @param dec pointer to a bit_decoder context + * + * @returns number of leading ones; + */ + +static __inline unsigned int bit_peek_leading_ones(const struct bit_decoder *dec) +{ + /* mask for the shift value register to prevent undefined behaviour */ + uint32_t const reg_mask = 0x3F; + /* shift out the bits we've already consumed */ + uint64_t const remaining_flip = ~(dec->bit_container << (dec->bits_consumed & reg_mask)); + + /* clzll(0) is undefined behaviour */ + return remaining_flip ? (unsigned int)__builtin_clzll(remaining_flip) : + sizeof(dec->bit_container)*8; +} + + +/** + * @brief mark next n bits in the local register as consumed + * + * @param dec pointer to a bit_decoder context + * @param nb_bits number of bits to skip + */ + +static __inline void bit_consume_bits(struct bit_decoder *dec, unsigned int nb_bits) +{ + dec->bits_consumed += nb_bits; +} + + +/** + * @brief read and consume next n bits from the local register + * @warning do not read more bits than the local register has unconsumed bits. + * If you do this, the bit_refill function will return the BIT_OVERFLOW + * status the next time the register is refilled. + * + * @param dec pointer to a bit_decoder context + * @param nb_bits number of bits to look; only works if 1 <= nb_bits <= 56 + * + * @returns extracted value + */ + +static __inline uint64_t bit_read_bits(struct bit_decoder *dec, unsigned int nb_bits) +{ + uint64_t const read_bits = bit_peek_bits(dec, nb_bits); + + bit_consume_bits(dec, nb_bits); + return read_bits; +} + + +/** + * @brief same as bit_read_bits32() but only returns 32 bit + * @warning do not read more bits than the local register has unconsumed bits. + * If you do this, the bit_refill function will return the BIT_OVERFLOW + * status the next time the register is refilled. + * + * @param dec pointer to a bit_decoder context + * @param nb_bits number of bits to read; only works if 1 <= nb_bits <= 32 + * + * @returns extracted 32 bit value + */ + +static __inline uint32_t bit_read_bits32(struct bit_decoder *dec, unsigned int nb_bits) +{ + assert(nb_bits <= 32); + + return (uint32_t)bit_read_bits(dec, nb_bits); +} + + +/** + * @brief same as bit_read_bits32() but subtract 1 from the extracted value + * @warning do not read more bits than the local register has unconsumed bits. + * If you do this, the bit_refill function will return the BIT_OVERFLOW + * status the next time the register is refilled. + * + * @param dec pointer to a bit_decoder context + * @param nb_bits number of bits to read; only works if nb_bits <= 32 + * + * @returns extracted 32 bit value minus 1 + * + * @note The difference to the bit_read_bits32() function with subtraction is + * that the subtracted value is masked with nb_bits. E.g. if you read 4 + * bits from the bitstream and get 0 and then subtract 1, you get 0xFF + * instead of 0xFFFFFFFF + */ + +static __inline uint32_t bit_read_bits32_sub_1(struct bit_decoder *dec, unsigned int nb_bits) +{ + /* mask for the shift value register to prevent undefined behaviour */ + uint32_t const reg_mask = sizeof(dec->bit_container)*8 - 1; + unsigned int const shift_bits = (64 - dec->bits_consumed - nb_bits) & reg_mask; + uint32_t bits_unmask; + + assert(nb_bits <= 32); + + bits_unmask = (uint32_t)(dec->bit_container >> shift_bits); + bit_consume_bits(dec, nb_bits); + return (bits_unmask - 1) & BIT_MASK[nb_bits]; +} + + +/** + * @brief refill the local register from the buffer previously set in + * bit_init_decoder() + * + * @param dec a bitstream decoding context + * + * @note this function is safe, it guarantees that it does not read beyond + * initialize buffer + * + * @returns the status of bit_decoder internal register; + * BIT_UNFINISHED: internal register is filled with at least _57-bits_ + * BIT_END_OF_BUFFER: reached the end of the buffer, only some bits are left in the bitstream + * BIT_ALL_READ_IN: _all_ bits of the buffer have been consumed + * BIT_OVERFLOW: more bits have been consumed than contained in the local register + */ + +static __inline int bit_refill(struct bit_decoder *dec) +{ + unsigned int const bytes_consumed = dec->bits_consumed >> 3; + + if (unlikely(dec->bits_consumed > sizeof(dec->bit_container)*8)) + return BIT_OVERFLOW; + + if (dec->cursor + bytes_consumed < dec->limit_ptr) { + /* Advance the pointer by the number of full bytes we consumed */ + dec->cursor += bytes_consumed; + /* Refill the bit container */ + dec->bit_container = bit_read_unaligned_64be(dec->cursor); + /* The number of bits that we have already consumed in the + * current byte, excluding the bits that formed a complete byte + * and were already processed. + */ + dec->bits_consumed &= 0x7; + return BIT_UNFINISHED; + } + + if (dec->cursor == dec->limit_ptr) { + if (dec->bits_consumed == sizeof(dec->bit_container)*8) + return BIT_ALL_READ_IN; + return BIT_END_OF_BUFFER; + } + + /* limit_ptr < (cursor + bytes_consumed) < end */ + dec->bits_consumed -= (dec->limit_ptr - dec->cursor)*8; + dec->cursor = dec->limit_ptr; + dec->bit_container = bit_read_unaligned_64be(dec->cursor); + + return BIT_END_OF_BUFFER; +} + + +/** + * @brief Check if the end of the bitstream has been reached + * + * @param dec a bitstream decoding context + * + * @returns 1 if bit_decoder has _exactly_ reached its end (all bits consumed) + */ + +static __inline unsigned int bit_end_of_stream(const struct bit_decoder *dec) +{ + return ((dec->cursor == dec->limit_ptr) && + (dec->bits_consumed == sizeof(dec->bit_container)*8)); +} + +#endif /* READ_BITSTREAM_H */ diff --git a/lib/cmp_icu.c b/lib/icu_compress/cmp_icu.c similarity index 57% rename from lib/cmp_icu.c rename to lib/icu_compress/cmp_icu.c index b710750153b93bb79de187604ed615cc52061ad0..36837c6441de21c2a4daf69c1ea411be7bff27e3 100644 --- a/lib/cmp_icu.c +++ b/lib/icu_compress/cmp_icu.c @@ -32,13 +32,42 @@ #include <string.h> #include <limits.h> -#include <byteorder.h> -#include <cmp_debug.h> -#include <cmp_data_types.h> -#include <cmp_support.h> -#include <cmp_icu.h> -#include <cmp_entity.h> +#include "../common/byteorder.h" +#include "../common/cmp_debug.h" +#include "../common/cmp_data_types.h" +#include "../common/cmp_support.h" +#include "../common/cmp_entity.h" +#include "../cmp_icu.h" +#include "../cmp_chunk.h" + + +/** + * @brief default implementation of the get_timestamp() function + * + * @returns 0 + */ + +static uint64_t default_get_timestamp(void) +{ + return 0; +} + + +/** + * @brief function pointer to a function returning a current PLATO timestamp + * initialised with the compress_chunk_init() function + */ + +static uint64_t (*get_timestamp)(void) = default_get_timestamp; + + +/** + * @brief holding the version_identifier for the compression header + * initialised with the compress_chunk_init() function + */ + +static uint32_t version_identifier; /** @@ -67,6 +96,23 @@ struct encoder_setupt { }; +/** + * @brief types of chunks containing different types of collections + * according to DetailedBudgetWorking_2023-10-11 + */ + +enum chunk_type { + CHUNK_TYPE_UNKNOWN, + CHUNK_TYPE_NCAM_IMAGETTE, + CHUNK_TYPE_SHORT_CADENCE, + CHUNK_TYPE_LONG_CADENCE, + CHUNK_TYPE_SAT_IMAGETTE, + CHUNK_TYPE_OFFSET_BACKGROUND, /* N-CAM */ + CHUNK_TYPE_SMEARING, + CHUNK_TYPE_F_CHAIN, +}; + + /** * @brief create an ICU compression configuration * @@ -92,7 +138,7 @@ struct cmp_cfg cmp_cfg_icu_create(enum cmp_data_type data_type, enum cmp_mode cm cfg.round = lossy_par; cfg.max_used_bits = &MAX_USED_BITS_SAFE; - if (cmp_cfg_gen_par_is_invalid(&cfg, ICU_CHECK)) + if (cmp_cfg_gen_par_is_invalid(&cfg, ICU_CHECK) || data_type == DATA_TYPE_CHUNK) cfg.data_type = DATA_TYPE_UNKNOWN; return cfg; @@ -119,6 +165,20 @@ struct cmp_cfg cmp_cfg_icu_create(enum cmp_data_type data_type, enum cmp_mode cm * * @returns the size of the compressed_data buffer on success; 0 if the * parameters are invalid + * + * @note There is a difference in the data_samples parameter when compressing + * imagette data compared to compressing non-imagette data! + * When compressing non-imagette data, the compressor expects that the + * collection header will always prefix the non-imagette data. Therefore, the + * data_samples parameter is simply the number of entries in the collection. It + * is not intended to join multiple non-imagette collections and compress them + * together. + * When compressing imagette data, the length of the entire data to be + * compressed, including the collection header, is measured in 16-bit samples. + * The compressor makes in this case no distinction between header and imagette + * data. Therefore, the data_samples parameter is the number of 16-bit imagette + * pixels plus the length of the collection header, measured in 16-bit units. + * The compression of multiple joined collections is possible. */ uint32_t cmp_cfg_icu_buffers(struct cmp_cfg *cfg, void *data_to_compress, @@ -129,7 +189,7 @@ uint32_t cmp_cfg_icu_buffers(struct cmp_cfg *cfg, void *data_to_compress, uint32_t cmp_data_size, hdr_size; if (!cfg) { - debug_print("Error: pointer to the compression configuration structure is NULL.\n"); + debug_print("Error: pointer to the compression configuration structure is NULL."); return 0; } @@ -138,6 +198,7 @@ uint32_t cmp_cfg_icu_buffers(struct cmp_cfg *cfg, void *data_to_compress, cfg->samples = data_samples; cfg->icu_new_model_buf = updated_model; cfg->icu_output_buf = compressed_data; + /* cfg->buffer_length = cmp_data_size; */ cfg->buffer_length = compressed_data_len_samples; if (cmp_cfg_icu_buffers_is_invalid(cfg)) @@ -147,7 +208,7 @@ uint32_t cmp_cfg_icu_buffers(struct cmp_cfg *cfg, void *data_to_compress, hdr_size = cmp_ent_cal_hdr_size(cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW); if ((cmp_data_size + hdr_size) > CMP_ENTITY_MAX_SIZE || cmp_data_size > CMP_ENTITY_MAX_SIZE) { - debug_print("Error: The buffer for the compressed data is too large to fit in a compression entity.\n"); + debug_print("Error: The buffer for the compressed data is too large to fit in a compression entity."); return 0; } @@ -172,8 +233,10 @@ uint32_t cmp_cfg_icu_buffers(struct cmp_cfg *cfg, void *data_to_compress, int cmp_cfg_icu_max_used_bits(struct cmp_cfg *cfg, const struct cmp_max_used_bits *max_used_bits) { - if (cfg) - cfg->max_used_bits = max_used_bits; + if (!cfg) + return -1; + + cfg->max_used_bits = max_used_bits; if (cmp_cfg_icu_max_used_bits_out_of_limit(max_used_bits)) return -1; @@ -202,7 +265,10 @@ int cmp_cfg_icu_imagette(struct cmp_cfg *cfg, uint32_t cmp_par, cfg->golomb_par = cmp_par; cfg->spill = spillover_par; - return cmp_cfg_imagette_is_invalid(cfg, ICU_CHECK); + if (cmp_cfg_imagette_is_invalid(cfg, ICU_CHECK)) + return -1; + + return 0; } @@ -253,7 +319,10 @@ int cmp_cfg_fx_cob(struct cmp_cfg *cfg, cfg->spill_ecob = spillover_ecob; cfg->spill_fx_cob_variance = spillover_fx_cob_variance; - return cmp_cfg_fx_cob_is_invalid(cfg); + if (cmp_cfg_fx_cob_is_invalid(cfg)) + return -1; + + return 0; } @@ -283,15 +352,40 @@ int cmp_cfg_aux(struct cmp_cfg *cfg, if (!cfg) return -1; - cfg->cmp_par_mean = cmp_par_mean; - cfg->cmp_par_variance = cmp_par_variance; - cfg->cmp_par_pixels_error = cmp_par_pixels_error; + switch (cfg->data_type) { + case DATA_TYPE_OFFSET: + case DATA_TYPE_F_CAM_OFFSET: + cfg->cmp_par_offset_mean = cmp_par_mean; + cfg->spill_offset_mean = spillover_mean; + cfg->cmp_par_offset_variance = cmp_par_variance; + cfg->spill_offset_variance = spillover_variance; + break; + case DATA_TYPE_BACKGROUND: + case DATA_TYPE_F_CAM_BACKGROUND: + cfg->cmp_par_background_mean = cmp_par_mean; + cfg->spill_background_mean = spillover_mean; + cfg->cmp_par_background_variance = cmp_par_variance; + cfg->spill_background_variance = spillover_variance; + cfg->cmp_par_background_pixels_error = cmp_par_pixels_error; + cfg->spill_background_pixels_error = spillover_pixels_error; + break; + case DATA_TYPE_SMEARING: + cfg->cmp_par_smearing_mean = cmp_par_mean; + cfg->spill_smearing_mean = spillover_mean; + cfg->cmp_par_smearing_variance = cmp_par_variance; + cfg->spill_smearing_variance = spillover_variance; + cfg->cmp_par_smearing_pixels_error = cmp_par_pixels_error; + cfg->spill_smearing_pixels_error = spillover_pixels_error; + break; + default: + debug_print("Error: The compression data type is not an auxiliary science compression data type."); + return -1; + } - cfg->spill_mean = spillover_mean; - cfg->spill_variance = spillover_variance; - cfg->spill_pixels_error = spillover_pixels_error; + if (cmp_cfg_aux_is_invalid(cfg)) + return -1; - return cmp_cfg_aux_is_invalid(cfg); + return 0; } @@ -325,15 +419,15 @@ static uint32_t map_to_pos(uint32_t value_to_map, unsigned int max_data_bits) /** - * @brief put the value of up to 32 bits into a bitstream + * @brief put the value of up to 32 bits into a big endian bitstream * - * @param value the value to put - * @param n_bits number of bits to put in the bitstream + * @param value the value to put into the bitstream + * @param n_bits number of bits to put into the bitstream * @param bit_offset bit index where the bits will be put, seen from * the very beginning of the bitstream * @param bitstream_adr this is the pointer to the beginning of the * bitstream (can be NULL) - * @param max_stream_len maximum length of the bitstream in bits; is + * @param max_stream_len maximum length of the bitstream in *bits*; is * ignored if bitstream_adr is NULL * * @returns length in bits of the generated bitstream on success; returns @@ -344,10 +438,22 @@ static uint32_t map_to_pos(uint32_t value_to_map, unsigned int max_data_bits) static int put_n_bits32(uint32_t value, unsigned int n_bits, int bit_offset, uint32_t *bitstream_adr, unsigned int max_stream_len) { + /* + * UNSEGMENTED + * |-----------|XXXXXX|---------------|--------------------------------| + * |-bits_left-|n_bits|-------------------bits_right-------------------| + * ^ + * local_adr + * SEGMENTED + * |-----------------------------|XXX|XXX|-----------------------------| + * |----------bits_left----------|n_bits-|---------bits_right----------| + */ + unsigned int bits_left = bit_offset & 0x1F; + unsigned int bits_right = 64 - bits_left - n_bits; + unsigned int shift_left = 32 - n_bits; + int stream_len = (int)(n_bits + (unsigned int)bit_offset); uint32_t *local_adr; - uint32_t mask; - unsigned int shiftRight, shiftLeft, bitsLeft, bitsRight; - int stream_len = (int)(n_bits + (unsigned int)bit_offset); /* overflow results in a negative return value */ + uint32_t mask, tmp; /* Leave in case of erroneous input */ if (bit_offset < 0) @@ -356,100 +462,37 @@ static int put_n_bits32(uint32_t value, unsigned int n_bits, int bit_offset, if (n_bits == 0) return stream_len; - if (n_bits > 32) + if ((int)shift_left < 0) /* check n_bits <= 32 */ return -1; - /* Do we need to write data to the bitstream? */ - if (!bitstream_adr) + if (!bitstream_adr) /* Do we need to write data to the bitstream? */ return stream_len; /* Check if bitstream buffer is large enough */ - if ((unsigned int)stream_len > max_stream_len) { - debug_print("Error: The buffer for the compressed data is too small to hold the compressed data. Try a larger buffer_length parameter.\n"); + if ((unsigned int)stream_len > max_stream_len) return CMP_ERROR_SMALL_BUF; - } - - /* (M) is the n_bits parameter large enough to cover all value bits; the - * calculations can be re-used in the unsegmented code, so we have no overhead - */ - shiftRight = 32 - n_bits; - mask = 0xFFFFFFFFU >> shiftRight; - value &= mask; - /* Separate the bit_offset into word offset (set local_adr pointer) and local bit offset (bitsLeft) */ local_adr = bitstream_adr + (bit_offset >> 5); - bitsLeft = bit_offset & 0x1F; - /* Calculate the bitsRight for the unsegmented case. If bitsRight is - * negative we need to split the value over two words - */ - bitsRight = shiftRight - bitsLeft; - - if ((int)bitsRight >= 0) { - /* UNSEGMENTED - * - *|-----------|XXXXX|----------------| - * bitsLeft n bitsRight - * - * -> to get the mask: - * shiftRight = bitsLeft + bitsRight = 32 - n - * shiftLeft = bitsRight = 32 - n - bitsLeft = shiftRight - bitsLeft - */ - - shiftLeft = bitsRight; - - /* generate the mask, the bits for the values will be true - * shiftRight = 32 - n_bits; see (M) above! - * mask = (0XFFFFFFFF >> shiftRight) << shiftLeft; see (M) above! - */ - mask <<= shiftLeft; - value <<= shiftLeft; - - /* clear the destination with inverse mask */ - *(local_adr) &= ~mask; - - /* assign the value */ - *(local_adr) |= value; + /* clear the destination with inverse mask */ + mask = (0XFFFFFFFFU << shift_left) >> bits_left; + tmp = be32_to_cpu(*local_adr) & ~mask; - } else { - /* SEGMENTED - * - *|-----------------------------|XXX| |XX|------------------------------| - * bitsLeft n1 n2 bitsRight - * - * -> to get the mask part 1: - * shiftRight = bitsLeft - * n1 = n - (bitsLeft + n - 32) = 32 - bitsLeft - * - * -> to get the mask part 2: - * n2 = bitsLeft + n - 32 = -(32 - n - bitsLeft) = -(bitsRight_UNSEGMENTED) - * shiftLeft = 32 - n2 = 32 - (bitsLeft + n - 32) = 64 - bitsLeft - n - * - */ - - unsigned int n2 = -bitsRight; - - /* part 1: */ - shiftRight = bitsLeft; - mask = 0XFFFFFFFFU >> shiftRight; - - /* clear the destination with inverse mask */ - *(local_adr) &= ~mask; - - /* assign the value part 1 */ - *(local_adr) |= (value >> n2); - - /* part 2: */ - /* adjust address */ - local_adr += 1; - shiftLeft = 32 - n2; - mask = 0XFFFFFFFFU >> n2; + /* put (the first part of) the value into the bitstream */ + tmp |= (value << shift_left) >> bits_left; + *local_adr = cpu_to_be32(tmp); + + /* Do we need to split the value over two words (SEGMENTED case) */ + if (bits_right < 32) { + local_adr++; /* adjust address */ /* clear the destination */ - *(local_adr) &= mask; + mask = 0XFFFFFFFFU << bits_right; + tmp = be32_to_cpu(*local_adr) & ~mask; - /* assign the value part 2 */ - *(local_adr) |= (value << shiftLeft); + /* put the 2nd part of the value into the bitstream */ + tmp |= value << bits_right; + *local_adr = cpu_to_be32(tmp); } return stream_len; } @@ -458,75 +501,70 @@ static int put_n_bits32(uint32_t value, unsigned int n_bits, int bit_offset, /** * @brief forms the codeword according to the Rice code * - * @param value value to be encoded + * @param value value to be encoded (must be smaller or equal than cmp_ima_max_spill(m)) * @param m Golomb parameter, only m's which are power of 2 are allowed - * @param log2_m Rice parameter, is log_2(m) calculate outside function + * maximum allowed Golomb parameter is 0x80000000 + * @param log2_m Rice parameter, is ilog_2(m) calculate outside function * for better performance - * @param cw address were the encode code word is stored + * @param cw address where the code word is stored * - * @returns the length of the formed code word in bits - * @note no check if the generated code word is not longer than 32 bits! + * @warning no check of the validity of the input parameters! + * @returns the length of the formed code word in bits; code word is invalid if + * the return value is greater than 32 */ static uint32_t rice_encoder(uint32_t value, uint32_t m, uint32_t log2_m, uint32_t *cw) { - uint32_t g; /* quotient of value/m */ - uint32_t q; /* quotient code without ending zero */ - uint32_t r; /* remainder of value/m */ - uint32_t rl; /* remainder length */ + uint32_t q = value >> log2_m; /* quotient of value/m */ + uint32_t qc = (1U << q) - 1; /* quotient code without ending zero */ - g = value >> log2_m; /* quotient, number of leading bits */ - q = (1U << g) - 1; /* prepare the quotient code without ending zero */ + uint32_t r = value & (m-1); /* remainder of value/m */ + uint32_t rl = log2_m + 1; /* length of the remainder (+1 for the 0 in the quotient code) */ - r = value & (m-1); /* calculate the remainder */ - rl = log2_m + 1; /* length of the remainder (+1 for the 0 in the quotient code) */ - *cw = (q << rl) | r; /* put the quotient and remainder code together */ + *cw = (qc << (rl & 0x1FU)) | r; /* put the quotient and remainder code together */ /* * NOTE: If log2_m = 31 -> rl = 32, (q << rl) leads to an undefined * behavior. However, in this case, a valid code with a maximum of 32 - * bits can only be formed if q = 0. Any shift with 0 << x always - * results in 0, which forms the correct codeword in this case. For - * performance reasons, this undefined behaviour is not caught. + * bits can only be formed if q = 0 and qc = 0. To prevent undefined + * behavior, the right shift operand is masked (& 0x1FU) */ - return rl + g; /* calculate the length of the code word */ + return rl + q; /* calculate the length of the code word */ } /** * @brief forms a codeword according to the Golomb code * - * @param value value to be encoded + * @param value value to be encoded (must be smaller or equal than cmp_ima_max_spill(m)) * @param m Golomb parameter (have to be bigger than 0) - * @param log2_m is log_2(m) calculate outside function for better - * performance - * @param cw address were the formed code word is stored + * @param log2_m is ilog_2(m) calculate outside function for better performance + * @param cw address where the code word is stored * - * @returns the length of the formed code word in bits - * @note no check if the generated code word is not longer than 32 bits! + * @warning no check of the validity of the input parameters! + * @returns the length of the formed code word in bits; code word is invalid if + * the return value is greater than 32 */ static uint32_t golomb_encoder(uint32_t value, uint32_t m, uint32_t log2_m, uint32_t *cw) { - uint32_t len0, b, g, q, lg; - uint32_t len; - uint32_t cutoff; - - len0 = log2_m + 1; /* codeword length in group 0 */ - cutoff = (1U << (log2_m + 1)) - m; /* members in group 0 */ + uint32_t len = log2_m + 1; /* codeword length in group 0 */ + uint32_t cutoff = (0x2U << log2_m) - m; /* members in group 0 */ if (value < cutoff) { /* group 0 */ *cw = value; - len = len0; } else { /* other groups */ - g = (value-cutoff) / m; /* this group is which one */ - b = cutoff << 1; /* form the base codeword */ - lg = len0 + g; /* it has lg remainder bits */ - q = (1U << g) - 1; /* prepare the left side in unary */ - *cw = (q << (len0+1)) + b + (value-cutoff) - g*m; /* composed codeword */ - len = lg + 1; /* length of the codeword */ + uint32_t const reg_mask = 0x1FU; /* mask for the right shift operand to prevent undefined behavior */ + uint32_t g = (value-cutoff) / m; /* group number of same cw length */ + uint32_t r = (value-cutoff) - g * m; /* member in the group */ + uint32_t gc = (1U << (g & reg_mask)) - 1; /* prepare the left side in unary */ + uint32_t b = cutoff << 1; /* form the base codeword */ + + *cw = gc << ((len+1) & reg_mask); /* composed codeword part 1 */ + *cw += b + r; /* composed codeword part 2 */ + len += 1 + g; /* length of the codeword */ } return len; } @@ -724,7 +762,7 @@ static int encode_value(uint32_t data, uint32_t model, int stream_len, model = round_fwd(model, setup->lossy_par); if (data & mask || model & mask) { - debug_print("Error: The data or the model of the data are bigger than expected.\n"); + debug_print("Error: The data or the model of the data are bigger than expected."); return CMP_ERROR_HIGH_VALUE; } @@ -737,16 +775,14 @@ static int encode_value(uint32_t data, uint32_t model, int stream_len, * @note we round down to the next 4-byte allied address because we access the * cmp_buffer in uint32_t words * - * @param buffer_length length of the icu_output_buf in samples - * @param data_type used compression data type + * @param buffer_length length of the icu_output_buf in bytes * * @returns buffer size in bits - * */ -static uint32_t cmp_buffer_length_to_bits(uint32_t buffer_length, enum cmp_data_type data_type) +static uint32_t cmp_buffer_length_to_bits(uint32_t buffer_length) { - return (cmp_cal_size_of_data(buffer_length, data_type) & ~0x3U) * CHAR_BIT; + return (buffer_length & ~0x3U) * 8; } @@ -760,38 +796,24 @@ static uint32_t cmp_buffer_length_to_bits(uint32_t buffer_length, enum cmp_data_ * @param max_data_bits how many bits are needed to represent the highest possible value * @param cfg pointer to the compression configuration structure * - * @returns 0 on success; otherwise error + * @warning input parameters are not checked for validity */ -static int configure_encoder_setup(struct encoder_setupt *setup, - uint32_t cmp_par, uint32_t spillover, - uint32_t lossy_par, uint32_t max_data_bits, - const struct cmp_cfg *cfg) +static void configure_encoder_setup(struct encoder_setupt *setup, + uint32_t cmp_par, uint32_t spillover, + uint32_t lossy_par, uint32_t max_data_bits, + const struct cmp_cfg *cfg) { - if (!setup) - return -1; - - if (!cfg) - return -1; - - if (max_data_bits > 32) { - debug_print("Error: max_data_bits parameter is bigger than 32 bits.\n"); - return -1; - } - - memset(setup, 0, sizeof(*setup)); + memset(setup, 0, sizeof(struct encoder_setupt)); setup->encoder_par1 = cmp_par; setup->max_data_bits = max_data_bits; setup->lossy_par = lossy_par; setup->bitstream_adr = cfg->icu_output_buf; - setup->max_stream_len = cmp_buffer_length_to_bits(cfg->buffer_length, cfg->data_type); + setup->max_stream_len = cmp_buffer_length_to_bits(cfg->buffer_length); if (cfg->cmp_mode != CMP_MODE_STUFF) { - if (ilog_2(cmp_par) < 0) - return -1; - setup->encoder_par2 = (uint32_t)ilog_2(cmp_par); - + setup->encoder_par2 = ilog_2(cmp_par); setup->spillover_par = spillover; /* for encoder_par1 which are a power of two we can use the faster rice_encoder */ @@ -814,13 +836,12 @@ static int configure_encoder_setup(struct encoder_setupt *setup, setup->encode_method_f = &encode_value_none; setup->max_data_bits = cmp_par; break; + /* LCOV_EXCL_START */ case CMP_MODE_RAW: - default: - return -1; + /* CMP_MODE_RAW is already handled before; nothing to do here */ + break; + /* LCOV_EXCL_STOP */ } - - - return 0; } @@ -835,12 +856,11 @@ static int configure_encoder_setup(struct encoder_setupt *setup, * bigger than the max_used_bits parameter allows */ -static int compress_imagette(const struct cmp_cfg *cfg) +static int compress_imagette(const struct cmp_cfg *cfg, int stream_len) { - int err; - int stream_len = 0; size_t i; struct encoder_setupt setup; + uint32_t max_data_bits; uint16_t *data_buf = cfg->input_buf; uint16_t *model_buf = cfg->model_buf; @@ -849,70 +869,50 @@ static int compress_imagette(const struct cmp_cfg *cfg) uint16_t *up_model_buf = NULL; if (model_mode_is_used(cfg->cmp_mode)) { - model = model_buf[0]; + model = get_unaligned(&model_buf[0]); next_model_p = &model_buf[1]; up_model_buf = cfg->icu_new_model_buf; } - err = configure_encoder_setup(&setup, cfg->golomb_par, cfg->spill, - cfg->round, cfg->max_used_bits->nc_imagette, cfg); - if (err) - return -1; + switch (cfg->data_type) { + case DATA_TYPE_IMAGETTE: + case DATA_TYPE_IMAGETTE_ADAPTIVE: + max_data_bits = cfg->max_used_bits->nc_imagette; + break; + case DATA_TYPE_SAT_IMAGETTE: + case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE: + max_data_bits = cfg->max_used_bits->saturated_imagette; + break; + default: + case DATA_TYPE_F_CAM_IMAGETTE: + case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE: + max_data_bits = cfg->max_used_bits->fc_imagette; + break; + } + + configure_encoder_setup(&setup, cfg->golomb_par, cfg->spill, cfg->round, + max_data_bits, cfg); for (i = 0;; i++) { - stream_len = encode_value(data_buf[i], model, stream_len, &setup); + stream_len = encode_value(get_unaligned(&data_buf[i]), + model, stream_len, &setup); if (stream_len <= 0) break; - if (up_model_buf) - up_model_buf[i] = cmp_up_model(data_buf[i], model, cfg->model_value, + if (up_model_buf) { + uint16_t data = get_unaligned(&data_buf[i]); + up_model_buf[i] = cmp_up_model(data, model, cfg->model_value, setup.lossy_par); + } if (i >= cfg->samples-1) break; - model = next_model_p[i]; + model = get_unaligned(&next_model_p[i]); } return stream_len; } -/** - * @brief compress the multi-entry packet header structure and sets the data, - * model and up_model pointers to the data after the header - * - * @param data pointer to a pointer pointing to the data to be compressed - * @param model pointer to a pointer pointing to the model of the data - * @param up_model pointer to a pointer pointing to the updated model buffer - * @param compressed_data pointer to the compressed data buffer - * - * @returns the bit length of the bitstream on success; negative on error, - * - * @note the (void **) cast relies on all pointer types having the same internal - * representation which is common, but not universal; http://www.c-faq.com/ptrs/genericpp.html - */ - -static int compress_multi_entry_hdr(void **data, void **model, void **up_model, - void *compressed_data) -{ - if (*up_model) { - if (*data) - memcpy(*up_model, *data, MULTI_ENTRY_HDR_SIZE); - *up_model = (uint8_t *)*up_model + MULTI_ENTRY_HDR_SIZE; - } - - if (*data) { - if (compressed_data) - memcpy(compressed_data, *data, MULTI_ENTRY_HDR_SIZE); - *data = (uint8_t *)*data + MULTI_ENTRY_HDR_SIZE; - } - - if (*model) - *model = (uint8_t *)*model + MULTI_ENTRY_HDR_SIZE; - - return MULTI_ENTRY_HDR_SIZE * CHAR_BIT; -} - - /** * @brief compress short normal light flux (S_FX) data * @@ -923,10 +923,8 @@ static int compress_multi_entry_hdr(void **data, void **model, void **up_model, * value in the bitstream */ -static int compress_s_fx(const struct cmp_cfg *cfg) +static int compress_s_fx(const struct cmp_cfg *cfg, int stream_len) { - int err; - int stream_len = 0; size_t i; struct s_fx *data_buf = cfg->input_buf; @@ -936,28 +934,19 @@ static int compress_s_fx(const struct cmp_cfg *cfg) struct s_fx model; struct encoder_setupt setup_exp_flag, setup_fx; - if (model_mode_is_used(cfg->cmp_mode)) - up_model_buf = cfg->icu_new_model_buf; - - stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf, - (void **)&up_model_buf, cfg->icu_output_buf); - if (model_mode_is_used(cfg->cmp_mode)) { model = model_buf[0]; next_model_p = &model_buf[1]; + up_model_buf = cfg->icu_new_model_buf; } else { memset(&model, 0, sizeof(model)); next_model_p = data_buf; } - err = configure_encoder_setup(&setup_exp_flag, cfg->cmp_par_exp_flags, cfg->spill_exp_flags, - cfg->round, cfg->max_used_bits->s_exp_flags, cfg); - if (err) - return -1; - err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, - cfg->round, cfg->max_used_bits->s_fx, cfg); - if (err) - return -1; + configure_encoder_setup(&setup_exp_flag, cfg->cmp_par_exp_flags, cfg->spill_exp_flags, + cfg->round, cfg->max_used_bits->s_exp_flags, cfg); + configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, + cfg->round, cfg->max_used_bits->s_fx, cfg); for (i = 0;; i++) { stream_len = encode_value(data_buf[i].exp_flags, model.exp_flags, @@ -995,10 +984,8 @@ static int compress_s_fx(const struct cmp_cfg *cfg) * value in the bitstream */ -static int compress_s_fx_efx(const struct cmp_cfg *cfg) +static int compress_s_fx_efx(const struct cmp_cfg *cfg, int stream_len) { - int err; - int stream_len = 0; size_t i; struct s_fx_efx *data_buf = cfg->input_buf; @@ -1008,32 +995,21 @@ static int compress_s_fx_efx(const struct cmp_cfg *cfg) struct s_fx_efx model; struct encoder_setupt setup_exp_flag, setup_fx, setup_efx; - if (model_mode_is_used(cfg->cmp_mode)) - up_model_buf = cfg->icu_new_model_buf; - - stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf, - (void **)&up_model_buf, cfg->icu_output_buf); - if (model_mode_is_used(cfg->cmp_mode)) { model = model_buf[0]; next_model_p = &model_buf[1]; + up_model_buf = cfg->icu_new_model_buf; } else { memset(&model, 0, sizeof(model)); next_model_p = data_buf; } - err = configure_encoder_setup(&setup_exp_flag, cfg->cmp_par_exp_flags, cfg->spill_exp_flags, - cfg->round, cfg->max_used_bits->s_exp_flags, cfg); - if (err) - return -1; - err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, - cfg->round, cfg->max_used_bits->s_fx, cfg); - if (err) - return -1; - err = configure_encoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx, - cfg->round, cfg->max_used_bits->s_efx, cfg); - if (err) - return -1; + configure_encoder_setup(&setup_exp_flag, cfg->cmp_par_exp_flags, cfg->spill_exp_flags, + cfg->round, cfg->max_used_bits->s_exp_flags, cfg); + configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, + cfg->round, cfg->max_used_bits->s_fx, cfg); + configure_encoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx, + cfg->round, cfg->max_used_bits->s_efx, cfg); for (i = 0;; i++) { stream_len = encode_value(data_buf[i].exp_flags, model.exp_flags, @@ -1077,10 +1053,8 @@ static int compress_s_fx_efx(const struct cmp_cfg *cfg) * value in the bitstream */ -static int compress_s_fx_ncob(const struct cmp_cfg *cfg) +static int compress_s_fx_ncob(const struct cmp_cfg *cfg, int stream_len) { - int err; - int stream_len = 0; size_t i; struct s_fx_ncob *data_buf = cfg->input_buf; @@ -1090,32 +1064,21 @@ static int compress_s_fx_ncob(const struct cmp_cfg *cfg) struct s_fx_ncob model; struct encoder_setupt setup_exp_flag, setup_fx, setup_ncob; - if (model_mode_is_used(cfg->cmp_mode)) - up_model_buf = cfg->icu_new_model_buf; - - stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf, - (void **)&up_model_buf, cfg->icu_output_buf); - if (model_mode_is_used(cfg->cmp_mode)) { model = model_buf[0]; next_model_p = &model_buf[1]; + up_model_buf = cfg->icu_new_model_buf; } else { memset(&model, 0, sizeof(model)); next_model_p = data_buf; } - err = configure_encoder_setup(&setup_exp_flag, cfg->cmp_par_exp_flags, cfg->spill_exp_flags, - cfg->round, cfg->max_used_bits->s_exp_flags, cfg); - if (err) - return -1; - err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, - cfg->round, cfg->max_used_bits->s_fx, cfg); - if (err) - return -1; - err = configure_encoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob, - cfg->round, cfg->max_used_bits->s_ncob, cfg); - if (err) - return -1; + configure_encoder_setup(&setup_exp_flag, cfg->cmp_par_exp_flags, cfg->spill_exp_flags, + cfg->round, cfg->max_used_bits->s_exp_flags, cfg); + configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, + cfg->round, cfg->max_used_bits->s_fx, cfg); + configure_encoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob, + cfg->round, cfg->max_used_bits->s_ncob, cfg); for (i = 0;; i++) { stream_len = encode_value(data_buf[i].exp_flags, model.exp_flags, @@ -1165,10 +1128,8 @@ static int compress_s_fx_ncob(const struct cmp_cfg *cfg) * value in the bitstream */ -static int compress_s_fx_efx_ncob_ecob(const struct cmp_cfg *cfg) +static int compress_s_fx_efx_ncob_ecob(const struct cmp_cfg *cfg, int stream_len) { - int err; - int stream_len = 0; size_t i; struct s_fx_efx_ncob_ecob *data_buf = cfg->input_buf; @@ -1179,40 +1140,25 @@ static int compress_s_fx_efx_ncob_ecob(const struct cmp_cfg *cfg) struct encoder_setupt setup_exp_flag, setup_fx, setup_ncob, setup_efx, setup_ecob; - if (model_mode_is_used(cfg->cmp_mode)) - up_model_buf = cfg->icu_new_model_buf; - - stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf, - (void **)&up_model_buf, cfg->icu_output_buf); - if (model_mode_is_used(cfg->cmp_mode)) { model = model_buf[0]; next_model_p = &model_buf[1]; + up_model_buf = cfg->icu_new_model_buf; } else { memset(&model, 0, sizeof(model)); next_model_p = data_buf; } - err = configure_encoder_setup(&setup_exp_flag, cfg->cmp_par_exp_flags, cfg->spill_exp_flags, - cfg->round, cfg->max_used_bits->s_exp_flags, cfg); - if (err) - return -1; - err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, - cfg->round, cfg->max_used_bits->s_fx, cfg); - if (err) - return -1; - err = configure_encoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob, - cfg->round, cfg->max_used_bits->s_ncob, cfg); - if (err) - return -1; - err = configure_encoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx, - cfg->round, cfg->max_used_bits->s_efx, cfg); - if (err) - return -1; - err = configure_encoder_setup(&setup_ecob, cfg->cmp_par_ecob, cfg->spill_ecob, - cfg->round, cfg->max_used_bits->s_ecob, cfg); - if (err) - return -1; + configure_encoder_setup(&setup_exp_flag, cfg->cmp_par_exp_flags, cfg->spill_exp_flags, + cfg->round, cfg->max_used_bits->s_exp_flags, cfg); + configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, + cfg->round, cfg->max_used_bits->s_fx, cfg); + configure_encoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob, + cfg->round, cfg->max_used_bits->s_ncob, cfg); + configure_encoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx, + cfg->round, cfg->max_used_bits->s_efx, cfg); + configure_encoder_setup(&setup_ecob, cfg->cmp_par_ecob, cfg->spill_ecob, + cfg->round, cfg->max_used_bits->s_ecob, cfg); for (i = 0;; i++) { stream_len = encode_value(data_buf[i].exp_flags, model.exp_flags, @@ -1280,10 +1226,8 @@ static int compress_s_fx_efx_ncob_ecob(const struct cmp_cfg *cfg) * value in the bitstream */ -static int compress_f_fx(const struct cmp_cfg *cfg) +static int compress_f_fx(const struct cmp_cfg *cfg, int stream_len) { - int err; - int stream_len = 0; size_t i; struct f_fx *data_buf = cfg->input_buf; @@ -1293,24 +1237,17 @@ static int compress_f_fx(const struct cmp_cfg *cfg) struct f_fx model; struct encoder_setupt setup_fx; - if (model_mode_is_used(cfg->cmp_mode)) - up_model_buf = cfg->icu_new_model_buf; - - stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf, - (void **)&up_model_buf, cfg->icu_output_buf); - if (model_mode_is_used(cfg->cmp_mode)) { model = model_buf[0]; next_model_p = &model_buf[1]; + up_model_buf = cfg->icu_new_model_buf; } else { memset(&model, 0, sizeof(model)); next_model_p = data_buf; } - err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, - cfg->round, cfg->max_used_bits->f_fx, cfg); - if (err) - return -1; + configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, + cfg->round, cfg->max_used_bits->f_fx, cfg); for (i = 0;; i++) { stream_len = encode_value(data_buf[i].fx, model.fx, stream_len, @@ -1342,10 +1279,8 @@ static int compress_f_fx(const struct cmp_cfg *cfg) * value in the bitstream */ -static int compress_f_fx_efx(const struct cmp_cfg *cfg) +static int compress_f_fx_efx(const struct cmp_cfg *cfg, int stream_len) { - int err; - int stream_len = 0; size_t i; struct f_fx_efx *data_buf = cfg->input_buf; @@ -1355,28 +1290,19 @@ static int compress_f_fx_efx(const struct cmp_cfg *cfg) struct f_fx_efx model; struct encoder_setupt setup_fx, setup_efx; - if (model_mode_is_used(cfg->cmp_mode)) - up_model_buf = cfg->icu_new_model_buf; - - stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf, - (void **)&up_model_buf, cfg->icu_output_buf); - if (model_mode_is_used(cfg->cmp_mode)) { model = model_buf[0]; next_model_p = &model_buf[1]; + up_model_buf = cfg->icu_new_model_buf; } else { memset(&model, 0, sizeof(model)); next_model_p = data_buf; } - err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, - cfg->round, cfg->max_used_bits->f_fx, cfg); - if (err) - return -1; - err = configure_encoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx, - cfg->round, cfg->max_used_bits->f_efx, cfg); - if (err) - return -1; + configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, + cfg->round, cfg->max_used_bits->f_fx, cfg); + configure_encoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx, + cfg->round, cfg->max_used_bits->f_efx, cfg); for (i = 0;; i++) { stream_len = encode_value(data_buf[i].fx, model.fx, stream_len, @@ -1414,10 +1340,8 @@ static int compress_f_fx_efx(const struct cmp_cfg *cfg) * value in the bitstream */ -static int compress_f_fx_ncob(const struct cmp_cfg *cfg) +static int compress_f_fx_ncob(const struct cmp_cfg *cfg, int stream_len) { - int err; - int stream_len = 0; size_t i; struct f_fx_ncob *data_buf = cfg->input_buf; @@ -1427,28 +1351,19 @@ static int compress_f_fx_ncob(const struct cmp_cfg *cfg) struct f_fx_ncob model; struct encoder_setupt setup_fx, setup_ncob; - if (model_mode_is_used(cfg->cmp_mode)) - up_model_buf = cfg->icu_new_model_buf; - - stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf, - (void **)&up_model_buf, cfg->icu_output_buf); - if (model_mode_is_used(cfg->cmp_mode)) { model = model_buf[0]; next_model_p = &model_buf[1]; + up_model_buf = cfg->icu_new_model_buf; } else { memset(&model, 0, sizeof(model)); next_model_p = data_buf; } - err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, - cfg->round, cfg->max_used_bits->f_fx, cfg); - if (err) - return -1; - err = configure_encoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob, - cfg->round, cfg->max_used_bits->f_ncob, cfg); - if (err) - return -1; + configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, + cfg->round, cfg->max_used_bits->f_fx, cfg); + configure_encoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob, + cfg->round, cfg->max_used_bits->f_ncob, cfg); for (i = 0;; i++) { stream_len = encode_value(data_buf[i].fx, model.fx, stream_len, @@ -1492,10 +1407,8 @@ static int compress_f_fx_ncob(const struct cmp_cfg *cfg) * value in the bitstream */ -static int compress_f_fx_efx_ncob_ecob(const struct cmp_cfg *cfg) +static int compress_f_fx_efx_ncob_ecob(const struct cmp_cfg *cfg, int stream_len) { - int err; - int stream_len = 0; size_t i; struct f_fx_efx_ncob_ecob *data_buf = cfg->input_buf; @@ -1505,36 +1418,23 @@ static int compress_f_fx_efx_ncob_ecob(const struct cmp_cfg *cfg) struct f_fx_efx_ncob_ecob model; struct encoder_setupt setup_fx, setup_ncob, setup_efx, setup_ecob; - if (model_mode_is_used(cfg->cmp_mode)) - up_model_buf = cfg->icu_new_model_buf; - - stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf, - (void **)&up_model_buf, cfg->icu_output_buf); - if (model_mode_is_used(cfg->cmp_mode)) { model = model_buf[0]; next_model_p = &model_buf[1]; + up_model_buf = cfg->icu_new_model_buf; } else { memset(&model, 0, sizeof(model)); next_model_p = data_buf; } - err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, - cfg->round, cfg->max_used_bits->f_fx, cfg); - if (err) - return -1; - err = configure_encoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob, - cfg->round, cfg->max_used_bits->f_ncob, cfg); - if (err) - return -1; - err = configure_encoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx, - cfg->round, cfg->max_used_bits->f_efx, cfg); - if (err) - return -1; - err = configure_encoder_setup(&setup_ecob, cfg->cmp_par_ecob, cfg->spill_ecob, - cfg->round, cfg->max_used_bits->f_ecob, cfg); - if (err) - return -1; + configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, + cfg->round, cfg->max_used_bits->f_fx, cfg); + configure_encoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob, + cfg->round, cfg->max_used_bits->f_ncob, cfg); + configure_encoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx, + cfg->round, cfg->max_used_bits->f_efx, cfg); + configure_encoder_setup(&setup_ecob, cfg->cmp_par_ecob, cfg->spill_ecob, + cfg->round, cfg->max_used_bits->f_ecob, cfg); for (i = 0;; i++) { stream_len = encode_value(data_buf[i].fx, model.fx, stream_len, @@ -1596,10 +1496,8 @@ static int compress_f_fx_efx_ncob_ecob(const struct cmp_cfg *cfg) * value in the bitstream */ -static int compress_l_fx(const struct cmp_cfg *cfg) +static int compress_l_fx(const struct cmp_cfg *cfg, int stream_len) { - int err; - int stream_len = 0; size_t i; struct l_fx *data_buf = cfg->input_buf; @@ -1609,32 +1507,21 @@ static int compress_l_fx(const struct cmp_cfg *cfg) struct l_fx model; struct encoder_setupt setup_exp_flag, setup_fx, setup_fx_var; - if (model_mode_is_used(cfg->cmp_mode)) - up_model_buf = cfg->icu_new_model_buf; - - stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf, - (void **)&up_model_buf, cfg->icu_output_buf); - if (model_mode_is_used(cfg->cmp_mode)) { model = model_buf[0]; next_model_p = &model_buf[1]; + up_model_buf = cfg->icu_new_model_buf; } else { memset(&model, 0, sizeof(model)); next_model_p = data_buf; } - err = configure_encoder_setup(&setup_exp_flag, cfg->cmp_par_exp_flags, cfg->spill_exp_flags, - cfg->round, cfg->max_used_bits->l_exp_flags, cfg); - if (err) - return -1; - err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, - cfg->round, cfg->max_used_bits->l_fx, cfg); - if (err) - return -1; - err = configure_encoder_setup(&setup_fx_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance, - cfg->round, cfg->max_used_bits->l_fx_variance, cfg); - if (err) - return -1; + configure_encoder_setup(&setup_exp_flag, cfg->cmp_par_exp_flags, cfg->spill_exp_flags, + cfg->round, cfg->max_used_bits->l_exp_flags, cfg); + configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, + cfg->round, cfg->max_used_bits->l_fx, cfg); + configure_encoder_setup(&setup_fx_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance, + cfg->round, cfg->max_used_bits->l_fx_variance, cfg); for (i = 0;; i++) { stream_len = encode_value(data_buf[i].exp_flags, model.exp_flags, @@ -1651,7 +1538,7 @@ static int compress_l_fx(const struct cmp_cfg *cfg) return stream_len; if (up_model_buf) { - up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags, + up_model_buf[i].exp_flags = cmp_up_model32(data_buf[i].exp_flags, model.exp_flags, cfg->model_value, setup_exp_flag.lossy_par); up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx, cfg->model_value, setup_fx.lossy_par); @@ -1678,10 +1565,8 @@ static int compress_l_fx(const struct cmp_cfg *cfg) * value in the bitstream */ -static int compress_l_fx_efx(const struct cmp_cfg *cfg) +static int compress_l_fx_efx(const struct cmp_cfg *cfg, int stream_len) { - int err; - int stream_len = 0; size_t i; struct l_fx_efx *data_buf = cfg->input_buf; @@ -1691,36 +1576,23 @@ static int compress_l_fx_efx(const struct cmp_cfg *cfg) struct l_fx_efx model; struct encoder_setupt setup_exp_flag, setup_fx, setup_efx, setup_fx_var; - if (model_mode_is_used(cfg->cmp_mode)) - up_model_buf = cfg->icu_new_model_buf; - - stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf, - (void **)&up_model_buf, cfg->icu_output_buf); - if (model_mode_is_used(cfg->cmp_mode)) { model = model_buf[0]; next_model_p = &model_buf[1]; + up_model_buf = cfg->icu_new_model_buf; } else { memset(&model, 0, sizeof(model)); next_model_p = data_buf; } - err = configure_encoder_setup(&setup_exp_flag, cfg->cmp_par_exp_flags, cfg->spill_exp_flags, - cfg->round, cfg->max_used_bits->l_exp_flags, cfg); - if (err) - return -1; - err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, - cfg->round, cfg->max_used_bits->l_fx, cfg); - if (err) - return -1; - err = configure_encoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx, - cfg->round, cfg->max_used_bits->l_efx, cfg); - if (err) - return -1; - err = configure_encoder_setup(&setup_fx_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance, - cfg->round, cfg->max_used_bits->l_fx_variance, cfg); - if (err) - return -1; + configure_encoder_setup(&setup_exp_flag, cfg->cmp_par_exp_flags, cfg->spill_exp_flags, + cfg->round, cfg->max_used_bits->l_exp_flags, cfg); + configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, + cfg->round, cfg->max_used_bits->l_fx, cfg); + configure_encoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx, + cfg->round, cfg->max_used_bits->l_efx, cfg); + configure_encoder_setup(&setup_fx_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance, + cfg->round, cfg->max_used_bits->l_fx_variance, cfg); for (i = 0;; i++) { stream_len = encode_value(data_buf[i].exp_flags, model.exp_flags, @@ -1741,7 +1613,7 @@ static int compress_l_fx_efx(const struct cmp_cfg *cfg) return stream_len; if (up_model_buf) { - up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags, + up_model_buf[i].exp_flags = cmp_up_model32(data_buf[i].exp_flags, model.exp_flags, cfg->model_value, setup_exp_flag.lossy_par); up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx, cfg->model_value, setup_fx.lossy_par); @@ -1770,10 +1642,8 @@ static int compress_l_fx_efx(const struct cmp_cfg *cfg) * value in the bitstream */ -static int compress_l_fx_ncob(const struct cmp_cfg *cfg) +static int compress_l_fx_ncob(const struct cmp_cfg *cfg, int stream_len) { - int err; - int stream_len = 0; size_t i; struct l_fx_ncob *data_buf = cfg->input_buf; @@ -1784,41 +1654,26 @@ static int compress_l_fx_ncob(const struct cmp_cfg *cfg) struct encoder_setupt setup_exp_flag, setup_fx, setup_ncob, setup_fx_var, setup_cob_var; - if (model_mode_is_used(cfg->cmp_mode)) - up_model_buf = cfg->icu_new_model_buf; - - stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf, - (void **)&up_model_buf, cfg->icu_output_buf); - if (model_mode_is_used(cfg->cmp_mode)) { model = model_buf[0]; next_model_p = &model_buf[1]; + up_model_buf = cfg->icu_new_model_buf; } else { memset(&model, 0, sizeof(model)); next_model_p = data_buf; } - err = configure_encoder_setup(&setup_exp_flag, cfg->cmp_par_exp_flags, cfg->spill_exp_flags, - cfg->round, cfg->max_used_bits->l_exp_flags, cfg); - if (err) - return -1; - err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, - cfg->round, cfg->max_used_bits->l_fx, cfg); - if (err) - return -1; - err = configure_encoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob, - cfg->round, cfg->max_used_bits->l_ncob, cfg); - if (err) - return -1; + configure_encoder_setup(&setup_exp_flag, cfg->cmp_par_exp_flags, cfg->spill_exp_flags, + cfg->round, cfg->max_used_bits->l_exp_flags, cfg); + configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, + cfg->round, cfg->max_used_bits->l_fx, cfg); + configure_encoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob, + cfg->round, cfg->max_used_bits->l_ncob, cfg); /* we use compression parameter for both variance data fields */ - err = configure_encoder_setup(&setup_fx_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance, - cfg->round, cfg->max_used_bits->l_fx_variance, cfg); - if (err) - return -1; - err = configure_encoder_setup(&setup_cob_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance, - cfg->round, cfg->max_used_bits->l_cob_variance, cfg); - if (err) - return -1; + configure_encoder_setup(&setup_fx_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance, + cfg->round, cfg->max_used_bits->l_fx_variance, cfg); + configure_encoder_setup(&setup_cob_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance, + cfg->round, cfg->max_used_bits->l_cob_variance, cfg); for (i = 0;; i++) { stream_len = encode_value(data_buf[i].exp_flags, model.exp_flags, @@ -1851,7 +1706,7 @@ static int compress_l_fx_ncob(const struct cmp_cfg *cfg) return stream_len; if (up_model_buf) { - up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags, + up_model_buf[i].exp_flags = cmp_up_model32(data_buf[i].exp_flags, model.exp_flags, cfg->model_value, setup_exp_flag.lossy_par); up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx, cfg->model_value, setup_fx.lossy_par); @@ -1886,10 +1741,8 @@ static int compress_l_fx_ncob(const struct cmp_cfg *cfg) * value in the bitstream */ -static int compress_l_fx_efx_ncob_ecob(const struct cmp_cfg *cfg) +static int compress_l_fx_efx_ncob_ecob(const struct cmp_cfg *cfg, int stream_len) { - int err; - int stream_len = 0; size_t i; struct l_fx_efx_ncob_ecob *data_buf = cfg->input_buf; @@ -1900,49 +1753,30 @@ static int compress_l_fx_efx_ncob_ecob(const struct cmp_cfg *cfg) struct encoder_setupt setup_exp_flag, setup_fx, setup_ncob, setup_efx, setup_ecob, setup_fx_var, setup_cob_var; - if (model_mode_is_used(cfg->cmp_mode)) - up_model_buf = cfg->icu_new_model_buf; - - stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf, - (void **)&up_model_buf, cfg->icu_output_buf); - if (model_mode_is_used(cfg->cmp_mode)) { model = model_buf[0]; next_model_p = &model_buf[1]; + up_model_buf = cfg->icu_new_model_buf; } else { memset(&model, 0, sizeof(model)); next_model_p = data_buf; } - err = configure_encoder_setup(&setup_exp_flag, cfg->cmp_par_exp_flags, cfg->spill_exp_flags, - cfg->round, cfg->max_used_bits->l_exp_flags, cfg); - if (err) - return -1; - err = configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, - cfg->round, cfg->max_used_bits->l_fx, cfg); - if (err) - return -1; - err = configure_encoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob, - cfg->round, cfg->max_used_bits->l_ncob, cfg); - if (err) - return -1; - err = configure_encoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx, - cfg->round, cfg->max_used_bits->l_efx, cfg); - if (err) - return -1; - err = configure_encoder_setup(&setup_ecob, cfg->cmp_par_ecob, cfg->spill_ecob, - cfg->round, cfg->max_used_bits->l_ecob, cfg); - if (err) - return -1; + configure_encoder_setup(&setup_exp_flag, cfg->cmp_par_exp_flags, cfg->spill_exp_flags, + cfg->round, cfg->max_used_bits->l_exp_flags, cfg); + configure_encoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx, + cfg->round, cfg->max_used_bits->l_fx, cfg); + configure_encoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob, + cfg->round, cfg->max_used_bits->l_ncob, cfg); + configure_encoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx, + cfg->round, cfg->max_used_bits->l_efx, cfg); + configure_encoder_setup(&setup_ecob, cfg->cmp_par_ecob, cfg->spill_ecob, + cfg->round, cfg->max_used_bits->l_ecob, cfg); /* we use compression parameter for both variance data fields */ - err = configure_encoder_setup(&setup_fx_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance, - cfg->round, cfg->max_used_bits->l_fx_variance, cfg); - if (err) - return -1; - err = configure_encoder_setup(&setup_cob_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance, - cfg->round, cfg->max_used_bits->l_cob_variance, cfg); - if (err) - return -1; + configure_encoder_setup(&setup_fx_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance, + cfg->round, cfg->max_used_bits->l_fx_variance, cfg); + configure_encoder_setup(&setup_cob_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance, + cfg->round, cfg->max_used_bits->l_cob_variance, cfg); for (i = 0;; i++) { stream_len = encode_value(data_buf[i].exp_flags, model.exp_flags, @@ -1987,7 +1821,7 @@ static int compress_l_fx_efx_ncob_ecob(const struct cmp_cfg *cfg) return stream_len; if (up_model_buf) { - up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags, + up_model_buf[i].exp_flags = cmp_up_model32(data_buf[i].exp_flags, model.exp_flags, cfg->model_value, setup_exp_flag.lossy_par); up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx, cfg->model_value, setup_fx.lossy_par); @@ -2019,7 +1853,7 @@ static int compress_l_fx_efx_ncob_ecob(const struct cmp_cfg *cfg) /** - * @brief compress offset data from the normal cameras + * @brief compress offset data from the normal and fast cameras * * @param cfg pointer to the compression configuration structure * @returns the bit length of the bitstream on success; negative on error, @@ -2027,41 +1861,45 @@ static int compress_l_fx_efx_ncob_ecob(const struct cmp_cfg *cfg) * value in the bitstream */ -static int compress_nc_offset(const struct cmp_cfg *cfg) +static int compress_offset(const struct cmp_cfg *cfg, int stream_len) { - int err; - int stream_len = 0; size_t i; - struct nc_offset *data_buf = cfg->input_buf; - struct nc_offset *model_buf = cfg->model_buf; - struct nc_offset *up_model_buf = NULL; - struct nc_offset *next_model_p; - struct nc_offset model; + struct offset *data_buf = cfg->input_buf; + struct offset *model_buf = cfg->model_buf; + struct offset *up_model_buf = NULL; + struct offset *next_model_p; + struct offset model; struct encoder_setupt setup_mean, setup_var; - if (model_mode_is_used(cfg->cmp_mode)) - up_model_buf = cfg->icu_new_model_buf; - - stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf, - (void **)&up_model_buf, cfg->icu_output_buf); - if (model_mode_is_used(cfg->cmp_mode)) { model = model_buf[0]; next_model_p = &model_buf[1]; + up_model_buf = cfg->icu_new_model_buf; } else { memset(&model, 0, sizeof(model)); next_model_p = data_buf; } - err = configure_encoder_setup(&setup_mean, cfg->cmp_par_mean, cfg->spill_mean, - cfg->round, cfg->max_used_bits->nc_offset_mean, cfg); - if (err) - return -1; - err = configure_encoder_setup(&setup_var, cfg->cmp_par_variance, cfg->spill_variance, - cfg->round, cfg->max_used_bits->nc_offset_variance, cfg); - if (err) - return -1; + { + unsigned int mean_bits_used, variance_bits_used; + + switch (cfg->data_type) { + case DATA_TYPE_F_CAM_OFFSET: + mean_bits_used = cfg->max_used_bits->fc_offset_mean; + variance_bits_used = cfg->max_used_bits->fc_offset_variance; + break; + case DATA_TYPE_OFFSET: + default: + mean_bits_used = cfg->max_used_bits->nc_offset_mean; + variance_bits_used = cfg->max_used_bits->nc_offset_variance; + break; + } + configure_encoder_setup(&setup_mean, cfg->cmp_par_offset_mean, cfg->spill_offset_mean, + cfg->round, mean_bits_used, cfg); + configure_encoder_setup(&setup_var, cfg->cmp_par_offset_variance, cfg->spill_offset_variance, + cfg->round, variance_bits_used, cfg); + } for (i = 0;; i++) { stream_len = encode_value(data_buf[i].mean, model.mean, @@ -2090,7 +1928,7 @@ static int compress_nc_offset(const struct cmp_cfg *cfg) /** - * @brief compress background data from the normal cameras + * @brief compress background data from the normal and fast cameras * * @param cfg pointer to the compression configuration structure * @returns the bit length of the bitstream on success; negative on error, @@ -2098,45 +1936,49 @@ static int compress_nc_offset(const struct cmp_cfg *cfg) * value in the bitstream */ -static int compress_nc_background(const struct cmp_cfg *cfg) +static int compress_background(const struct cmp_cfg *cfg, int stream_len) { - int err; - int stream_len = 0; size_t i; - struct nc_background *data_buf = cfg->input_buf; - struct nc_background *model_buf = cfg->model_buf; - struct nc_background *up_model_buf = NULL; - struct nc_background *next_model_p; - struct nc_background model; + struct background *data_buf = cfg->input_buf; + struct background *model_buf = cfg->model_buf; + struct background *up_model_buf = NULL; + struct background *next_model_p; + struct background model; struct encoder_setupt setup_mean, setup_var, setup_pix; - if (model_mode_is_used(cfg->cmp_mode)) - up_model_buf = cfg->icu_new_model_buf; - - stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf, - (void **)&up_model_buf, cfg->icu_output_buf); - if (model_mode_is_used(cfg->cmp_mode)) { model = model_buf[0]; next_model_p = &model_buf[1]; + up_model_buf = cfg->icu_new_model_buf; } else { memset(&model, 0, sizeof(model)); next_model_p = data_buf; } - err = configure_encoder_setup(&setup_mean, cfg->cmp_par_mean, cfg->spill_mean, - cfg->round, cfg->max_used_bits->nc_background_mean, cfg); - if (err) - return -1; - err = configure_encoder_setup(&setup_var, cfg->cmp_par_variance, cfg->spill_variance, - cfg->round, cfg->max_used_bits->nc_background_variance, cfg); - if (err) - return -1; - err = configure_encoder_setup(&setup_pix, cfg->cmp_par_pixels_error, cfg->spill_pixels_error, - cfg->round, cfg->max_used_bits->nc_background_outlier_pixels, cfg); - if (err) - return -1; + { + unsigned int mean_used_bits, varinace_used_bits, pixels_error_used_bits; + + switch (cfg->data_type) { + case DATA_TYPE_F_CAM_BACKGROUND: + mean_used_bits = cfg->max_used_bits->fc_background_mean; + varinace_used_bits = cfg->max_used_bits->fc_background_variance; + pixels_error_used_bits = cfg->max_used_bits->fc_background_outlier_pixels; + break; + case DATA_TYPE_BACKGROUND: + default: + mean_used_bits = cfg->max_used_bits->nc_background_mean; + varinace_used_bits = cfg->max_used_bits->nc_background_variance; + pixels_error_used_bits = cfg->max_used_bits->nc_background_outlier_pixels; + break; + } + configure_encoder_setup(&setup_mean, cfg->cmp_par_background_mean, cfg->spill_background_mean, + cfg->round, mean_used_bits, cfg); + configure_encoder_setup(&setup_var, cfg->cmp_par_background_variance, cfg->spill_background_variance, + cfg->round, varinace_used_bits, cfg); + configure_encoder_setup(&setup_pix, cfg->cmp_par_background_pixels_error, cfg->spill_background_pixels_error, + cfg->round, pixels_error_used_bits, cfg); + } for (i = 0;; i++) { stream_len = encode_value(data_buf[i].mean, model.mean, @@ -2180,10 +2022,8 @@ static int compress_nc_background(const struct cmp_cfg *cfg) * value in the bitstream */ -static int compress_smearing(const struct cmp_cfg *cfg) +static int compress_smearing(const struct cmp_cfg *cfg, int stream_len) { - int err; - int stream_len = 0; size_t i; struct smearing *data_buf = cfg->input_buf; @@ -2193,32 +2033,21 @@ static int compress_smearing(const struct cmp_cfg *cfg) struct smearing model; struct encoder_setupt setup_mean, setup_var_mean, setup_pix; - if (model_mode_is_used(cfg->cmp_mode)) - up_model_buf = cfg->icu_new_model_buf; - - stream_len = compress_multi_entry_hdr((void **)&data_buf, (void **)&model_buf, - (void **)&up_model_buf, cfg->icu_output_buf); - if (model_mode_is_used(cfg->cmp_mode)) { model = model_buf[0]; next_model_p = &model_buf[1]; + up_model_buf = cfg->icu_new_model_buf; } else { memset(&model, 0, sizeof(model)); next_model_p = data_buf; } - err = configure_encoder_setup(&setup_mean, cfg->cmp_par_mean, cfg->spill_mean, - cfg->round, cfg->max_used_bits->smearing_mean, cfg); - if (err) - return -1; - err = configure_encoder_setup(&setup_var_mean, cfg->cmp_par_variance, cfg->spill_variance, - cfg->round, cfg->max_used_bits->smearing_variance_mean, cfg); - if (err) - return -1; - err = configure_encoder_setup(&setup_pix, cfg->cmp_par_pixels_error, cfg->spill_pixels_error, - cfg->round, cfg->max_used_bits->smearing_outlier_pixels, cfg); - if (err) - return -1; + configure_encoder_setup(&setup_mean, cfg->cmp_par_smearing_mean, cfg->spill_smearing_mean, + cfg->round, cfg->max_used_bits->smearing_mean, cfg); + configure_encoder_setup(&setup_var_mean, cfg->cmp_par_smearing_variance, cfg->spill_smearing_variance, + cfg->round, cfg->max_used_bits->smearing_variance_mean, cfg); + configure_encoder_setup(&setup_pix, cfg->cmp_par_smearing_pixels_error, cfg->spill_smearing_pixels_error, + cfg->round, cfg->max_used_bits->smearing_outlier_pixels, cfg); for (i = 0;; i++) { stream_len = encode_value(data_buf[i].mean, model.mean, @@ -2278,7 +2107,7 @@ static int pad_bitstream(const struct cmp_cfg *cfg, int cmp_size) return cmp_size; /* maximum length of the bitstream/icu_output_buf in bits */ - output_buf_len_bits = cmp_buffer_length_to_bits(cfg->buffer_length, cfg->data_type); + output_buf_len_bits = cmp_buffer_length_to_bits(cfg->buffer_length); n_pad_bits = 32 - ((unsigned int)cmp_size & 0x1FU); if (n_pad_bits < 32) { @@ -2293,93 +2122,60 @@ static int pad_bitstream(const struct cmp_cfg *cfg, int cmp_size) /** - * @brief change the endianness of the compressed data to big-endian + * @brief internal data compression function + * This function can compress all types of collection data (one at a time). + * This function does not take the header of a collection into account. * - * @param cfg pointer to the compression configuration structure - * @param cmp_size length of the bitstream in bits + * @param cfg pointer to a compression configuration + * + * @note the validity of the cfg structure is checked before the compression is + * started * - * @returns 0 on success; non-zero on failure + * @returns the bit length of the bitstream on success; negative on error, + * CMP_ERROR_SMALL_BUF (-2) if the compressed data buffer is too small to + * hold the whole compressed data, CMP_ERROR_HIGH_VALUE (-3) if a data or + * model value is bigger than the max_used_bits parameter */ -static int cmp_data_to_big_endian(const struct cmp_cfg *cfg, int cmp_size) +static int compress_data_internal(const struct cmp_cfg *cfg, int stream_len) { -#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) - size_t i; - uint32_t *p; - uint32_t s = (uint32_t)cmp_size; + int bitsize = 0; - if (cmp_size < 0) - return cmp_size; + if (!cfg) + return -1; - if (!cfg->icu_output_buf) - return cmp_size; - - if (cfg->cmp_mode == CMP_MODE_RAW) { - if (s & 0x7) /* size must be a multiple of 8 in RAW mode */ - return -1; - if (cmp_input_big_to_cpu_endianness(cfg->icu_output_buf, - s/CHAR_BIT, cfg->data_type)) - cmp_size = -1; - } else { - if (rdcu_supported_data_type_is_used(cfg->data_type)) { - p = cfg->icu_output_buf; - } else { - p = &cfg->icu_output_buf[MULTI_ENTRY_HDR_SIZE/sizeof(uint32_t)]; - s -= MULTI_ENTRY_HDR_SIZE * CHAR_BIT; - } - - for (i = 0; i < cmp_bit_to_4byte(s)/sizeof(uint32_t); i++) - cpu_to_be32s(&p[i]); - } -#else - /* do nothing data are already in big-endian */ - (void)cfg; -#endif /*__BYTE_ORDER__ */ - return cmp_size; -} - - -/** - * @brief compress data on the ICU in software - * - * @param cfg pointer to a compression configuration (created with the - * cmp_cfg_icu_create() function, setup with the cmp_cfg_xxx() functions) - * - * @note the validity of the cfg structure is checked before the compression is - * started - * - * @returns the bit length of the bitstream on success; negative on error, - * CMP_ERROR_SMALL_BUF (-2) if the compressed data buffer is too small to - * hold the whole compressed data, CMP_ERROR_HIGH_VALUE (-3) if a data or - * model value is bigger than the max_used_bits parameter allows (set with - * the cmp_set_max_used_bits() function) - */ + if (stream_len < 0) + return stream_len; -int icu_compress_data(const struct cmp_cfg *cfg) -{ - int cmp_size = 0; + if (cfg->samples == 0) /* nothing to compress we are done */ + return stream_len; - if (!cfg) + if (stream_len & 0x7) { + debug_print("Error: The stream_len parameter must be a multiple of 8."); return -1; + } - if (cfg->samples == 0) /* nothing to compress we are done*/ - return 0; - - if (raw_mode_is_used(cfg->cmp_mode)) - if (cfg->samples > cfg->buffer_length) + if (raw_mode_is_used(cfg->cmp_mode) && cfg->icu_output_buf) + if (((uint32_t)stream_len >> 3) + cfg->samples * size_of_a_sample(cfg->data_type) > cfg->buffer_length) return CMP_ERROR_SMALL_BUF; if (cmp_cfg_icu_is_invalid(cfg)) return -1; if (raw_mode_is_used(cfg->cmp_mode)) { - cmp_size = cmp_cal_size_of_data(cfg->samples, cfg->data_type); - if (cfg->icu_output_buf) - memcpy(cfg->icu_output_buf, cfg->input_buf, cmp_size); - cmp_size *= CHAR_BIT; /* convert to bits */ + uint32_t raw_size = cfg->samples * (uint32_t)size_of_a_sample(cfg->data_type); + + if (cfg->icu_output_buf) { + uint8_t *p = (uint8_t *)cfg->icu_output_buf + (stream_len >> 3); + + memcpy(p, cfg->input_buf, raw_size); + if (cpu_to_be_data_type(p, raw_size, cfg->data_type)) + return -1; + } + bitsize += stream_len + (int)raw_size*8; /* convert to bits */ } else { if (cfg->icu_output_buf && cfg->samples/3 > cfg->buffer_length) - debug_print("Warning: The size of the compressed_data buffer is 3 times smaller than the data_to_compress. This is probably unintended.\n"); + debug_print("Warning: The size of the compressed_data buffer is 3 times smaller than the data_to_compress. This is probably unintended."); switch (cfg->data_type) { case DATA_TYPE_IMAGETTE: @@ -2388,71 +2184,692 @@ int icu_compress_data(const struct cmp_cfg *cfg) case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE: case DATA_TYPE_F_CAM_IMAGETTE: case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE: - cmp_size = compress_imagette(cfg); + bitsize = compress_imagette(cfg, stream_len); break; case DATA_TYPE_S_FX: - cmp_size = compress_s_fx(cfg); + bitsize = compress_s_fx(cfg, stream_len); break; case DATA_TYPE_S_FX_EFX: - cmp_size = compress_s_fx_efx(cfg); + bitsize = compress_s_fx_efx(cfg, stream_len); break; case DATA_TYPE_S_FX_NCOB: - cmp_size = compress_s_fx_ncob(cfg); + bitsize = compress_s_fx_ncob(cfg, stream_len); break; case DATA_TYPE_S_FX_EFX_NCOB_ECOB: - cmp_size = compress_s_fx_efx_ncob_ecob(cfg); + bitsize = compress_s_fx_efx_ncob_ecob(cfg, stream_len); break; case DATA_TYPE_F_FX: - cmp_size = compress_f_fx(cfg); + bitsize = compress_f_fx(cfg, stream_len); break; case DATA_TYPE_F_FX_EFX: - cmp_size = compress_f_fx_efx(cfg); + bitsize = compress_f_fx_efx(cfg, stream_len); break; case DATA_TYPE_F_FX_NCOB: - cmp_size = compress_f_fx_ncob(cfg); + bitsize = compress_f_fx_ncob(cfg, stream_len); break; case DATA_TYPE_F_FX_EFX_NCOB_ECOB: - cmp_size = compress_f_fx_efx_ncob_ecob(cfg); + bitsize = compress_f_fx_efx_ncob_ecob(cfg, stream_len); break; case DATA_TYPE_L_FX: - cmp_size = compress_l_fx(cfg); + bitsize = compress_l_fx(cfg, stream_len); break; case DATA_TYPE_L_FX_EFX: - cmp_size = compress_l_fx_efx(cfg); + bitsize = compress_l_fx_efx(cfg, stream_len); break; case DATA_TYPE_L_FX_NCOB: - cmp_size = compress_l_fx_ncob(cfg); + bitsize = compress_l_fx_ncob(cfg, stream_len); break; case DATA_TYPE_L_FX_EFX_NCOB_ECOB: - cmp_size = compress_l_fx_efx_ncob_ecob(cfg); + bitsize = compress_l_fx_efx_ncob_ecob(cfg, stream_len); break; case DATA_TYPE_OFFSET: - cmp_size = compress_nc_offset(cfg); + case DATA_TYPE_F_CAM_OFFSET: + bitsize = compress_offset(cfg, stream_len); break; case DATA_TYPE_BACKGROUND: - cmp_size = compress_nc_background(cfg); + case DATA_TYPE_F_CAM_BACKGROUND: + bitsize = compress_background(cfg, stream_len); break; case DATA_TYPE_SMEARING: - cmp_size = compress_smearing(cfg); + bitsize = compress_smearing(cfg, stream_len); break; - case DATA_TYPE_F_CAM_OFFSET: - case DATA_TYPE_F_CAM_BACKGROUND: /* LCOV_EXCL_START */ case DATA_TYPE_UNKNOWN: default: - debug_print("Error: Data type not supported.\n"); - cmp_size = -1; + debug_print("Error: Data type not supported."); + bitsize = -1; } /* LCOV_EXCL_STOP */ } - cmp_size = pad_bitstream(cfg, cmp_size); - cmp_size = cmp_data_to_big_endian(cfg, cmp_size); + bitsize = pad_bitstream(cfg, bitsize); - return cmp_size; + return bitsize; +} + + +/** + * @brief compress data on the ICU in software + * + * @param cfg pointer to a compression configuration (created with the + * cmp_cfg_icu_create() function, setup with the cmp_cfg_xxx() functions) + * + * @note the validity of the cfg structure is checked before the compression is + * started + * + * @returns the bit length of the bitstream on success; negative on error, + * CMP_ERROR_SMALL_BUF (-2) if the compressed data buffer is too small to + * hold the whole compressed data, CMP_ERROR_HIGH_VALUE (-3) if a data or + * model value is bigger than the max_used_bits parameter allows (set with + * the cmp_set_max_used_bits() function) + */ + +int icu_compress_data(const struct cmp_cfg *cfg) +{ + struct cmp_cfg cfg_cpy; + int dst_capacity_used = 0; + + if (cfg) { + if (cfg->samples == 0) + return 0; + cfg_cpy = *cfg; + cfg_cpy.buffer_length = cmp_cal_size_of_data(cfg->buffer_length, cfg->data_type); + if (!cfg_cpy.buffer_length) + return -1; + + if (!rdcu_supported_data_type_is_used(cfg->data_type) && !cmp_data_type_is_invalid(cfg->data_type)) { + if (cfg->icu_new_model_buf) { + if (cfg->input_buf) + memcpy(cfg->icu_new_model_buf, cfg->input_buf, COLLECTION_HDR_SIZE); + cfg_cpy.icu_new_model_buf = (uint8_t *)cfg_cpy.icu_new_model_buf + COLLECTION_HDR_SIZE; + } + if (cfg->icu_output_buf && cfg->input_buf && cfg->buffer_length) + memcpy(cfg->icu_output_buf, cfg->input_buf, COLLECTION_HDR_SIZE); + if (cfg->input_buf) + cfg_cpy.input_buf = (uint8_t *)cfg->input_buf + COLLECTION_HDR_SIZE; + if (cfg->model_buf) + cfg_cpy.model_buf = (uint8_t *)cfg->model_buf + COLLECTION_HDR_SIZE; + dst_capacity_used = COLLECTION_HDR_SIZE*8; + } + return compress_data_internal(&cfg_cpy, dst_capacity_used); + } + return compress_data_internal(NULL, dst_capacity_used); +} + + +/** + * @brief estimate a "good" spillover threshold parameter + * + * @param golomb_par Golomb parameter + * + * @returns a spill over threshold parameter + * TODO: tune this calculation for multi escape symbol mechanism + */ + +static uint32_t cmp_guess_good_spill(uint32_t golomb_par) +{ + if (!golomb_par) + return 0; + return cmp_icu_max_spill(golomb_par); +} + + +/** + * @brief set the compressed collection size field + * + * @param cmp_col_size_field pointer to the compressed collection size field + * @param cmp_col_size size of the compressed collection (not including + * the compressed collection header size and the + * size of the compressed collection size field + * itself) + * + * @returns 0 on success; -1 on failure + */ + +static int set_cmp_col_size(uint8_t *cmp_col_size_field, int32_t cmp_col_size) +{ + uint16_t const v = cpu_to_be16((uint16_t)cmp_col_size); + + if (cmp_col_size > UINT16_MAX) + return -1; + + if (cmp_col_size_field) + memcpy(cmp_col_size_field, &v, CMP_COLLECTION_FILD_SIZE); + + return 0; +} + + +/** + * @brief compresses a collection (with a collection header followed by data) + * + * @param col pointer to a collection header + * @param model pointer to the model to be used for compression, or NULL + * if not applicable + * @param updated_model pointer to the buffer where the updated model will be + * stored, or NULL if not applicable + * @param dst pointer to the buffer where the compressed data will be + * stored, or NULL to only get the compressed data size + * @param dst_capacity the size of the dst buffer in bytes + * @param cfg pointer to a compression configuration + * @param dst_size the already used size of the dst buffer in bytes + * + * @returns the size of the compressed data in bytes (new dst_size) on + * success; negative on error, CMP_ERROR_SMALL_BUF (-2) if the compressed + * data buffer is too small to hold the whole compressed data; the + * compressed and updated model are only valid on positive return + * values + */ + +static int32_t cmp_collection(uint8_t *col, uint8_t *model, uint8_t *updated_model, + uint32_t *dst, uint32_t dst_capacity, + struct cmp_cfg *cfg, int32_t dst_size) +{ + int32_t dst_size_begin = dst_size; + int dst_size_bits; + + if (dst_size < 0) + return dst_size; + if (!col) + return -1; + + if (cfg->cmp_mode != CMP_MODE_RAW) { + /* we put the compressed data size be */ + dst_size += CMP_COLLECTION_FILD_SIZE; + } + + /* we do not compress the collection header, we simply copy the header + * into the compressed data + */ + if (dst) { + if ((uint32_t)dst_size + COLLECTION_HDR_SIZE > dst_capacity) + return CMP_ERROR_SMALL_BUF; + memcpy((uint8_t *)dst + dst_size, col, COLLECTION_HDR_SIZE); + } + dst_size += COLLECTION_HDR_SIZE; + + if (model_mode_is_used(cfg->cmp_mode) && updated_model) + memcpy(updated_model, col, COLLECTION_HDR_SIZE); + + /* prepare the different buffers */ + cfg->icu_output_buf = dst; + cfg->input_buf = col + COLLECTION_HDR_SIZE; + if (model) + cfg->model_buf = model + COLLECTION_HDR_SIZE; + if (updated_model) + cfg->icu_new_model_buf = updated_model + COLLECTION_HDR_SIZE; + + { + struct collection_hdr *col_hdr = (struct collection_hdr *)col; + uint8_t subservice = cmp_col_get_subservice(col_hdr); + uint16_t col_data_length = cmp_col_get_data_length(col_hdr); + + cfg->data_type = convert_subservice_to_cmp_data_type(subservice); + + if (!size_of_a_sample(cfg->data_type)) + return -1; + if (col_data_length % size_of_a_sample(cfg->data_type)) + return -1; + cfg->samples = col_data_length/size_of_a_sample(cfg->data_type); + if ((dst && (uint32_t)dst_size + col_data_length > dst_capacity) || + cfg->cmp_mode == CMP_MODE_RAW) { + cfg->buffer_length = dst_capacity; + dst_size_bits = compress_data_internal(cfg, dst_size<<3); + if (dst_size < 0) + return dst_size_bits; + } else { + /* we limit the size of the compressed data buffer */ + cfg->buffer_length = (uint32_t)dst_size + col_data_length-1; + dst_size_bits = compress_data_internal(cfg, dst_size<<3); + if (dst_size_bits == CMP_ERROR_SMALL_BUF || + (!dst && (int)cmp_bit_to_byte((unsigned int)dst_size_bits)-dst_size > col_data_length)) { /* if dst == NULL icu_compress_data_2 will not return a CMP_ERROR_SMALL_BUF */ + enum cmp_mode cmp_mode_cpy = cfg->cmp_mode; + + cfg->buffer_length = (uint32_t)dst_size + col_data_length; + cfg->cmp_mode = CMP_MODE_RAW; + dst_size_bits = compress_data_internal(cfg, dst_size<<3); + cfg->cmp_mode = cmp_mode_cpy; + if (model_mode_is_used(cfg->cmp_mode) && cfg->icu_new_model_buf) + memcpy(cfg->icu_new_model_buf, cfg->input_buf, col_data_length); + } + } + if (dst_size_bits < 0) + return dst_size_bits; + } + + dst_size = (int32_t)cmp_bit_to_byte((unsigned int)dst_size_bits); /*TODO: fix casts */ + if (dst && cfg->cmp_mode != CMP_MODE_RAW) { + int32_t cmp_col_size = dst_size - dst_size_begin - + COLLECTION_HDR_SIZE - CMP_COLLECTION_FILD_SIZE; + + if (set_cmp_col_size((uint8_t *)dst+dst_size_begin, cmp_col_size)) + return -1; + } + + return dst_size; +} + + +/** + * @brief builds a compressed entity header for a compressed chunk + * + * @param ent start address of the compression entity header + * (can be NULL if you only want the entity header + * size) + * @param chunk_size the original size of the chunk in bytes + * @param cfg pointer to the compression configuration used to + * compress the chunk + * @param start_timestamp the start timestamp of the chunk compression + * @param cmp_ent_size_byte the size of the compression entity (entity + * header plus compressed data) + * + * @return the size of the compressed entity header in bytes, or -1 if an error + * occurred + */ + +static int cmp_ent_build_chunk_header(struct cmp_entity *ent, uint32_t chunk_size, + const struct cmp_cfg *cfg, uint64_t start_timestamp, + int32_t cmp_ent_size_byte) +{ + if (ent) { /* setup the compressed entity header */ + int err = 0; + + if (cmp_ent_size_byte < 0) + cmp_ent_size_byte = 0; + err |= cmp_ent_set_version_id(ent, version_identifier); + err |= cmp_ent_set_size(ent, (uint32_t)cmp_ent_size_byte); + if (cmp_ent_set_original_size(ent, chunk_size)) { + debug_print("Error: The size of the chunk is too."); + return -1; + } + err |= cmp_ent_set_start_timestamp(ent, start_timestamp); + err |= cmp_ent_set_data_type(ent, DATA_TYPE_CHUNK, cfg->cmp_mode == CMP_MODE_RAW); + err |= cmp_ent_set_cmp_mode(ent, cfg->cmp_mode); + err |= cmp_ent_set_model_value(ent, cfg->model_value); + err |= cmp_ent_set_model_id(ent, 0); + err |= cmp_ent_set_model_counter(ent, 0); + if (cfg->max_used_bits) + err |= cmp_ent_set_max_used_bits_version(ent, cfg->max_used_bits->version); + else + err |= cmp_ent_set_max_used_bits_version(ent, 0); + err |= cmp_ent_set_lossy_cmp_par(ent, cfg->round); + if (cfg->cmp_mode != CMP_MODE_RAW) { + err |= cmp_ent_set_non_ima_spill1(ent, cfg->spill_par_1); + err |= cmp_ent_set_non_ima_cmp_par1(ent, cfg->cmp_par_1); + err |= cmp_ent_set_non_ima_spill2(ent, cfg->spill_par_2); + err |= cmp_ent_set_non_ima_cmp_par2(ent, cfg->cmp_par_2); + err |= cmp_ent_set_non_ima_spill3(ent, cfg->spill_par_3); + err |= cmp_ent_set_non_ima_cmp_par3(ent, cfg->cmp_par_3); + err |= cmp_ent_set_non_ima_spill4(ent, cfg->spill_par_4); + err |= cmp_ent_set_non_ima_cmp_par4(ent, cfg->cmp_par_4); + err |= cmp_ent_set_non_ima_spill5(ent, cfg->spill_par_5); + err |= cmp_ent_set_non_ima_cmp_par5(ent, cfg->cmp_par_5); + err |= cmp_ent_set_non_ima_spill6(ent, cfg->spill_par_6); + err |= cmp_ent_set_non_ima_cmp_par6(ent, cfg->cmp_par_6); + } + err |= cmp_ent_set_end_timestamp(ent, get_timestamp()); + if (err) + return -1; + } + + if (cfg->cmp_mode == CMP_MODE_RAW) + return GENERIC_HEADER_SIZE; + else + return NON_IMAGETTE_HEADER_SIZE; +} + + +/** + * @brief map a sub-service to a chunk service according to + * DetailedBudgetWorking_2023-10-11 + * + * @param subservice subservice of a science data product + * + * @returns the chunk type of the subservice on success, CHUNK_TYPE_UNKNOWN on + * failure + */ + +static enum chunk_type get_chunk_type(uint8_t subservice) +{ + enum chunk_type chunk_type = CHUNK_TYPE_UNKNOWN; + + switch (subservice) { + case SST_NCxx_S_SCIENCE_IMAGETTE: + chunk_type = CHUNK_TYPE_NCAM_IMAGETTE; + break; + case SST_NCxx_S_SCIENCE_SAT_IMAGETTE: + chunk_type = CHUNK_TYPE_SAT_IMAGETTE; + break; + case SST_NCxx_S_SCIENCE_OFFSET: + case SST_NCxx_S_SCIENCE_BACKGROUND: + chunk_type = CHUNK_TYPE_OFFSET_BACKGROUND; + break; + case SST_NCxx_S_SCIENCE_SMEARING: + chunk_type = CHUNK_TYPE_SMEARING; + break; + case SST_NCxx_S_SCIENCE_S_FX: + case SST_NCxx_S_SCIENCE_S_FX_EFX: + case SST_NCxx_S_SCIENCE_S_FX_NCOB: + case SST_NCxx_S_SCIENCE_S_FX_EFX_NCOB_ECOB: + chunk_type = CHUNK_TYPE_SHORT_CADENCE; + break; + case SST_NCxx_S_SCIENCE_L_FX: + case SST_NCxx_S_SCIENCE_L_FX_EFX: + case SST_NCxx_S_SCIENCE_L_FX_NCOB: + case SST_NCxx_S_SCIENCE_L_FX_EFX_NCOB_ECOB: + chunk_type = CHUNK_TYPE_LONG_CADENCE; + break; + case SST_FCx_S_SCIENCE_IMAGETTE: + case SST_FCx_S_SCIENCE_OFFSET_VALUES: + case SST_FCx_S_BACKGROUND_VALUES: + chunk_type = CHUNK_TYPE_F_CHAIN; + break; + case SST_NCxx_S_SCIENCE_F_FX: + case SST_NCxx_S_SCIENCE_F_FX_EFX: + case SST_NCxx_S_SCIENCE_F_FX_NCOB: + case SST_NCxx_S_SCIENCE_F_FX_EFX_NCOB_ECOB: + debug_print("Error: No chunk is defined for fast cadence subservices"); + chunk_type = CHUNK_TYPE_UNKNOWN; + break; + default: + debug_print("Error: Unknown subservice: %i.", subservice); + chunk_type = CHUNK_TYPE_UNKNOWN; + break; + }; + + return chunk_type; +} + + +/** + * @brief get the chunk_type of a collection + * + * @param col pointer to a collection header + * + * @returns chunk type of the collection + */ + +static enum chunk_type cmp_col_get_chunk_type(const struct collection_hdr *col) +{ + return get_chunk_type(cmp_col_get_subservice(col)); +} + + +/** + * @brief Set the compression configuration from the compression parameters + * based on the chunk type + * + * @param[in] par pointer to a compression parameters struct + * @param[in] chunk_type the type of the chunk to be compressed + * @param[out] cfg pointer to a compression configuration + * + * @returns 0 success; -1 on failure + */ + +static int init_cmp_cfg_from_cmp_par(const struct cmp_par *par, enum chunk_type chunk_type, + struct cmp_cfg *cfg) +{ + memset(cfg, 0, sizeof(struct cmp_cfg)); + + cfg->cmp_mode = par->cmp_mode; + cfg->model_value = par->model_value; + cfg->round = par->lossy_par; + cfg->max_used_bits = &MAX_USED_BITS_SAFE; + + switch (chunk_type) { + case CHUNK_TYPE_NCAM_IMAGETTE: + cfg->cmp_par_imagette = par->nc_imagette; + break; + case CHUNK_TYPE_SAT_IMAGETTE: + cfg->cmp_par_imagette = par->saturated_imagette; + break; + case CHUNK_TYPE_SHORT_CADENCE: + cfg->cmp_par_exp_flags = par->s_exp_flags; + cfg->cmp_par_fx = par->s_fx; + cfg->cmp_par_ncob = par->s_ncob; + cfg->cmp_par_efx = par->s_efx; + cfg->cmp_par_ecob = par->s_ecob; + break; + case CHUNK_TYPE_LONG_CADENCE: + cfg->cmp_par_exp_flags = par->l_exp_flags; + cfg->cmp_par_fx = par->l_fx; + cfg->cmp_par_ncob = par->l_ncob; + cfg->cmp_par_efx = par->l_efx; + cfg->cmp_par_ecob = par->l_ecob; + cfg->cmp_par_fx_cob_variance = par->l_fx_cob_variance; + break; + case CHUNK_TYPE_OFFSET_BACKGROUND: + cfg->cmp_par_offset_mean = par->nc_offset_mean; + cfg->cmp_par_offset_variance = par->nc_offset_variance; + + cfg->cmp_par_background_mean = par->nc_background_mean; + cfg->cmp_par_background_variance = par->nc_background_variance; + cfg->cmp_par_background_pixels_error = par->nc_background_outlier_pixels; + break; + + case CHUNK_TYPE_SMEARING: + cfg->cmp_par_smearing_mean = par->smearing_mean; + cfg->cmp_par_smearing_variance = par->smearing_variance_mean; + cfg->cmp_par_smearing_pixels_error = par->smearing_outlier_pixels; + break; + + case CHUNK_TYPE_F_CHAIN: + cfg->cmp_par_imagette = par->fc_imagette; + + cfg->cmp_par_offset_mean = par->fc_offset_mean; + cfg->cmp_par_offset_variance = par->fc_offset_variance; + + cfg->cmp_par_background_mean = par->fc_background_mean; + cfg->cmp_par_background_variance = par->fc_background_variance; + cfg->cmp_par_background_pixels_error = par->fc_background_outlier_pixels; + break; + case CHUNK_TYPE_UNKNOWN: + default: + return -1; + }; + + cfg->spill_par_1 = cmp_guess_good_spill(cfg->cmp_par_1); + cfg->spill_par_2 = cmp_guess_good_spill(cfg->cmp_par_2); + cfg->spill_par_3 = cmp_guess_good_spill(cfg->cmp_par_3); + cfg->spill_par_4 = cmp_guess_good_spill(cfg->cmp_par_4); + cfg->spill_par_5 = cmp_guess_good_spill(cfg->cmp_par_5); + cfg->spill_par_6 = cmp_guess_good_spill(cfg->cmp_par_6); + return 0; +} + + +/** + * @brief initialise the compress_chunk() function + * + * If not initialised the compress_chunk() function sets the timestamps and + * version_id in the compression entity header to zero + * + * @param return_timestamp pointer to a function returning a current 48-bit + * timestamp + * @param version_id version identifier of the applications software + */ + +void compress_chunk_init(uint64_t(return_timestamp)(void), uint32_t version_id) +{ + if (return_timestamp) + get_timestamp = return_timestamp; + + version_identifier = version_id; +} + + +/** + * @brief compress a data chunk consisting of put together data collections + * + * @param chunk pointer to the chunk to be compressed + * @param chunk_size byte size of the chunk + * @param chunk_model pointer to a model of a chunk; has the same size + * as the chunk (can be NULL if no model compression + * mode is used) + * @param updated_chunk_model pointer to store the updated model for the next + * model mode compression; has the same size as the + * chunk (can be the same as the model_of_data + * buffer for in-place update or NULL if updated + * model is not needed) + * @param dst destination pointer to the compressed data + * buffer; has to be 4-byte aligned; can be NULL to + * only get the compressed data size + * @param dst_capacity capacity of the dst buffer; it's recommended to + * provide a dst_capacity >= + * compress_chunk_cmp_size_bound(chunk, chunk_size) + * as it eliminates one potential failure scenario: + * not enough space in the dst buffer to write the + * compressed data; size is internally round down + * to a multiple of 4 + * @returns the byte size of the compressed_data buffer on success; negative on + * error, CMP_ERROR_SMALL_BUF (-2) if the compressed data buffer is too + * small to hold the whole compressed data; the compressed and updated + * model are only valid on non negative return values + */ + +int32_t compress_chunk(void *chunk, uint32_t chunk_size, + void *chunk_model, void *updated_chunk_model, + uint32_t *dst, uint32_t dst_capacity, + const struct cmp_par *cmp_par) +{ + uint64_t start_timestamp = get_timestamp(); + size_t read_bytes; + struct collection_hdr *col = (struct collection_hdr *)chunk; + int32_t cmp_size_byte; /* size of the compressed data in bytes */ + enum chunk_type chunk_type; + struct cmp_cfg cfg; + int err; + + if (!chunk) { + debug_print("Error: Pointer to the data chunk is NULL. No data no compression."); + return -1; + } + if (chunk_size < COLLECTION_HDR_SIZE) { + debug_print("Error: The chunk size is smaller than the minimum size."); + return -1; + } + if (chunk_size > CMP_ENTITY_MAX_ORIGINAL_SIZE) { + debug_print("Error: The chunk size is bigger than the maximum allowed chunk size."); + return -1; + } + + chunk_type = cmp_col_get_chunk_type(col); + if (init_cmp_cfg_from_cmp_par(cmp_par, chunk_type, &cfg)) + return -1; + + /* we will build the compression header after the compression of the chunk */ + cmp_size_byte = cmp_ent_build_chunk_header(NULL, chunk_size, &cfg, start_timestamp, 0); + if (dst) { + if (dst_capacity < (uint32_t)cmp_size_byte) { + debug_print("Error: The destination capacity is smaller than the minimum compression entity size."); + return CMP_ERROR_SMALL_BUF; + } + memset(dst, 0, (uint32_t)cmp_size_byte); + } + + for (read_bytes = 0; + read_bytes <= chunk_size - COLLECTION_HDR_SIZE; + read_bytes += cmp_col_get_size(col)) { + uint8_t *col_model = NULL; + uint8_t *col_up_model = NULL; + /* setup pointers for the next collection we want to compress */ + col = (struct collection_hdr *)((uint8_t *)chunk + read_bytes); + if (chunk_model) + col_model = ((uint8_t *)chunk_model + read_bytes); + if (updated_chunk_model) + col_up_model = ((uint8_t *)updated_chunk_model + read_bytes); + + if (cmp_col_get_chunk_type(col) != chunk_type) { + debug_print("Error: The chunk contains collections with an incompatible mix of subservices."); + return -1; + } + if (read_bytes + cmp_col_get_size(col) > chunk_size) + break; + + cmp_size_byte = cmp_collection((uint8_t *)col, col_model, col_up_model, + dst, dst_capacity, &cfg, cmp_size_byte); + } + + if (read_bytes != chunk_size) { + debug_print("Error: The sum of the compressed collections does not match the size of the data in the compression header."); + return -1; + } + + err = cmp_ent_build_chunk_header((struct cmp_entity *)dst, chunk_size, + &cfg, start_timestamp, cmp_size_byte); + if (err < 0) + return err; + + return cmp_size_byte; +} + + +/** + * @brief returns the maximum compressed size in a worst case scenario + * + * In case the input data is not compressible + * This function is primarily useful for memory allocation purposes + * (destination buffer size). + * + * @note if the number of collections is known you can use the + * COMPRESS_CHUNK_BOUND macro for compilation-time evaluation + * (stack memory allocation for example) + * + * @param chunk pointer to the chunk you want compress + * @param chunk_size size of the chunk in bytes + * + * @returns maximum compressed size for a chunk compression; 0 on error + */ + +uint32_t compress_chunk_cmp_size_bound(const void *chunk, size_t chunk_size) +{ + int32_t read_bytes; + uint32_t num_col = 0; + + if (chunk_size > CMP_ENTITY_MAX_ORIGINAL_SIZE-NON_IMAGETTE_HEADER_SIZE-CMP_COLLECTION_FILD_SIZE) { + debug_print("Error: The chunk size is bigger than the maximum allowed chunk size."); + return 0; + } + + for (read_bytes = 0; + read_bytes <= (int32_t)chunk_size-COLLECTION_HDR_SIZE; + read_bytes += cmp_col_get_size((const struct collection_hdr *)((const uint8_t *)chunk + read_bytes))) + num_col++; + + + if ((uint32_t)read_bytes != chunk_size) { + debug_print("Error: The sum of the compressed collections does not match the size of the data in the compression header."); + return 0; + } + + return (uint32_t)COMPRESS_CHUNK_BOUND(chunk_size, num_col); +} + + +/** + * @brief set the model id and model counter in the compression entity header + * + * @param dst pointer to the compressed data starting with a + * compression entity header + * @param dst_size byte size of the dst buffer + * @param model_id model identifier; for identifying entities that originate + * from the same starting model + * @param model_counter model_counter; counts how many times the model was + * updated; for non model mode compression use 0 + * + * @returns 0 on success, otherwise error + */ + +int compress_chunk_set_model_id_and_counter(void *dst, int dst_size, + uint16_t model_id, uint8_t model_counter) +{ + if (dst_size < GENERIC_HEADER_SIZE) + return 1; + + return cmp_ent_set_model_id(dst, model_id) || cmp_ent_set_model_counter(dst, model_counter); } diff --git a/lib/icu_compress/meson.build b/lib/icu_compress/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..01f4d370992dd60de5a047e2a0ce7bd850b6825f --- /dev/null +++ b/lib/icu_compress/meson.build @@ -0,0 +1,3 @@ +icu_compress_sources = files([ + 'cmp_icu.c' +]) diff --git a/lib/meson.build b/lib/meson.build index 2d35635c0590646b27fa4374fd0acc0381505a32..8d40f7c0c80292390699ffff5815ff2840af89d9 100644 --- a/lib/meson.build +++ b/lib/meson.build @@ -1,25 +1,11 @@ -cmplib_sources = files([ - 'cmp_data_types.c', - 'cmp_icu.c', - 'cmp_support.c', - 'rdcu_ctrl.c', - 'rmap.c', - 'cmp_entity.c', - 'cmp_io.c', - 'decmp.c', - 'rdcu_pkt_to_file.c', - 'cmp_guess.c', - 'cmp_rdcu_cfg.c', - 'cmp_rdcu.c', - 'rdcu_cmd.c', - 'rdcu_rmap.c', - 'cmp_max_used_bits.c', - 'cmp_max_used_bits_list.c' -]) +subdir('common') +subdir('decompress') +subdir('icu_compress') +subdir('rdcu_compress') -cmp_lib = static_library('cmp_lib', - sources : cmplib_sources, - include_directories : incdir, - c_args : ['-DDEBUGLEVEL=1'], -# install : 'true' # linking under windows mingw only works if this is set + +incdir = include_directories('.', 'common', 'decompress', 'icu_compress', 'rdcu_compress') + +cmp_lib = static_library('cmp', + sources : [ common_sources, decompress_sources, icu_compress_sources, rdcu_compress_sources] ) diff --git a/lib/cmp_rdcu.c b/lib/rdcu_compress/cmp_rdcu.c similarity index 68% rename from lib/cmp_rdcu.c rename to lib/rdcu_compress/cmp_rdcu.c index 2469988e42af7988fcfad1f121cb6292c58db7d0..7feeda49f3ef0f971414d476c49dec5f2e5887e2 100644 --- a/lib/cmp_rdcu.c +++ b/lib/rdcu_compress/cmp_rdcu.c @@ -28,18 +28,14 @@ #include <stdint.h> -#include <stdio.h> -#include <cmp_debug.h> -#include <cmp_support.h> -#include <cmp_rdcu_cfg.h> -#include <rdcu_ctrl.h> -#include <rdcu_rmap.h> +#include "../common/cmp_debug.h" +#include "../common/cmp_support.h" +#include "cmp_rdcu_cfg.h" +#include "rdcu_ctrl.h" +#include "rdcu_rmap.h" -#define IMA_SAM2BYT \ - 2 /* imagette sample to byte conversion factor; one imagette samples has 16 bits (2 bytes) */ - #define RDCU_INTR_SIG_ENA 1 /* RDCU interrupt signal enabled */ #define RDCU_INTR_SIG_DIS 0 /* RDCU interrupt signal disable */ #define RDCU_INTR_SIG_DEFAULT RDCU_INTR_SIG_ENA /* default start value for RDCU interrupt signal */ @@ -57,28 +53,52 @@ static int interrupt_signal_enabled = RDCU_INTR_SIG_DEFAULT; * @note prints abort message if pending status is non-zero after 10 retries */ -static void sync(void) +static void rdcu_syncing(void) { #if 0 not needed for packed generation int cnt = 0; - printf("syncing..."); + debug_print("syncing..."); while (rdcu_rmap_sync_status()) { - printf("pending: %d\n", rdcu_rmap_sync_status()); + debug_print("pending: %d", rdcu_rmap_sync_status()); if (cnt++ > 10) { - printf("aborting; de"); + debug_print("aborting; de-"); break; } } - printf("synced\n"); + debug_print("synced"); #endif } +/** + * @brief interrupt a data compression + * + * @returns 0 on success, error otherwise + */ + +int rdcu_interrupt_compression(void) +{ + /* interrupt a compression */ + rdcu_set_data_compr_interrupt(); + if (rdcu_sync_compr_ctrl()) + return -1; + rdcu_syncing(); + + /* clear local bit immediately, this is a write-only register. + * we would not want to restart compression by accidentially calling + * rdcu_sync_compr_ctrl() again + */ + rdcu_clear_data_compr_interrupt(); + + return 0; +} + + /** * @brief set up RDCU compression register * @@ -88,10 +108,24 @@ static void sync(void) * @returns 0 on success, error otherwise */ -int rdcu_set_compression_register(const struct cmp_cfg *cfg) +static int rdcu_set_compression_register(const struct cmp_cfg *cfg) { if (rdcu_cmp_cfg_is_invalid(cfg)) return -1; +#if 1 + /* + * There is a bug in the RDCU HW data compressor, when a non-raw mode + * compression is performed after a raw mode compression, the compressor + * gets stuck due to a deadlock condition. Performing a compression + * interrupt after a raw mode compression work around this bug. + */ + if (rdcu_sync_used_param1()) + return -1; + rdcu_syncing(); + if (rdcu_get_compression_mode() == CMP_MODE_RAW) + rdcu_interrupt_compression(); +#endif + /* first, set compression parameters in local mirror registers */ if (rdcu_set_compression_mode(cfg->cmp_mode)) @@ -151,6 +185,9 @@ int rdcu_set_compression_register(const struct cmp_cfg *cfg) if (rdcu_sync_compr_data_buf_len()) return -1; + /* wait for it */ + rdcu_syncing(); + return 0; } @@ -175,7 +212,7 @@ int rdcu_start_compression(void) rdcu_set_data_compr_start(); if (rdcu_sync_compr_ctrl()) return -1; - sync(); + rdcu_syncing(); /* clear local bit immediately, this is a write-only register. * we would not want to restart compression by accidentally calling @@ -188,37 +225,27 @@ int rdcu_start_compression(void) /** - * @brief compressing data with the help of the RDCU hardware compressor + * @brief set up RDCU SRAM for compression * - * @param cfg configuration contains all parameters required for compression - * - * @note Before the rdcu_compress function can be used, an initialisation of - * the RMAP library is required. This is achieved with the functions - * rdcu_ctrl_init() and rdcu_rmap_init(). - * @note The validity of the cfg structure is checked before the compression is - * started. + * @param cfg pointer to a compression configuration * * @returns 0 on success, error otherwise */ -int rdcu_compress_data(const struct cmp_cfg *cfg) +static int rdcu_transfer_sram(const struct cmp_cfg *cfg) { - if (!cfg) - return -1; - - if (rdcu_set_compression_register(cfg)) - return -1; - if (cfg->input_buf != NULL) { /* round up needed size must be a multiple of 4 bytes */ uint32_t size = (cfg->samples * 2 + 3) & ~3U; /* now set the data in the local mirror... */ - if (rdcu_write_sram_16(cfg->input_buf, cfg->rdcu_data_adr, - cfg->samples * 2) < 0) + if (rdcu_write_sram_16(cfg->input_buf, cfg->rdcu_data_adr, cfg->samples * 2) < 0) { + debug_print("Error: The data to be compressed cannot be transferred to the SRAM of the RDCU."); return -1; - if (rdcu_sync_mirror_to_sram(cfg->rdcu_data_adr, size, - rdcu_get_data_mtu())) + } + if (rdcu_sync_mirror_to_sram(cfg->rdcu_data_adr, size, rdcu_get_data_mtu())) { + debug_print("Error: The data to be compressed cannot be transferred to the SRAM of the RDCU."); return -1; + } } /*...and the model when needed */ if (cfg->model_buf != NULL) { @@ -227,20 +254,46 @@ int rdcu_compress_data(const struct cmp_cfg *cfg) /* round up needed size must be a multiple of 4 bytes */ uint32_t size = (cfg->samples * 2 + 3) & ~3U; /* set the model in the local mirror... */ - if (rdcu_write_sram_16(cfg->model_buf, - cfg->rdcu_model_adr, - cfg->samples * 2) < 0) + if (rdcu_write_sram_16(cfg->model_buf, cfg->rdcu_model_adr, cfg->samples * 2) < 0) { + debug_print("Error: The model buffer cannot be transferred to the SRAM of the RDCU."); return -1; - if (rdcu_sync_mirror_to_sram(cfg->rdcu_model_adr, size, - rdcu_get_data_mtu())) + } + if (rdcu_sync_mirror_to_sram(cfg->rdcu_model_adr, size, rdcu_get_data_mtu())) { + debug_print("Error: The model buffer cannot be transferred to the SRAM of the RDCU."); return -1; + } } } /* ...and wait for completion */ - sync(); + rdcu_syncing(); + + return 0; +} + + +/** + * @brief compressing data with the help of the RDCU hardware compressor + * + * @param cfg configuration contains all parameters required for compression + * + * @note Before the rdcu_compress function can be used, an initialisation of + * the RMAP library is required. This is achieved with the functions + * rdcu_ctrl_init() and rdcu_rmap_init(). + * @note The validity of the cfg structure is checked before the compression is + * started. + * + * @returns 0 on success, error otherwise + */ + +int rdcu_compress_data(const struct cmp_cfg *cfg) +{ + if (rdcu_set_compression_register(cfg)) + return -1; + + if (rdcu_transfer_sram(cfg)) + return -1; - /* start the compression */ if (rdcu_start_compression()) return -1; @@ -263,7 +316,7 @@ int rdcu_read_cmp_status(struct cmp_status *status) if (rdcu_sync_compr_status()) return -1; - sync(); + rdcu_syncing(); if (status) { status->data_valid = (uint8_t)rdcu_get_compr_status_valid(); @@ -309,15 +362,15 @@ int rdcu_read_cmp_info(struct cmp_info *info) if (rdcu_sync_samples_used()) return -1; - sync(); + rdcu_syncing(); if (info) { /* put the data in the cmp_info structure */ info->cmp_mode_used = rdcu_get_compression_mode(); info->golomb_par_used = rdcu_get_golomb_param(); info->spill_used = rdcu_get_spillover_threshold(); - info->model_value_used = rdcu_get_weighting_param(); - info->round_used = rdcu_get_noise_bits_rounded(); + info->model_value_used = (uint8_t)rdcu_get_weighting_param(); + info->round_used = (uint8_t)rdcu_get_noise_bits_rounded(); info->rdcu_new_model_adr_used = rdcu_get_new_model_addr_used(); info->samples_used = rdcu_get_samples_used(); info->rdcu_cmp_adr_used = rdcu_get_compr_data_start_addr(); @@ -325,6 +378,27 @@ int rdcu_read_cmp_info(struct cmp_info *info) info->ap1_cmp_size = rdcu_get_compr_data_adaptive_1_size_bit(); info->ap2_cmp_size = rdcu_get_compr_data_adaptive_2_size_bit(); info->cmp_err = rdcu_get_compr_error(); +#ifdef FPGA_VERSION_0_7 + /* There is a bug up to RDCU FPGA version 0.7 where the + * compressed size is not updated accordingly in RAW mode. + */ + if (info->cmp_mode_used == CMP_MODE_RAW) { + info->cmp_size = info->samples_used * IMA_SAM2BYT * 8; + info->ap1_cmp_size = info->cmp_size; + info->ap2_cmp_size = info->cmp_size; + } +#endif +#if 1 + /* There is a bug in RDCU FPGA version 1.1 where the compressed + * size is not updated accordingly in RAW mode when the samples + * parameter is smaller than 3. + */ + if (info->cmp_mode_used == CMP_MODE_RAW && info->samples_used < 3) { + info->cmp_size = info->samples_used * IMA_SAM2BYT * 8; + info->ap1_cmp_size = info->cmp_size; + info->ap2_cmp_size = info->cmp_size; + } +#endif } return 0; } @@ -358,7 +432,7 @@ int rdcu_read_cmp_bitstream(const struct cmp_info *info, void *compressed_data) return -1; /* wait for it */ - sync(); + rdcu_syncing(); return rdcu_read_sram(compressed_data, info->rdcu_cmp_adr_used, s); } @@ -393,53 +467,140 @@ int rdcu_read_model(const struct cmp_info *info, void *updated_model) return -1; /* wait for it */ - sync(); + rdcu_syncing(); return rdcu_read_sram(updated_model, info->rdcu_new_model_adr_used, s); } /** - * @brief interrupt a data compression - * - * @returns 0 on success, error otherwise + * @brief enable the RDCU to signal a finished compression with an interrupt signal */ -int rdcu_interrupt_compression(void) +void rdcu_enable_interrput_signal(void) { - /* interrupt a compression */ - rdcu_set_data_compr_interrupt(); - if (rdcu_sync_compr_ctrl()) - return -1; - sync(); - - /* clear local bit immediately, this is a write-only register. - * we would not want to restart compression by accidentally calling - * rdcu_sync_compr_ctrl() again - */ - rdcu_clear_data_compr_interrupt(); - - return 0; + interrupt_signal_enabled = RDCU_INTR_SIG_ENA; } /** - * @brief enable the RDCU to signal a finished compression with an interrupt signal + * @brief deactivated the RDCU interrupt signal */ -void rdcu_enable_interrput_signal(void) +void rdcu_disable_interrput_signal(void) { - interrupt_signal_enabled = RDCU_INTR_SIG_ENA; + interrupt_signal_enabled = RDCU_INTR_SIG_DIS; } /** - * @brief deactivated the RDCU interrupt signal + * @brief inject a SRAM edac multi bit error into the RDCU SRAM + * + * @param cfg configuration to inject error + * @param addr SRAM address to inject edac error */ -void rdcu_disable_interrput_signal(void) +int rdcu_inject_edac_error(const struct cmp_cfg *cfg, uint32_t addr) { - interrupt_signal_enabled = RDCU_INTR_SIG_DIS; + uint32_t sub_chip_die_addr; + uint8_t buf[4] = {0}; + + if (rdcu_set_compression_register(cfg)) + return -1; + + if (rdcu_transfer_sram(cfg)) + return -1; + + /* disable edac */ + for (sub_chip_die_addr = 1; sub_chip_die_addr <= 4; sub_chip_die_addr++) { + rdcu_edac_set_sub_chip_die_addr(sub_chip_die_addr); + rdcu_edac_set_ctrl_reg_write_op(); + rdcu_edac_set_bypass(); + if (rdcu_sync_sram_edac_ctrl()) { + debug_print("Error: rdcu_sync_sram_edac_ctrl"); + return -1; + } + rdcu_syncing(); + /* verify bypass aktiv */ + rdcu_edac_set_ctrl_reg_read_op(); + if (rdcu_sync_sram_edac_ctrl()) { + debug_print("Error: rdcu_sync_sram_edac_ctrl"); + return -1; + } + rdcu_syncing(); + if (rdcu_sync_sram_edac_status()) { + debug_print("Error: rdcu_sync_sram_edac_status"); + return -1; + } + rdcu_syncing(); + if (rdcu_edac_get_sub_chip_die_addr() != sub_chip_die_addr) { + debug_print("Error: sub_chip_die_addr unexpected!"); + return -1; + } +#if 1 + /* It looks like there is a bug when displaying the bypass status of the 2. and 4. SRAM chip. */ + if (2 != sub_chip_die_addr && 4 != sub_chip_die_addr) +#endif + if (rdcu_edac_get_bypass_status() == 0) { + debug_print("Error: bypass status unexpected!"); + return -1; + } + } + + /* inject multi bit error */ + if (rdcu_sync_sram_to_mirror(addr, sizeof(buf), rdcu_get_data_mtu())) + return -1; + rdcu_syncing(); + if (rdcu_read_sram(buf, addr, sizeof(buf)) < 0) + return -1; + + buf[0] ^= 1 << 0; + buf[1] ^= 1 << 1; + buf[2] ^= 1 << 2; + buf[3] ^= 1 << 3; + + if (rdcu_write_sram(buf, addr, sizeof(buf)) < 0) + return -1; + if (rdcu_sync_mirror_to_sram(addr, sizeof(buf), rdcu_get_data_mtu())) { + debug_print("Error: The data to be compressed cannot be transferred to the SRAM of the RDCU."); + return -1; + } + rdcu_syncing(); + + + /* enable edac again */ + for (sub_chip_die_addr = 1; sub_chip_die_addr <= 4; sub_chip_die_addr++) { + if (rdcu_edac_set_sub_chip_die_addr(sub_chip_die_addr)) + return -1; + rdcu_edac_set_ctrl_reg_write_op(); + rdcu_edac_clear_bypass(); + if (rdcu_sync_sram_edac_ctrl()) { + debug_print("Error: rdcu_sync_sram_edac_ctrl"); + return -1; + } + rdcu_syncing(); + /* verify bypass disable */ + rdcu_edac_set_ctrl_reg_read_op(); + if (rdcu_sync_sram_edac_ctrl()) { + debug_print("Error: rdcu_sync_sram_edac_ctrl"); + return -1; + } + rdcu_syncing(); + if (rdcu_sync_sram_edac_status()) { + debug_print("Error: rdcu_sync_sram_edac_status"); + return -1; + } + rdcu_syncing(); + if (rdcu_edac_get_sub_chip_die_addr() != sub_chip_die_addr) { + debug_print("Error: sub_chip_die_addr unexpected!"); + return -1; + } + if (1 == rdcu_edac_get_bypass_status()) { + debug_print("Error: bypass status unexpected!"); + return -1; + } + } + return 0; } @@ -487,7 +648,7 @@ int rdcu_compress_data_parallel(const struct cmp_cfg *cfg, return -1; /* calculate the need bytes for the bitstream */ - cmp_size_4byte = ((last_info->cmp_size >> 3) + 3) & ~0x3U; + cmp_size_4byte = cmp_bit_to_4byte(last_info->cmp_size); /* parallel read compressed data and write input data from sram * to mirror */ @@ -496,7 +657,7 @@ int rdcu_compress_data_parallel(const struct cmp_cfg *cfg, rdcu_get_data_mtu())) return -1; /* wait for it */ - sync(); + rdcu_syncing(); if (cfg->icu_output_buf) { if (rdcu_read_sram(cfg->icu_output_buf, last_info->rdcu_cmp_adr_used, @@ -504,14 +665,14 @@ int rdcu_compress_data_parallel(const struct cmp_cfg *cfg, return -1; } } else { - debug_print("Warning: input_buf = NULL; input_buf is not written to the sram and compressed data is not read from the SRAM\n"); + debug_print("Warning: input_buf = NULL; input_buf is not written to the sram and compressed data is not read from the SRAM."); } /* read model and write model in parallel */ if (cfg->model_buf && model_mode_is_used(cfg->cmp_mode) && model_mode_is_used(last_info->cmp_mode_used)) { if (cfg->rdcu_model_adr == last_info->rdcu_new_model_adr_used && cfg->samples == last_info->samples_used) { - printf("The last updated model buffer and the current model buffer overlap exactly in the SRAM of the RDCU. Skip model transfer.\n"); + debug_print("The last updated model buffer and the current model buffer overlap exactly in the SRAM of the RDCU. Skip model transfer."); } else { uint32_t new_model_size_4byte; @@ -527,7 +688,7 @@ int rdcu_compress_data_parallel(const struct cmp_cfg *cfg, samples_4byte, rdcu_get_data_mtu())) return -1; /* wait for it */ - sync(); + rdcu_syncing(); if (cfg->icu_new_model_buf) { if (rdcu_read_sram(cfg->icu_new_model_buf, last_info->rdcu_new_model_adr_used, @@ -552,7 +713,7 @@ int rdcu_compress_data_parallel(const struct cmp_cfg *cfg, } /* ...and wait for completion */ - sync(); + rdcu_syncing(); if (rdcu_start_compression()) return -1; diff --git a/lib/cmp_rdcu_cfg.c b/lib/rdcu_compress/cmp_rdcu_cfg.c similarity index 85% rename from lib/cmp_rdcu_cfg.c rename to lib/rdcu_compress/cmp_rdcu_cfg.c index 0efd4a90cd75ff0077d925fa07acaeca1a698380..8f1b3f6d79ce9c0955fe5c9219f1d71894e95ad4 100644 --- a/lib/cmp_rdcu_cfg.c +++ b/lib/rdcu_compress/cmp_rdcu_cfg.c @@ -21,13 +21,10 @@ #include <stdint.h> #include <string.h> -#include <cmp_debug.h> -#include <cmp_support.h> -#include <rdcu_cmd.h> - - -#define IMA_SAM2BYT \ -2 /* imagette sample to byte conversion factor; one imagette samples has 16 bits (2 bytes) */ +#include "../common/cmp_debug.h" +#include "../common/cmp_support.h" +#include "rdcu_cmd.h" +#include "cmp_rdcu_cfg.h" /** @@ -73,7 +70,7 @@ struct cmp_cfg rdcu_cfg_create(enum cmp_data_type data_type, enum cmp_mode cmp_m static int outside_sram_range(uint32_t addr, uint32_t size) { - if (addr + size > RDCU_SRAM_END) + if (addr + size > RDCU_SRAM_START + RDCU_SRAM_SIZE) return 1; if (addr > RDCU_SRAM_END) @@ -124,28 +121,28 @@ static int rdcu_cfg_buffers_is_invalid(const struct cmp_cfg *cfg) if (cfg->cmp_mode == CMP_MODE_RAW) { if (cfg->buffer_length < cfg->samples) { - debug_print("rdcu_buffer_length is smaller than the samples parameter. There is not enough space to copy the data in RAW mode.\n"); + debug_print("rdcu_buffer_length is smaller than the samples parameter. There is not enough space to copy the data in RAW mode."); cfg_invalid++; } } if (cfg->rdcu_data_adr & 0x3) { - debug_print("Error: The RDCU data to compress start address is not 4-Byte aligned.\n"); + debug_print("Error: The RDCU data to compress start address is not 4-Byte aligned."); cfg_invalid++; } if (cfg->rdcu_buffer_adr & 0x3) { - debug_print("Error: The RDCU compressed data start address is not 4-Byte aligned.\n"); + debug_print("Error: The RDCU compressed data start address is not 4-Byte aligned."); cfg_invalid++; } if (outside_sram_range(cfg->rdcu_data_adr, cfg->samples * IMA_SAM2BYT)) { - debug_print("Error: The RDCU data to compress buffer is outside the RDCU SRAM address space.\n"); + debug_print("Error: The RDCU data to compress buffer is outside the RDCU SRAM address space."); cfg_invalid++; } if (outside_sram_range(cfg->rdcu_buffer_adr, cfg->buffer_length * IMA_SAM2BYT)) { - debug_print("Error: The RDCU compressed data buffer is outside the RDCU SRAM address space.\n"); + debug_print("Error: The RDCU compressed data buffer is outside the RDCU SRAM address space."); cfg_invalid++; } @@ -153,23 +150,23 @@ static int rdcu_cfg_buffers_is_invalid(const struct cmp_cfg *cfg) cfg->rdcu_data_adr + cfg->samples * IMA_SAM2BYT, cfg->rdcu_buffer_adr, cfg->rdcu_buffer_adr + cfg->buffer_length * IMA_SAM2BYT)) { - debug_print("Error: The RDCU data to compress buffer and the RDCU compressed data buffer are overlapping.\n"); + debug_print("Error: The RDCU data to compress buffer and the RDCU compressed data buffer are overlapping."); cfg_invalid++; } if (model_mode_is_used(cfg->cmp_mode)) { if (cfg->model_buf && cfg->model_buf == cfg->input_buf) { - debug_print("Error: The model buffer (model_buf) and the data to be compressed (input_buf) are equal.\n"); + debug_print("Error: The model buffer (model_buf) and the data to be compressed (input_buf) are equal."); cfg_invalid++; } if (cfg->rdcu_model_adr & 0x3) { - debug_print("Error: The RDCU model start address is not 4-Byte aligned.\n"); + debug_print("Error: The RDCU model start address is not 4-Byte aligned."); cfg_invalid++; } if (outside_sram_range(cfg->rdcu_model_adr, cfg->samples * IMA_SAM2BYT)) { - debug_print("Error: The RDCU model buffer is outside the RDCU SRAM address space.\n"); + debug_print("Error: The RDCU model buffer is outside the RDCU SRAM address space."); cfg_invalid++; } @@ -178,7 +175,7 @@ static int rdcu_cfg_buffers_is_invalid(const struct cmp_cfg *cfg) cfg->rdcu_model_adr + cfg->samples * IMA_SAM2BYT, cfg->rdcu_data_adr, cfg->rdcu_data_adr + cfg->samples * IMA_SAM2BYT)) { - debug_print("Error: The model buffer and the data to compress buffer are overlapping.\n"); + debug_print("Error: The model buffer and the data to compress buffer are overlapping."); cfg_invalid++; } @@ -188,19 +185,19 @@ static int rdcu_cfg_buffers_is_invalid(const struct cmp_cfg *cfg) cfg->rdcu_buffer_adr, cfg->rdcu_buffer_adr + cfg->buffer_length * IMA_SAM2BYT) ) { - debug_print("Error: The model buffer and the compressed data buffer are overlapping.\n"); + debug_print("Error: The model buffer and the compressed data buffer are overlapping."); cfg_invalid++; } if (cfg->rdcu_model_adr != cfg->rdcu_new_model_adr) { if (cfg->rdcu_new_model_adr & 0x3) { - debug_print("Error: The RDCU updated model start address (rdcu_new_model_adr) is not 4-Byte aligned.\n"); + debug_print("Error: The RDCU updated model start address (rdcu_new_model_adr) is not 4-Byte aligned."); cfg_invalid++; } if (outside_sram_range(cfg->rdcu_new_model_adr, cfg->samples * IMA_SAM2BYT)) { - debug_print("Error: The RDCU updated model buffer is outside the RDCU SRAM address space.\n"); + debug_print("Error: The RDCU updated model buffer is outside the RDCU SRAM address space."); cfg_invalid++; } @@ -210,7 +207,7 @@ static int rdcu_cfg_buffers_is_invalid(const struct cmp_cfg *cfg) cfg->rdcu_data_adr, cfg->rdcu_data_adr + cfg->samples * IMA_SAM2BYT) ) { - debug_print("Error: The updated model buffer and the data to compress buffer are overlapping.\n"); + debug_print("Error: The updated model buffer and the data to compress buffer are overlapping."); cfg_invalid++; } @@ -220,7 +217,7 @@ static int rdcu_cfg_buffers_is_invalid(const struct cmp_cfg *cfg) cfg->rdcu_buffer_adr, cfg->rdcu_buffer_adr + cfg->buffer_length * IMA_SAM2BYT) ) { - debug_print("Error: The updated model buffer and the compressed data buffer are overlapping.\n"); + debug_print("Error: The updated model buffer and the compressed data buffer are overlapping."); cfg_invalid++; } if (buffers_overlap( @@ -229,7 +226,7 @@ static int rdcu_cfg_buffers_is_invalid(const struct cmp_cfg *cfg) cfg->rdcu_model_adr, cfg->rdcu_model_adr + cfg->samples * IMA_SAM2BYT) ) { - debug_print("Error: The updated model buffer and the model buffer are overlapping.\n"); + debug_print("Error: The updated model buffer and the model buffer are overlapping."); cfg_invalid++; } } @@ -273,7 +270,7 @@ int rdcu_cfg_buffers(struct cmp_cfg *cfg, uint16_t *data_to_compress, uint32_t rdcu_buffer_lenght) { if (!cfg) { - debug_print("Error: pointer to the compression configuration structure is NULL.\n"); + debug_print("Error: pointer to the compression configuration structure is NULL."); return -1; } @@ -311,7 +308,7 @@ int rdcu_cfg_imagette(struct cmp_cfg *cfg, uint32_t ap2_golomb_par, uint32_t ap2_spillover_par) { if (!cfg) { - debug_print("Error: pointer to the compression configuration structure is NULL.\n"); + debug_print("Error: pointer to the compression configuration structure is NULL."); return -1; } @@ -326,6 +323,39 @@ int rdcu_cfg_imagette(struct cmp_cfg *cfg, } +/** + * @brief set up the default configuration parameters for an RDCU imagette + * compression based on the set compression mode + * + * @returns 0 if parameters are valid, non-zero if parameters are invalid + */ + +int rdcu_cfg_imagette_default(struct cmp_cfg *cfg) +{ + + if (!cfg) { + debug_print("Error: pointer to the compression configuration structure is NULL."); + return -1; + } + + if (model_mode_is_used(cfg->cmp_mode)) { + return rdcu_cfg_imagette(cfg, CMP_DEF_IMA_MODEL_GOLOMB_PAR, + CMP_DEF_IMA_MODEL_SPILL_PAR, + CMP_DEF_IMA_MODEL_AP1_GOLOMB_PAR, + CMP_DEF_IMA_MODEL_AP1_SPILL_PAR, + CMP_DEF_IMA_MODEL_AP2_GOLOMB_PAR, + CMP_DEF_IMA_MODEL_AP2_SPILL_PAR); + } else { + return rdcu_cfg_imagette(cfg, CMP_DEF_IMA_DIFF_GOLOMB_PAR, + CMP_DEF_IMA_DIFF_SPILL_PAR, + CMP_DEF_IMA_DIFF_AP1_GOLOMB_PAR, + CMP_DEF_IMA_DIFF_AP1_SPILL_PAR, + CMP_DEF_IMA_DIFF_AP2_GOLOMB_PAR, + CMP_DEF_IMA_DIFF_AP2_SPILL_PAR); + } +} + + /** * @brief check if the compressor configuration is invalid for an RDCU compression, * see the user manual for more information (PLATO-UVIE-PL-UM-0001). @@ -341,29 +371,29 @@ int rdcu_cmp_cfg_is_invalid(const struct cmp_cfg *cfg) int cfg_invalid = 0; if (!cfg) { - debug_print("Error: pointer to the compression configuration structure is NULL.\n"); + debug_print("Error: pointer to the compression configuration structure is NULL."); return -1; } if (!cfg->input_buf) - debug_print("Warning: The data to compress buffer is set to NULL. No data will be transferred to the rdcu_data_adr in the RDCU SRAM.\n"); + debug_print("Warning: The data to compress buffer is set to NULL. No data will be transferred to the rdcu_data_adr in the RDCU SRAM."); if (model_mode_is_used(cfg->cmp_mode)) { if (!cfg->model_buf) - debug_print("Warning: The model buffer is set to NULL. No model data will be transferred to the rdcu_model_adr in the RDCU SRAM.\n"); + debug_print("Warning: The model buffer is set to NULL. No model data will be transferred to the rdcu_model_adr in the RDCU SRAM."); } if (cfg->samples == 0) - debug_print("Warning: The samples parameter is set to 0. No data will be compressed.\n"); + debug_print("Warning: The samples parameter is set to 0. No data will be compressed."); if (cfg->icu_new_model_buf) - debug_print("Warning: ICU updated model buffer is set. This buffer is not used for an RDCU compression.\n"); + debug_print("Warning: ICU updated model buffer is set. This buffer is not used for an RDCU compression."); if (cfg->icu_output_buf) - debug_print("Warning: ICU compressed data buffer is set. This buffer is not used for an RDCU compression.\n"); + debug_print("Warning: ICU compressed data buffer is set. This buffer is not used for an RDCU compression."); if (cfg->buffer_length == 0) { - debug_print("Error: The buffer_length is set to 0. There is no place to store the compressed data.\n"); + debug_print("Error: The buffer_length is set to 0. There is no place to store the compressed data."); cfg_invalid++; } diff --git a/include/cmp_rdcu_cfg.h b/lib/rdcu_compress/cmp_rdcu_cfg.h similarity index 89% rename from include/cmp_rdcu_cfg.h rename to lib/rdcu_compress/cmp_rdcu_cfg.h index c8ef639971aeb243851912731ea4dab05b579ff4..46a597662cb89729e7ea3252d9f8f839b4b1c433 100644 --- a/include/cmp_rdcu_cfg.h +++ b/lib/rdcu_compress/cmp_rdcu_cfg.h @@ -16,11 +16,10 @@ * @brief hardware compressor configuration library */ +#ifndef CMP_RDCU_CFG_H +#define CMP_RDCU_CFG_H -#ifndef _CMP_RDCU_CFG_H_ -#define _CMP_RDCU_CFG_H_ - -#include <cmp_support.h> +#include "../common/cmp_support.h" struct cmp_cfg rdcu_cfg_create(enum cmp_data_type data_type, enum cmp_mode cmp_mode, @@ -36,7 +35,8 @@ int rdcu_cfg_imagette(struct cmp_cfg *cfg, uint32_t golomb_par, uint32_t spillover_par, uint32_t ap1_golomb_par, uint32_t ap1_spillover_par, uint32_t ap2_golomb_par, uint32_t ap2_spillover_par); +int rdcu_cfg_imagette_default(struct cmp_cfg *cfg); int rdcu_cmp_cfg_is_invalid(const struct cmp_cfg *cfg); -#endif /* _CMP_RDCU_CFG_H_ */ +#endif /* CMP_RDCU_CFG_H */ diff --git a/lib/rdcu_compress/meson.build b/lib/rdcu_compress/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..cad28df11e5ae6c67fe70fb9d90e7a3caab617ad --- /dev/null +++ b/lib/rdcu_compress/meson.build @@ -0,0 +1,8 @@ +rdcu_compress_sources = files([ + 'cmp_rdcu.c', + 'cmp_rdcu_cfg.c', + 'rdcu_cmd.c', + 'rdcu_ctrl.c', + 'rdcu_rmap.c', + 'rmap.c' +]) diff --git a/lib/rdcu_cmd.c b/lib/rdcu_compress/rdcu_cmd.c similarity index 99% rename from lib/rdcu_cmd.c rename to lib/rdcu_compress/rdcu_cmd.c index a4e21d265a663c0a3d62afaca55f894719611f67..79ac6148f034bd44c775c0a341f11717b1f63d2e 100644 --- a/lib/rdcu_cmd.c +++ b/lib/rdcu_compress/rdcu_cmd.c @@ -18,11 +18,9 @@ */ -#include <stdlib.h> - -#include <rmap.h> -#include <rdcu_cmd.h> -#include <rdcu_rmap.h> +#include "rmap.h" +#include "rdcu_cmd.h" +#include "rdcu_rmap.h" /** diff --git a/include/rdcu_cmd.h b/lib/rdcu_compress/rdcu_cmd.h similarity index 98% rename from include/rdcu_cmd.h rename to lib/rdcu_compress/rdcu_cmd.h index d1244727f5e76cf006af9a532448baf479a0e76e..fbbbb31bee1ef9109e0ccd335c8d60202728b71c 100644 --- a/include/rdcu_cmd.h +++ b/lib/rdcu_compress/rdcu_cmd.h @@ -16,8 +16,9 @@ * @brief RMAP RDCU RMAP command library header file * @see FPGA Requirement Specification PLATO-IWF-PL-RS-005 Issue 0.6 */ -#ifndef _RDCU_CMD_H_ -#define _RDCU_CMD_H_ + +#ifndef RDCU_CMD_H +#define RDCU_CMD_H #include <stdint.h> @@ -159,5 +160,4 @@ int rdcu_read_cmd_sram_edac_status(uint16_t trans_id, uint8_t *cmd); /* SRAM EDAC write accessors */ int rdcu_write_cmd_sram_edac_ctrl(uint16_t trans_id, uint8_t *cmd); - -#endif /* _RDCU_CMD_H_ */ +#endif /* RDCU_CMD_H */ diff --git a/lib/rdcu_ctrl.c b/lib/rdcu_compress/rdcu_ctrl.c similarity index 96% rename from lib/rdcu_ctrl.c rename to lib/rdcu_compress/rdcu_ctrl.c index 579db5e15e761086504db66f5c5ca80fc21a5f1c..0c23b5bf7396386f886ff763ada7552f6b454bd7 100644 --- a/lib/rdcu_ctrl.c +++ b/lib/rdcu_compress/rdcu_ctrl.c @@ -57,15 +57,15 @@ */ -#include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <string.h> -#include <byteorder.h> -#include <rdcu_cmd.h> -#include <rdcu_ctrl.h> -#include <rdcu_rmap.h> +#include "../common/byteorder.h" +#include "../common/cmp_debug.h" +#include "rdcu_cmd.h" +#include "rdcu_ctrl.h" +#include "rdcu_rmap.h" static struct rdcu_mirror *rdcu; @@ -200,7 +200,7 @@ uint8_t rdcu_get_rmap_target_cmd_key(void) uint32_t rdcu_get_lvds_link_enabled(uint32_t link) { if (link > 7) - return -1; + return -1U; return (rdcu->lvds_core_status >> link) & 0x1UL; } @@ -663,14 +663,14 @@ void rdcu_clear_rdcu_board_reset(void) * @note value is scaling factor minus 1 */ -int rdcu_set_spw_link_run_clkdiv(uint8_t div) +int rdcu_set_spw_link_run_clkdiv(uint8_t divisor) { - if (div > 49) + if (divisor > 49) return -1; /* clear and set */ rdcu->spw_link_ctrl &= ~(0x3FUL << 8); - rdcu->spw_link_ctrl |= ((uint32_t) div << 8); + rdcu->spw_link_ctrl |= ((uint32_t) divisor << 8); return 0; } @@ -947,13 +947,13 @@ int rdcu_set_spillover_threshold(uint32_t spill) if (spill < 2) return -1; - if (spill > 16383) + if (spill > 0x3FFUL) return -1; #endif /*SKIP_CMP_PAR_CHECK*/ /* clear and set */ - rdcu->compressor_param2 &= ~(0x3FFFUL << 8); - rdcu->compressor_param2 |= (spill << 8); + rdcu->compressor_param2 &= ~(0x3FFUL << 8); + rdcu->compressor_param2 |= (spill << 8); return 0; } @@ -997,13 +997,13 @@ int rdcu_set_adaptive_1_spillover_threshold(uint32_t spill) if (spill < 2) return -1; - if (spill > 16383) + if (spill > 0x3FFUL) return -1; #endif /*SKIP_CMP_PAR_CHECK*/ /* clear and set */ - rdcu->adaptive_param1 &= ~(0x3FFFUL << 8); - rdcu->adaptive_param1 |= (spill << 8); + rdcu->adaptive_param1 &= ~(0x3FFUL << 8); + rdcu->adaptive_param1 |= (spill << 8); return 0; } @@ -1048,13 +1048,13 @@ int rdcu_set_adaptive_2_spillover_threshold(uint32_t spill) if (spill < 2) return -1; - if (spill > 16383) + if (spill > 0x3FFUL) return -1; #endif /*SKIP_CMP_PAR_CHECK*/ /* clear and set */ - rdcu->adaptive_param2 &= ~(0x3FFFUL << 8); - rdcu->adaptive_param2 |= (spill << 8); + rdcu->adaptive_param2 &= ~(0x3FFUL << 8); + rdcu->adaptive_param2 |= (spill << 8); return 0; } @@ -1274,7 +1274,7 @@ uint32_t rdcu_get_weighting_param(void) uint32_t rdcu_get_spillover_threshold(void) { - return (rdcu->used_param2 >> 8) & 0x3FFFUL; + return (rdcu->used_param2 >> 8) & 0x3FFUL; } @@ -1564,7 +1564,7 @@ int rdcu_read_sram(void *buf, uint32_t addr, uint32_t size) if (size > RDCU_SRAM_SIZE) return -1; - if (addr + size > RDCU_SRAM_END) + if (addr + size > RDCU_SRAM_START + RDCU_SRAM_SIZE) return -1; if (buf) @@ -1585,7 +1585,7 @@ int rdcu_read_sram(void *buf, uint32_t addr, uint32_t size) * @returns the number of bytes written, < 0 on error */ -int rdcu_write_sram(void *buf, uint32_t addr, uint32_t size) +int rdcu_write_sram(const void *buf, uint32_t addr, uint32_t size) { if (!buf) return 0; @@ -1596,7 +1596,7 @@ int rdcu_write_sram(void *buf, uint32_t addr, uint32_t size) if (size > RDCU_SRAM_SIZE) return -1; - if (addr + size > RDCU_SRAM_END) + if (addr + size > RDCU_SRAM_START + RDCU_SRAM_SIZE) return -1; if (buf) @@ -1618,7 +1618,7 @@ int rdcu_write_sram(void *buf, uint32_t addr, uint32_t size) * @returns the number of bytes written, < 0 on error */ -int rdcu_write_sram_8(uint8_t *buf, uint32_t addr, uint32_t size) +int rdcu_write_sram_8(const uint8_t *buf, uint32_t addr, uint32_t size) { return rdcu_write_sram(buf, addr, size); } @@ -1636,7 +1636,7 @@ int rdcu_write_sram_8(uint8_t *buf, uint32_t addr, uint32_t size) * @returns the number of bytes written, < 0 on error */ -int rdcu_write_sram_16(uint16_t *buf, uint32_t addr, uint32_t size) +int rdcu_write_sram_16(const uint16_t *buf, uint32_t addr, uint32_t size) { if (!buf) return 0; @@ -1650,7 +1650,7 @@ int rdcu_write_sram_16(uint16_t *buf, uint32_t addr, uint32_t size) if (size > RDCU_SRAM_SIZE) return -1; - if (addr + size > RDCU_SRAM_END) + if (addr + size > RDCU_SRAM_START + RDCU_SRAM_SIZE) return -1; #if !(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) @@ -1660,9 +1660,9 @@ int rdcu_write_sram_16(uint16_t *buf, uint32_t addr, uint32_t size) uint32_t i; for (i = 0; i < size/sizeof(uint16_t); i++) { - uint16_t *sram_buf = (uint16_t *)&rdcu->sram[addr]; + uint16_t tmp = cpu_to_be16(buf[i]); - sram_buf[i] = cpu_to_be16(buf[i]); + memcpy(&rdcu->sram[addr+i*sizeof(tmp)], &tmp, sizeof(tmp)); } } return (int)size; /* lol */ @@ -1682,7 +1682,7 @@ int rdcu_write_sram_16(uint16_t *buf, uint32_t addr, uint32_t size) * @returns the number of bytes written, < 0 on error */ -int rdcu_write_sram_32(uint32_t *buf, uint32_t addr, uint32_t size) +int rdcu_write_sram_32(const uint32_t *buf, uint32_t addr, uint32_t size) { if (!buf) return 0; @@ -1696,7 +1696,7 @@ int rdcu_write_sram_32(uint32_t *buf, uint32_t addr, uint32_t size) if (size > RDCU_SRAM_SIZE) return -1; - if (addr + size > RDCU_SRAM_END) + if (addr + size > RDCU_SRAM_START + RDCU_SRAM_SIZE) return -1; #if !(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) @@ -1706,9 +1706,9 @@ int rdcu_write_sram_32(uint32_t *buf, uint32_t addr, uint32_t size) uint32_t i; for (i = 0; i < size/sizeof(uint32_t); i++) { - uint32_t *sram_buf = (uint32_t *)&rdcu->sram[addr]; + uint32_t tmp = cpu_to_be32(buf[i]); - sram_buf[i] = cpu_to_be32(buf[i]); + memcpy(&rdcu->sram[addr+i*sizeof(tmp)], &tmp, sizeof(tmp)); } } return (int)size; /* lol */ @@ -2260,7 +2260,7 @@ int rdcu_sync_mirror_to_sram(uint32_t addr, uint32_t size, uint32_t mtu) if (size > RDCU_SRAM_SIZE) return -1; - if ((addr + size) > (RDCU_SRAM_END + 1)) + if (addr + size > RDCU_SRAM_START + RDCU_SRAM_SIZE) return -1; @@ -2334,7 +2334,7 @@ int rdcu_sync_sram_to_mirror(uint32_t addr, uint32_t size, uint32_t mtu) if (size > RDCU_SRAM_SIZE) return -1; - if ((addr + size) > (RDCU_SRAM_END + 1)) + if (addr + size > RDCU_SRAM_START + RDCU_SRAM_SIZE) return -1; @@ -2440,7 +2440,7 @@ int rdcu_sync_sram_mirror_parallel(uint32_t rx_addr, uint32_t rx_size, /* check buffer overlap */ if (rx_addr < tx_addr+tx_size && rx_addr+rx_size > tx_addr) { - printf("Error: The two parallel transferring buffers overlap. Read buffer: 0x%x size: %u. Write buffer: 0x%x size: %u.\n", + debug_print("Error: The two parallel transferring buffers overlap. Read buffer: 0x%x size: %u. Write buffer: 0x%x size: %u.", rx_addr, rx_size, tx_addr, tx_size); return -1; } @@ -2524,17 +2524,17 @@ int rdcu_ctrl_init(void) { rdcu = (struct rdcu_mirror *) calloc(1, sizeof(struct rdcu_mirror)); if (!rdcu) { - printf("Error allocating memory for the RDCU mirror\n"); + debug_print("Error allocating memory for the RDCU mirror"); return -1; } -#if (__sparc__) +#if defined(__sparc__) rdcu->sram = (uint8_t *) 0x60000000; #else /* assume PC */ rdcu->sram = (uint8_t *) malloc(RDCU_SRAM_SIZE); if (!rdcu->sram) { - printf("Error allocating memory for the RDCU SRAM mirror\n"); + debug_print("Error allocating memory for the RDCU SRAM mirror"); return -1; } #endif diff --git a/include/rdcu_ctrl.h b/lib/rdcu_compress/rdcu_ctrl.h similarity index 95% rename from include/rdcu_ctrl.h rename to lib/rdcu_compress/rdcu_ctrl.h index 6b73f4bc9f4dc3a205cc1a7fdc5a665804135626..b3cfa66f67d1309aeab0c0709d38ffbb3eb8a870 100644 --- a/include/rdcu_ctrl.h +++ b/lib/rdcu_compress/rdcu_ctrl.h @@ -17,9 +17,8 @@ * @see FPGA Requirement Specification PLATO-IWF-PL-RS-005 Issue 0.6 */ - -#ifndef _RDCU_CTRL_H_ -#define _RDCU_CTRL_H_ +#ifndef RDCU_CTRL_H +#define RDCU_CTRL_H #include <stdint.h> @@ -140,6 +139,7 @@ uint16_t rdcu_get_fpga_version(void); uint32_t rdcu_get_rdcu_status_board_serial_number(void); uint32_t rdcu_get_rdcu_status_fpga_core_power_good(void); +uint32_t rdcu_get_rdcu_status_core_power_good(void); uint32_t rdcu_get_rdcu_status_io_power_good(void); uint32_t rdcu_get_rdcu_status_reset_by_register(void); uint32_t rdcu_get_rdcu_status_power_on_reset(void); @@ -193,7 +193,7 @@ void rdcu_clear_rdcu_spw_error_cntr_reset(void); void rdcu_set_rdcu_board_reset(void); void rdcu_clear_rdcu_board_reset(void); -int rdcu_set_spw_link_run_clkdiv(uint8_t div); +int rdcu_set_spw_link_run_clkdiv(uint8_t divisor); int rdcu_set_lvds_link_enabled(uint32_t link); int rdcu_set_lvds_link_disabled(uint32_t link); @@ -282,13 +282,12 @@ uint8_t rdcu_edac_get_scrub_info(void); /* SRAM */ int rdcu_read_sram(void *buf, uint32_t addr, uint32_t size); -int rdcu_write_sram(void *buf, uint32_t addr, uint32_t size); -int rdcu_write_sram_8(uint8_t *buf, uint32_t addr, uint32_t size); -int rdcu_write_sram_16(uint16_t *buf, uint32_t addr, uint32_t size); -int rdcu_write_sram_32(uint32_t *buf, uint32_t addr, uint32_t size); +int rdcu_write_sram(const void *buf, uint32_t addr, uint32_t size); +int rdcu_write_sram_8(const uint8_t *buf, uint32_t addr, uint32_t size); +int rdcu_write_sram_16(const uint16_t *buf, uint32_t addr, uint32_t size); +int rdcu_write_sram_32(const uint32_t *buf, uint32_t addr, uint32_t size); int rdcu_ctrl_init(void); - -#endif /* _RDCU_CTRL_H_ */ +#endif /* RDCU_CTRL_H */ diff --git a/lib/rdcu_rmap.c b/lib/rdcu_compress/rdcu_rmap.c similarity index 86% rename from lib/rdcu_rmap.c rename to lib/rdcu_compress/rdcu_rmap.c index 0e14b775f9dace881025ee7e7a51d85095d825d8..7a740e8c205585a62be58ed05bd0960e89e6b217 100644 --- a/lib/rdcu_rmap.c +++ b/lib/rdcu_compress/rdcu_rmap.c @@ -62,13 +62,13 @@ */ -#include <stdio.h> #include <stdlib.h> #include <string.h> -#include <byteorder.h> -#include <rmap.h> -#include <rdcu_rmap.h> +#include "../common/byteorder.h" +#include "../common/cmp_debug.h" +#include "rmap.h" +#include "rdcu_rmap.h" #define RDCU_CONFIG_DEBUG 0 @@ -91,7 +91,7 @@ static int32_t (*rmap_tx)(const void *hdr, uint32_t hdr_size, const void *data, uint32_t data_size); static uint32_t (*rmap_rx)(uint8_t *pkt); -static size_t data_mtu; /* maximum data transfer size per unit */ +static uint32_t data_mtu; /* maximum data transfer size per unit */ @@ -228,7 +228,7 @@ static void *trans_log_get_addr(int slot) static int rdcu_process_rx(void) { - int n; + uint32_t n; int cnt = 0; uint32_t *local_addr; @@ -246,7 +246,7 @@ static int rdcu_process_rx(void) /* we received something, allocate enough space for the packet */ spw_pckt = (uint8_t *) malloc(n); if (!spw_pckt) { - printf("malloc() for packet failed!\n"); + debug_print("malloc() for packet failed!"); return -1; } @@ -254,7 +254,7 @@ static int rdcu_process_rx(void) n = rmap_rx(spw_pckt); if (!n) { - printf("Unknown error in rmap_rx()\n"); + debug_print("Unknown error in rmap_rx()"); free(spw_pckt); return -1; } @@ -269,21 +269,20 @@ static int rdcu_process_rx(void) free(spw_pckt); if (!rp) { - printf("Error converting to RMAP packet\n"); + debug_print("Error converting to RMAP packet"); continue; } local_addr = trans_log_get_addr(rp->tr_id); if (!local_addr) { - printf("Warning: response packet received not in transaction log\n"); + debug_print("Warning: response packet received not in transaction log"); rmap_erase_packet(rp); continue; } if (rp->data_len & 0x3) { - printf("Error: response packet data size is not a multiple of 4, transaction dropped\n"); - + debug_print("Error: response packet data size is not a multiple of 4, transaction dropped"); trans_log_release_slot(rp->tr_id); rmap_erase_packet(rp); return -1; @@ -292,20 +291,22 @@ static int rdcu_process_rx(void) if (rp->data_len) { uint8_t crc8; - /* convert endianness if needed */ + /* convert endianness in-place if needed */ #if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) { - unsigned int i; - uint32_t *p = (uint32_t *) rp->data; + uint32_t i, tmp; - for (i = 0; i < (rp->data_len / 4); i++) - be32_to_cpus(&p[i]); + for (i = 0; i < rp->data_len; i += sizeof(tmp)) { + memcpy(&tmp, &rp->data[i], sizeof(tmp)); + be32_to_cpus(&tmp); + memcpy(&rp->data[i], &tmp, sizeof(tmp)); + } } #endif /* __BYTE_ORDER__ */ crc8 = rmap_crc8(rp->data, rp->data_len); if (crc8 != rp->data_crc) { - printf("Error: data CRC8 mismatch, data invalid or packet truncated. Transaction dropped\n"); + debug_print("Error: data CRC8 mismatch, data invalid or packet truncated. Transaction dropped"); trans_log_release_slot(rp->tr_id); rmap_erase_packet(rp); @@ -335,8 +336,8 @@ static int rdcu_process_rx(void) * @returns 0 on success, otherwise error */ -int rdcu_submit_tx(const uint8_t *cmd, int cmd_size, - const uint8_t *data, int data_size) +int rdcu_submit_tx(const uint8_t *cmd, uint32_t cmd_size, + const uint8_t *data, uint32_t data_size) { /* try to process pending responses */ rdcu_process_rx(); @@ -345,10 +346,10 @@ int rdcu_submit_tx(const uint8_t *cmd, int cmd_size, return -1; if (RDCU_CONFIG_DEBUG) - printf("Transmitting RMAP command\n"); + debug_print("Transmitting RMAP command"); if (rmap_tx(cmd, cmd_size, dpath_len, data, data_size)) { - printf("rmap_tx() returned error!\n"); + debug_print("rmap_tx() returned error!"); return -1; } @@ -382,7 +383,7 @@ int rdcu_gen_cmd(uint16_t trans_id, uint8_t *cmd, pkt = rmap_create_packet(); if (!pkt) { - printf("Error creating packet\n"); + debug_print("Error creating packet"); return 0; } @@ -399,12 +400,12 @@ int rdcu_gen_cmd(uint16_t trans_id, uint8_t *cmd, /* determine header size */ n = rmap_build_hdr(pkt, NULL); - if (!cmd) { + if (!cmd || n <= 0) { rmap_erase_packet(pkt); return n; } - memset(cmd, 0, n); /* clear command buffer */ + memset(cmd, 0, (size_t)n); /* clear command buffer */ n = rmap_build_hdr(pkt, cmd); @@ -432,7 +433,7 @@ int rdcu_gen_cmd(uint16_t trans_id, uint8_t *cmd, int rdcu_sync(int (*fn)(uint16_t trans_id, uint8_t *cmd), - void *addr, int data_len) + void *addr, uint32_t data_len) { int n; int slot; @@ -444,23 +445,27 @@ int rdcu_sync(int (*fn)(uint16_t trans_id, uint8_t *cmd), return -1; slot = trans_log_grab_slot(addr); - if (slot < 0) + if (slot < 0 || slot > UINT16_MAX) return -1; /* determine size of command */ - n = fn(slot, NULL); + n = fn((uint16_t)slot, NULL); + if (n <= 0) { + debug_print("Error creating command packet"); + return -1; + } - rmap_cmd = (uint8_t *) malloc(n); + rmap_cmd = (uint8_t *)malloc((size_t)n); if (!rmap_cmd) { - printf("Error allocating rmap cmd"); + debug_print("Error allocating rmap cmd"); return -1; } /* now fill actual command */ - n = fn(slot, rmap_cmd); - if (!n) { - printf("Error creating command packet\n"); + n = fn((uint16_t)slot, rmap_cmd); + if (n <= 0) { + debug_print("Error creating command packet"); free(rmap_cmd); return -1; } @@ -468,9 +473,9 @@ int rdcu_sync(int (*fn)(uint16_t trans_id, uint8_t *cmd), /* convert endianness if needed */ #if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) if (data_len) { - int i; + uint32_t i; uint32_t *tmp_buf = alloca(data_len); - uint32_t *p = (uint32_t *) addr; + uint32_t *p = (uint32_t *)addr; for (i = 0; i < (data_len / 4); i++) tmp_buf[i] = cpu_to_be32(p[i]); @@ -479,7 +484,7 @@ int rdcu_sync(int (*fn)(uint16_t trans_id, uint8_t *cmd), } #endif /* __BYTE_ORDER__ */ - n = rdcu_submit_tx(rmap_cmd, n, addr, data_len); + n = rdcu_submit_tx(rmap_cmd, (uint32_t)n, addr, data_len); free(rmap_cmd); return n; @@ -514,39 +519,42 @@ int rdcu_sync_data(int (*fn)(uint16_t trans_id, uint8_t *cmd, uint8_t *rmap_cmd; - - rdcu_process_rx(); slot = trans_log_grab_slot(data); - if (slot < 0) { + if (slot < 0 || slot > UINT16_MAX) { if (RDCU_CONFIG_DEBUG) - printf("Error: all slots busy!\n"); + debug_print("Error: all slots busy!"); return 1; } /* determine size of command */ - n = fn(slot, NULL, addr, data_len); + n = fn((uint16_t)slot, NULL, addr, data_len); + if (n <= 0) { + debug_print("Error creating command packet"); + return -1; + } - rmap_cmd = (uint8_t *) malloc(n); + + rmap_cmd = (uint8_t *)malloc((size_t)n); if (!rmap_cmd) { - printf("Error allocating rmap cmd"); + debug_print("Error allocating rmap cmd"); return -1; } /* now fill actual command */ - n = fn(slot, rmap_cmd, addr, data_len); - if (!n) { - printf("Error creating command packet\n"); + n = fn((uint16_t)slot, rmap_cmd, addr, data_len); + if (n <= 0) { + debug_print("Error creating command packet"); free(rmap_cmd); return -1; } if (read) - n = rdcu_submit_tx(rmap_cmd, n, NULL, 0); + n = rdcu_submit_tx(rmap_cmd, (uint32_t)n, NULL, 0); else - n = rdcu_submit_tx(rmap_cmd, n, data, data_len); + n = rdcu_submit_tx(rmap_cmd, (uint32_t)n, data, data_len); free(rmap_cmd); @@ -574,14 +582,14 @@ int rdcu_sync_data(int (*fn)(uint16_t trans_id, uint8_t *cmd, * @returns the size of the blob or 0 on error */ -int rdcu_package(uint8_t *blob, - const uint8_t *cmd, uint32_t cmd_size, - const uint8_t non_crc_bytes, - const uint8_t *data, uint32_t data_size) +uint32_t rdcu_package(uint8_t *blob, + const uint8_t *cmd, uint32_t cmd_size, + const uint8_t non_crc_bytes, + const uint8_t *data, uint32_t data_size) { - int n; + uint32_t n; int has_data_crc = 0; - struct rmap_instruction *ri; + const struct rmap_instruction *ri; if (data_size & 0x3) /* must be multiple of 4 */ @@ -599,7 +607,7 @@ int rdcu_package(uint8_t *blob, /* allocate space for header, header crc, data, data crc */ n = cmd_size + 1; - ri = (struct rmap_instruction *) &cmd[non_crc_bytes + RMAP_INSTRUCTION]; + ri = (const struct rmap_instruction *)&cmd[non_crc_bytes + RMAP_INSTRUCTION]; /* see if the type of command needs a data crc field at the end */ switch (ri->cmd) { @@ -745,7 +753,7 @@ void rdcu_set_destination_key(uint8_t key) * @returns the mtu */ -size_t rdcu_get_data_mtu(void) +uint32_t rdcu_get_data_mtu(void) { return data_mtu; } @@ -791,7 +799,7 @@ void rdcu_rmap_reset_log(void) * @returns 0 on success, otherwise error */ -int rdcu_rmap_init(size_t mtu, +int rdcu_rmap_init(uint32_t mtu, int32_t (*tx)(const void *hdr, uint32_t hdr_size, const uint8_t non_crc_bytes, const void *data, uint32_t data_size), diff --git a/include/rdcu_rmap.h b/lib/rdcu_compress/rdcu_rmap.h similarity index 76% rename from include/rdcu_rmap.h rename to lib/rdcu_compress/rdcu_rmap.h index b0cdc84fd1692d3d179563e9ccf03095db35b4de..2f157a5ee054002be2856697950428d663d1fe20 100644 --- a/include/rdcu_rmap.h +++ b/lib/rdcu_compress/rdcu_rmap.h @@ -16,15 +16,15 @@ * @brief RMAP RDCU link interface header file */ -#ifndef _RDCU_RMAP_H_ -#define _RDCU_RMAP_H_ +#ifndef RDCU_RMAP_H +#define RDCU_RMAP_H #include <stdint.h> -int rdcu_submit_tx(const uint8_t *cmd, int cmd_size, - const uint8_t *data, int data_size); +int rdcu_submit_tx(const uint8_t *cmd, uint32_t cmd_size, + const uint8_t *data, uint32_t data_size); int rdcu_gen_cmd(uint16_t trans_id, uint8_t *cmd, @@ -32,16 +32,16 @@ int rdcu_gen_cmd(uint16_t trans_id, uint8_t *cmd, uint32_t addr, uint32_t size); int rdcu_sync(int (*fn)(uint16_t trans_id, uint8_t *cmd), - void *addr, int data_len); + void *addr, uint32_t data_len); int rdcu_sync_data(int (*fn)(uint16_t trans_id, uint8_t *cmd, uint32_t addr, uint32_t data_len), uint32_t addr, void *data, uint32_t data_len, int read); -int rdcu_package(uint8_t *blob, - const uint8_t *cmd, uint32_t cmd_size, - const uint8_t non_crc_bytes, - const uint8_t *data, uint32_t data_size); +uint32_t rdcu_package(uint8_t *blob, + const uint8_t *cmd, uint32_t cmd_size, + const uint8_t non_crc_bytes, + const uint8_t *data, uint32_t data_size); void rdcu_set_destination_logical_address(uint8_t addr); @@ -49,13 +49,13 @@ int rdcu_set_destination_path(uint8_t *path, uint8_t len); int rdcu_set_return_path(uint8_t *path, uint8_t len); void rdcu_set_source_logical_address(uint8_t addr); void rdcu_set_destination_key(uint8_t key); -size_t rdcu_get_data_mtu(void); +uint32_t rdcu_get_data_mtu(void); int rdcu_rmap_sync_status(void); void rdcu_rmap_reset_log(void); -int rdcu_rmap_init(size_t mtu, +int rdcu_rmap_init(uint32_t mtu, int32_t (*tx)(const void *hdr, uint32_t hdr_size, const uint8_t non_crc_bytes, const void *data, uint32_t data_size), @@ -63,4 +63,4 @@ int rdcu_rmap_init(size_t mtu, -#endif /* _RDCU_RMAP_H_ */ +#endif /* RDCU_RMAP_H */ diff --git a/lib/rmap.c b/lib/rdcu_compress/rmap.c similarity index 78% rename from lib/rmap.c rename to lib/rdcu_compress/rmap.c index 686e3b1047cf5b3b549fd52a4accbaf8b43fef4a..2361329552aabc07674e600a554e38ba6ad8b349 100644 --- a/lib/rmap.c +++ b/lib/rdcu_compress/rmap.c @@ -22,10 +22,10 @@ #include <string.h> #include <stdlib.h> -#include <stdio.h> -#include <rmap.h> -#include <my_inttypes.h> +#include "../common/cmp_debug.h" +#include "../common/leon_inttypes.h" +#include "rmap.h" /** @@ -176,7 +176,7 @@ struct rmap_pkt *rmap_create_packet(void) struct rmap_pkt *pkt; - pkt = (struct rmap_pkt *) calloc(1, sizeof(struct rmap_pkt)); + pkt = (struct rmap_pkt *)calloc(1, sizeof(struct rmap_pkt)); if (pkt) pkt->proto_id = RMAP_PROTOCOL_ID; @@ -184,20 +184,6 @@ struct rmap_pkt *rmap_create_packet(void) } -/** - * @brief destroys an RMAP packet - * - * @param pkt a struct rmap_pkt - * - * @note this will NOT deallocate and pointer references assigned by the user - */ - -void rmap_destroy_packet(struct rmap_pkt *pkt) -{ - free(pkt); -} - - /** * @brief completely destroys an RMAP packet * @@ -287,7 +273,7 @@ int rmap_set_reply_path(struct rmap_pkt *pkt, const uint8_t *rpath, uint8_t len) pkt->rpath_len = len; if (len) { - pkt->rpath = (uint8_t *) malloc(pkt->rpath_len); + pkt->rpath = (uint8_t *)malloc(pkt->rpath_len); if (!pkt->rpath) return -1; @@ -329,7 +315,7 @@ int rmap_set_dest_path(struct rmap_pkt *pkt, const uint8_t *path, uint8_t len) if (!len) return 0; - pkt->path = (uint8_t *) malloc(pkt->path_len); + pkt->path = (uint8_t *)malloc(pkt->path_len); if (!pkt->path) return -1; @@ -461,17 +447,17 @@ int rmap_build_hdr(struct rmap_pkt *pkt, uint8_t *hdr) hdr[n++] = pkt->rpath[i]; /* return path to source */ hdr[n++] = pkt->src; /* source logical address */ - hdr[n++] = (uint8_t) (pkt->tr_id >> 8); /* MSB of transaction id */ - hdr[n++] = (uint8_t) pkt->tr_id; /* LSB of transaction id */ + hdr[n++] = (uint8_t)(pkt->tr_id >> 8); /* MSB of transaction id */ + hdr[n++] = (uint8_t)pkt->tr_id; /* LSB of transaction id */ /* commands have a data address */ if (pkt->ri.cmd_resp) { hdr[n++] = 0x0; /* extended address field (unused) */ - hdr[n++] = (uint8_t) (pkt->addr >> 24); /* data addr MSB */ - hdr[n++] = (uint8_t) (pkt->addr >> 16); - hdr[n++] = (uint8_t) (pkt->addr >> 8); - hdr[n++] = (uint8_t) pkt->addr; /* data addr LSB */ + hdr[n++] = (uint8_t)(pkt->addr >> 24); /* data addr MSB */ + hdr[n++] = (uint8_t)(pkt->addr >> 16); + hdr[n++] = (uint8_t)(pkt->addr >> 8); + hdr[n++] = (uint8_t)pkt->addr; /* data addr LSB */ } else if (!pkt->ri.cmd_resp && pkt->ri.cmd & RMAP_CMD_BIT_WRITE) { /* all headers have data length unless they are a write reply */ return n; @@ -479,9 +465,9 @@ int rmap_build_hdr(struct rmap_pkt *pkt, uint8_t *hdr) hdr[n++] = 0x0; /* on other replies, this is a reserved field */ } - hdr[n++] = (uint8_t) (pkt->data_len >> 16); /* data len MSB */ - hdr[n++] = (uint8_t) (pkt->data_len >> 8); - hdr[n++] = (uint8_t) pkt->data_len; /* data len LSB */ + hdr[n++] = (uint8_t)(pkt->data_len >> 16); /* data len MSB */ + hdr[n++] = (uint8_t)(pkt->data_len >> 8); + hdr[n++] = (uint8_t)pkt->data_len; /* data len LSB */ return n; } @@ -511,19 +497,19 @@ struct rmap_pkt *rmap_pkt_from_buffer(uint8_t *buf, uint32_t len) goto error; if (len < RMAP_HDR_MIN_SIZE_WRITE_REP) { - printf("buffer len is smaller than the smallest RMAP packet\n"); + debug_print("buffer len is smaller than the smallest RMAP packet"); goto error; } if (buf[RMAP_PROTOCOL_ID] != RMAP_PROTOCOL_ID) { - printf("Not an RMAP packet, got %x but expected %x\n", + debug_print("Not an RMAP packet, got %x but expected %x", buf[RMAP_PROTOCOL_ID], RMAP_PROTOCOL_ID); goto error; } pkt = rmap_create_packet(); if (!pkt) { - printf("Error creating packet\n"); + debug_print("Error creating packet"); goto error; } @@ -537,19 +523,19 @@ struct rmap_pkt *rmap_pkt_from_buffer(uint8_t *buf, uint32_t len) goto error; if (len < (uint32_t)min_hdr_size) { - printf("buffer len is smaller than the contained RMAP packet\n"); + debug_print("buffer len is smaller than the contained RMAP packet"); goto error; } if (pkt->ri.cmd_resp) { - pkt->rpath_len = pkt->ri.reply_addr_len << 2; + pkt->rpath_len = (pkt->ri.reply_addr_len << 2) & 0xFF; if (len < (uint32_t)min_hdr_size + pkt->rpath_len) { - printf("buffer is smaller than the contained RMAP packet\n"); + debug_print("buffer is smaller than the contained RMAP packet"); goto error; } - pkt->rpath = (uint8_t *) malloc(pkt->rpath_len); + pkt->rpath = (uint8_t *)malloc(pkt->rpath_len); if (!pkt->rpath) goto error; @@ -560,23 +546,23 @@ struct rmap_pkt *rmap_pkt_from_buffer(uint8_t *buf, uint32_t len) } pkt->src = buf[RMAP_SRC_ADDR + n]; - pkt->tr_id = ((uint16_t) buf[RMAP_TRANS_ID_BYTE0 + n] << 8) | - (uint16_t) buf[RMAP_TRANS_ID_BYTE1 + n]; + pkt->tr_id = (((uint16_t)buf[RMAP_TRANS_ID_BYTE0 + n] << 8) & 0xFF00) | + (uint16_t)buf[RMAP_TRANS_ID_BYTE1 + n]; /* commands have a data address */ if (pkt->ri.cmd_resp) { - pkt->addr = ((uint32_t) buf[RMAP_ADDR_BYTE0 + n] << 24) | - ((uint32_t) buf[RMAP_ADDR_BYTE1 + n] << 16) | - ((uint32_t) buf[RMAP_ADDR_BYTE2 + n] << 8) | - (uint32_t) buf[RMAP_ADDR_BYTE3 + n]; + pkt->addr = ((uint32_t)buf[RMAP_ADDR_BYTE0 + n] << 24) | + ((uint32_t)buf[RMAP_ADDR_BYTE1 + n] << 16) | + ((uint32_t)buf[RMAP_ADDR_BYTE2 + n] << 8) | + (uint32_t)buf[RMAP_ADDR_BYTE3 + n]; n += 4; /* addr skip, extended byte is incorporated in define */ } /* all headers have data length unless they are a write reply */ if (!(!pkt->ri.cmd_resp && (pkt->ri.cmd & (RMAP_CMD_BIT_WRITE)))) { - pkt->data_len = ((uint32_t) buf[RMAP_DATALEN_BYTE0 + n] << 16) | - ((uint32_t) buf[RMAP_DATALEN_BYTE1 + n] << 8) | - (uint32_t) buf[RMAP_DATALEN_BYTE2 + n]; + pkt->data_len = ((uint32_t)buf[RMAP_DATALEN_BYTE0 + n] << 16) | + ((uint32_t)buf[RMAP_DATALEN_BYTE1 + n] << 8) | + (uint32_t)buf[RMAP_DATALEN_BYTE2 + n]; } pkt->hdr_crc = buf[RMAP_HEADER_CRC]; @@ -585,14 +571,14 @@ struct rmap_pkt *rmap_pkt_from_buffer(uint8_t *buf, uint32_t len) size_t pkt_size = RMAP_DATA_START + n + pkt->data_len + 1; /* +1 for data CRC */ if (len < pkt_size) { - printf("buffer len is smaller than the contained RMAP packet; buf len: %" PRIu32 " bytes vs RMAP: %zu bytes needed\n", + debug_print("buffer len is smaller than the contained RMAP packet; buf len: %" PRIu32 " bytes vs RMAP: %zu bytes needed", len, pkt_size); goto error; } if (len > pkt_size) - printf("warning: the buffer is larger than the included RMAP packet\n"); + debug_print("warning: the buffer is larger than the included RMAP packet"); - pkt->data = (uint8_t *) malloc(pkt->data_len); + pkt->data = (uint8_t *)malloc(pkt->data_len); if (!pkt->data) goto error; @@ -623,58 +609,53 @@ error: __extension__ static int rmap_check_status(uint8_t status) { - - - printf("\tStatus: "); + debug_print("Status: "); switch (status) { case RMAP_STATUS_SUCCESS: - printf("Command executed successfully"); + debug_print("Command executed successfully"); break; case RMAP_STATUS_GENERAL_ERROR: - printf("General error code"); + debug_print("General error code"); break; case RMAP_STATUS_UNUSED_TYPE_OR_CODE: - printf("Unused RMAP Packet Type or Command Code"); + debug_print("Unused RMAP Packet Type or Command Code"); break; case RMAP_STATUS_INVALID_KEY: - printf("Invalid key"); + debug_print("Invalid key"); break; case RMAP_STATUS_INVALID_DATA_CRC: - printf("Invalid Data CRC"); + debug_print("Invalid Data CRC"); break; case RMAP_STATUS_EARLY_EOP: - printf("Early EOP"); + debug_print("Early EOP"); break; case RMAP_STATUS_TOO_MUCH_DATA: - printf("Too much data"); + debug_print("Too much data"); break; case RMAP_STATUS_EEP: - printf("EEP"); + debug_print("EEP"); break; case RMAP_STATUS_RESERVED: - printf("Reserved"); + debug_print("Reserved"); break; case RMAP_STATUS_VERIFY_BUFFER_OVERRRUN: - printf("Verify buffer overrun"); + debug_print("Verify buffer overrun"); break; case RMAP_STATUS_CMD_NOT_IMPL_OR_AUTH: - printf("RMAP Command not implemented or not authorised"); + debug_print("RMAP Command not implemented or not authorised"); break; case RMAP_STATUS_RMW_DATA_LEN_ERROR: - printf("RMW Data Length error"); + debug_print("RMW Data Length error"); break; case RMAP_STATUS_INVALID_TARGET_LOGICAL_ADDR: - printf("Invalid Target Logical Address"); + debug_print("Invalid Target Logical Address"); break; default: - printf("Reserved unused error code %d", status); + debug_print("Reserved unused error code %d", status); break; } - printf("\n"); - - return status; } @@ -687,21 +668,19 @@ static void rmap_process_read_reply(uint8_t *pkt) uint32_t len = 0; - len |= ((uint32_t) pkt[RMAP_DATALEN_BYTE0]) << 16; - len |= ((uint32_t) pkt[RMAP_DATALEN_BYTE1]) << 8; - len |= ((uint32_t) pkt[RMAP_DATALEN_BYTE2]) << 0; + len |= ((uint32_t)pkt[RMAP_DATALEN_BYTE0]) << 16; + len |= ((uint32_t)pkt[RMAP_DATALEN_BYTE1]) << 8; + len |= ((uint32_t)pkt[RMAP_DATALEN_BYTE2]) << 0; -#if (__sparc__) - printf("\tData length is %lu bytes:\n\t", len); +#if defined(__sparc__) + debug_print("Data length is %lu bytes:", len); #else - printf("\tData length is %u bytes:\n\t", len); + debug_print("Data length is %u bytes:", len); #endif for (i = 0; i < len; i++) - printf("%02x:", pkt[RMAP_DATA_START + i]); - - printf("\b\n"); + debug_print("%02x:", pkt[RMAP_DATA_START + i]); } @@ -709,8 +688,8 @@ static void rmap_process_read_reply(uint8_t *pkt) static void rmap_parse_cmd_pkt(uint8_t *pkt) { - (void) pkt; - printf("\trmap_parse_cmd_pkt() not implemented\n"); + (void)pkt; + debug_print("rmap_parse_cmd_pkt() not implemented"); } @@ -719,31 +698,31 @@ static void rmap_parse_reply_pkt(uint8_t *pkt) struct rmap_instruction *ri; - ri = (struct rmap_instruction *) &pkt[RMAP_INSTRUCTION]; + ri = (struct rmap_instruction *)&pkt[RMAP_INSTRUCTION]; - printf("\tInstruction: "); + debug_print("Instruction: "); switch (ri->cmd) { case RMAP_READ_ADDR_SINGLE: - printf("Read single address\n"); + debug_print("Read single address"); rmap_process_read_reply(pkt); break; case RMAP_READ_ADDR_INC: - printf("Read incrementing address\n"); + debug_print("Read incrementing address"); rmap_process_read_reply(pkt); break; case RMAP_READ_MODIFY_WRITE_ADDR_INC: - printf("RMW incrementing address verify reply\n"); + debug_print("RMW incrementing address verify reply"); break; case RMAP_WRITE_ADDR_INC_VERIFY_REPLY: - printf("Write incrementing address verify reply\n"); + debug_print("Write incrementing address verify reply"); break; case RMAP_WRITE_ADDR_INC_REPLY: - printf("Write incrementing address reply\n"); + debug_print("Write incrementing address reply"); break; default: - printf("decoding of instruction 0x%02X not implemented\n", + debug_print("decoding of instruction 0x%02X not implemented", ri->cmd); break; } @@ -761,20 +740,20 @@ void rmap_parse_pkt(uint8_t *pkt) struct rmap_instruction *ri; if (pkt[RMAP_PROTOCOL_ID] != RMAP_PROTOCOL_ID) { - printf("\nNot an RMAP packet, got %x but expected %x\n", + debug_print("Not an RMAP packet, got %x but expected %x", pkt[RMAP_PROTOCOL_ID], RMAP_PROTOCOL_ID); return; } - ri = (struct rmap_instruction *) &pkt[RMAP_INSTRUCTION]; + ri = (struct rmap_instruction *)&pkt[RMAP_INSTRUCTION]; if (ri->cmd_resp) { - printf("This is a command packet\n"); + debug_print("This is a command packet"); if (!rmap_check_status(pkt[RMAP_REPLY_STATUS])) rmap_parse_cmd_pkt(pkt); } else { - printf("This is a reply packet\n"); + debug_print("This is a reply packet"); if (!rmap_check_status(pkt[RMAP_REPLY_STATUS])) rmap_parse_reply_pkt(pkt); } diff --git a/include/rmap.h b/lib/rdcu_compress/rmap.h similarity index 99% rename from include/rmap.h rename to lib/rdcu_compress/rmap.h index 3752dbada946d70462586fa04322adce06471f07..3dde00952ef8241ea944406b67f622463d83b562 100644 --- a/include/rmap.h +++ b/lib/rdcu_compress/rmap.h @@ -20,7 +20,9 @@ #define RMAP_H #include <stdint.h> -#include <compiler.h> +#include <stddef.h> + +#include "../common/compiler.h" /** * valid RMAP command codes, see Table 5-1 of ECSS‐E‐ST‐50‐52C diff --git a/meson.build b/meson.build index e617be18e978a4d85ff8ab387c084180ee498fb9..6eadf1ab1877d5466f1ad531911878d7a842116d 100644 --- a/meson.build +++ b/meson.build @@ -1,13 +1,50 @@ project('cmp_tool', 'c', - version : '0.12-b1', + version : '0.12-b2', meson_version : '>= 0.56', license : 'GPL-2.0', - default_options : ['warning_level=3', 'c_std=gnu99'] + default_options : [ + 'warning_level=3', + 'c_std=gnu99' + ] ) -add_project_arguments('-DDEBUGLEVEL=1', language : 'c') +cc = meson.get_compiler('c') -if (host_machine.system() == 'windows' or host_machine.system() == 'cygwin') and meson.get_compiler('c').get_id() == 'gcc' +# Built-in options +use_debug = get_option('debug') + +# Custom options +debug_level = get_option('debug_level') +feature_argument_input_mode = get_option('argument_input_mode') + + +# Compiler flags +cc_flags = ['-DDEBUGLEVEL=@0@'.format(debug_level)] +if use_debug + debug_flags = [ + '-Wstrict-aliasing=1', + '-Wcast-align', + '-Wredundant-decls', + '-Wundef', + '-Wshadow', + '-Wdeclaration-after-statement', + '-Wstrict-prototypes', + '-Wpointer-arith', + '-Wvla', + '-Wformat=2', + '-Winit-self', + '-Wfloat-equal', + '-Wwrite-strings', + '-Wold-style-definition', + '-Waggregate-return', + '-Wmissing-declarations', + '-Wmissing-include-dirs' + ] + cc_flags += cc.get_supported_arguments(debug_flags) +endif +add_project_arguments(cc_flags, language : 'c') + +if ['windows', 'cygwin'].contains(host_machine.system()) and cc.get_id() == 'gcc' # by default, MinGW on win32 behaves as if it ignores __attribute__((packed)), # you need to add -mno-ms-bitfields to make it work as expected. # See: https://wintermade.it/blog/posts/__attribute__packed-on-windows-is-ignored-with-mingw.html @@ -15,17 +52,10 @@ if (host_machine.system() == 'windows' or host_machine.system() == 'cygwin') and add_global_link_arguments('-static', language: 'c') endif -subdir('include') -subdir('lib') - -main = files('cmp_tool.c') - -cmp_tool_exe = executable('cmp_tool', - sources : main, - include_directories : incdir, - link_with : cmp_lib, - install : 'true' -) +# Subdirs +subdir('lib') +subdir('programs') subdir('test') subdir('doc/doxygen') +subdir('examples') diff --git a/meson_options.txt b/meson_options.txt index fe8670ef9356c298fd3cc2fe813aeca7165d35f5..fc27689bb4a6e18bc5c1c4beb04579af179ea3d2 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,2 +1,4 @@ +option('debug_level', type: 'integer', min: 0, max: 9, value: 1, + description: 'Enable run-time debug. See lib/common/cmp_debug.h') option('argument_input_mode', type : 'boolean', value : false, description : 'If set, the data file is set with the first argument and the model file with the second one') diff --git a/lib/cmp_guess.c b/programs/cmp_guess.c similarity index 98% rename from lib/cmp_guess.c rename to programs/cmp_guess.c index 8cdf7513e2a543533f52c1c5b6c8c33a59f17962..bda3c3e9d3743a544db5303c4aa4d690ff7c6c11 100644 --- a/lib/cmp_guess.c +++ b/programs/cmp_guess.c @@ -25,7 +25,7 @@ #include <cmp_data_types.h> #include <cmp_icu.h> #include <cmp_guess.h> -#include <my_inttypes.h> +#include <leon_inttypes.h> #define CMP_GUESS_MAX_CAL_STEPS 20274 @@ -142,7 +142,7 @@ static uint32_t pre_cal_method(struct cmp_cfg *cfg) cfg->golomb_par = golomb_par_best; cfg->spill = spill_best; - return cmp_size_best; + return (uint32_t)cmp_size_best; } @@ -199,7 +199,7 @@ static uint32_t brute_force(struct cmp_cfg *cfg) cfg->golomb_par = golomb_par_best; cfg->spill = spill_best; - return cmp_size_best; + return (uint32_t)cmp_size_best; } diff --git a/include/cmp_guess.h b/programs/cmp_guess.h similarity index 100% rename from include/cmp_guess.h rename to programs/cmp_guess.h diff --git a/lib/cmp_io.c b/programs/cmp_io.c similarity index 96% rename from lib/cmp_io.c rename to programs/cmp_io.c index 8f511e614373b4fda0c8b84ebf20436f697ecddc..90a933be50484574e7272c42a1071d31ff06a3e3 100644 --- a/lib/cmp_io.c +++ b/programs/cmp_io.c @@ -25,14 +25,16 @@ #include <ctype.h> #include <sys/stat.h> + #include <cmp_tool-config.h> -#include <cmp_io.h> +#include <compiler.h> + +#include "cmp_io.h" #include <cmp_support.h> #include <rdcu_cmd.h> #include <byteorder.h> #include <cmp_data_types.h> -#include <my_inttypes.h> -#include <cmp_io.h> +#include <leon_inttypes.h> /* directory to convert from data_type to string */ @@ -163,10 +165,9 @@ static FILE *open_file(const char *dirname, const char *filename) * @returns 0 on success, error otherwise */ -int write_input_data_to_file(void *data, uint32_t data_size, enum cmp_data_type data_type, +int write_input_data_to_file(const void *data, uint32_t data_size, enum cmp_data_type data_type, const char *output_prefix, const char *name_extension, int flags) { - size_t sample_size = size_of_a_sample(data_type); uint8_t *tmp_buf; int return_value; @@ -176,17 +177,20 @@ int write_input_data_to_file(void *data, uint32_t data_size, enum cmp_data_type if (data_size == 0) return 0; - if (!sample_size) - return -1; - tmp_buf = malloc(data_size); if (!tmp_buf) return -1; + memcpy(tmp_buf, data, data_size); - cmp_input_big_to_cpu_endianness(tmp_buf, data_size, data_type); - return_value = write_data_to_file(tmp_buf, data_size, output_prefix, - name_extension, flags); + if (data_type == DATA_TYPE_CHUNK) + return_value = cpu_to_be_chunk(tmp_buf, data_size); + else + return_value = cmp_input_big_to_cpu_endianness(tmp_buf, data_size, data_type); + + if (!return_value) + return_value = write_data_to_file(tmp_buf, data_size, output_prefix, + name_extension, flags); free(tmp_buf); @@ -416,7 +420,7 @@ enum cmp_data_type string2data_type(const char *data_type_str) if (isalpha(data_type_str[0])) { /* check if mode is given as text */ size_t j; - for (j = 0; j < sizeof(data_type_string_table) / sizeof(data_type_string_table[0]); j++) { + for (j = 0; j < ARRAY_SIZE(data_type_string_table); j++) { if (!strcmp(data_type_str, data_type_string_table[j].str)) { data_type = data_type_string_table[j].data_type; break; @@ -449,7 +453,7 @@ const char *data_type2string(enum cmp_data_type data_type) size_t j; const char *string = "DATA_TYPE_UNKNOWN"; - for (j = 0; j < sizeof(data_type_string_table) / sizeof(data_type_string_table[0]); j++) { + for (j = 0; j < ARRAY_SIZE(data_type_string_table); j++) { if (data_type == data_type_string_table[j].data_type) { string = data_type_string_table[j].str; break; @@ -472,7 +476,6 @@ const char *data_type2string(enum cmp_data_type data_type) int cmp_mode_parse(const char *cmp_mode_str, enum cmp_mode *cmp_mode) { - size_t j; static const struct { uint32_t cmp_mode; const char *str; @@ -495,7 +498,9 @@ int cmp_mode_parse(const char *cmp_mode_str, enum cmp_mode *cmp_mode) return -1; if (isalpha(cmp_mode_str[0])) { /* check if mode is given as text */ - for (j = 0; j < sizeof(conversion) / sizeof(conversion[0]); ++j) { + size_t j; + + for (j = 0; j < ARRAY_SIZE(conversion); j++) { if (!strcmp(cmp_mode_str, conversion[j].str)) { *cmp_mode = conversion[j].cmp_mode; return 0; @@ -673,6 +678,7 @@ static int parse_cfg(FILE *fp, struct cmp_cfg *cfg) return -1; continue; } +#if 0 if (!strcmp(token1, "cmp_par_mean")) { if (atoui32(token1, token2, &cfg->cmp_par_mean)) return -1; @@ -703,6 +709,7 @@ static int parse_cfg(FILE *fp, struct cmp_cfg *cfg) return -1; continue; } +#endif if (!strcmp(token1, "rdcu_data_adr")) { int i = sram_addr_to_int(token2); @@ -1427,17 +1434,22 @@ ssize_t read_file_data(const char *file_name, enum cmp_data_type data_type, if (size < 0) return size; - samples = cmp_input_size_to_samples((uint32_t)size, data_type); - if (samples < 0) { - fprintf(stderr, "%s: %s: Error: The data are not correct formatted for the used compression data type.\n", - PROGRAM_NAME, file_name); - return -1; - } - - err = cmp_input_big_to_cpu_endianness(buf, (uint32_t)size, data_type); - if (err) - return -1; + if (data_type != DATA_TYPE_CHUNK) { + samples = cmp_input_size_to_samples((uint32_t)size, data_type); + if (samples < 0) { + fprintf(stderr, "%s: %s: Error: The data are not correct formatted for the used compression data type.\n", + PROGRAM_NAME, file_name); + return -1; + } + err = cmp_input_big_to_cpu_endianness(buf, (uint32_t)size, data_type); + if (err) + return -1; + } else { + err = be_to_cpu_chunk(buf, (uint32_t)size); + if (err) + return -1; + } return size; } @@ -1493,41 +1505,6 @@ ssize_t read_file_cmp_entity(const char *file_name, struct cmp_entity *ent, } -/** - * @brief reads hex-encoded uint32_t samples from a file into a buffer - * - * @param file_name data/model file name - * @param buf buffer to write the file content (can be NULL) - * @param buf_size size of the buf buffer in bytes - * @param verbose_en print verbose output if not zero - * - * @returns the size in bytes to store the file content; negative on error - */ - -ssize_t read_file32(const char *file_name, uint32_t *buf, uint32_t buf_size, - int verbose_en) -{ - ssize_t size = read_file8(file_name, (uint8_t *)buf, buf_size, verbose_en); - - if (size < 0) - return -1; - - if (size & 0x3) { - fprintf(stderr, "%s: %s: Error: The data are not correct formatted. Expected multiple of 4 hex words.\n", - PROGRAM_NAME, file_name); - return -1; - } - - if (buf) { - size_t i; - for (i = 0; i < buf_size/sizeof(uint32_t); i++) - be32_to_cpus(&buf[i]); - } - - return size; -} - - /* * @brief generate from the cmp_tool version string a version_id for the * compression entity header @@ -1610,7 +1587,7 @@ static void write_cfg_internal(FILE *fp, const struct cmp_cfg *cfg) fprintf(fp, "# 3: model mode with multi escape symbol mechanism\n"); fprintf(fp, "# 4: 1d differencing mode without input model multi escape symbol mechanism\n"); fprintf(fp, "\n"); - fprintf(fp, "cmp_mode = %u\n", cfg->cmp_mode); + fprintf(fp, "cmp_mode = %d\n", cfg->cmp_mode); fprintf(fp, "\n"); fprintf(fp, "#-------------------------------------------------------------------------------\n"); fprintf(fp, "# Number of samples to compress, length of the data and model buffer\n"); @@ -1694,7 +1671,7 @@ static void write_cfg_internal(FILE *fp, const struct cmp_cfg *cfg) fprintf(fp, "\n"); fprintf(fp, "#-------------------------------------------------------------------------------\n"); } - +#if 0 if (cmp_aux_data_type_is_used(cfg->data_type)) { fprintf(fp, "# mean compression parameter\n"); fprintf(fp, "\n"); @@ -1716,7 +1693,8 @@ static void write_cfg_internal(FILE *fp, const struct cmp_cfg *cfg) fprintf(fp, "spill_variance = %" PRIu32 "\n", cfg->spill_variance); fprintf(fp, "\n"); fprintf(fp, "#-------------------------------------------------------------------------------\n"); - if (cfg->data_type != DATA_TYPE_OFFSET) { + if (cfg->data_type != DATA_TYPE_OFFSET && + cfg->data_type != DATA_TYPE_F_CAM_OFFSET) { fprintf(fp, "# outlier pixels number compression parameter\n"); fprintf(fp, "\n"); fprintf(fp, "cmp_par_pixels_error = %" PRIu32 "\n", cfg->cmp_par_pixels_error); @@ -1728,8 +1706,8 @@ static void write_cfg_internal(FILE *fp, const struct cmp_cfg *cfg) fprintf(fp, "\n"); fprintf(fp, "#-------------------------------------------------------------------------------\n"); } - /* TODO: implemented DATA_TYPE_F_CAM_OFFSET, DATA_TYPE_F_CAM_BACKGROUND */ } +#endif if (cmp_fx_cob_data_type_is_used(cfg->data_type)) { struct fx_cob_par needed_pars; diff --git a/include/cmp_io.h b/programs/cmp_io.h similarity index 93% rename from include/cmp_io.h rename to programs/cmp_io.h index bb30f04e8c223c58942cfd5ad6f93690e747b3dd..60c3910a4eba1526bf1619a99d4caf1d7b8481ef 100644 --- a/include/cmp_io.h +++ b/programs/cmp_io.h @@ -17,6 +17,10 @@ * @brief compression tool input/output library header file */ + +#ifndef CMP_IO_H +#define CMP_IO_H + #include <string.h> #include <cmp_support.h> @@ -48,7 +52,7 @@ uint32_t cmp_tool_gen_version_id(const char *version); int write_data_to_file(const void *buf, uint32_t buf_size, const char *output_prefix, const char *name_extension, int flags); -int write_input_data_to_file(void *data, uint32_t data_size, enum cmp_data_type data_type, +int write_input_data_to_file(const void *data, uint32_t data_size, enum cmp_data_type data_type, const char *output_prefix, const char *name_extension, int flags); int cmp_info_to_file(const struct cmp_info *info, const char *output_prefix, int rdcu_cfg); int cmp_cfg_fo_file(const struct cmp_cfg *cfg, const char *output_prefix, int verbose); @@ -59,3 +63,5 @@ int cmp_mode_parse(const char *cmp_mode_str, enum cmp_mode *cmp_mode); enum cmp_data_type string2data_type(const char *data_type_str); const char *data_type2string(enum cmp_data_type data_type); + +#endif /* CMP_IO_H */ diff --git a/cmp_tool.c b/programs/cmp_tool.c similarity index 95% rename from cmp_tool.c rename to programs/cmp_tool.c index 9d26d09d129cb072afe7d0f882100dd9a1465415..9560c9da244d92f316c64ded1c540de162b5048c 100644 --- a/cmp_tool.c +++ b/programs/cmp_tool.c @@ -299,14 +299,15 @@ int main(int argc, char **argv) } { - char str[] = "### PLATO Compression/Decompression Tool Version " CMP_TOOL_VERSION " ###\n"; + static const char str[] = "### PLATO Compression/Decompression Tool Version " CMP_TOOL_VERSION " ###\n"; size_t str_len = strlen(str) - 1; /* -1 for \n */ size_t i; - for (i = 0; i < str_len; ++i) + + for (i = 0; i < str_len; i++) printf("#"); printf("\n"); printf("%s", str); - for (i = 0; i < str_len; ++i) + for (i = 0; i < str_len; i++) printf("#"); printf("\n"); } @@ -372,7 +373,6 @@ int main(int argc, char **argv) if (info_file_name) { ssize_t f_size; size_t ent_size; - uint32_t cmp_size_byte; printf("Importing decompression information file %s ... ", info_file_name); error = cmp_info_read(info_file_name, &info, io_flags & CMP_IO_VERBOSE); @@ -383,7 +383,7 @@ int main(int argc, char **argv) printf("Importing compressed data file %s ... ", data_file_name); ent_size = cmp_ent_create(NULL, DATA_TYPE_IMAGETTE, info.cmp_mode_used == CMP_MODE_RAW, - cmp_bit_to_4byte(info.cmp_size)); + cmp_bit_to_byte(info.cmp_size)); if (!ent_size) goto fail; decomp_entity = calloc(1, ent_size); @@ -392,13 +392,12 @@ int main(int argc, char **argv) goto fail; } ent_size = cmp_ent_create(decomp_entity, DATA_TYPE_IMAGETTE, info.cmp_mode_used == CMP_MODE_RAW, - cmp_bit_to_4byte(info.cmp_size)); + cmp_bit_to_byte(info.cmp_size)); if (!ent_size) goto fail; - cmp_size_byte = (info.cmp_size+7)/CHAR_BIT; f_size = read_file8(data_file_name, cmp_ent_get_data_buf(decomp_entity), - cmp_size_byte, io_flags); + cmp_bit_to_byte(info.cmp_size), io_flags); if (f_size < 0) goto fail; @@ -417,10 +416,6 @@ int main(int argc, char **argv) buf_size = (size_t)size; if (buf_size < sizeof(struct cmp_entity)) buf_size = sizeof(struct cmp_entity); - /* The compressed data is read in 4-byte words, so our - * data buffer must be a multiple of 4 bytes. - */ - buf_size = (buf_size + 3) & ~((size_t)0x3); decomp_entity = calloc(1, buf_size); if (!decomp_entity) { @@ -432,11 +427,6 @@ int main(int argc, char **argv) if (size < 0) goto fail; - if (cmp_ent_get_size(decomp_entity) & 0x3) { - printf("\nThe size of the compression entity is not a multiple of 4 bytes. Padding the compression entity to a multiple of 4 bytes.\n"); - cmp_ent_set_size(decomp_entity, (uint32_t)buf_size); - } - if (io_flags & CMP_IO_VERBOSE_EXTRA) { cmp_ent_print(decomp_entity); printf("\n"); @@ -600,7 +590,7 @@ static int guess_cmp_pars(struct cmp_cfg *cfg, const char *guess_cmp_mode, return -1; if (include_cmp_header) - cmp_size_bit = CHAR_BIT * (cmp_bit_to_4byte(cmp_size_bit) + + cmp_size_bit = CHAR_BIT * (cmp_bit_to_byte(cmp_size_bit) + cmp_ent_cal_hdr_size(cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW)); printf("DONE\n"); @@ -622,7 +612,7 @@ static int guess_cmp_pars(struct cmp_cfg *cfg, const char *guess_cmp_mode, * @brief generate packets to setup an RDCU compression */ -static int gen_rdcu_write_pkts(struct cmp_cfg *cfg) +static int gen_rdcu_write_pkts(const struct cmp_cfg *cfg) { int error; @@ -768,9 +758,8 @@ static int compression(struct cmp_cfg *cfg, struct cmp_info *info) } printf("Compress data ... "); - /* round up to a multiple of 4 */ - out_buf_size = (cmp_cal_size_of_data(cfg->buffer_length, cfg->data_type) + 3) & ~0x3U; + out_buf_size = cmp_cal_size_of_data(cfg->buffer_length, cfg->data_type); cmp_entity = calloc(1, out_buf_size + sizeof(struct cmp_entity)); if (cmp_entity == NULL) { fprintf(stderr, "%s: Error allocating memory for output buffer.\n", PROGRAM_NAME); @@ -784,8 +773,11 @@ static int compression(struct cmp_cfg *cfg, struct cmp_info *info) cfg->icu_output_buf = cmp_ent_get_data_buf(cmp_entity); cmp_size = icu_compress_data(cfg); - if (cmp_size < 0) + if (cmp_size < 0) { + if (cmp_size == CMP_ERROR_SMALL_BUF) + fprintf(stderr, "Error: The buffer for the compressed data is too small to hold the compressed data. Try a larger buffer_length parameter.\n"); goto error_cleanup; + } if (model_id_str) { uint32_t red_val; @@ -821,10 +813,7 @@ static int compression(struct cmp_cfg *cfg, struct cmp_info *info) if (cmp_gernate_rdcu_info(cfg, cmp_size, ap1_cmp_size, ap2_cmp_size, info)) goto error_cleanup; data_to_write_to_file = cmp_ent_get_data_buf(cmp_entity); - if (cfg->cmp_mode == CMP_MODE_RAW) - cmp_size_byte = info->cmp_size/CHAR_BIT; - else - cmp_size_byte = cmp_bit_to_4byte(info->cmp_size); + cmp_size_byte = cmp_ent_get_cmp_data_size(cmp_entity); } printf("DONE\n"); diff --git a/programs/meson.build b/programs/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..ad9de48a3134ba7fb5b529796e34b9a835d49500 --- /dev/null +++ b/programs/meson.build @@ -0,0 +1,28 @@ +cmp_tool_src = files([ + 'cmp_guess.c', + 'cmp_io.c', + 'cmp_tool.c', + 'rdcu_pkt_to_file.c' +]) + + +# generate the cmp_tool-config.h configuration file +cdata = configuration_data() +cdata.set_quoted('PROGRAM_NAME', 'cmp_tool') +cdata.set_quoted('CMP_TOOL_VERSION', meson.project_version()) +if feature_argument_input_mode + cdata.set('ARGUMENT_INPUT_MODE', 1) +endif + +configure_file( + output : 'cmp_tool-config.h', + configuration : cdata +) + + +cmp_tool_exe = executable('cmp_tool', + sources : cmp_tool_src, + include_directories : incdir, + link_with : cmp_lib, + install : 'true' +) diff --git a/lib/rdcu_pkt_to_file.c b/programs/rdcu_pkt_to_file.c similarity index 95% rename from lib/rdcu_pkt_to_file.c rename to programs/rdcu_pkt_to_file.c index 80da5b2442783ef6c4ca6011108ae42b8f7232ff..28df657cf3df16d4d7842f141b3b404838263437 100644 --- a/lib/rdcu_pkt_to_file.c +++ b/programs/rdcu_pkt_to_file.c @@ -71,7 +71,7 @@ void set_tc_folder_dir(const char *dir_name) * @see https://developers.redhat.com/blog/2018/05/24/detecting-string-truncation-with-gcc-8/ */ -static FILE *open_file(const char *dir_name, int n_tc) +static FILE *open_file_tc(const char *dir_name, int n_tc) { char *pathname; FILE *fp; @@ -116,7 +116,7 @@ static int32_t rmap_tx_to_file(const void *hdr, uint32_t hdr_size, static int n_pkt = 1; /* number of packets */ static char tc_folder_dir_old[MAX_TC_FOLDER_DIR_LEN] = {0}; uint8_t *blob = NULL; - int n, i; + uint32_t n, i; FILE *fp; if (hdr == NULL) @@ -148,21 +148,21 @@ static int32_t rmap_tx_to_file(const void *hdr, uint32_t hdr_size, } n = rdcu_package(NULL, hdr, hdr_size, non_crc_bytes, data, data_size); - if (n <= 0) + if (!n) return -1; - blob = malloc((unsigned int)n); + blob = malloc(n); if (!blob) { printf("malloc for tx_pkt failed\n"); return -1; } n = rdcu_package(blob, hdr, hdr_size, non_crc_bytes, data, data_size); - if (n <= 0) { + if (!n) { free(blob); return -1; } - fp = open_file(tc_folder_dir, n_pkt); + fp = open_file_tc(tc_folder_dir, n_pkt); if (fp == NULL) { perror("fopen()"); @@ -211,7 +211,7 @@ static uint32_t rmap_rx_dummy(uint8_t *pkt) */ static int read_rdcu_pkt_mode_cfg(uint8_t *icu_addr, uint8_t *rdcu_addr, - unsigned long *mtu) + uint32_t *mtu) { /* TODO: Build string" %s/.rdcu_pkt_mode_cfg", RDCU_PKT_MODE_DIR */ char line[256]; @@ -224,7 +224,7 @@ static int read_rdcu_pkt_mode_cfg(uint8_t *icu_addr, uint8_t *rdcu_addr, if (fp == NULL) { /* use default values */ - printf("Use ICU_ADDR = %#02X, RDCU_ADDR = %#02X and MTU = %lu for the RAMP packets.\n", *icu_addr, *rdcu_addr, *mtu); + printf("Use ICU_ADDR = %#02X, RDCU_ADDR = %#02X and MTU = %u for the RAMP packets.\n", *icu_addr, *rdcu_addr, *mtu); return 0; } @@ -274,19 +274,19 @@ static int read_rdcu_pkt_mode_cfg(uint8_t *icu_addr, uint8_t *rdcu_addr, end = NULL; errno = 0; i = strtoul(line + l, &end, 0); - if (end == line + l || errno == ERANGE || i > INT_MAX) { + if (end == line + l || errno == ERANGE || i > INT32_MAX) { fprintf(stderr, "Error reading MTU.\n"); errno = 0; fclose(fp); return -1; } - *mtu = i; + *mtu = (uint32_t)i; continue; } } fclose(fp); - printf("Use ICU_ADDR = %#02X, RDCU_ADDR = %#02X and MTU = %lu for the RAMP packets.\n", *icu_addr, *rdcu_addr, *mtu); + printf("Use ICU_ADDR = %#02X, RDCU_ADDR = %#02X and MTU = %u for the RAMP packets.\n", *icu_addr, *rdcu_addr, *mtu); return 0; } @@ -304,7 +304,7 @@ static int read_rdcu_pkt_mode_cfg(uint8_t *icu_addr, uint8_t *rdcu_addr, int init_rmap_pkt_to_file(void) { uint8_t icu_addr, rdcu_addr; - unsigned long mtu; + uint32_t mtu; if (read_rdcu_pkt_mode_cfg(&icu_addr, &rdcu_addr, &mtu)) return -1; diff --git a/include/rdcu_pkt_to_file.h b/programs/rdcu_pkt_to_file.h similarity index 93% rename from include/rdcu_pkt_to_file.h rename to programs/rdcu_pkt_to_file.h index a5364401ab73ce5b6b9d71036c580990f701ee5e..d185e59a2179e933e38dbec1d061e320b183d5ca 100644 --- a/include/rdcu_pkt_to_file.h +++ b/programs/rdcu_pkt_to_file.h @@ -16,8 +16,8 @@ * @brief RDCU packets to file library header file */ -#ifndef _RDCU_PKT_TO_FILE_H_ -#define _RDCU_PKT_TO_FILE_H_ +#ifndef RDCU_PKT_TO_FILE_H +#define RDCU_PKT_TO_FILE_H #include <cmp_support.h> @@ -42,4 +42,4 @@ int gen_read_rdcu_pkts(const struct cmp_info *info); int gen_rdcu_parallel_pkts(const struct cmp_cfg *cfg, const struct cmp_info *last_info); -#endif /* _RDCU_PKT_TO_FILE_H_ */ +#endif /* RDCU_PKT_TO_FILE_H */ diff --git a/subprojects/packagefiles/pcg-c-basic/meson.build b/subprojects/packagefiles/pcg-c-basic/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..efe83ebf8cb6f7cbc98690e22ff87b575867e78a --- /dev/null +++ b/subprojects/packagefiles/pcg-c-basic/meson.build @@ -0,0 +1,13 @@ +project('pcg-c-basic', 'c', + version: '0.9', + license: 'Apache 2.0', +) + +inc = include_directories('.') +libpcg_basic = static_library('pcg_basic', + 'pcg_basic.c', + include_directories : inc, + install : true) + +libpcg_basic_dep = declare_dependency(include_directories : inc, + link_with : libpcg_basic) diff --git a/subprojects/pcg-c-basic.wrap b/subprojects/pcg-c-basic.wrap new file mode 100644 index 0000000000000000000000000000000000000000..1b24864cc6df36a5e3e62b90f9ab21a579b516d0 --- /dev/null +++ b/subprojects/pcg-c-basic.wrap @@ -0,0 +1,6 @@ +[wrap-file] +directory = pcg-c-basic-0.9 +source_url = https://www.pcg-random.org/downloads/pcg-c-basic-0.9.zip +source_filename = pcg-c-basic-0.9.zip +source_hash = 143f9cc0edc7e81064bde5ed6c5f16cbf7ca2f373d35543286f5fe4475a2eff1 +patch_directory = pcg-c-basic diff --git a/test/cmp_data_types/test_cmp_data_types.c b/test/cmp_data_types/test_cmp_data_types.c index 2057348f3d3a0e68da6da828a00da9902fb21eb4..a09c50c568a3787ddb92a8a03f140e4bd255dcda 100644 --- a/test/cmp_data_types/test_cmp_data_types.c +++ b/test/cmp_data_types/test_cmp_data_types.c @@ -18,11 +18,137 @@ #include <stdint.h> +#include <string.h> +#include <stdlib.h> #include <unity.h> #include <cmp_data_types.h> +/** + * @test cmp_collection_get_subservie + */ + +void test_cmp_col_get_subservice(void) +{ + struct collection_hdr col; + + memset(&col, 0, sizeof(struct collection_hdr)); + memset(&col.collection_id, 0x7E, 1); /* set all bit of the subservice field */ + + TEST_ASSERT_EQUAL(0x3F, cmp_col_get_subservice(&col)); + cmp_col_set_subservice(&col, 0x35); + TEST_ASSERT_EQUAL(0x35, cmp_col_get_subservice(&col)); +} + +void test_cmp_col_get_and_set(void) +{ + int err; + size_t i; + struct collection_hdr *col = malloc(sizeof(struct collection_hdr)); + uint8_t *u8_p = (uint8_t *)col; + uint64_t timestamp; + uint16_t configuration_id, collection_id, collection_length; + uint8_t pkt_type, subservice, ccd_id, sequence_num; + + TEST_ASSERT_TRUE(col); + + memset(col, 0, sizeof(struct collection_hdr)); + + err = cmp_col_set_timestamp(col, 0x000102030405); + TEST_ASSERT_FALSE(err); + timestamp = cmp_col_get_timestamp(col); + TEST_ASSERT_EQUAL(0x000102030405, timestamp); + /* error cases */ + err = cmp_col_set_timestamp(NULL, 0x000102030405); + TEST_ASSERT_TRUE(err); + err = cmp_col_set_timestamp(col, 0x1000000000000); + TEST_ASSERT_TRUE(err); + + err = cmp_col_set_configuration_id(col, 0x0607); + TEST_ASSERT_FALSE(err); + configuration_id = cmp_col_get_configuration_id(col); + TEST_ASSERT_EQUAL_HEX16(0x0607, configuration_id); + /* error cases */ + err = cmp_col_set_configuration_id(NULL, 0x0607); + TEST_ASSERT_TRUE(err); + + + err = cmp_col_set_pkt_type(col, 1); + TEST_ASSERT_FALSE(err); + pkt_type = cmp_col_get_pkt_type(col); + TEST_ASSERT_EQUAL_HEX16(pkt_type, pkt_type); + TEST_ASSERT_EQUAL_HEX16(0x8000, cmp_col_get_col_id(col)); + /* error cases */ + err = cmp_col_set_pkt_type(col, 2); + TEST_ASSERT_TRUE(err); + err = cmp_col_set_pkt_type(NULL, 1); + TEST_ASSERT_TRUE(err); + err = cmp_col_set_pkt_type(col, 0); + TEST_ASSERT_FALSE(err); + + err = cmp_col_set_subservice(col, 0x3F); + TEST_ASSERT_FALSE(err); + subservice = cmp_col_get_subservice(col); + TEST_ASSERT_EQUAL_HEX16(subservice, subservice); + TEST_ASSERT_EQUAL_HEX16(0x7E00, cmp_col_get_col_id(col)); + /* error cases */ + err = cmp_col_set_subservice(col, 0x40); + TEST_ASSERT_TRUE(err); + err = cmp_col_set_subservice(NULL, 0x3F); + TEST_ASSERT_TRUE(err); + err = cmp_col_set_subservice(col, 0); + TEST_ASSERT_FALSE(err); + + err = cmp_col_set_ccd_id(col, 0x3); + TEST_ASSERT_FALSE(err); + ccd_id = cmp_col_get_ccd_id(col); + TEST_ASSERT_EQUAL_HEX16(ccd_id, ccd_id); + TEST_ASSERT_EQUAL_HEX16(0x0180, cmp_col_get_col_id(col)); + /* error cases */ + err = cmp_col_set_ccd_id(col, 0x4); + TEST_ASSERT_TRUE(err); + err = cmp_col_set_ccd_id(NULL, 0x3); + TEST_ASSERT_TRUE(err); + err = cmp_col_set_ccd_id(col, 0); + TEST_ASSERT_FALSE(err); + + err = cmp_col_set_sequence_num(col, 0x7F); + TEST_ASSERT_FALSE(err); + sequence_num = cmp_col_get_sequence_num(col); + TEST_ASSERT_EQUAL_HEX16(0x7F, sequence_num); + TEST_ASSERT_EQUAL_HEX16(0x007F, cmp_col_get_col_id(col)); + /* error cases */ + err = cmp_col_set_sequence_num(col, 0x80); + TEST_ASSERT_TRUE(err); + err = cmp_col_set_sequence_num(NULL, 0x7F); + TEST_ASSERT_TRUE(err); + + + err = cmp_col_set_col_id(col, 0x0809); + TEST_ASSERT_FALSE(err); + collection_id = cmp_col_get_col_id(col); + TEST_ASSERT_EQUAL_HEX16(0x0809, collection_id); + /* error cases */ + err = cmp_col_set_col_id(NULL, 0x0809); + TEST_ASSERT_TRUE(err); + + err = cmp_col_set_data_length(col, 0x0A0B); + TEST_ASSERT_FALSE(err); + collection_length = cmp_col_get_data_length(col); + TEST_ASSERT_EQUAL_HEX16(0x0A0B, collection_length); + /* error cases */ + err = cmp_col_set_data_length(NULL, 0x0A0B); + TEST_ASSERT_TRUE(err); + + for (i = 0; i < sizeof(struct collection_hdr); i++) { + TEST_ASSERT_EQUAL_HEX8(i, u8_p[i]); + } + free(col); + +} + + /** * @test size_of_a_sample */ @@ -30,17 +156,36 @@ void test_size_of_a_sample(void) { size_t size; - /* TODO: implied DATA_TYPE_F_CAM_OFFSET and DATA_TYPE_F_CAM_BACKGROUND DATA_TYPE_F_CAM_BACKGROUND*/ - size = size_of_a_sample(DATA_TYPE_F_CAM_OFFSET); - TEST_ASSERT_EQUAL(0, size); - size = size_of_a_sample(DATA_TYPE_F_CAM_BACKGROUND); - TEST_ASSERT_EQUAL(0, size); /* test error cases */ size = size_of_a_sample(DATA_TYPE_UNKNOWN); TEST_ASSERT_EQUAL(0, size); size = size_of_a_sample(DATA_TYPE_F_CAM_BACKGROUND+1); TEST_ASSERT_EQUAL(0, size); + + TEST_ASSERT_EQUAL(sizeof(uint16_t), size_of_a_sample(DATA_TYPE_IMAGETTE)); + TEST_ASSERT_EQUAL(sizeof(uint16_t), size_of_a_sample(DATA_TYPE_IMAGETTE_ADAPTIVE)); + TEST_ASSERT_EQUAL(sizeof(uint16_t), size_of_a_sample(DATA_TYPE_SAT_IMAGETTE)); + TEST_ASSERT_EQUAL(sizeof(uint16_t), size_of_a_sample(DATA_TYPE_SAT_IMAGETTE_ADAPTIVE)); + TEST_ASSERT_EQUAL(sizeof(struct offset), size_of_a_sample(DATA_TYPE_OFFSET)); + TEST_ASSERT_EQUAL(sizeof(struct background), size_of_a_sample(DATA_TYPE_BACKGROUND)); + TEST_ASSERT_EQUAL(sizeof(struct smearing), size_of_a_sample(DATA_TYPE_SMEARING)); + TEST_ASSERT_EQUAL(sizeof(struct s_fx), size_of_a_sample(DATA_TYPE_S_FX)); + TEST_ASSERT_EQUAL(sizeof(struct s_fx_efx), size_of_a_sample(DATA_TYPE_S_FX_EFX)); + TEST_ASSERT_EQUAL(sizeof(struct s_fx_ncob), size_of_a_sample(DATA_TYPE_S_FX_NCOB)); + TEST_ASSERT_EQUAL(sizeof(struct s_fx_efx_ncob_ecob), size_of_a_sample(DATA_TYPE_S_FX_EFX_NCOB_ECOB)); + TEST_ASSERT_EQUAL(sizeof(struct l_fx), size_of_a_sample(DATA_TYPE_L_FX)); + TEST_ASSERT_EQUAL(sizeof(struct l_fx_efx), size_of_a_sample(DATA_TYPE_L_FX_EFX)); + TEST_ASSERT_EQUAL(sizeof(struct l_fx_ncob), size_of_a_sample(DATA_TYPE_L_FX_NCOB)); + TEST_ASSERT_EQUAL(sizeof(struct l_fx_efx_ncob_ecob), size_of_a_sample(DATA_TYPE_L_FX_EFX_NCOB_ECOB)); + TEST_ASSERT_EQUAL(sizeof(struct f_fx), size_of_a_sample(DATA_TYPE_F_FX)); + TEST_ASSERT_EQUAL(sizeof(struct f_fx_efx), size_of_a_sample(DATA_TYPE_F_FX_EFX)); + TEST_ASSERT_EQUAL(sizeof(struct f_fx_ncob), size_of_a_sample(DATA_TYPE_F_FX_NCOB)); + TEST_ASSERT_EQUAL(sizeof(struct f_fx_efx_ncob_ecob), size_of_a_sample(DATA_TYPE_F_FX_EFX_NCOB_ECOB)); + TEST_ASSERT_EQUAL(sizeof(uint16_t), size_of_a_sample(DATA_TYPE_F_CAM_IMAGETTE)); + TEST_ASSERT_EQUAL(sizeof(uint16_t), size_of_a_sample(DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE)); + TEST_ASSERT_EQUAL(sizeof(struct offset), size_of_a_sample(DATA_TYPE_F_CAM_OFFSET)); + TEST_ASSERT_EQUAL(sizeof(struct background), size_of_a_sample(DATA_TYPE_F_CAM_BACKGROUND)); } @@ -59,10 +204,14 @@ void test_cmp_cal_size_of_data(void) TEST_ASSERT_EQUAL_UINT(32 * sizeof(uint16_t), s); s = cmp_cal_size_of_data(1, DATA_TYPE_F_FX); - TEST_ASSERT_EQUAL_UINT(sizeof(struct f_fx)+MULTI_ENTRY_HDR_SIZE, s); + TEST_ASSERT_EQUAL_UINT(sizeof(struct f_fx)+COLLECTION_HDR_SIZE, s); s = cmp_cal_size_of_data(4, DATA_TYPE_F_FX); - TEST_ASSERT_EQUAL_UINT(4*sizeof(struct f_fx)+MULTI_ENTRY_HDR_SIZE, s); + TEST_ASSERT_EQUAL_UINT(4*sizeof(struct f_fx)+COLLECTION_HDR_SIZE, s); + + /* error cases */ + s = cmp_cal_size_of_data(33, DATA_TYPE_UNKNOWN); + TEST_ASSERT_EQUAL_UINT(0, s); /* overflow tests */ s = cmp_cal_size_of_data(0x1999999A, DATA_TYPE_BACKGROUND); @@ -110,22 +259,368 @@ void test_cmp_input_size_to_samples(void) /* error cases */ data_type = DATA_TYPE_S_FX_NCOB; - size = MULTI_ENTRY_HDR_SIZE - 1; + size = COLLECTION_HDR_SIZE - 1; samples_get = cmp_input_size_to_samples(size, data_type); TEST_ASSERT_EQUAL(-1, samples_get); data_type = DATA_TYPE_S_FX_NCOB; - size = MULTI_ENTRY_HDR_SIZE + 4*sizeof(struct s_fx_ncob) - 1; + size = COLLECTION_HDR_SIZE + 4*sizeof(struct s_fx_ncob) - 1; samples_get = cmp_input_size_to_samples(size, data_type); TEST_ASSERT_EQUAL(-1, samples_get); } +static void check_endianness(void* data, size_t size, enum cmp_data_type data_type) +{ + int error; + uint8_t *p_8 = data; + size_t i; + + TEST_ASSERT_TRUE(size > COLLECTION_HDR_SIZE); + + error = cmp_input_big_to_cpu_endianness(data, (uint32_t)size, data_type); + TEST_ASSERT_FALSE(error); + + for (i = 0; i < COLLECTION_HDR_SIZE; i++) + TEST_ASSERT_EQUAL(0, p_8[i]); + + for (i = 0; i < size-COLLECTION_HDR_SIZE; i++) + TEST_ASSERT_EQUAL((uint8_t)i, p_8[COLLECTION_HDR_SIZE+i]); +} + + /** * @test cmp_input_big_to_cpu_endianness */ void test_cmp_input_big_to_cpu_endianness(void) +{ + enum cmp_data_type data_type; + + { + int error; + uint16_t data[2] = {0x0001, 0x0203}; + uint8_t data_cmp[4] = {0x00, 0x01, 0x02, 0x03}; + + data_type = DATA_TYPE_SAT_IMAGETTE; + + error = cmp_input_big_to_cpu_endianness(data, sizeof(data), data_type); + TEST_ASSERT_FALSE(error); + TEST_ASSERT_EQUAL_MEMORY(data, data_cmp, sizeof(data_cmp)); + } + { + struct { + uint8_t hdr[COLLECTION_HDR_SIZE]; + struct offset entry[2]; + } __attribute__((packed)) data = {0}; + + data_type = DATA_TYPE_OFFSET; + + data.entry[0].mean = 0x00010203; + data.entry[0].variance = 0x04050607; + data.entry[1].mean = 0x08090A0B; + data.entry[1].variance = 0x0C0D0E0F; + + check_endianness(&data, sizeof(data), data_type); + + data_type = DATA_TYPE_F_CAM_OFFSET; + + data.entry[0].mean = 0x00010203; + data.entry[0].variance = 0x04050607; + data.entry[1].mean = 0x08090A0B; + data.entry[1].variance = 0x0C0D0E0F; + + check_endianness(&data, sizeof(data), data_type); + } + { + struct { + uint8_t hdr[COLLECTION_HDR_SIZE]; + struct background entry[2]; + } __attribute__((packed)) data = {0}; + + data_type = DATA_TYPE_BACKGROUND; + + data.entry[0].mean = 0x00010203; + data.entry[0].variance = 0x04050607; + data.entry[0].outlier_pixels = 0x0809; + data.entry[1].mean = 0x0A0B0C0D; + data.entry[1].variance = 0x0E0F1011; + data.entry[1].outlier_pixels = 0x1213; + + check_endianness(&data, sizeof(data), data_type); + + data_type = DATA_TYPE_F_CAM_BACKGROUND; + + data.entry[0].mean = 0x00010203; + data.entry[0].variance = 0x04050607; + data.entry[0].outlier_pixels = 0x0809; + data.entry[1].mean = 0x0A0B0C0D; + data.entry[1].variance = 0x0E0F1011; + data.entry[1].outlier_pixels = 0x1213; + + check_endianness(&data, sizeof(data), data_type); + } + { + struct { + uint8_t hdr[COLLECTION_HDR_SIZE]; + struct smearing entry[2]; + } __attribute__((packed)) data = {0}; + + data_type = DATA_TYPE_SMEARING; + + data.entry[0].mean = 0x00010203; + data.entry[0].variance_mean = 0x0405; + data.entry[0].outlier_pixels = 0x0607; + data.entry[1].mean = 0x08090A0B; + data.entry[1].variance_mean = 0x0C0D; + data.entry[1].outlier_pixels = 0x0E0F; + + check_endianness(&data, sizeof(data), data_type); + } + { + struct { + uint8_t hdr[COLLECTION_HDR_SIZE]; + struct s_fx entry[2]; + } __attribute__((packed)) data = {0}; + + data_type = DATA_TYPE_S_FX; + + data.entry[0].exp_flags = 0x00; + data.entry[0].fx = 0x01020304; + data.entry[1].exp_flags = 0x05; + data.entry[1].fx = 0x06070809; + + check_endianness(&data, sizeof(data), data_type); + } + { + struct { + uint8_t hdr[COLLECTION_HDR_SIZE]; + struct s_fx_efx entry[2]; + } __attribute__((packed)) data = {0}; + + data_type = DATA_TYPE_S_FX_EFX; + + data.entry[0].exp_flags = 0x00; + data.entry[0].fx = 0x01020304; + data.entry[0].efx = 0x05060708; + data.entry[1].exp_flags = 0x09; + data.entry[1].fx = 0x0A0B0C0D; + data.entry[1].efx = 0x0E0F1011; + + check_endianness(&data, sizeof(data), data_type); + } + { + struct { + uint8_t hdr[COLLECTION_HDR_SIZE]; + struct s_fx_ncob entry[2]; + } __attribute__((packed)) data = {0}; + + data_type = DATA_TYPE_S_FX_NCOB; + + data.entry[0].exp_flags = 0x00; + data.entry[0].fx = 0x01020304; + data.entry[0].ncob_x = 0x05060708; + data.entry[0].ncob_y = 0x090A0B0C; + data.entry[1].exp_flags = 0x0D; + data.entry[1].fx = 0x0E0F1011; + data.entry[1].ncob_x = 0x12131415; + data.entry[1].ncob_y = 0x16171819; + + check_endianness(&data, sizeof(data), data_type); + } + { + struct { + uint8_t hdr[COLLECTION_HDR_SIZE]; + struct s_fx_efx_ncob_ecob entry[2]; + } __attribute__((packed)) data = {0}; + + data_type = DATA_TYPE_S_FX_EFX_NCOB_ECOB; + + data.entry[0].exp_flags = 0x00; + data.entry[0].fx = 0x01020304; + data.entry[0].ncob_x = 0x05060708; + data.entry[0].ncob_y = 0x090A0B0C; + data.entry[0].efx = 0x0D0E0F10; + data.entry[0].ecob_x = 0x11121314; + data.entry[0].ecob_y = 0x15161718; + data.entry[1].exp_flags = 0x19; + data.entry[1].fx = 0x1A1B1C1D; + data.entry[1].ncob_x = 0x1E1F2021; + data.entry[1].ncob_y = 0x22232425; + data.entry[1].efx = 0x26272829; + data.entry[1].ecob_x = 0x2A2B2C2D; + data.entry[1].ecob_y = 0x2E2F3031; + + check_endianness(&data, sizeof(data), data_type); + } + { + struct { + uint8_t hdr[COLLECTION_HDR_SIZE]; + struct f_fx entry[2]; + } __attribute__((packed)) data = {0}; + + data_type = DATA_TYPE_F_FX; + + data.entry[0].fx = 0x00010203; + data.entry[1].fx = 0x04050607; + + check_endianness(&data, sizeof(data), data_type); + } + { + struct { + uint8_t hdr[COLLECTION_HDR_SIZE]; + struct f_fx_efx entry[2]; + } __attribute__((packed)) data = {0}; + + data_type = DATA_TYPE_F_FX_EFX; + + data.entry[0].fx = 0x00010203; + data.entry[0].efx = 0x04050607; + data.entry[1].fx = 0x08090A0B; + data.entry[1].efx = 0x0C0D0E0F; + + check_endianness(&data, sizeof(data), data_type); + } + { + struct { + uint8_t hdr[COLLECTION_HDR_SIZE]; + struct f_fx_ncob entry[2]; + } __attribute__((packed)) data = {0}; + + data_type = DATA_TYPE_F_FX_NCOB; + + data.entry[0].fx = 0x00010203; + data.entry[0].ncob_x = 0x04050607; + data.entry[0].ncob_y = 0x08090A0B; + data.entry[1].fx = 0x0C0D0E0F; + data.entry[1].ncob_x = 0x10111213; + data.entry[1].ncob_y = 0x14151617; + + check_endianness(&data, sizeof(data), data_type); + } + { + struct { + uint8_t hdr[COLLECTION_HDR_SIZE]; + struct f_fx_efx_ncob_ecob entry[2]; + } __attribute__((packed)) data = {0}; + + data_type = DATA_TYPE_F_FX_EFX_NCOB_ECOB; + + data.entry[0].fx = 0x00010203; + data.entry[0].ncob_x = 0x04050607; + data.entry[0].ncob_y = 0x08090A0B; + data.entry[0].efx = 0x0C0D0E0F; + data.entry[0].ecob_x = 0x10111213; + data.entry[0].ecob_y = 0x14151617; + data.entry[1].fx = 0x18191A1B; + data.entry[1].ncob_x = 0x1C1D1E1F; + data.entry[1].ncob_y = 0x20212223; + data.entry[1].efx = 0x24252627; + data.entry[1].ecob_x = 0x28292A2B; + data.entry[1].ecob_y = 0x2C2D2E2F; + + check_endianness(&data, sizeof(data), data_type); + } + { + struct { + uint8_t hdr[COLLECTION_HDR_SIZE]; + struct l_fx entry[2]; + } __attribute__((packed)) data = {0}; + + data_type = DATA_TYPE_L_FX; + + data.entry[0].exp_flags = 0x000102; + data.entry[0].fx = 0x03040506; + data.entry[0].fx_variance = 0x0708090A; + data.entry[1].exp_flags = 0x0B0C0D; + data.entry[1].fx = 0x0E0F1011; + data.entry[1].fx_variance = 0x12131415; + + check_endianness(&data, sizeof(data), data_type); + } + { + struct { + uint8_t hdr[COLLECTION_HDR_SIZE]; + struct l_fx_efx entry[2]; + } __attribute__((packed)) data = {0}; + + data_type = DATA_TYPE_L_FX_EFX; + + data.entry[0].exp_flags = 0x000102; + data.entry[0].fx = 0x03040506; + data.entry[0].efx = 0x0708090A; + data.entry[0].fx_variance = 0x0B0C0D0E; + data.entry[1].exp_flags = 0x0F1011; + data.entry[1].fx = 0x12131415; + data.entry[1].efx = 0x16171819; + data.entry[1].fx_variance = 0x1A1B1C1D; + + check_endianness(&data, sizeof(data), data_type); + } + { + struct { + uint8_t hdr[COLLECTION_HDR_SIZE]; + struct l_fx_ncob entry[2]; + } __attribute__((packed)) data = {0}; + + data_type = DATA_TYPE_L_FX_NCOB; + + data.entry[0].exp_flags = 0x000102; + data.entry[0].fx = 0x03040506; + data.entry[0].ncob_x = 0x0708090A; + data.entry[0].ncob_y = 0x0B0C0D0E; + data.entry[0].fx_variance = 0x0F101112; + data.entry[0].cob_x_variance = 0x13141516; + data.entry[0].cob_y_variance = 0x1718191A; + data.entry[1].exp_flags = 0x1B1C1D; + data.entry[1].fx = 0x1E1F2021; + data.entry[1].ncob_x = 0x22232425; + data.entry[1].ncob_y = 0x26272829; + data.entry[1].fx_variance = 0x2A2B2C2D; + data.entry[1].cob_x_variance = 0x2E2F3031; + data.entry[1].cob_y_variance = 0x32333435; + + check_endianness(&data, sizeof(data), data_type); + } + { + struct { + uint8_t hdr[COLLECTION_HDR_SIZE]; + struct l_fx_efx_ncob_ecob entry[2]; + } __attribute__((packed)) data = {0}; + + data_type = DATA_TYPE_L_FX_EFX_NCOB_ECOB; + + data.entry[0].exp_flags = 0x000102; + data.entry[0].fx = 0x03040506; + data.entry[0].ncob_x = 0x0708090A; + data.entry[0].ncob_y = 0x0B0C0D0E; + data.entry[0].efx = 0x0F101112; + data.entry[0].ecob_x = 0x13141516; + data.entry[0].ecob_y = 0x1718191A; + data.entry[0].fx_variance = 0x1B1C1D1E; + data.entry[0].cob_x_variance = 0x1F202122; + data.entry[0].cob_y_variance = 0x23242526; + data.entry[1].exp_flags = 0x272829; + data.entry[1].fx = 0x2A2B2C2D; + data.entry[1].ncob_x = 0x2E2F3031; + data.entry[1].ncob_y = 0x32333435; + data.entry[1].efx = 0x36373839; + data.entry[1].ecob_x = 0x3A3B3C3D; + data.entry[1].ecob_y = 0x3E3F4041; + data.entry[1].fx_variance = 0x42434445; + data.entry[1].cob_x_variance = 0x46474849; + data.entry[1].cob_y_variance = 0x4A4B4C4D; + + check_endianness(&data, sizeof(data), data_type); + } +} + + +/** + * @test cmp_input_big_to_cpu_endianness + */ + +void test_cmp_input_big_to_cpu_endianness_error_cases(void) { int error; void *data; diff --git a/test/cmp_decmp/meson.build b/test/cmp_decmp/meson.build index 9c72c6b3a1e093d7041f8088843fa79385938034..33a6f47b6ec7aa61fc87df95bd3715f5ce52217a 100644 --- a/test/cmp_decmp/meson.build +++ b/test/cmp_decmp/meson.build @@ -4,7 +4,7 @@ test_runner = test_runner_generator.process(test_case) test_cmp_decmp = executable('test_cmp_decmp', test_case, test_runner, include_directories : incdir, - link_with : cmp_lib, + link_with : [cmp_lib, test_common_lib], dependencies : unity_dep, build_by_default : false ) diff --git a/test/cmp_decmp/test_cmp_decmp.c b/test/cmp_decmp/test_cmp_decmp.c index ffc9963f7d61a061ec5cfcfed91522ce8bc4c71b..1331f3de4fb4c775da781436081ffbffa51ca53c 100644 --- a/test/cmp_decmp/test_cmp_decmp.c +++ b/test/cmp_decmp/test_cmp_decmp.c @@ -25,10 +25,13 @@ #include <stdlib.h> #include <unity.h> +#include "../test_common/test_common.h" #include <cmp_icu.h> +#include <cmp_chunk.h> #include <decmp.h> #include <cmp_data_types.h> +#include <leon_inttypes.h> #if defined __has_include # if __has_include(<time.h>) @@ -41,8 +44,7 @@ #define IMAX_BITS(m) ((m)/((m)%255+1) / 255%255*8 + 7-86/((m)%255+12)) #define RAND_MAX_WIDTH IMAX_BITS(RAND_MAX) -#define set_n_bits(n) (n != 32 ? ~(~0UL << (n)):0xFFFFFFFF) - +#define ROUND_UP_TO_MULTIPLE_OF_4(x) (((x) + 3) & ~3) /** * @brief Seeds the pseudo-random number generator used by rand() @@ -50,279 +52,417 @@ void setUp(void) { - unsigned int seed; + uint64_t seed; static int n; #if HAS_TIME_H - seed = (unsigned int)(time(NULL) * getpid()); + seed = (uint64_t)(time(NULL) ^ getpid() ^ (intptr_t)&setUp); #else seed = 1; #endif if (!n) { n = 1; - srand(seed); - printf("seed: %u\n", seed); + cmp_rand_seed(seed); + printf("seed: %"PRIu64"\n", seed); } } -/** - * @brief generate a uint32_t random number - * - * @return a "random" uint32_t value - * @see https://stackoverflow.com/a/33021408 - */ - -uint32_t rand32(void) +static size_t gen_ima_data(uint16_t *data, uint32_t samples, + const struct cmp_max_used_bits *max_used_bits) { - int i; - uint32_t r = 0; + uint32_t i; - for (i = 0; i < 32; i += RAND_MAX_WIDTH) { - r <<= RAND_MAX_WIDTH; - r ^= (unsigned int) rand(); - } - return r; + if (data) + for (i = 0; i < samples; i++) + data[i] = (uint16_t)cmp_rand_nbits(max_used_bits->nc_imagette); + return sizeof(*data) * samples; } -/** - * @brief generate a random number in a range - * - * @param min minimum value (inclusive) - * @param max maximum value (inclusive) - * - * @returns "random" numbers in the range [min, max] - * - * @see https://c-faq.com/lib/randrange.html - */ - -uint32_t random_between(unsigned int min, unsigned int max) +static size_t gen_nc_offset_data(struct offset *data, uint32_t samples, + const struct cmp_max_used_bits *max_used_bits) { - TEST_ASSERT(min < max); - if (max-min < RAND_MAX) - return min + rand() / (RAND_MAX / (max - min + 1ULL) + 1); - else - return min + rand32() / (UINT32_MAX / (max - min + 1ULL) + 1); + uint32_t i; + + if (data) { + for (i = 0; i < samples; i++) { + data[i].mean = cmp_rand_nbits(max_used_bits->nc_offset_mean); + data[i].variance = cmp_rand_nbits(max_used_bits->nc_offset_variance); + } + } + return sizeof(*data) * samples; } -static void gen_ima_data(uint16_t *data, uint32_t samples, const struct cmp_max_used_bits *max_used_bits) +static size_t gen_fc_offset_data(struct offset *data, uint32_t samples, + const struct cmp_max_used_bits *max_used_bits) { uint32_t i; - for (i = 0; i < samples; i++) - data[i] = (uint16_t)random_between(0, set_n_bits(max_used_bits->nc_imagette)); + if (data) { + for (i = 0; i < samples; i++) { + data[i].mean = cmp_rand_nbits(max_used_bits->fc_offset_mean); + data[i].variance = cmp_rand_nbits(max_used_bits->fc_offset_variance); + } + } + return sizeof(*data) * samples; } -static void gen_offset_data(struct nc_offset *data, uint32_t samples, - const struct cmp_max_used_bits *max_used_bits) +static size_t gen_nc_background_data(struct background *data, uint32_t samples, + const struct cmp_max_used_bits *max_used_bits) { uint32_t i; - for (i = 0; i < samples; i++) { - data[i].mean = random_between(0, set_n_bits(max_used_bits->nc_offset_mean)); - data[i].variance = random_between(0, set_n_bits(max_used_bits->nc_offset_variance)); + if (data) { + for (i = 0; i < samples; i++) { + data[i].mean = cmp_rand_nbits(max_used_bits->nc_background_mean); + data[i].variance = cmp_rand_nbits(max_used_bits->nc_background_variance); + data[i].outlier_pixels = (__typeof__(data[i].outlier_pixels))cmp_rand_nbits(max_used_bits->nc_background_outlier_pixels); + } } + return sizeof(*data) * samples; } -static void gen_background_data(struct nc_background *data, uint32_t samples, - const struct cmp_max_used_bits *max_used_bits) +static size_t gen_fc_background_data(struct background *data, uint32_t samples, + const struct cmp_max_used_bits *max_used_bits) { uint32_t i; - for (i = 0; i < samples; i++) { - data[i].mean = random_between(0, set_n_bits(max_used_bits->nc_background_mean)); - data[i].variance = random_between(0, set_n_bits(max_used_bits->nc_background_variance)); - data[i].outlier_pixels = random_between(0, set_n_bits(max_used_bits->nc_background_outlier_pixels)); + if (data) { + for (i = 0; i < samples; i++) { + data[i].mean = cmp_rand_nbits(max_used_bits->fc_background_mean); + data[i].variance = cmp_rand_nbits(max_used_bits->fc_background_variance); + data[i].outlier_pixels = (__typeof__(data[i].outlier_pixels))cmp_rand_nbits(max_used_bits->fc_background_outlier_pixels); + } } + return sizeof(*data) * samples; } -static void gen_smearing_data(struct smearing *data, uint32_t samples, - const struct cmp_max_used_bits *max_used_bits) +static size_t gen_smearing_data(struct smearing *data, uint32_t samples, + const struct cmp_max_used_bits *max_used_bits) { uint32_t i; - for (i = 0; i < samples; i++) { - data[i].mean = random_between(0, set_n_bits(max_used_bits->smearing_mean)); - data[i].variance_mean = random_between(0, set_n_bits(max_used_bits->smearing_variance_mean)); - data[i].outlier_pixels = random_between(0, set_n_bits(max_used_bits->smearing_outlier_pixels)); + if (data) { + for (i = 0; i < samples; i++) { + data[i].mean = cmp_rand_nbits(max_used_bits->smearing_mean); + data[i].variance_mean = (__typeof__(data[i].variance_mean))cmp_rand_nbits(max_used_bits->smearing_variance_mean); + data[i].outlier_pixels = (__typeof__(data[i].outlier_pixels))cmp_rand_nbits(max_used_bits->smearing_outlier_pixels); + } } + return sizeof(*data) * samples; } -static void gen_s_fx_data(struct s_fx *data, uint32_t samples, - const struct cmp_max_used_bits *max_used_bits) +static size_t gen_s_fx_data(struct s_fx *data, uint32_t samples, + const struct cmp_max_used_bits *max_used_bits) { uint32_t i; - for (i = 0; i < samples; i++) { - data[i].exp_flags = random_between(0, set_n_bits(max_used_bits->s_exp_flags)); - data[i].fx = random_between(0, set_n_bits(max_used_bits->s_fx)); + if (data) { + for (i = 0; i < samples; i++) { + data[i].exp_flags = (__typeof__(data[i].exp_flags))cmp_rand_nbits(max_used_bits->s_exp_flags); + data[i].fx = cmp_rand_nbits(max_used_bits->s_fx); + } } + return sizeof(*data) * samples; } -static void gen_s_fx_efx_data(struct s_fx_efx *data, uint32_t samples, - const struct cmp_max_used_bits *max_used_bits) +static size_t gen_s_fx_efx_data(struct s_fx_efx *data, uint32_t samples, + const struct cmp_max_used_bits *max_used_bits) { uint32_t i; - for (i = 0; i < samples; i++) { - data[i].exp_flags = random_between(0, set_n_bits(max_used_bits->s_exp_flags)); - data[i].fx = random_between(0, set_n_bits(max_used_bits->s_fx)); - data[i].efx = random_between(0, set_n_bits(max_used_bits->s_efx)); + if (data) { + for (i = 0; i < samples; i++) { + data[i].exp_flags = (__typeof__(data[i].exp_flags))cmp_rand_nbits(max_used_bits->s_exp_flags); + data[i].fx = cmp_rand_nbits(max_used_bits->s_fx); + data[i].efx = cmp_rand_nbits(max_used_bits->s_efx); + } } + return sizeof(*data) * samples; } -static void gen_s_fx_ncob_data(struct s_fx_ncob *data, uint32_t samples, - const struct cmp_max_used_bits *max_used_bits) +static size_t gen_s_fx_ncob_data(struct s_fx_ncob *data, uint32_t samples, + const struct cmp_max_used_bits *max_used_bits) { uint32_t i; - for (i = 0; i < samples; i++) { - data[i].exp_flags = random_between(0, set_n_bits(max_used_bits->s_exp_flags)); - data[i].fx = random_between(0, set_n_bits(max_used_bits->s_fx)); - data[i].ncob_x = random_between(0, set_n_bits(max_used_bits->s_ncob)); - data[i].ncob_y = random_between(0, set_n_bits(max_used_bits->s_ncob)); + if (data) { + for (i = 0; i < samples; i++) { + data[i].exp_flags = (__typeof__(data[i].exp_flags))cmp_rand_nbits(max_used_bits->s_exp_flags); + data[i].fx = cmp_rand_nbits(max_used_bits->s_fx); + data[i].ncob_x = cmp_rand_nbits(max_used_bits->s_ncob); + data[i].ncob_y = cmp_rand_nbits(max_used_bits->s_ncob); + } } + return sizeof(*data) * samples; } -static void gen_s_fx_efx_ncob_ecob_data(struct s_fx_efx_ncob_ecob *data, uint32_t samples, - const struct cmp_max_used_bits *max_used_bits) +static size_t gen_s_fx_efx_ncob_ecob_data(struct s_fx_efx_ncob_ecob *data, uint32_t samples, + const struct cmp_max_used_bits *max_used_bits) { uint32_t i; - for (i = 0; i < samples; i++) { - data[i].exp_flags = random_between(0, set_n_bits(max_used_bits->s_exp_flags)); - data[i].fx = random_between(0, set_n_bits(max_used_bits->s_fx)); - data[i].ncob_x = random_between(0, set_n_bits(max_used_bits->s_ncob)); - data[i].ncob_y = random_between(0, set_n_bits(max_used_bits->s_ncob)); - data[i].efx = random_between(0, set_n_bits(max_used_bits->s_efx)); - data[i].ecob_x = random_between(0, set_n_bits(max_used_bits->s_ecob)); - data[i].ecob_y = random_between(0, set_n_bits(max_used_bits->s_ecob)); + if (data) { + for (i = 0; i < samples; i++) { + data[i].exp_flags = (__typeof__(data[i].exp_flags))cmp_rand_nbits(max_used_bits->s_exp_flags); + data[i].fx = cmp_rand_nbits(max_used_bits->s_fx); + data[i].ncob_x = cmp_rand_nbits(max_used_bits->s_ncob); + data[i].ncob_y = cmp_rand_nbits(max_used_bits->s_ncob); + data[i].efx = cmp_rand_nbits(max_used_bits->s_efx); + data[i].ecob_x = cmp_rand_nbits(max_used_bits->s_ecob); + data[i].ecob_y = cmp_rand_nbits(max_used_bits->s_ecob); + } } + return sizeof(*data) * samples; } -static void gen_f_fx_data(struct f_fx *data, uint32_t samples, - const struct cmp_max_used_bits *max_used_bits) +static size_t gen_f_fx_data(struct f_fx *data, uint32_t samples, + const struct cmp_max_used_bits *max_used_bits) { uint32_t i; - for (i = 0; i < samples; i++) - data[i].fx = random_between(0, set_n_bits(max_used_bits->f_fx)); + if (data) + for (i = 0; i < samples; i++) + data[i].fx = cmp_rand_nbits(max_used_bits->f_fx); + return sizeof(*data) * samples; } -static void gen_f_fx_efx_data(struct f_fx_efx *data, uint32_t samples, - const struct cmp_max_used_bits *max_used_bits) +static size_t gen_f_fx_efx_data(struct f_fx_efx *data, uint32_t samples, + const struct cmp_max_used_bits *max_used_bits) { uint32_t i; - for (i = 0; i < samples; i++) { - data[i].fx = random_between(0, set_n_bits(max_used_bits->f_fx)); - data[i].efx = random_between(0, set_n_bits(max_used_bits->f_efx)); + if (data) { + for (i = 0; i < samples; i++) { + data[i].fx = cmp_rand_nbits(max_used_bits->f_fx); + data[i].efx = cmp_rand_nbits(max_used_bits->f_efx); + } } + return sizeof(*data) * samples; } -static void gen_f_fx_ncob_data(struct f_fx_ncob *data, uint32_t samples, - const struct cmp_max_used_bits *max_used_bits) +static size_t gen_f_fx_ncob_data(struct f_fx_ncob *data, uint32_t samples, + const struct cmp_max_used_bits *max_used_bits) { uint32_t i; - for (i = 0; i < samples; i++) { - data[i].fx = random_between(0, set_n_bits(max_used_bits->f_fx)); - data[i].ncob_x = random_between(0, set_n_bits(max_used_bits->f_ncob)); - data[i].ncob_y = random_between(0, set_n_bits(max_used_bits->f_ncob)); + if (data) { + for (i = 0; i < samples; i++) { + data[i].fx = cmp_rand_nbits(max_used_bits->f_fx); + data[i].ncob_x = cmp_rand_nbits(max_used_bits->f_ncob); + data[i].ncob_y = cmp_rand_nbits(max_used_bits->f_ncob); + } } + return sizeof(*data) * samples; } -static void gen_f_fx_efx_ncob_ecob_data(struct f_fx_efx_ncob_ecob *data, uint32_t samples, - const struct cmp_max_used_bits *max_used_bits) +static size_t gen_f_fx_efx_ncob_ecob_data(struct f_fx_efx_ncob_ecob *data, uint32_t samples, + const struct cmp_max_used_bits *max_used_bits) { uint32_t i; - for (i = 0; i < samples; i++) { - data[i].fx = random_between(0, set_n_bits(max_used_bits->f_fx)); - data[i].ncob_x = random_between(0, set_n_bits(max_used_bits->f_ncob)); - data[i].ncob_y = random_between(0, set_n_bits(max_used_bits->f_ncob)); - data[i].efx = random_between(0, set_n_bits(max_used_bits->f_efx)); - data[i].ecob_x = random_between(0, set_n_bits(max_used_bits->f_ecob)); - data[i].ecob_y = random_between(0, set_n_bits(max_used_bits->f_ecob)); + if (data) { + for (i = 0; i < samples; i++) { + data[i].fx = cmp_rand_nbits(max_used_bits->f_fx); + data[i].ncob_x = cmp_rand_nbits(max_used_bits->f_ncob); + data[i].ncob_y = cmp_rand_nbits(max_used_bits->f_ncob); + data[i].efx = cmp_rand_nbits(max_used_bits->f_efx); + data[i].ecob_x = cmp_rand_nbits(max_used_bits->f_ecob); + data[i].ecob_y = cmp_rand_nbits(max_used_bits->f_ecob); + } } + return sizeof(*data) * samples; } -static void gen_l_fx_data(struct l_fx *data, uint32_t samples, - const struct cmp_max_used_bits *max_used_bits) +static size_t gen_l_fx_data(struct l_fx *data, uint32_t samples, + const struct cmp_max_used_bits *max_used_bits) { uint32_t i; - for (i = 0; i < samples; i++) { - data[i].exp_flags = random_between(0, set_n_bits(max_used_bits->l_exp_flags)); - data[i].fx = random_between(0, set_n_bits(max_used_bits->l_fx)); - data[i].fx_variance = random_between(0, set_n_bits(max_used_bits->l_fx_variance)); + if (data) { + for (i = 0; i < samples; i++) { + data[i].exp_flags = cmp_rand_nbits(max_used_bits->l_exp_flags); + data[i].fx = cmp_rand_nbits(max_used_bits->l_fx); + data[i].fx_variance = cmp_rand_nbits(max_used_bits->l_fx_variance); + } } + return sizeof(*data) * samples; } -static void gen_l_fx_efx_data(struct l_fx_efx *data, uint32_t samples, - const struct cmp_max_used_bits *max_used_bits) +static size_t gen_l_fx_efx_data(struct l_fx_efx *data, uint32_t samples, + const struct cmp_max_used_bits *max_used_bits) { uint32_t i; - for (i = 0; i < samples; i++) { - data[i].exp_flags = random_between(0, set_n_bits(max_used_bits->l_exp_flags)); - data[i].fx = random_between(0, set_n_bits(max_used_bits->l_fx)); - data[i].efx = random_between(0, set_n_bits(max_used_bits->l_efx)); - data[i].fx_variance = random_between(0, set_n_bits(max_used_bits->l_fx_variance)); + if (data) { + for (i = 0; i < samples; i++) { + data[i].exp_flags = cmp_rand_nbits(max_used_bits->l_exp_flags); + data[i].fx = cmp_rand_nbits(max_used_bits->l_fx); + data[i].efx = cmp_rand_nbits(max_used_bits->l_efx); + data[i].fx_variance = cmp_rand_nbits(max_used_bits->l_fx_variance); + } } + return sizeof(*data) * samples; } -static void gen_l_fx_ncob_data(struct l_fx_ncob *data, uint32_t samples, - const struct cmp_max_used_bits *max_used_bits) +static size_t gen_l_fx_ncob_data(struct l_fx_ncob *data, uint32_t samples, + const struct cmp_max_used_bits *max_used_bits) { - uint32_t i; + if (data) { + uint32_t i; + + for (i = 0; i < samples; i++) { + data[i].exp_flags = cmp_rand_nbits(max_used_bits->l_exp_flags); + data[i].fx = cmp_rand_nbits(max_used_bits->l_fx); + data[i].ncob_x = cmp_rand_nbits(max_used_bits->l_ncob); + data[i].ncob_y = cmp_rand_nbits(max_used_bits->l_ncob); + data[i].fx_variance = cmp_rand_nbits(max_used_bits->l_fx_variance); + data[i].cob_x_variance = cmp_rand_nbits(max_used_bits->l_cob_variance); + data[i].cob_y_variance = cmp_rand_nbits(max_used_bits->l_cob_variance); + } + } + return sizeof(*data) * samples; +} - for (i = 0; i < samples; i++) { - data[i].exp_flags = random_between(0, set_n_bits(max_used_bits->l_exp_flags)); - data[i].fx = random_between(0, set_n_bits(max_used_bits->l_fx)); - data[i].ncob_x = random_between(0, set_n_bits(max_used_bits->l_ncob)); - data[i].ncob_y = random_between(0, set_n_bits(max_used_bits->l_ncob)); - data[i].fx_variance = random_between(0, set_n_bits(max_used_bits->l_fx_variance)); - data[i].cob_x_variance = random_between(0, set_n_bits(max_used_bits->l_cob_variance)); - data[i].cob_y_variance = random_between(0, set_n_bits(max_used_bits->l_cob_variance)); + +static size_t gen_l_fx_efx_ncob_ecob_data(struct l_fx_efx_ncob_ecob *data, uint32_t samples, + const struct cmp_max_used_bits *max_used_bits) +{ + if (data) { + uint32_t i; + + for (i = 0; i < samples; i++) { + data[i].exp_flags = cmp_rand_nbits(max_used_bits->l_exp_flags); + data[i].fx = cmp_rand_nbits(max_used_bits->l_fx); + data[i].ncob_x = cmp_rand_nbits(max_used_bits->l_ncob); + data[i].ncob_y = cmp_rand_nbits(max_used_bits->l_ncob); + data[i].efx = cmp_rand_nbits(max_used_bits->l_efx); + data[i].ecob_x = cmp_rand_nbits(max_used_bits->l_ecob); + data[i].ecob_y = cmp_rand_nbits(max_used_bits->l_ecob); + data[i].fx_variance = cmp_rand_nbits(max_used_bits->l_fx_variance); + data[i].cob_x_variance = cmp_rand_nbits(max_used_bits->l_cob_variance); + data[i].cob_y_variance = cmp_rand_nbits(max_used_bits->l_cob_variance); + } } + return sizeof(*data) * samples; } -static void gen_l_fx_efx_ncob_ecob_data(struct l_fx_efx_ncob_ecob *data, uint32_t samples, - const struct cmp_max_used_bits *max_used_bits) +static uint8_t get_sst(enum cmp_data_type data_type) { - uint32_t i; + uint8_t sst = 0; - for (i = 0; i < samples; i++) { - data[i].exp_flags = random_between(0, set_n_bits(max_used_bits->l_exp_flags)); - data[i].fx = random_between(0, set_n_bits(max_used_bits->l_fx)); - data[i].ncob_x = random_between(0, set_n_bits(max_used_bits->l_ncob)); - data[i].ncob_y = random_between(0, set_n_bits(max_used_bits->l_ncob)); - data[i].efx = random_between(0, set_n_bits(max_used_bits->l_efx)); - data[i].ecob_x = random_between(0, set_n_bits(max_used_bits->l_ecob)); - data[i].ecob_y = random_between(0, set_n_bits(max_used_bits->l_ecob)); - data[i].fx_variance = random_between(0, set_n_bits(max_used_bits->l_fx_variance)); - data[i].cob_x_variance = random_between(0, set_n_bits(max_used_bits->l_cob_variance)); - data[i].cob_y_variance = random_between(0, set_n_bits(max_used_bits->l_cob_variance)); + switch (data_type) { + case DATA_TYPE_IMAGETTE: + case DATA_TYPE_IMAGETTE_ADAPTIVE: + sst = SST_NCxx_S_SCIENCE_IMAGETTE; + break; + case DATA_TYPE_SAT_IMAGETTE: + case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE: + sst = SST_NCxx_S_SCIENCE_SAT_IMAGETTE; + break; + case DATA_TYPE_OFFSET: + sst = SST_NCxx_S_SCIENCE_OFFSET; + break; + case DATA_TYPE_BACKGROUND: + sst = SST_NCxx_S_SCIENCE_BACKGROUND; + break; + case DATA_TYPE_SMEARING: + sst = SST_NCxx_S_SCIENCE_SMEARING; + break; + case DATA_TYPE_S_FX: + sst = SST_NCxx_S_SCIENCE_S_FX; + break; + case DATA_TYPE_S_FX_EFX: + sst = SST_NCxx_S_SCIENCE_S_FX_EFX; + break; + case DATA_TYPE_S_FX_NCOB: + sst = SST_NCxx_S_SCIENCE_S_FX_NCOB; + break; + case DATA_TYPE_S_FX_EFX_NCOB_ECOB: + sst = SST_NCxx_S_SCIENCE_S_FX_EFX_NCOB_ECOB; + break; + case DATA_TYPE_L_FX: + sst = SST_NCxx_S_SCIENCE_L_FX; + break; + case DATA_TYPE_L_FX_EFX: + sst = SST_NCxx_S_SCIENCE_L_FX_EFX; + break; + case DATA_TYPE_L_FX_NCOB: + sst = SST_NCxx_S_SCIENCE_L_FX_NCOB; + break; + case DATA_TYPE_L_FX_EFX_NCOB_ECOB: + sst = SST_NCxx_S_SCIENCE_L_FX_EFX_NCOB_ECOB; + break; + case DATA_TYPE_F_FX: + sst = SST_NCxx_S_SCIENCE_F_FX; + break; + case DATA_TYPE_F_FX_EFX: + sst = SST_NCxx_S_SCIENCE_F_FX_EFX; + break; + case DATA_TYPE_F_FX_NCOB: + sst = SST_NCxx_S_SCIENCE_F_FX_NCOB; + break; + case DATA_TYPE_F_FX_EFX_NCOB_ECOB: + sst = SST_NCxx_S_SCIENCE_F_FX_EFX_NCOB_ECOB; + break; + case DATA_TYPE_F_CAM_IMAGETTE: + case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE: + sst = SST_FCx_S_SCIENCE_IMAGETTE; + break; + case DATA_TYPE_F_CAM_OFFSET: + sst = SST_FCx_S_SCIENCE_OFFSET_VALUES; + break; + case DATA_TYPE_F_CAM_BACKGROUND: + sst = SST_FCx_S_BACKGROUND_VALUES; + break; + default: + case DATA_TYPE_UNKNOWN: + TEST_FAIL(); + /* debug_print("Error: Unknown compression data type!\n"); */ + }; + + return sst; +} + + +size_t generate_random_collection_hdr(struct collection_hdr *col, enum cmp_data_type data_type, + uint32_t samples) +{ + static uint8_t sequence_num; + size_t data_size = size_of_a_sample(data_type)*samples; + + TEST_ASSERT(data_size <= UINT16_MAX); + + if (col) { + TEST_ASSERT_FALSE(cmp_col_set_timestamp(col, cmp_ent_create_timestamp(NULL))); + TEST_ASSERT_FALSE(cmp_col_set_configuration_id(col, (uint16_t)cmp_rand32())); + + TEST_ASSERT_FALSE(cmp_col_set_pkt_type(col, COL_SCI_PKTS_TYPE)); + TEST_ASSERT_FALSE(cmp_col_set_subservice(col, get_sst(data_type))); + TEST_ASSERT_FALSE(cmp_col_set_ccd_id(col, (uint8_t)cmp_rand_between(0, 3))); + TEST_ASSERT_FALSE(cmp_col_set_sequence_num(col, sequence_num++)); + + TEST_ASSERT_FALSE(cmp_col_set_data_length(col, (uint16_t)data_size)); } + return COLLECTION_HDR_SIZE; } @@ -336,26 +476,31 @@ static void gen_l_fx_efx_ncob_ecob_data(struct l_fx_efx_ncob_ecob *data, uint32_ * @returns a pointer to the generated random test data */ -void *generate_random_test_data(uint32_t samples, enum cmp_data_type data_type, - const struct cmp_max_used_bits *max_used_bits) +size_t generate_random_collection(struct collection_hdr *col, enum cmp_data_type data_type, + uint32_t samples, const struct cmp_max_used_bits *max_used_bits) { - size_t data_size = cmp_cal_size_of_data(samples, data_type); - void *data = malloc(data_size); - void *data_cpy = data; - uint8_t *p = data; + size_t size; + void *science_data = NULL; - TEST_ASSERT_NOT_EQUAL_INT(data_size, 0); - TEST_ASSERT(data_size < (CMP_ENTITY_MAX_SIZE - NON_IMAGETTE_HEADER_SIZE)); - TEST_ASSERT_NOT_NULL(data); + if (col) + science_data = col->entry; - if (!rdcu_supported_data_type_is_used(data_type)) { - int i; + if (rdcu_supported_data_type_is_used(data_type)) { + /* for the rdcu the header counts as data */ + size_t hdr_in_samples = COLLECTION_HDR_SIZE/size_of_a_sample(data_type); + TEST_ASSERT(samples >= hdr_in_samples); + samples -= hdr_in_samples; + } - TEST_ASSERT(data_size > MULTI_ENTRY_HDR_SIZE); - for (i = 0; i < MULTI_ENTRY_HDR_SIZE; ++i) - *p++ = random_between(0, UINT8_MAX); - data = p; + size = generate_random_collection_hdr(col, data_type, samples); + /* TDOO remove me */ + int i; + for (i = 0; i < size_of_a_sample(data_type)*samples; ++i) { + if (col){ + col->entry[i] = i; + } } + return size+i; switch (data_type) { case DATA_TYPE_IMAGETTE: @@ -364,60 +509,87 @@ void *generate_random_test_data(uint32_t samples, enum cmp_data_type data_type, case DATA_TYPE_SAT_IMAGETTE_ADAPTIVE: case DATA_TYPE_F_CAM_IMAGETTE: case DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE: - gen_ima_data(data, samples, max_used_bits); + size += gen_ima_data(science_data, samples, max_used_bits); break; case DATA_TYPE_OFFSET: - gen_offset_data(data, samples, max_used_bits); + size += gen_nc_offset_data(science_data, samples, max_used_bits); break; case DATA_TYPE_BACKGROUND: - gen_background_data(data, samples, max_used_bits); + size += gen_nc_background_data(science_data, samples, max_used_bits); break; case DATA_TYPE_SMEARING: - gen_smearing_data(data, samples, max_used_bits); + size += gen_smearing_data(science_data, samples, max_used_bits); break; case DATA_TYPE_S_FX: - gen_s_fx_data(data, samples, max_used_bits); + size += gen_s_fx_data(science_data, samples, max_used_bits); break; case DATA_TYPE_S_FX_EFX: - gen_s_fx_efx_data(data, samples, max_used_bits); + size += gen_s_fx_efx_data(science_data, samples, max_used_bits); break; case DATA_TYPE_S_FX_NCOB: - gen_s_fx_ncob_data(data, samples, max_used_bits); + size += gen_s_fx_ncob_data(science_data, samples, max_used_bits); break; case DATA_TYPE_S_FX_EFX_NCOB_ECOB: - gen_s_fx_efx_ncob_ecob_data(data, samples, max_used_bits); + size += gen_s_fx_efx_ncob_ecob_data(science_data, samples, max_used_bits); break; case DATA_TYPE_L_FX: - gen_l_fx_data(data, samples, max_used_bits); + size += gen_l_fx_data(science_data, samples, max_used_bits); break; case DATA_TYPE_L_FX_EFX: - gen_l_fx_efx_data(data, samples, max_used_bits); + size += gen_l_fx_efx_data(science_data, samples, max_used_bits); break; case DATA_TYPE_L_FX_NCOB: - gen_l_fx_ncob_data(data, samples, max_used_bits); + size += gen_l_fx_ncob_data(science_data, samples, max_used_bits); break; case DATA_TYPE_L_FX_EFX_NCOB_ECOB: - gen_l_fx_efx_ncob_ecob_data(data, samples, max_used_bits); + size += gen_l_fx_efx_ncob_ecob_data(science_data, samples, max_used_bits); break; case DATA_TYPE_F_FX: - gen_f_fx_data(data, samples, max_used_bits); + size += gen_f_fx_data(science_data, samples, max_used_bits); break; case DATA_TYPE_F_FX_EFX: - gen_f_fx_efx_data(data, samples, max_used_bits); + size += gen_f_fx_efx_data(science_data, samples, max_used_bits); break; case DATA_TYPE_F_FX_NCOB: - gen_f_fx_ncob_data(data, samples, max_used_bits); + size += gen_f_fx_ncob_data(science_data, samples, max_used_bits); break; case DATA_TYPE_F_FX_EFX_NCOB_ECOB: - gen_f_fx_efx_ncob_ecob_data(data, samples, max_used_bits); + size += gen_f_fx_efx_ncob_ecob_data(science_data, samples, max_used_bits); + break; + case DATA_TYPE_F_CAM_OFFSET: + size += gen_fc_offset_data(science_data, samples, max_used_bits); + break; + case DATA_TYPE_F_CAM_BACKGROUND: + size += gen_fc_background_data(science_data, samples, max_used_bits); break; - case DATA_TYPE_F_CAM_OFFSET: /* TODO: implement this */ - case DATA_TYPE_F_CAM_BACKGROUND: /* TODO: implement this */ default: TEST_FAIL(); } - return data_cpy; + return size; +} + +struct chunk_def { + enum cmp_data_type data_type; + uint32_t samples; +}; + + +static size_t generate_random_chunk(void *chunk, struct chunk_def col_array[], size_t array_elements, + const struct cmp_max_used_bits *max_used_bits) +{ + size_t i; + size_t chunk_size = 0; + struct collection_hdr *col = NULL; + + for (i = 0; i < array_elements; i++) { + if (chunk) + col = (struct collection_hdr *)((uint8_t *)chunk + chunk_size); + + chunk_size += generate_random_collection(col, col_array[i].data_type, + col_array[i].samples, max_used_bits); + } + return chunk_size; } @@ -429,49 +601,43 @@ void *generate_random_test_data(uint32_t samples, enum cmp_data_type data_type, void generate_random_cmp_par(struct cmp_cfg *cfg) { - cfg->golomb_par = random_between(MIN_IMA_GOLOMB_PAR, MAX_IMA_GOLOMB_PAR); - cfg->ap1_golomb_par = random_between(MIN_IMA_GOLOMB_PAR, MAX_IMA_GOLOMB_PAR); - cfg->ap2_golomb_par = random_between(MIN_IMA_GOLOMB_PAR, MAX_IMA_GOLOMB_PAR); - - cfg->cmp_par_exp_flags = random_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - cfg->cmp_par_fx = random_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - cfg->cmp_par_ncob = random_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - cfg->cmp_par_efx = random_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - cfg->cmp_par_ecob = random_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - cfg->cmp_par_fx_cob_variance = random_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - cfg->cmp_par_mean = random_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - cfg->cmp_par_variance = random_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - cfg->cmp_par_pixels_error = random_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - - - cfg->spill = random_between(MIN_IMA_SPILL, cmp_ima_max_spill(cfg->golomb_par)); - cfg->ap1_spill = random_between(MIN_IMA_SPILL, cmp_ima_max_spill(cfg->ap1_golomb_par)); - cfg->ap2_spill = random_between(MIN_IMA_SPILL, cmp_ima_max_spill(cfg->ap2_golomb_par)); - - cfg->spill_exp_flags = random_between(MIN_NON_IMA_SPILL, cmp_icu_max_spill(cfg->cmp_par_exp_flags)); - cfg->spill_fx = random_between(MIN_NON_IMA_SPILL, cmp_icu_max_spill(cfg->cmp_par_fx)); - cfg->spill_ncob = random_between(MIN_NON_IMA_SPILL, cmp_icu_max_spill(cfg->cmp_par_ncob)); - cfg->spill_efx = random_between(MIN_NON_IMA_SPILL, cmp_icu_max_spill(cfg->cmp_par_efx)); - cfg->spill_ecob = random_between(MIN_NON_IMA_SPILL, cmp_icu_max_spill(cfg->cmp_par_ecob)); - cfg->spill_fx_cob_variance = random_between(MIN_NON_IMA_SPILL, cmp_icu_max_spill(cfg->cmp_par_fx_cob_variance)); - cfg->spill_mean = random_between(MIN_NON_IMA_SPILL, cmp_icu_max_spill(cfg->cmp_par_mean)); - cfg->spill_variance = random_between(MIN_NON_IMA_SPILL, cmp_icu_max_spill(cfg->cmp_par_variance)); - cfg->spill_pixels_error = random_between(MIN_NON_IMA_SPILL, cmp_icu_max_spill(cfg->cmp_par_pixels_error)); + if (cmp_imagette_data_type_is_used(cfg->data_type)) { + cfg->cmp_par_imagette = cmp_rand_between(MIN_IMA_GOLOMB_PAR, MAX_IMA_GOLOMB_PAR); + cfg->ap1_golomb_par = cmp_rand_between(MIN_IMA_GOLOMB_PAR, MAX_IMA_GOLOMB_PAR); + cfg->ap2_golomb_par = cmp_rand_between(MIN_IMA_GOLOMB_PAR, MAX_IMA_GOLOMB_PAR); + cfg->spill_imagette = cmp_rand_between(MIN_IMA_SPILL, cmp_ima_max_spill(cfg->golomb_par)); + cfg->ap1_spill = cmp_rand_between(MIN_IMA_SPILL, cmp_ima_max_spill(cfg->ap1_golomb_par)); + cfg->ap2_spill = cmp_rand_between(MIN_IMA_SPILL, cmp_ima_max_spill(cfg->ap2_golomb_par)); + } else { + cfg->cmp_par_1 = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + cfg->cmp_par_2 = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + cfg->cmp_par_3 = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + cfg->cmp_par_4 = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + cfg->cmp_par_5 = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + cfg->cmp_par_6 = cmp_rand_between(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); + cfg->spill_par_1 = cmp_rand_between(MIN_NON_IMA_SPILL, cmp_icu_max_spill(cfg->cmp_par_exp_flags)); + cfg->spill_par_2 = cmp_rand_between(MIN_NON_IMA_SPILL, cmp_icu_max_spill(cfg->cmp_par_fx)); + cfg->spill_par_3 = cmp_rand_between(MIN_NON_IMA_SPILL, cmp_icu_max_spill(cfg->cmp_par_ncob)); + cfg->spill_par_4 = cmp_rand_between(MIN_NON_IMA_SPILL, cmp_icu_max_spill(cfg->cmp_par_efx)); + cfg->spill_par_5 = cmp_rand_between(MIN_NON_IMA_SPILL, cmp_icu_max_spill(cfg->cmp_par_ecob)); + cfg->spill_par_6 = cmp_rand_between(MIN_NON_IMA_SPILL, cmp_icu_max_spill(cfg->cmp_par_fx_cob_variance)); + } + #if 0 if (cfg->cmp_mode == CMP_MODE_STUFF) { - /* cfg->golomb_par = random_between(16, MAX_STUFF_CMP_PAR); */ + /* cfg->golomb_par = cmp_rand_between(16, MAX_STUFF_CMP_PAR); */ cfg->golomb_par = 16; - cfg->ap1_golomb_par = random_between(0, MAX_STUFF_CMP_PAR); - cfg->ap2_golomb_par = random_between(0, MAX_STUFF_CMP_PAR); - cfg->cmp_par_exp_flags = random_between(0, MAX_STUFF_CMP_PAR); - cfg->cmp_par_fx = random_between(0, MAX_STUFF_CMP_PAR); - cfg->cmp_par_ncob = random_between(0, MAX_STUFF_CMP_PAR); - cfg->cmp_par_efx = random_between(0, MAX_STUFF_CMP_PAR); - cfg->cmp_par_ecob = random_between(0, MAX_STUFF_CMP_PAR); - cfg->cmp_par_fx_cob_variance = random_between(0, MAX_STUFF_CMP_PAR); - cfg->cmp_par_mean = random_between(0, MAX_STUFF_CMP_PAR); - cfg->cmp_par_variance = random_between(0, MAX_STUFF_CMP_PAR); - cfg->cmp_par_pixels_error = random_between(0, MAX_STUFF_CMP_PAR); + cfg->ap1_golomb_par = cmp_rand_between(0, MAX_STUFF_CMP_PAR); + cfg->ap2_golomb_par = cmp_rand_between(0, MAX_STUFF_CMP_PAR); + cfg->cmp_par_exp_flags = cmp_rand_between(0, MAX_STUFF_CMP_PAR); + cfg->cmp_par_fx = cmp_rand_between(0, MAX_STUFF_CMP_PAR); + cfg->cmp_par_ncob = cmp_rand_between(0, MAX_STUFF_CMP_PAR); + cfg->cmp_par_efx = cmp_rand_between(0, MAX_STUFF_CMP_PAR); + cfg->cmp_par_ecob = cmp_rand_between(0, MAX_STUFF_CMP_PAR); + cfg->cmp_par_fx_cob_variance = cmp_rand_between(0, MAX_STUFF_CMP_PAR); + cfg->cmp_par_mean = cmp_rand_between(0, MAX_STUFF_CMP_PAR); + cfg->cmp_par_variance = cmp_rand_between(0, MAX_STUFF_CMP_PAR); + cfg->cmp_par_pixels_error = cmp_rand_between(0, MAX_STUFF_CMP_PAR); return; } #endif @@ -488,7 +654,7 @@ void generate_random_cmp_par(struct cmp_cfg *cfg) void compression_decompression(struct cmp_cfg *cfg) { int cmp_size_bits, s, error; - int data_size, cmp_data_size; + uint32_t data_size, cmp_data_size, cmp_ent_size; struct cmp_entity *ent; void *decompressed_data; static void *model_of_data; @@ -507,14 +673,14 @@ void compression_decompression(struct cmp_cfg *cfg) /* create a compression entity */ cmp_data_size = cmp_cal_size_of_data(cfg->buffer_length, cfg->data_type); - cmp_data_size &= ~0x3; /* the size of the compressed data should be a multiple of 4 */ + cmp_data_size &= ~0x3U; /* the size of the compressed data should be a multiple of 4 */ TEST_ASSERT_NOT_EQUAL_INT(0, cmp_data_size); - s = cmp_ent_create(NULL, cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW, cmp_data_size); - TEST_ASSERT_NOT_EQUAL_INT(0, s); - ent = malloc(s); TEST_ASSERT_TRUE(ent); - s = cmp_ent_create(ent, cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW, cmp_data_size); - TEST_ASSERT_NOT_EQUAL_INT(0, s); + cmp_ent_size = cmp_ent_create(NULL, cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW, cmp_data_size); + TEST_ASSERT_NOT_EQUAL_UINT(0, cmp_ent_size); + ent = malloc(cmp_ent_size); TEST_ASSERT_TRUE(ent); + cmp_ent_size = cmp_ent_create(ent, cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW, cmp_data_size); + TEST_ASSERT_NOT_EQUAL_UINT(0, cmp_ent_size); /* we put the coompressed data direct into the compression entity */ cfg->icu_output_buf = cmp_ent_get_data_buf(ent); @@ -525,13 +691,26 @@ void compression_decompression(struct cmp_cfg *cfg) TEST_ASSERT(cmp_size_bits > 0); /* put the compression parameters in the entity header */ - error = cmp_ent_write_cmp_pars(ent, cfg, cmp_size_bits); - TEST_ASSERT_FALSE(error); + { + /* mock values */ + uint32_t version_id = ~0U; + uint64_t start_time = 32; + uint64_t end_time = 42; + uint16_t model_id = 0xCAFE; + uint8_t model_counter = 0; + uint32_t ent_size; + + ent_size = cmp_ent_build(ent, version_id, start_time, end_time, + model_id, model_counter, cfg, cmp_size_bits); + TEST_ASSERT_NOT_EQUAL_UINT(0, ent_size); + error = cmp_ent_set_size(ent, ent_size); + TEST_ASSERT_FALSE(error); + } /* allocate the buffers for decompression */ TEST_ASSERT_NOT_EQUAL_INT(0, data_size); s = decompress_cmp_entiy(ent, model_of_data, NULL, NULL); - decompressed_data = malloc(s); TEST_ASSERT_NOT_NULL(decompressed_data); + decompressed_data = malloc((size_t)s); TEST_ASSERT_NOT_NULL(decompressed_data); if (model_mode_is_used(cfg->cmp_mode)) { updated_model = malloc(data_size); @@ -574,22 +753,37 @@ void compression_decompression(struct cmp_cfg *cfg) * @test decompress_cmp_entiy */ +#define MB *(1U<<20) +#define MAX_DATA_TO_COMPRESS_SIZE 0x1000B void test_random_compression_decompression(void) { enum cmp_data_type data_type; enum cmp_mode cmp_mode; struct cmp_cfg cfg; - int cmp_buffer_size; + uint32_t cmp_buffer_size; + void *data_to_compress1 = malloc(MAX_DATA_TO_COMPRESS_SIZE); + void *data_to_compress2 = malloc(MAX_DATA_TO_COMPRESS_SIZE); + void *updated_model = calloc(1, MAX_DATA_TO_COMPRESS_SIZE); - /* TODO: extend test for DATA_TYPE_F_CAM_BACKGROUND, DATA_TYPE_F_CAM_OFFSET */ - for (data_type = 1; data_type <= DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE; data_type++) { + for (data_type = 1; data_type <= DATA_TYPE_F_CAM_BACKGROUND; data_type++) { /* printf("%s\n", data_type2string(data_type)); */ /* generate random data*/ - uint32_t samples = random_between(1, 430179/CMP_BUFFER_FAKTOR); - uint32_t model_value = random_between(0, MAX_MODEL_VALUE); - void *data_to_compress1 = generate_random_test_data(samples, data_type, &MAX_USED_BITS_V1); - void *data_to_compress2 = generate_random_test_data(samples, data_type, &MAX_USED_BITS_V1); - void *updated_model = calloc(1, cmp_cal_size_of_data(samples, data_type)); + /* uint32_t samples = cmp_rand_between(1, 430179/CMP_BUFFER_FAKTOR); */ + size_t size; + uint32_t samples = cmp_rand_between(1, UINT16_MAX/size_of_a_sample(data_type)); + uint32_t model_value = cmp_rand_between(0, MAX_MODEL_VALUE); + /* void *data_to_compress1 = generate_random_test_data(samples, data_type, &MAX_USED_BITS_V1); */ + /* void *data_to_compress2 = generate_random_test_data(samples, data_type, &MAX_USED_BITS_V1); */ + /* void *updated_model = calloc(1, cmp_cal_size_of_data(samples, data_type)); */ + /* memset(updated_model, 0, MAX_DATA_TO_COMPRESS_SIZE); */ + + size = generate_random_collection(NULL, data_type, samples, &MAX_USED_BITS_V1); + TEST_ASSERT(size <= MAX_DATA_TO_COMPRESS_SIZE); + size = generate_random_collection(data_to_compress1, data_type, samples, &MAX_USED_BITS_V1); + TEST_ASSERT(size <= MAX_DATA_TO_COMPRESS_SIZE); + size = generate_random_collection(data_to_compress2, data_type, samples, &MAX_USED_BITS_V1); + TEST_ASSERT(size <= MAX_DATA_TO_COMPRESS_SIZE); + /* for (cmp_mode = CMP_MODE_RAW; cmp_mode <= CMP_MODE_STUFF; cmp_mode++) { */ for (cmp_mode = CMP_MODE_RAW; cmp_mode <= CMP_MODE_DIFF_MULTI; cmp_mode++) { /* printf("cmp_mode: %i\n", cmp_mode); */ @@ -606,19 +800,19 @@ void test_random_compression_decompression(void) cmp_buffer_size = cmp_cfg_icu_buffers(&cfg, data_to_compress2, samples, data_to_compress1, updated_model, NULL, samples*CMP_BUFFER_FAKTOR); - TEST_ASSERT_EQUAL_INT(cmp_buffer_size, cmp_cal_size_of_data(CMP_BUFFER_FAKTOR*samples, data_type)); + TEST_ASSERT_EQUAL_UINT(cmp_buffer_size, cmp_cal_size_of_data(CMP_BUFFER_FAKTOR*samples, data_type)); compression_decompression(&cfg); } - free(data_to_compress1); - free(data_to_compress2); - free(updated_model); } compression_decompression(NULL); + free(data_to_compress1); + free(data_to_compress2); + free(updated_model); } -#define N_SAMPLES 5 +#define N_SAMPLES 5 void test_random_compression_decompression2(void) { struct cmp_cfg cfg; @@ -641,7 +835,7 @@ void test_random_compression_decompression2(void) cmp_size_bits = icu_compress_data(&cfg); TEST_ASSERT(cmp_size_bits > 0); - info.cmp_size = cmp_size_bits; + info.cmp_size = (uint32_t)cmp_size_bits; info.cmp_mode_used = (uint8_t)cfg.cmp_mode; info.model_value_used = (uint8_t)cfg.model_value; info.round_used = (uint8_t)cfg.round; @@ -653,7 +847,7 @@ void test_random_compression_decompression2(void) s = decompress_rdcu_data(compressed_data, &info, NULL, NULL, NULL); TEST_ASSERT(s > 0); - decompressed_data = malloc(s); + decompressed_data = malloc((size_t)s); s = decompress_rdcu_data(compressed_data, &info, NULL, NULL, decompressed_data); TEST_ASSERT(s > 0); @@ -664,3 +858,635 @@ void test_random_compression_decompression2(void) free(compressed_data); free(decompressed_data); } + +#if 0 +int icu_compress_chunk(void *chunk, size_t chunk_size, void *model, void *dst, + size_t dst_capacity); +void no_test_chunk(void) +{ + size_t s, i; + struct todo chunk_struct[3]; + uint8_t *buf; + uint8_t *dst; + + cmp_rand_seed(0); + chunk_struct[0].data_type = DATA_TYPE_F_FX; + chunk_struct[0].samples = 10; + + chunk_struct[1].data_type = DATA_TYPE_S_FX; + chunk_struct[1].samples = 3; + + chunk_struct[2].data_type = DATA_TYPE_SMEARING; + chunk_struct[2].samples = 4; + + s = generate_random_chunk(NULL, chunk_struct, ARRAY_SIZE(chunk_struct), &MAX_USED_BITS_V1); + printf("s: %zu\n", s); + + buf = malloc(s); + s = generate_random_chunk(buf, chunk_struct, ARRAY_SIZE(chunk_struct), &MAX_USED_BITS_V1); + printf("data to compress (s: %zu)\n", s); + for (i = 0; i < s; ++i) { + printf("%02X", buf[i]); + if ((i + 1) % 2 == 0) + printf("\n"); + } + + dst = malloc(s+1000); + s = icu_compress_chunk(buf, s, NULL, dst, s+1000); + printf("\n\ncompressed data (s: %zu)\n", s); + for (i = 0; i < s; ++i) { + printf("%02X", dst[i]); + if ((i + 1) % 2 == 0) + printf("\n"); + } + + free(dst); + free(buf); +} +#endif +#include <byteorder.h> + +size_t set_cmp_size(uint8_t *p, uint16_t v) +{ + v -= COLLECTION_HDR_SIZE; + memset(p, v >> 8, 1); + memset(p+1, v & 0xFF, 1); + return sizeof(uint16_t); +} + +uint16_t get_cmp_size(uint8_t *p) +{ + return ((uint16_t)p[0]<<8) + p[1]; +} +#if 0 +remove this +void no_test_new_format(void) +{ + uint32_t data_size = cmp_cal_size_of_data(3, DATA_TYPE_L_FX_EFX_NCOB_ECOB); + data_size += cmp_cal_size_of_data(2, DATA_TYPE_L_FX_EFX_NCOB_ECOB); + data_size += cmp_cal_size_of_data(5, DATA_TYPE_L_FX); + data_size += cmp_cal_size_of_data(2, DATA_TYPE_L_FX); + data_size += 3*sizeof(uint16_t); + + uint32_t ent_size = cmp_ent_create(NULL, DATA_TYPE_L_FX, 1, data_size); + void *ent = calloc(1, ent_size); + ent_size = cmp_ent_create(ent, DATA_TYPE_L_FX, 1, data_size); + + char *p = cmp_ent_get_data_buf(ent); + p +=2; + uint16_t s = generate_random_collection(p, DATA_TYPE_L_FX, 2, &MAX_USED_BITS_V1); + p += set_cmp_size(p-2, s); + p += s; + s = generate_random_collection(p, DATA_TYPE_L_FX, 5, &MAX_USED_BITS_V1); + p += set_cmp_size(p-2, s); + p += s; + s = generate_random_collection(p, DATA_TYPE_L_FX_EFX_NCOB_ECOB, 2, &MAX_USED_BITS_V1); + p += set_cmp_size(p-2, s); + p += s; + s = generate_random_collection(p, DATA_TYPE_L_FX_EFX_NCOB_ECOB, 2, &MAX_USED_BITS_V1); + p+=s; + + int num_of_coll =4; + + uint8_t *d_p = cmp_ent_get_data_buf(ent); + uint32_t sum =0; + s =0; + for (int c = 1; c <= num_of_coll ; c++) { + uint16_t cmp_col_size; + if (c == num_of_coll) + cmp_col_size = cmp_ent_get_cmp_data_size(ent)- sum; + else{ + cmp_col_size = get_cmp_size(&d_p[s]); + sum += cmp_col_size; + s+=2; + } + + uint16_t col_size = cmp_col_get_data_length(&d_p[s]); + printf("cmp_col_sizel: %X col_size: %X\n", cmp_col_size, col_size); + for (int i = s-2; i < s+col_size +COLLECTION_HDR_SIZE; ++i) { + printf("%02X ",((uint8_t *)d_p)[i]); + if ((i + 1) % 2 == 0) + printf("\n"); + } + TEST_ASSERT(cmp_col_size == col_size); + s+=col_size+COLLECTION_HDR_SIZE; + } + +} +#endif +#if 0 +/* #include "../../lib/common/byteorder.h" */ +void NOOO_test_cmp_collection_raw(void) +{ + struct collection_hdr *col = NULL; + uint32_t samples = 2; + size_t col_size, dst_capacity = 0; + struct s_fx *data; + uint32_t *dst = NULL; + int dst_capacity_used = 0; + struct cmp_par par = {0}; + const size_t exp_col_size = COLLECTION_HDR_SIZE+2*sizeof(struct s_fx); + const size_t exp_cmp_size_byte = exp_col_size; + + par.cmp_mode = CMP_MODE_RAW; + + col_size = generate_random_collection(col, DATA_TYPE_S_FX, samples, &MAX_USED_BITS_SAFE); + TEST_ASSERT_EQUAL(exp_col_size, col_size); + col = malloc(col_size); + TEST_ASSERT_NOT_NULL(col); + col_size = generate_random_collection(col, DATA_TYPE_S_FX, samples, &MAX_USED_BITS_SAFE); + TEST_ASSERT_EQUAL(exp_col_size, col_size); + + data = (struct s_fx *)col->entry; + data[0].exp_flags = 0; + data[0].fx = 0; + data[1].exp_flags = 0xF0; + data[1].fx = 0xABCDE0FF; + + + dst_capacity = (size_t)cmp_collection(col, NULL, dst, dst_capacity, &par, dst_capacity_used); + TEST_ASSERT_EQUAL_INT(exp_cmp_size_byte, dst_capacity); + dst = malloc(dst_capacity); + TEST_ASSERT_NOT_NULL(dst); + dst_capacity_used = cmp_collection(col, NULL, dst, dst_capacity, &par, dst_capacity_used); + TEST_ASSERT_EQUAL_INT(exp_cmp_size_byte, dst_capacity_used); + + { + uint8_t *p = (uint8_t *)dst; + struct collection_hdr *raw_cmp_col = (struct collection_hdr *)p; + struct s_fx *raw_cmp_data = (void *)raw_cmp_col->entry; + + /* TEST_ASSERT_EQUAL_UINT(cpu_to_be16(2*sizeof(struct s_fx)), ((uint16_t *)p)[0]); */ + TEST_ASSERT(memcmp(col, raw_cmp_col, COLLECTION_HDR_SIZE) == 0); + TEST_ASSERT_EQUAL_HEX(data[0].exp_flags, raw_cmp_data[0].exp_flags); + TEST_ASSERT_EQUAL_HEX(data[0].fx, be32_to_cpu(raw_cmp_data[0].fx)); + TEST_ASSERT_EQUAL_HEX(data[1].exp_flags, raw_cmp_data[1].exp_flags); + TEST_ASSERT_EQUAL_HEX(data[1].fx, be32_to_cpu(raw_cmp_data[1].fx)); + } + + memset(dst, 0, dst_capacity); + + dst_capacity -= 1; + dst_capacity_used = cmp_collection(col, NULL, dst, dst_capacity, &par, dst_capacity_used); + TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, dst_capacity_used); + + free(col); + free(dst); +} + + +void NOOO_test_cmp_collection_diff(void) +{ + struct collection_hdr *col = NULL; + uint32_t *dst = NULL; + size_t dst_capacity = 0; + int dst_capacity_used = 33; + struct cmp_par par = {0}; + const uint16_t cmp_size_byte_exp= 2; + + + { /* generate test data */ + struct s_fx *data; + uint32_t samples = 2; + size_t col_size; + const size_t exp_col_size = COLLECTION_HDR_SIZE+samples*sizeof(*data); + + col_size = generate_random_collection(col, DATA_TYPE_S_FX, samples, &MAX_USED_BITS_SAFE); + TEST_ASSERT_EQUAL(exp_col_size, col_size); + col = malloc(col_size); TEST_ASSERT_NOT_NULL(col); + col_size = generate_random_collection(col, DATA_TYPE_S_FX, samples, &MAX_USED_BITS_SAFE); + TEST_ASSERT_EQUAL(exp_col_size, col_size); + + data = (struct s_fx *)col->entry; + data[0].exp_flags = 0; + data[0].fx = 0; + data[1].exp_flags = 1; + data[1].fx = 1; + } + + { /* compress data */ + int cmp_size_byte; + const int exp_cmp_size_byte = dst_capacity_used + CMP_COLLECTION_FILD_SIZE + + COLLECTION_HDR_SIZE + cmp_size_byte_exp;; + + par.cmp_mode = CMP_MODE_DIFF_ZERO; + par.s_exp_flags = 1; + par.s_fx = 1; + + cmp_size_byte = cmp_collection(col, NULL, dst, dst_capacity, &par, dst_capacity_used); + TEST_ASSERT_EQUAL_INT(exp_cmp_size_byte, cmp_size_byte); + dst_capacity = (size_t)ROUND_UP_TO_MULTIPLE_OF_4(cmp_size_byte); + dst = malloc(dst_capacity); TEST_ASSERT_NOT_NULL(dst); + memset(dst, 0xFF, dst_capacity); + cmp_size_byte = cmp_collection(col, NULL, dst, dst_capacity, &par, dst_capacity_used); + TEST_ASSERT_EQUAL_INT(exp_cmp_size_byte, cmp_size_byte); + } + + { /* check the compressed data */ + uint8_t *p = (uint8_t *)dst; + uint16_t cmp_collection_size_exp = cpu_to_be16(cmp_size_byte_exp); + + TEST_ASSERT_EACH_EQUAL_HEX8(0xFF, p, dst_capacity_used); + p += dst_capacity_used; + + TEST_ASSERT_EQUAL_HEX8_ARRAY(&cmp_collection_size_exp, p, CMP_COLLECTION_FILD_SIZE); + p += CMP_COLLECTION_FILD_SIZE; + + TEST_ASSERT(memcmp(col, p, COLLECTION_HDR_SIZE) == 0); + p += COLLECTION_HDR_SIZE; + + TEST_ASSERT_EQUAL_HEX8(0xAE, *p++); + TEST_ASSERT_EQUAL_HEX8(0xE0, *p++); + TEST_ASSERT_EQUAL_HEX8(0x00, *p++); + TEST_ASSERT_EQUAL_HEX8(0x00, *p++); + TEST_ASSERT_EQUAL_HEX8(0x00, *p++); + + TEST_ASSERT_EQUAL_size_t(dst_capacity, p - (uint8_t *)dst); + } + + + /* error cases dst buffer to small */ + dst_capacity -= 1; + dst_capacity_used = cmp_collection(col, NULL, dst, dst_capacity, &par, dst_capacity_used); + TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, dst_capacity_used); + + free(col); + free(dst); +} + + +void NOOO_test_cmp_collection_worst_case(void) +{ + struct collection_hdr *col = NULL; + uint32_t *dst = NULL; + size_t dst_capacity = 0; + int dst_capacity_used = 4; + struct cmp_par par = {0}; + const uint16_t cmp_size_byte_exp= 2*sizeof(struct s_fx); + int cmp_size_byte; + + { /* generate test data */ + struct s_fx *data; + uint32_t samples = 2; + size_t col_size; + const size_t exp_col_size = COLLECTION_HDR_SIZE+samples*sizeof(*data); + + col_size = generate_random_collection(col, DATA_TYPE_S_FX, samples, &MAX_USED_BITS_SAFE); + TEST_ASSERT_EQUAL(exp_col_size, col_size); + col = malloc(col_size); TEST_ASSERT_NOT_NULL(col); + col_size = generate_random_collection(col, DATA_TYPE_S_FX, samples, &MAX_USED_BITS_SAFE); + TEST_ASSERT_EQUAL(exp_col_size, col_size); + + data = (struct s_fx *)col->entry; + data[0].exp_flags = 0x4; + data[0].fx = 0x0000000E; + data[1].exp_flags = 0x4; + data[1].fx = 0x00000016; +; + } + + { /* compress data */ + const int exp_cmp_size_byte = dst_capacity_used + CMP_COLLECTION_FILD_SIZE + + COLLECTION_HDR_SIZE + cmp_size_byte_exp;; + + par.cmp_mode = CMP_MODE_DIFF_ZERO; + par.s_exp_flags = 1; + par.s_fx = 1; + + cmp_size_byte = cmp_collection(col, NULL, dst, dst_capacity, &par, dst_capacity_used); + TEST_ASSERT_EQUAL_INT(exp_cmp_size_byte, cmp_size_byte); + dst_capacity = 1000; + dst = malloc(dst_capacity); TEST_ASSERT_NOT_NULL(dst); + memset(dst, 0xFF, dst_capacity); + cmp_size_byte = cmp_collection(col, NULL, dst, dst_capacity, &par, dst_capacity_used); + TEST_ASSERT_EQUAL_INT(exp_cmp_size_byte, cmp_size_byte); + } + + { /* check the compressed data */ + uint8_t *p = (uint8_t *)dst; + uint16_t cmp_collection_size_exp = cpu_to_be16(cmp_size_byte_exp); + + TEST_ASSERT_EACH_EQUAL_HEX8(0xFF, p, dst_capacity_used); + p += dst_capacity_used; + + TEST_ASSERT_EQUAL_HEX8_ARRAY(&cmp_collection_size_exp, p, CMP_COLLECTION_FILD_SIZE); + p += CMP_COLLECTION_FILD_SIZE; + + TEST_ASSERT(memcmp(col, p, COLLECTION_HDR_SIZE) == 0); + p += COLLECTION_HDR_SIZE; + + TEST_ASSERT_EQUAL_HEX8(0x04, *p++); + TEST_ASSERT_EQUAL_HEX8(0x00, *p++); + TEST_ASSERT_EQUAL_HEX8(0x00, *p++); + TEST_ASSERT_EQUAL_HEX8(0x00, *p++); + TEST_ASSERT_EQUAL_HEX8(0x0E, *p++); + TEST_ASSERT_EQUAL_HEX8(0x04, *p++); + TEST_ASSERT_EQUAL_HEX8(0x00, *p++); + TEST_ASSERT_EQUAL_HEX8(0x00, *p++); + TEST_ASSERT_EQUAL_HEX8(0x00, *p++); + TEST_ASSERT_EQUAL_HEX8(0x16, *p++); + + TEST_ASSERT_EQUAL_size_t(cmp_size_byte, p - (uint8_t *)dst); + } +} +#endif + + +void test_cmp_chunk_raw2(void) +{ + struct cmp_par par = {0}; + struct chunk_def chunk_def[2] = {{DATA_TYPE_S_FX, 2}, {DATA_TYPE_S_FX_EFX_NCOB_ECOB, 3}}; + size_t chunk_size; + size_t chunk_size_exp = 2*sizeof(struct s_fx) + 3*sizeof(struct s_fx_efx_ncob_ecob) + 2*COLLECTION_HDR_SIZE; + void *chunk = NULL; + uint32_t *dst = NULL; + int dst_capacity = 0; + + /* generate test data */ + chunk_size = generate_random_chunk(chunk, chunk_def, ARRAY_SIZE(chunk_def), &MAX_USED_BITS_SAFE); + TEST_ASSERT_EQUAL_size_t(chunk_size_exp, chunk_size); + chunk = calloc(1, chunk_size); + TEST_ASSERT_NOT_NULL(chunk); + chunk_size = generate_random_chunk(chunk, chunk_def, ARRAY_SIZE(chunk_def), &MAX_USED_BITS_SAFE); + TEST_ASSERT_EQUAL_size_t(chunk_size_exp, chunk_size); + + /* "compress" data */ + { + size_t cmp_size_byte_exp = GENERIC_HEADER_SIZE + chunk_size_exp; + + par.cmp_mode = CMP_MODE_RAW; + + dst_capacity = compress_chunk(chunk, chunk_size, NULL, NULL, dst, dst_capacity, &par); + TEST_ASSERT_EQUAL_INT(cmp_size_byte_exp, dst_capacity); + dst = calloc(1, dst_capacity); + TEST_ASSERT_NOT_NULL(dst); + dst_capacity = compress_chunk(chunk, chunk_size, NULL, NULL, dst, dst_capacity, &par); + TEST_ASSERT_EQUAL_INT(cmp_size_byte_exp, dst_capacity); + } + + /* check results */ + { + uint8_t *p = (uint8_t *)dst; + /* uint16_t cmp_collection_size_exp = cpu_to_be16(2*sizeof(struct s_fx)); */ + struct collection_hdr *col = (struct collection_hdr *)chunk; + struct s_fx *cmp_data_raw_1; + struct s_fx *data = (void *)col->entry; + int i; + + /* TODO: Check header */ + TEST_ASSERT_EQUAL_HEX(chunk_size, cmp_ent_get_original_size(dst)); + TEST_ASSERT_EQUAL_HEX(chunk_size+GENERIC_HEADER_SIZE, cmp_ent_get_size(dst)); + + p += GENERIC_HEADER_SIZE; + + + /* TEST_ASSERT(memcmp(p, &cmp_collection_size_exp, CMP_COLLECTION_FILD_SIZE) == 0); */ + /* p += CMP_COLLECTION_FILD_SIZE; */ + + TEST_ASSERT(memcmp(col, p, COLLECTION_HDR_SIZE) == 0); + p += COLLECTION_HDR_SIZE; + + cmp_data_raw_1 = (struct s_fx *)p; + TEST_ASSERT_EQUAL_HEX(data[0].exp_flags, cmp_data_raw_1[0].exp_flags); + TEST_ASSERT_EQUAL_HEX(data[0].fx, be32_to_cpu(cmp_data_raw_1[0].fx)); + TEST_ASSERT_EQUAL_HEX(data[1].exp_flags, cmp_data_raw_1[1].exp_flags); + TEST_ASSERT_EQUAL_HEX(data[1].fx, be32_to_cpu(cmp_data_raw_1[1].fx)); + p += 2*sizeof(struct s_fx); + + /* check 2nd collection */ + /* cmp_collection_size_exp = cpu_to_be16(3*sizeof(struct s_fx_efx_ncob_ecob)); */ + /* TEST_ASSERT(memcmp(p, &cmp_collection_size_exp, CMP_COLLECTION_FILD_SIZE) == 0); */ + /* p += CMP_COLLECTION_FILD_SIZE; */ + + col = (struct collection_hdr *) ((char *)col + cmp_col_get_size(col)); + TEST_ASSERT(memcmp(col, p, COLLECTION_HDR_SIZE) == 0); + p += COLLECTION_HDR_SIZE; + + for (i = 0; i < 3; i++) { + struct s_fx_efx_ncob_ecob *raw_cmp_data2 = (struct s_fx_efx_ncob_ecob *)p; + struct s_fx_efx_ncob_ecob *data2 = (struct s_fx_efx_ncob_ecob *)col->entry; + + TEST_ASSERT_EQUAL_HEX(data2[i].exp_flags, raw_cmp_data2[i].exp_flags); + TEST_ASSERT_EQUAL_HEX(data2[i].fx, be32_to_cpu(raw_cmp_data2[i].fx)); + TEST_ASSERT_EQUAL_HEX(data2[i].efx, be32_to_cpu(raw_cmp_data2[i].efx)); + TEST_ASSERT_EQUAL_HEX(data2[i].ncob_x, be32_to_cpu(raw_cmp_data2[i].ncob_x)); + TEST_ASSERT_EQUAL_HEX(data2[i].ncob_y, be32_to_cpu(raw_cmp_data2[i].ncob_y)); + TEST_ASSERT_EQUAL_HEX(data2[i].ecob_x, be32_to_cpu(raw_cmp_data2[i].ecob_x)); + TEST_ASSERT_EQUAL_HEX(data2[i].ecob_y, be32_to_cpu(raw_cmp_data2[i].ecob_y)); + } + } + { + void *decompressed_data = NULL; + int decmp_size = decompress_cmp_entiy((void *)dst, NULL, NULL, decompressed_data); + TEST_ASSERT_EQUAL_size_t(chunk_size, decmp_size); + decompressed_data = malloc((size_t)decmp_size); TEST_ASSERT_NOT_NULL(decompressed_data); + decmp_size = decompress_cmp_entiy((void *)dst, NULL, NULL, decompressed_data); + + TEST_ASSERT_EQUAL_INT(chunk_size, decmp_size); + TEST_ASSERT_EQUAL_HEX8_ARRAY(chunk, decompressed_data, chunk_size); + } + + /* error cases */ + memset(dst, 0, dst_capacity); + + /* buffer to small for compressed data */ + dst_capacity -=1 ; + dst_capacity = compress_chunk(chunk, chunk_size, NULL, NULL, dst, dst_capacity, &par); + TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, dst_capacity); + + free(chunk); +} + + +void test_cmp_decmp_chunk_worst_case(void) +{ + struct chunk_def chunk_def[2] = {{DATA_TYPE_S_FX, 2}, {DATA_TYPE_S_FX_EFX_NCOB_ECOB, 3}}; + uint32_t chunk_size; + enum {CHUNK_SIZE_EXP = 2*sizeof(struct s_fx) + 3*sizeof(struct s_fx_efx_ncob_ecob) + 2*COLLECTION_HDR_SIZE}; + void *chunk = NULL; + uint32_t dst[COMPRESS_CHUNK_BOUND(CHUNK_SIZE_EXP, ARRAY_SIZE(chunk_def))/sizeof(uint32_t)]; + int cmp_size_byte = 0; + struct cmp_par par = {0}; + + /* generate test data */ + chunk_size = (uint32_t)generate_random_chunk(chunk, chunk_def, ARRAY_SIZE(chunk_def), &MAX_USED_BITS_SAFE); + TEST_ASSERT_EQUAL_size_t(CHUNK_SIZE_EXP, chunk_size); + chunk = calloc(1, chunk_size); + TEST_ASSERT_NOT_NULL(chunk); + chunk_size = (uint32_t)generate_random_chunk(chunk, chunk_def, ARRAY_SIZE(chunk_def), &MAX_USED_BITS_SAFE); + TEST_ASSERT_EQUAL_size_t(CHUNK_SIZE_EXP, chunk_size); + + /* "compress" data */ + { + size_t cmp_size_byte_exp = NON_IMAGETTE_HEADER_SIZE + 2*CMP_COLLECTION_FILD_SIZE + CHUNK_SIZE_EXP; + + par.cmp_mode = CMP_MODE_DIFF_ZERO; + par.s_exp_flags = 1; + par.s_fx = 1; + par.s_efx = 1; + par.s_ncob = 1; + par.s_ecob = 1; + + + TEST_ASSERT_NOT_NULL(dst); + cmp_size_byte = compress_chunk(chunk, chunk_size, NULL, NULL, dst, sizeof(dst), &par); + TEST_ASSERT_EQUAL_INT(cmp_size_byte_exp, cmp_size_byte); + } + + /* check results */ + { + uint8_t *p = (uint8_t *)dst; + uint16_t cmp_collection_size_exp = cpu_to_be16(2*sizeof(struct s_fx)); + struct collection_hdr *col = (struct collection_hdr *)chunk; + struct s_fx *cmp_data_raw_1; + struct s_fx *data = (void *)col->entry; + int i; + + /* TODO: Check header */ + p += NON_IMAGETTE_HEADER_SIZE; + + TEST_ASSERT_EQUAL_HEX8_ARRAY(&cmp_collection_size_exp, p, CMP_COLLECTION_FILD_SIZE); + p += CMP_COLLECTION_FILD_SIZE; + + TEST_ASSERT(memcmp(col, p, COLLECTION_HDR_SIZE) == 0); + p += COLLECTION_HDR_SIZE; + + cmp_data_raw_1 = (struct s_fx *)p; + TEST_ASSERT_EQUAL_HEX(data[0].exp_flags, cmp_data_raw_1[0].exp_flags); + TEST_ASSERT_EQUAL_HEX(data[0].fx, be32_to_cpu(cmp_data_raw_1[0].fx)); + TEST_ASSERT_EQUAL_HEX(data[1].exp_flags, cmp_data_raw_1[1].exp_flags); + TEST_ASSERT_EQUAL_HEX(data[1].fx, be32_to_cpu(cmp_data_raw_1[1].fx)); + p += 2*sizeof(struct s_fx); + + /* check 2nd collection */ + cmp_collection_size_exp = cpu_to_be16(3*sizeof(struct s_fx_efx_ncob_ecob)); + TEST_ASSERT(memcmp(p, &cmp_collection_size_exp, CMP_COLLECTION_FILD_SIZE) == 0); + p += CMP_COLLECTION_FILD_SIZE; + + col = (struct collection_hdr *) ((char *)col + cmp_col_get_size(col)); + TEST_ASSERT(memcmp(col, p, COLLECTION_HDR_SIZE) == 0); + p += COLLECTION_HDR_SIZE; + + for (i = 0; i < 3; i++) { + struct s_fx_efx_ncob_ecob *raw_cmp_data2 = (struct s_fx_efx_ncob_ecob *)p; + struct s_fx_efx_ncob_ecob *data2 = (struct s_fx_efx_ncob_ecob *)col->entry; + + TEST_ASSERT_EQUAL_HEX(data2[i].exp_flags, raw_cmp_data2[i].exp_flags); + TEST_ASSERT_EQUAL_HEX(data2[i].fx, be32_to_cpu(raw_cmp_data2[i].fx)); + TEST_ASSERT_EQUAL_HEX(data2[i].efx, be32_to_cpu(raw_cmp_data2[i].efx)); + TEST_ASSERT_EQUAL_HEX(data2[i].ncob_x, be32_to_cpu(raw_cmp_data2[i].ncob_x)); + TEST_ASSERT_EQUAL_HEX(data2[i].ncob_y, be32_to_cpu(raw_cmp_data2[i].ncob_y)); + TEST_ASSERT_EQUAL_HEX(data2[i].ecob_x, be32_to_cpu(raw_cmp_data2[i].ecob_x)); + TEST_ASSERT_EQUAL_HEX(data2[i].ecob_y, be32_to_cpu(raw_cmp_data2[i].ecob_y)); + } + } + { + void *decompressed_data = NULL; + int decmp_size = decompress_cmp_entiy((void *)dst, NULL, NULL, decompressed_data); + TEST_ASSERT_EQUAL_size_t(chunk_size, decmp_size); + decompressed_data = malloc((size_t)decmp_size); TEST_ASSERT_NOT_NULL(decompressed_data); + decmp_size = decompress_cmp_entiy((void *)dst, NULL, NULL, decompressed_data); + + TEST_ASSERT_EQUAL_INT(chunk_size, decmp_size); + TEST_ASSERT_EQUAL_HEX8_ARRAY(chunk, decompressed_data, chunk_size); + } + + /* error cases */ + memset(dst, 0, sizeof(dst)); + + /* buffer to small for compressed data */ + cmp_size_byte = compress_chunk(chunk, chunk_size, NULL, NULL, dst, chunk_size, &par); + TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, cmp_size_byte); + + free(chunk); +} + + +void test_cmp_decmp_diff(void) +{ + struct chunk_def chunk_def[2] = {{DATA_TYPE_S_FX, 2}, {DATA_TYPE_S_FX_EFX_NCOB_ECOB, 3}}; + size_t chunk_size; + void *chunk = NULL; + uint32_t *dst = NULL; + int dst_capacity = 0; + + /* generate test data */ + { + struct s_fx *col_data1; + struct s_fx_efx_ncob_ecob *col_data2; + struct collection_hdr *col; + size_t chunk_size_exp = 2*sizeof(struct s_fx) + 3*sizeof(struct s_fx_efx_ncob_ecob) + 2*COLLECTION_HDR_SIZE; + + chunk_size = generate_random_chunk(chunk, chunk_def, ARRAY_SIZE(chunk_def), &MAX_USED_BITS_SAFE); + TEST_ASSERT_EQUAL_size_t(chunk_size_exp, chunk_size); + chunk = calloc(1, chunk_size); + TEST_ASSERT_NOT_NULL(chunk); + chunk_size = generate_random_chunk(chunk, chunk_def, ARRAY_SIZE(chunk_def), &MAX_USED_BITS_SAFE); + TEST_ASSERT_EQUAL_size_t(chunk_size_exp, chunk_size); + + col = (struct collection_hdr *)chunk; + col_data1 = (struct s_fx *)(col->entry); + col_data1[0].exp_flags = 0; + col_data1[0].fx = 0; + col_data1[1].exp_flags = 1; + col_data1[1].fx = 1; + + col = (struct collection_hdr *)((char *)col + cmp_col_get_size(col)); + col_data2 = (struct s_fx_efx_ncob_ecob *)(col->entry); + col_data2[0].exp_flags = 0; + col_data2[0].fx = 1; + col_data2[0].efx = 2; + col_data2[0].ncob_x = 0; + col_data2[0].ncob_y = 1; + col_data2[0].ecob_x = 3; + col_data2[0].ecob_y = 7; + col_data2[1].exp_flags = 1; + col_data2[1].fx = 1; + col_data2[1].efx = 1; + col_data2[1].ncob_x = 1; + col_data2[1].ncob_y = 2; + col_data2[1].ecob_x = 1; + col_data2[1].ecob_y = 1; + col_data2[2].exp_flags = 2; + col_data2[2].fx = 2; + col_data2[2].efx = 2; + col_data2[2].ncob_x = 2; + col_data2[2].ncob_y = 45; + col_data2[2].ecob_x = 2; + col_data2[2].ecob_y = 2; + } + + + /* compress data */ + { + struct cmp_par par = {0}; + + par.cmp_mode = CMP_MODE_DIFF_ZERO; + par.s_exp_flags = 1; + par.s_fx = 2; + par.s_efx = 3; + par.s_ncob = 4; + par.s_ecob = 5; + + + dst_capacity = compress_chunk(chunk, chunk_size, NULL, NULL, dst, dst_capacity, &par); + TEST_ASSERT_GREATER_THAN_INT(0, dst_capacity); + /* TODO: */ dst_capacity = ROUND_UP_TO_MULTIPLE_OF_4(dst_capacity); + dst = malloc(dst_capacity); + TEST_ASSERT_NOT_NULL(dst); + dst_capacity = compress_chunk(chunk, chunk_size, NULL, NULL, dst, dst_capacity, &par); + TEST_ASSERT_GREATER_THAN_INT(0, dst_capacity); + } + { + void *decompressed_data = NULL; + int decmp_size = decompress_cmp_entiy((void *)dst, NULL, NULL, + decompressed_data); + TEST_ASSERT_EQUAL_size_t(chunk_size, decmp_size); + decompressed_data = malloc((size_t)decmp_size); TEST_ASSERT_NOT_NULL(decompressed_data); + decmp_size = decompress_cmp_entiy((void *)dst, NULL, NULL, + decompressed_data); + + TEST_ASSERT_EQUAL_INT(chunk_size, decmp_size); + TEST_ASSERT_EQUAL_HEX8_ARRAY(chunk, decompressed_data, chunk_size); + } +} diff --git a/test/cmp_entity/test_cmp_entity.c b/test/cmp_entity/test_cmp_entity.c index a36c92d6c8853846197fd73b319713f7c17e9e33..5bd6b1ef9297218cee9275da673b76a4a9071c51 100644 --- a/test/cmp_entity/test_cmp_entity.c +++ b/test/cmp_entity/test_cmp_entity.c @@ -30,6 +30,7 @@ #include <cmp_entity.h> #include <cmp_data_types.h> +#include <decmp.h> /** @@ -44,9 +45,7 @@ void test_cmp_ent_cal_hdr_size(void) /* raw_mode test */ raw_mode_flag = 1; - /*TODO: implement: DATA_TYPE_F_CAM_OFFSET, DATA_TYPE_F_CAM_BACKGROUND */ - /* for (data_type = DATA_TYPE_IMAGETTE; data_type <= DATA_TYPE_F_CAM_BACKGROUND; data_type++) { */ - for (data_type = DATA_TYPE_IMAGETTE; data_type <= DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE; data_type++) { + for (data_type = DATA_TYPE_IMAGETTE; data_type <= DATA_TYPE_F_CAM_BACKGROUND; data_type++) { hdr_size = cmp_ent_cal_hdr_size(data_type, raw_mode_flag); TEST_ASSERT_EQUAL_INT(GENERIC_HEADER_SIZE, hdr_size); @@ -209,7 +208,7 @@ void test_ent_start_timestamp(void) uint16_t fine_start_timestamp_read; uint8_t *entity_p = (uint8_t *)&ent; - start_timestamp = 0x123456789ABC; + start_timestamp = 0x123456789ABCULL; error = cmp_ent_set_start_timestamp(&ent, start_timestamp); TEST_ASSERT_FALSE(error); @@ -230,7 +229,7 @@ void test_ent_start_timestamp(void) TEST_ASSERT_EQUAL_UINT64(0x9ABC, fine_start_timestamp_read); /* error cases */ - start_timestamp = 0x1000000000000; + start_timestamp = 0x1000000000000ULL; error = cmp_ent_set_start_timestamp(&ent, start_timestamp); TEST_ASSERT_TRUE(error); error = cmp_ent_set_start_timestamp(NULL, start_timestamp); @@ -321,7 +320,7 @@ void test_ent_end_timestamp(void) uint16_t fine_end_timestamp_read; uint8_t *entity_p = (uint8_t *)&ent; - end_timestamp = 0x123456789ABC; + end_timestamp = 0x123456789ABCULL; error = cmp_ent_set_end_timestamp(&ent, end_timestamp); TEST_ASSERT_FALSE(error); @@ -342,7 +341,7 @@ void test_ent_end_timestamp(void) TEST_ASSERT_EQUAL_UINT64(0x9ABC, fine_end_timestamp_read); /* error cases */ - end_timestamp = 0x1000000000000; + end_timestamp = 0x1000000000000ULL; error = cmp_ent_set_end_timestamp(&ent, end_timestamp); TEST_ASSERT_TRUE(error); error = cmp_ent_set_end_timestamp(NULL, end_timestamp); @@ -432,8 +431,8 @@ void test_cmp_ent_data_type(void) int raw_mode_flag, raw_mode_flag_read; uint8_t *entity_p = (uint8_t *)&ent; - /* test non raw_mode */ - raw_mode_flag = 0; + /* test raw_mode */ + raw_mode_flag = 1; data_type = DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE; error = cmp_ent_set_data_type(&ent, data_type, raw_mode_flag); TEST_ASSERT_FALSE(error); @@ -444,11 +443,11 @@ void test_cmp_ent_data_type(void) TEST_ASSERT_EQUAL(raw_mode_flag, raw_mode_flag_read); /* check the right position in the header */ - TEST_ASSERT_EQUAL_HEX(0, entity_p[22]); + TEST_ASSERT_EQUAL_HEX(0x80, entity_p[22]); TEST_ASSERT_EQUAL_HEX(21, entity_p[23]); - /* test raw_mode */ - raw_mode_flag = 1; + /* test non raw_mode */ + raw_mode_flag = 0; data_type = DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE; error = cmp_ent_set_data_type(&ent, data_type, raw_mode_flag); TEST_ASSERT_FALSE(error); @@ -459,9 +458,10 @@ void test_cmp_ent_data_type(void) TEST_ASSERT_EQUAL(raw_mode_flag, raw_mode_flag_read); /* check the right position in the header */ - TEST_ASSERT_EQUAL_HEX(0x80, entity_p[22]); + TEST_ASSERT_EQUAL_HEX(0, entity_p[22]); TEST_ASSERT_EQUAL_HEX(21, entity_p[23]); + /* error cases */ raw_mode_flag = 0; data_type = 0x8000; @@ -1294,14 +1294,14 @@ void test_ent_non_ima_cmp_par6(void) void test_cmp_ent_get_data_buf(void) { - enum cmp_data_type data_type;/*TODO: implement: DATA_TYPE_F_CAM_OFFSET, DATA_TYPE_F_CAM_BACKGROUND */ + enum cmp_data_type data_type; struct cmp_entity ent = {0}; char *adr; uint32_t s, hdr_size; int error; for (data_type = DATA_TYPE_IMAGETTE; - data_type <= DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE; + data_type <= DATA_TYPE_F_CAM_BACKGROUND; data_type++) { s = cmp_ent_create(&ent, data_type, 0, 0); TEST_ASSERT_NOT_EQUAL_INT(0, s); @@ -1315,7 +1315,7 @@ void test_cmp_ent_get_data_buf(void) /* RAW mode test */ for (data_type = DATA_TYPE_IMAGETTE; - data_type <= DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE; + data_type <= DATA_TYPE_F_CAM_BACKGROUND; data_type++) { s = cmp_ent_create(&ent, data_type, 1, 0); TEST_ASSERT_NOT_EQUAL_INT(0, s); @@ -1422,8 +1422,6 @@ void test_cmp_ent_get_cmp_data_size(void) } - - /** * @test cmp_ent_write_rdcu_cmp_pars */ @@ -1859,6 +1857,15 @@ void test_cmp_ent_build(void) TEST_ASSERT_EQUAL_INT(cfg.ap2_spill, cmp_ent_get_ima_ap2_spill(ent)); TEST_ASSERT_EQUAL_INT(cfg.ap2_golomb_par, cmp_ent_get_ima_ap2_golomb_par(ent)); + /* entity size is smaller than */ + cmp_size_bits = 2; + size = cmp_ent_build(NULL, version_id, start_time, end_time, model_id, + model_counter, &cfg, cmp_size_bits); + TEST_ASSERT_EQUAL_UINT(IMAGETTE_ADAPTIVE_HEADER_SIZE+cmp_bit_to_byte((unsigned int)cmp_size_bits), size); + size = cmp_ent_build(ent, version_id, start_time, end_time, model_id, + model_counter, &cfg, cmp_size_bits); + TEST_ASSERT_EQUAL_UINT(IMAGETTE_ADAPTIVE_HEADER_SIZE+cmp_bit_to_byte((unsigned int)cmp_size_bits), size); + /** error cases **/ /* cfg = NULL */ size = cmp_ent_build(NULL, version_id, start_time, end_time, model_id, @@ -1888,23 +1895,23 @@ void test_cmp_ent_build(void) #endif /* start_time to high */ - start_time = 0x1000000000000; + start_time = 0x1000000000000ULL; size = cmp_ent_build(ent, version_id, start_time, end_time, model_id, model_counter, &cfg, cmp_size_bits); TEST_ASSERT_EQUAL_UINT(0, size); /* this should work */ - start_time = 0xFFFFFFFFFFFF; + start_time = 0xFFFFFFFFFFFFULL; size = cmp_ent_build(ent, version_id, start_time, end_time, model_id, model_counter, &cfg, cmp_size_bits); TEST_ASSERT_EQUAL_UINT(IMAGETTE_ADAPTIVE_HEADER_SIZE+60, size); /* end_time to high */ - end_time = 0x1000000000000; + end_time = 0x1000000000000ULL; size = cmp_ent_build(ent, version_id, start_time, end_time, model_id, model_counter, &cfg, cmp_size_bits); TEST_ASSERT_EQUAL_UINT(0, size); /* this should work */ - end_time = 0xFFFFFFFFFFFF; + end_time = 0xFFFFFFFFFFFFULL; size = cmp_ent_build(ent, version_id, start_time, end_time, model_id, model_counter, &cfg, cmp_size_bits); TEST_ASSERT_EQUAL_UINT(IMAGETTE_ADAPTIVE_HEADER_SIZE+60, size); diff --git a/test/cmp_icu/meson.build b/test/cmp_icu/meson.build index 9c06d726172c0e6e65e9b0b52cc70608a11a86cc..f92d5ee1ef58c281d453cc92869046d2f887c752 100644 --- a/test/cmp_icu/meson.build +++ b/test/cmp_icu/meson.build @@ -2,25 +2,11 @@ test_case = files('test_cmp_icu.c') test_runner = test_runner_generator.process(test_case) test_cmp_icu = executable('test_cmp_icu', - test_case, test_runner, + test_case, test_runner, include_directories : incdir, - link_with : cmp_lib, + link_with : [cmp_lib, test_common_lib], dependencies : unity_dep, build_by_default : false ) test('cmp_icu Unit Tests', test_cmp_icu) - - -test_case = files('test_decmp.c') -test_runner = test_runner_generator.process(test_case) - -test_decmp = executable('test_decmp', - test_case, test_runner, - include_directories : incdir, - link_with : cmp_lib, - dependencies : unity_dep, - build_by_default : false -) - -test('Decompression Unit Tests', test_decmp) diff --git a/test/cmp_icu/test_cmp_icu.c b/test/cmp_icu/test_cmp_icu.c index 3a338c406c6b163e1d79cc6ef2b5d57f8313ebb8..adc12f04c5aa65d66b94274cc2c5b4b734777c5b 100644 --- a/test/cmp_icu/test_cmp_icu.c +++ b/test/cmp_icu/test_cmp_icu.c @@ -18,6 +18,7 @@ #include <stdlib.h> +#include <leon_inttypes.h> #if defined __has_include # if __has_include(<time.h>) @@ -28,8 +29,11 @@ #endif #include "unity.h" -#include "cmp_icu.h" -#include "../lib/cmp_icu.c" /* this is a hack to test static functions */ +#include "../test_common/test_common.h" + +#include <cmp_icu.h> +#include <cmp_data_types.h> +#include "../../lib/icu_compress/cmp_icu.c" /* this is a hack to test static functions */ /** @@ -38,42 +42,23 @@ void setUp(void) { - unsigned int seed; + uint64_t seed; static int n; #if HAS_TIME_H - seed = time(NULL) * getpid(); + seed = (uint64_t)(time(NULL) ^ getpid() ^ (intptr_t)&setUp); #else seed = 1; #endif if (!n) { n = 1; - srand(seed); - printf("seed: %u\n", seed); + cmp_rand_seed(seed); + printf("seed: %"PRIu64"\n", seed); } } -/** - * @brief generate a random number - * - * @param min minimum value (inclusive) - * @param max maximum value (inclusive) - * - * @returns "random" numbers in the range [M, N] - * - * @see https://c-faq.com/lib/randrange.html - */ - -int random_between(unsigned int min, unsigned int max) -{ - TEST_ASSERT(min < max); - TEST_ASSERT(max-min <= RAND_MAX); - return min + rand() / (RAND_MAX / (max - min + 1) + 1); -} - - /** * @test cmp_cfg_icu_create */ @@ -84,9 +69,7 @@ void test_cmp_cfg_icu_create(void) enum cmp_data_type data_type; enum cmp_mode cmp_mode; uint32_t model_value, lossy_par; - /* TODO: change that when DATA_TYPE_BACKGROUND and - * DATA_TYPE_F_CAM_BACKGROUND are implemented */ - const enum cmp_data_type biggest_data_type = DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE; + const enum cmp_data_type biggest_data_type = DATA_TYPE_F_CAM_BACKGROUND; /* wrong data type tests */ data_type = DATA_TYPE_UNKNOWN; /* not valid data type */ @@ -108,6 +91,7 @@ void test_cmp_cfg_icu_create(void) TEST_ASSERT_EQUAL_INT(CMP_MODE_RAW, cfg.cmp_mode); TEST_ASSERT_EQUAL_INT(0, cfg.model_value); TEST_ASSERT_EQUAL_INT(0, cfg.round); + TEST_ASSERT_EQUAL(&MAX_USED_BITS_SAFE, cfg.max_used_bits); memset(&cfg, 0, sizeof(cfg)); /* this should work */ @@ -117,6 +101,7 @@ void test_cmp_cfg_icu_create(void) TEST_ASSERT_EQUAL_INT(CMP_MODE_RAW, cfg.cmp_mode); TEST_ASSERT_EQUAL_INT(0, cfg.model_value); TEST_ASSERT_EQUAL_INT(0, cfg.round); + TEST_ASSERT_EQUAL(&MAX_USED_BITS_SAFE, cfg.max_used_bits); memset(&cfg, 0, sizeof(cfg)); /* wrong compression mode tests */ @@ -125,7 +110,7 @@ void test_cmp_cfg_icu_create(void) TEST_ASSERT_EQUAL_INT(DATA_TYPE_UNKNOWN, cfg.data_type); memset(&cfg, 0, sizeof(cfg)); - cmp_mode = -1; + cmp_mode = (enum cmp_mode)-1; cfg = cmp_cfg_icu_create(data_type, cmp_mode, model_value, lossy_par); TEST_ASSERT_EQUAL_INT(DATA_TYPE_UNKNOWN, cfg.data_type); memset(&cfg, 0, sizeof(cfg)); @@ -137,6 +122,7 @@ void test_cmp_cfg_icu_create(void) TEST_ASSERT_EQUAL_INT(CMP_MODE_STUFF, cfg.cmp_mode); TEST_ASSERT_EQUAL_INT(0, cfg.model_value); TEST_ASSERT_EQUAL_INT(0, cfg.round); + TEST_ASSERT_EQUAL(&MAX_USED_BITS_SAFE, cfg.max_used_bits); memset(&cfg, 0, sizeof(cfg)); /* wrong model_value tests */ @@ -156,6 +142,7 @@ void test_cmp_cfg_icu_create(void) TEST_ASSERT_EQUAL_INT(CMP_MODE_MODEL_MULTI, cfg.cmp_mode); TEST_ASSERT_EQUAL_INT(16, cfg.model_value); TEST_ASSERT_EQUAL_INT(0, cfg.round); + TEST_ASSERT_EQUAL(&MAX_USED_BITS_SAFE, cfg.max_used_bits); /* no checks for model mode -> no model cmp_mode */ cmp_mode = CMP_MODE_STUFF; @@ -165,6 +152,7 @@ void test_cmp_cfg_icu_create(void) TEST_ASSERT_EQUAL_INT(CMP_MODE_STUFF, cfg.cmp_mode); TEST_ASSERT_EQUAL_INT(MAX_MODEL_VALUE + 1, cfg.model_value); TEST_ASSERT_EQUAL_INT(0, cfg.round); + TEST_ASSERT_EQUAL(&MAX_USED_BITS_SAFE, cfg.max_used_bits); model_value = MAX_MODEL_VALUE; /* wrong lossy_par tests */ @@ -183,17 +171,19 @@ void test_cmp_cfg_icu_create(void) TEST_ASSERT_EQUAL_INT(CMP_MODE_STUFF, cfg.cmp_mode); TEST_ASSERT_EQUAL_INT(16, cfg.model_value); TEST_ASSERT_EQUAL_INT(3, cfg.round); + TEST_ASSERT_EQUAL(&MAX_USED_BITS_SAFE, cfg.max_used_bits); /* random test */ - data_type = random_between(DATA_TYPE_IMAGETTE, biggest_data_type); - cmp_mode = random_between(CMP_MODE_RAW, CMP_MODE_STUFF); - model_value = random_between(0, MAX_MODEL_VALUE); - lossy_par = random_between(CMP_LOSSLESS, MAX_ICU_ROUND); + data_type = cmp_rand_between(DATA_TYPE_IMAGETTE, biggest_data_type); + cmp_mode = cmp_rand_between(CMP_MODE_RAW, CMP_MODE_STUFF); + model_value = cmp_rand_between(0, MAX_MODEL_VALUE); + lossy_par = cmp_rand_between(CMP_LOSSLESS, MAX_ICU_ROUND); cfg = cmp_cfg_icu_create(data_type, cmp_mode, model_value, lossy_par); TEST_ASSERT_EQUAL_INT(data_type, cfg.data_type); TEST_ASSERT_EQUAL_INT(cmp_mode, cfg.cmp_mode); TEST_ASSERT_EQUAL_INT(model_value, cfg.model_value); TEST_ASSERT_EQUAL_INT(lossy_par, cfg.round); + TEST_ASSERT_EQUAL(&MAX_USED_BITS_SAFE, cfg.max_used_bits); } @@ -459,6 +449,34 @@ void test_cmp_cfg_icu_buffers(void) } +/** + * @test cmp_cfg_icu_max_used_bits + */ + +void test_cmp_cfg_icu_max_used_bits(void) +{ + int error; + struct cmp_cfg cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_MODEL_ZERO, 0, CMP_LOSSLESS); + struct cmp_max_used_bits max_used_bits = MAX_USED_BITS_SAFE; + + error = cmp_cfg_icu_max_used_bits(&cfg, &max_used_bits); + TEST_ASSERT_FALSE(error); + TEST_ASSERT_EQUAL(&max_used_bits, cfg.max_used_bits); + + /* error cases */ + max_used_bits.s_fx = 33; /* this value is to big */ + error = cmp_cfg_icu_max_used_bits(&cfg, &max_used_bits); + TEST_ASSERT_TRUE(error); + max_used_bits.s_fx = 1; + + error = cmp_cfg_icu_max_used_bits(NULL, &max_used_bits); + TEST_ASSERT_TRUE(error); + + error = cmp_cfg_icu_max_used_bits(&cfg, NULL); + TEST_ASSERT_TRUE(error); +} + + /** * @test cmp_cfg_icu_imagette */ @@ -1046,6 +1064,7 @@ void test_cmp_cfg_fx_cob(void) TEST_ASSERT_EQUAL_INT(spillover_ecob, cfg.spill_ecob); } + /** * @test cmp_cfg_aux */ @@ -1053,11 +1072,11 @@ void test_cmp_cfg_fx_cob(void) void test_cmp_cfg_aux(void) { struct cmp_cfg cfg; uint32_t cmp_par_mean = 2; - uint32_t spillover_mean = 2; - uint32_t cmp_par_variance = 2; - uint32_t spillover_variance = 2; - uint32_t cmp_par_pixels_error = 2; - uint32_t spillover_pixels_error = 2; + uint32_t spillover_mean = 3; + uint32_t cmp_par_variance = 4; + uint32_t spillover_variance = 5; + uint32_t cmp_par_pixels_error = 6; + uint32_t spillover_pixels_error = 7; int error; enum cmp_data_type data_type; @@ -1067,20 +1086,32 @@ void test_cmp_cfg_aux(void) error = cmp_cfg_aux(&cfg, cmp_par_mean, spillover_mean, cmp_par_variance, spillover_variance, cmp_par_pixels_error, spillover_pixels_error); - if (data_type == DATA_TYPE_OFFSET || - data_type == DATA_TYPE_BACKGROUND || - data_type == DATA_TYPE_SMEARING - /* data_type == DATA_TYPE_F_CAM_OFFSET || */ - /* data_type == DATA_TYPE_F_CAM_BACKGROUND */ - ) { + if (data_type == DATA_TYPE_OFFSET || data_type == DATA_TYPE_F_CAM_OFFSET) { + TEST_ASSERT_FALSE(error); + TEST_ASSERT_EQUAL_INT(data_type, cfg.data_type); + TEST_ASSERT_EQUAL_INT(2, cfg.cmp_par_offset_mean); + TEST_ASSERT_EQUAL_INT(3, cfg.spill_offset_mean); + TEST_ASSERT_EQUAL_INT(4, cfg.cmp_par_offset_variance); + TEST_ASSERT_EQUAL_INT(5, cfg.spill_offset_variance); + } else if (data_type == DATA_TYPE_BACKGROUND || + data_type == DATA_TYPE_F_CAM_BACKGROUND) { + TEST_ASSERT_FALSE(error); + TEST_ASSERT_EQUAL_INT(data_type, cfg.data_type); + TEST_ASSERT_EQUAL_INT(2, cfg.cmp_par_background_mean); + TEST_ASSERT_EQUAL_INT(3, cfg.spill_background_mean); + TEST_ASSERT_EQUAL_INT(4, cfg.cmp_par_background_variance); + TEST_ASSERT_EQUAL_INT(5, cfg.spill_background_variance); + TEST_ASSERT_EQUAL_INT(6, cfg.cmp_par_background_pixels_error); + TEST_ASSERT_EQUAL_INT(7, cfg.spill_background_pixels_error); + } else if (data_type == DATA_TYPE_SMEARING) { TEST_ASSERT_FALSE(error); TEST_ASSERT_EQUAL_INT(data_type, cfg.data_type); - TEST_ASSERT_EQUAL_INT(2, cfg.cmp_par_mean); - TEST_ASSERT_EQUAL_INT(2, cfg.spill_mean); - TEST_ASSERT_EQUAL_INT(2, cfg.cmp_par_variance); - TEST_ASSERT_EQUAL_INT(2, cfg.spill_variance); - TEST_ASSERT_EQUAL_INT(2, cfg.cmp_par_pixels_error); - TEST_ASSERT_EQUAL_INT(2, cfg.spill_pixels_error); + TEST_ASSERT_EQUAL_INT(2, cfg.cmp_par_smearing_mean); + TEST_ASSERT_EQUAL_INT(3, cfg.spill_smearing_mean); + TEST_ASSERT_EQUAL_INT(4, cfg.cmp_par_smearing_variance); + TEST_ASSERT_EQUAL_INT(5, cfg.spill_smearing_variance); + TEST_ASSERT_EQUAL_INT(6, cfg.cmp_par_smearing_pixels_error); + TEST_ASSERT_EQUAL_INT(7, cfg.spill_smearing_pixels_error); } else { TEST_ASSERT_TRUE(error); } @@ -1106,10 +1137,10 @@ void test_cmp_cfg_aux(void) cmp_par_variance, spillover_variance, cmp_par_pixels_error, spillover_pixels_error); TEST_ASSERT_FALSE(error); - TEST_ASSERT_EQUAL_INT(MIN_NON_IMA_GOLOMB_PAR, cfg.cmp_par_mean); - TEST_ASSERT_EQUAL_INT(cmp_icu_max_spill(MIN_NON_IMA_GOLOMB_PAR), cfg.spill_mean); - TEST_ASSERT_EQUAL_INT(MIN_NON_IMA_GOLOMB_PAR, cfg.cmp_par_variance); - TEST_ASSERT_EQUAL_INT(2, cfg.spill_variance); + TEST_ASSERT_EQUAL_INT(MIN_NON_IMA_GOLOMB_PAR, cfg.cmp_par_offset_mean); + TEST_ASSERT_EQUAL_INT(cmp_icu_max_spill(MIN_NON_IMA_GOLOMB_PAR), cfg.spill_offset_mean); + TEST_ASSERT_EQUAL_INT(MIN_NON_IMA_GOLOMB_PAR, cfg.cmp_par_offset_variance); + TEST_ASSERT_EQUAL_INT(2, cfg.spill_offset_variance); /* This should fail */ cmp_par_mean = MIN_NON_IMA_GOLOMB_PAR-1; @@ -1119,6 +1150,59 @@ void test_cmp_cfg_aux(void) TEST_ASSERT_TRUE(error); + /* DATA_TYPE_F_CAM_OFFSET */ + cfg = cmp_cfg_icu_create(DATA_TYPE_F_CAM_OFFSET, CMP_MODE_DIFF_MULTI, 7, CMP_LOSSLESS); + cmp_par_mean = MIN_NON_IMA_GOLOMB_PAR; + spillover_mean = cmp_icu_max_spill(MIN_NON_IMA_GOLOMB_PAR); + cmp_par_variance = MIN_NON_IMA_GOLOMB_PAR; + spillover_variance = MIN_NON_IMA_SPILL; + cmp_par_pixels_error = ~0U; + spillover_pixels_error = ~0U; + + error = cmp_cfg_aux(&cfg, cmp_par_mean, spillover_mean, + cmp_par_variance, spillover_variance, + cmp_par_pixels_error, spillover_pixels_error); + TEST_ASSERT_FALSE(error); + TEST_ASSERT_EQUAL_INT(MIN_NON_IMA_GOLOMB_PAR, cfg.cmp_par_offset_mean); + TEST_ASSERT_EQUAL_INT(cmp_icu_max_spill(MIN_NON_IMA_GOLOMB_PAR), cfg.spill_offset_mean); + TEST_ASSERT_EQUAL_INT(MIN_NON_IMA_GOLOMB_PAR, cfg.cmp_par_offset_variance); + TEST_ASSERT_EQUAL_INT(2, cfg.spill_offset_variance); + + /* This should fail */ + cmp_par_variance = MIN_NON_IMA_GOLOMB_PAR-1; + error = cmp_cfg_aux(&cfg, cmp_par_mean, spillover_mean, + cmp_par_variance, spillover_variance, + cmp_par_pixels_error, spillover_pixels_error); + TEST_ASSERT_TRUE(error); + + + cfg = cmp_cfg_icu_create(DATA_TYPE_BACKGROUND, CMP_MODE_DIFF_ZERO, 7, CMP_LOSSLESS); + cmp_par_mean = MAX_NON_IMA_GOLOMB_PAR; + spillover_mean = cmp_icu_max_spill(MAX_NON_IMA_GOLOMB_PAR); + cmp_par_variance = MIN_NON_IMA_GOLOMB_PAR; + spillover_variance = MIN_NON_IMA_SPILL; + cmp_par_pixels_error = 42; + spillover_pixels_error = 23; + + error = cmp_cfg_aux(&cfg, cmp_par_mean, spillover_mean, + cmp_par_variance, spillover_variance, + cmp_par_pixels_error, spillover_pixels_error); + TEST_ASSERT_FALSE(error); + TEST_ASSERT_EQUAL_INT(MAX_NON_IMA_GOLOMB_PAR, cfg.cmp_par_background_mean); + TEST_ASSERT_EQUAL_INT(cmp_icu_max_spill(MAX_NON_IMA_GOLOMB_PAR), cfg.spill_background_mean); + TEST_ASSERT_EQUAL_INT(MIN_NON_IMA_GOLOMB_PAR, cfg.cmp_par_background_variance); + TEST_ASSERT_EQUAL_INT(MIN_NON_IMA_SPILL, cfg.spill_background_variance); + TEST_ASSERT_EQUAL_INT(42, cfg.cmp_par_background_pixels_error); + TEST_ASSERT_EQUAL_INT(23, cfg.spill_background_pixels_error); + + /* This should fail */ + cmp_par_variance = MIN_NON_IMA_GOLOMB_PAR-1; + error = cmp_cfg_aux(&cfg, cmp_par_mean, spillover_mean, + cmp_par_variance, spillover_variance, + cmp_par_pixels_error, spillover_pixels_error); + TEST_ASSERT_TRUE(error); + + /* DATA_TYPE_BACKGROUND */ cfg = cmp_cfg_icu_create(DATA_TYPE_BACKGROUND, CMP_MODE_DIFF_ZERO, 7, CMP_LOSSLESS); cmp_par_mean = MAX_NON_IMA_GOLOMB_PAR; @@ -1132,12 +1216,12 @@ void test_cmp_cfg_aux(void) cmp_par_variance, spillover_variance, cmp_par_pixels_error, spillover_pixels_error); TEST_ASSERT_FALSE(error); - TEST_ASSERT_EQUAL_INT(MAX_NON_IMA_GOLOMB_PAR, cfg.cmp_par_mean); - TEST_ASSERT_EQUAL_INT(cmp_icu_max_spill(MAX_NON_IMA_GOLOMB_PAR), cfg.spill_mean); - TEST_ASSERT_EQUAL_INT(MIN_NON_IMA_GOLOMB_PAR, cfg.cmp_par_variance); - TEST_ASSERT_EQUAL_INT(MIN_NON_IMA_SPILL, cfg.spill_variance); - TEST_ASSERT_EQUAL_INT(42, cfg.cmp_par_pixels_error); - TEST_ASSERT_EQUAL_INT(23, cfg.spill_pixels_error); + TEST_ASSERT_EQUAL_INT(MAX_NON_IMA_GOLOMB_PAR, cfg.cmp_par_background_mean); + TEST_ASSERT_EQUAL_INT(cmp_icu_max_spill(MAX_NON_IMA_GOLOMB_PAR), cfg.spill_background_mean); + TEST_ASSERT_EQUAL_INT(MIN_NON_IMA_GOLOMB_PAR, cfg.cmp_par_background_variance); + TEST_ASSERT_EQUAL_INT(MIN_NON_IMA_SPILL, cfg.spill_background_variance); + TEST_ASSERT_EQUAL_INT(42, cfg.cmp_par_background_pixels_error); + TEST_ASSERT_EQUAL_INT(23, cfg.spill_background_pixels_error); /* This should fail */ cmp_par_variance = MIN_NON_IMA_GOLOMB_PAR-1; @@ -1147,6 +1231,34 @@ void test_cmp_cfg_aux(void) TEST_ASSERT_TRUE(error); + /* DATA_TYPE_F_CAM_BACKGROUND */ + cfg = cmp_cfg_icu_create(DATA_TYPE_F_CAM_BACKGROUND, CMP_MODE_DIFF_MULTI, 7, CMP_LOSSLESS); + cmp_par_mean = MAX_NON_IMA_GOLOMB_PAR; + spillover_mean = cmp_icu_max_spill(MAX_NON_IMA_GOLOMB_PAR); + cmp_par_variance = MIN_NON_IMA_GOLOMB_PAR; + spillover_variance = MIN_NON_IMA_SPILL; + cmp_par_pixels_error = 42; + spillover_pixels_error = 23; + + error = cmp_cfg_aux(&cfg, cmp_par_mean, spillover_mean, + cmp_par_variance, spillover_variance, + cmp_par_pixels_error, spillover_pixels_error); + TEST_ASSERT_FALSE(error); + TEST_ASSERT_EQUAL_INT(MAX_NON_IMA_GOLOMB_PAR, cfg.cmp_par_background_mean); + TEST_ASSERT_EQUAL_INT(cmp_icu_max_spill(MAX_NON_IMA_GOLOMB_PAR), cfg.spill_background_mean); + TEST_ASSERT_EQUAL_INT(MIN_NON_IMA_GOLOMB_PAR, cfg.cmp_par_background_variance); + TEST_ASSERT_EQUAL_INT(MIN_NON_IMA_SPILL, cfg.spill_background_variance); + TEST_ASSERT_EQUAL_INT(42, cfg.cmp_par_background_pixels_error); + TEST_ASSERT_EQUAL_INT(23, cfg.spill_background_pixels_error); + + /* This should fail */ + cmp_par_pixels_error = MIN_NON_IMA_GOLOMB_PAR-1; + error = cmp_cfg_aux(&cfg, cmp_par_mean, spillover_mean, + cmp_par_variance, spillover_variance, + cmp_par_pixels_error, spillover_pixels_error); + TEST_ASSERT_TRUE(error); + + /* DATA_TYPE_SMEARING */ cfg = cmp_cfg_icu_create(DATA_TYPE_SMEARING, CMP_MODE_DIFF_ZERO, 7, CMP_LOSSLESS); cmp_par_mean = MAX_NON_IMA_GOLOMB_PAR; @@ -1160,12 +1272,12 @@ void test_cmp_cfg_aux(void) cmp_par_variance, spillover_variance, cmp_par_pixels_error, spillover_pixels_error); TEST_ASSERT_FALSE(error); - TEST_ASSERT_EQUAL_INT(MAX_NON_IMA_GOLOMB_PAR, cfg.cmp_par_mean); - TEST_ASSERT_EQUAL_INT(cmp_icu_max_spill(MAX_NON_IMA_GOLOMB_PAR), cfg.spill_mean); - TEST_ASSERT_EQUAL_INT(MIN_NON_IMA_GOLOMB_PAR, cfg.cmp_par_variance); - TEST_ASSERT_EQUAL_INT(MIN_NON_IMA_SPILL, cfg.spill_variance); - TEST_ASSERT_EQUAL_INT(42, cfg.cmp_par_pixels_error); - TEST_ASSERT_EQUAL_INT(23, cfg.spill_pixels_error); + TEST_ASSERT_EQUAL_INT(MAX_NON_IMA_GOLOMB_PAR, cfg.cmp_par_smearing_mean); + TEST_ASSERT_EQUAL_INT(cmp_icu_max_spill(MAX_NON_IMA_GOLOMB_PAR), cfg.spill_smearing_mean); + TEST_ASSERT_EQUAL_INT(MIN_NON_IMA_GOLOMB_PAR, cfg.cmp_par_smearing_variance); + TEST_ASSERT_EQUAL_INT(MIN_NON_IMA_SPILL, cfg.spill_smearing_variance); + TEST_ASSERT_EQUAL_INT(42, cfg.cmp_par_smearing_pixels_error); + TEST_ASSERT_EQUAL_INT(23, cfg.spill_smearing_pixels_error); /* This should fail */ spillover_pixels_error = cmp_icu_max_spill(42)+1; @@ -1173,14 +1285,6 @@ void test_cmp_cfg_aux(void) cmp_par_variance, spillover_variance, cmp_par_pixels_error, spillover_pixels_error); TEST_ASSERT_TRUE(error); - -#if 0 -TODO: implemented F_CAM DATA_TYPE_F_CAM_OFFSET and DATA_TYPE_F_CAM_BACKGROUND - /* DATA_TYPE_F_CAM_OFFSET */ - cfg = cmp_cfg_icu_create(DATA_TYPE_F_CAM_OFFSET, CMP_MODE_DIFF_ZERO, 7, CMP_LOSSLESS); - /* DATA_TYPE_F_CAM_BACKGROUND */ - cfg = cmp_cfg_icu_create(DATA_TYPE_F_CAM_BACKGROUND, CMP_MODE_DIFF_ZERO, 7, CMP_LOSSLESS); -#endif } @@ -1217,7 +1321,7 @@ void test_map_to_pos(void) mapped_value = map_to_pos(value_to_map, max_data_bits); TEST_ASSERT_EQUAL_HEX(UINT32_MAX-1, mapped_value); - value_to_map = INT32_MIN; + value_to_map = (uint32_t)INT32_MIN; mapped_value = map_to_pos(value_to_map, max_data_bits); TEST_ASSERT_EQUAL_HEX(UINT32_MAX, mapped_value); @@ -1377,13 +1481,13 @@ void test_put_n_bits32(void) rval = put_n_bits32(v, n, o, testarray1, l); TEST_ASSERT_EQUAL_INT(1, rval); - TEST_ASSERT(testarray1[0] == 0x7fffffff); + TEST_ASSERT(testarray1[0] == cpu_to_be32(0x7fffffff)); /* left border, write 1 */ v = 1; n = 1; o = 0; rval = put_n_bits32(v, n, o, testarray0, l); TEST_ASSERT_EQUAL_INT(1, rval); - TEST_ASSERT(testarray0[0] == 0x80000000); + TEST_ASSERT(testarray0[0] == cpu_to_be32(0x80000000)); rval = put_n_bits32(v, n, o, testarray1, l); TEST_ASSERT_EQUAL_INT(1, rval); @@ -1393,12 +1497,12 @@ void test_put_n_bits32(void) v = 0xf0f0abcd; n = 32; o = 0; rval = put_n_bits32(v, n, o, testarray0, l); TEST_ASSERT_EQUAL_INT(rval, 32); - TEST_ASSERT(testarray0[0] == 0xf0f0abcd); + TEST_ASSERT(testarray0[0] == cpu_to_be32(0xf0f0abcd)); TEST_ASSERT(testarray0[1] == 0); rval = put_n_bits32(v, n, o, testarray1, l); TEST_ASSERT_EQUAL_INT(rval, 32); - TEST_ASSERT(testarray1[0] == 0xf0f0abcd); + TEST_ASSERT(testarray1[0] == cpu_to_be32(0xf0f0abcd)); TEST_ASSERT(testarray1[1] == 0xffffffff); /* re-init input arrays after clobbering */ init_PB32_arrays(testarray0, testarray1); @@ -1407,7 +1511,7 @@ void test_put_n_bits32(void) v = 3; n = 2; o = 29; rval = put_n_bits32(v, n, o, testarray0, l); TEST_ASSERT_EQUAL_INT(rval, 31); - TEST_ASSERT(testarray0[0] == 0x6); + TEST_ASSERT(testarray0[0] == cpu_to_be32(0x6)); rval = put_n_bits32(v, n, o, testarray1, l); TEST_ASSERT(testarray1[0] == 0xffffffff); @@ -1424,7 +1528,7 @@ void test_put_n_bits32(void) TEST_ASSERT(testarray0[0] == 0); rval = put_n_bits32(v, n, o, testarray1, l); - TEST_ASSERT(testarray1[0] == 0x07ffffff); + TEST_ASSERT(testarray1[0] == cpu_to_be32(0x07ffffff)); TEST_ASSERT_EQUAL_INT(rval, 5); /* re-init input arrays after clobbering */ init_PB32_arrays(testarray0, testarray1); @@ -1433,7 +1537,7 @@ void test_put_n_bits32(void) v = 0x1f; n = 5; o = 0; rval = put_n_bits32(v, n, o, testarray0, l); TEST_ASSERT_EQUAL_INT(rval, 5); - TEST_ASSERT(testarray0[0] == 0xf8000000); + TEST_ASSERT(testarray0[0] == cpu_to_be32(0xf8000000)); rval = put_n_bits32(v, n, o, testarray1, l); TEST_ASSERT_EQUAL_INT(rval, 5); @@ -1449,7 +1553,7 @@ void test_put_n_bits32(void) rval = put_n_bits32(v, n, o, testarray1, l); TEST_ASSERT_EQUAL_INT(rval, 12); - TEST_ASSERT(testarray1[0] == 0xfe0fffff); + TEST_ASSERT(testarray1[0] == cpu_to_be32(0xfe0fffff)); /* re-init input arrays after clobbering */ init_PB32_arrays(testarray0, testarray1); @@ -1457,7 +1561,7 @@ void test_put_n_bits32(void) v = 0x1f; n = 5; o = 7; rval = put_n_bits32(v, n, o, testarray0, l); TEST_ASSERT_EQUAL_INT(rval, 12); - TEST_ASSERT(testarray0[0] == 0x01f00000); + TEST_ASSERT(testarray0[0] == cpu_to_be32(0x01f00000)); rval = put_n_bits32(v, n, o, testarray1, l); TEST_ASSERT_EQUAL_INT(rval, 12); @@ -1477,7 +1581,7 @@ void test_put_n_bits32(void) TEST_ASSERT_EQUAL_INT(rval, 96); TEST_ASSERT(testarray1[0] == 0xffffffff); TEST_ASSERT(testarray1[1] == 0xffffffff); - TEST_ASSERT(testarray1[2] == 0xffffffe0); + TEST_ASSERT(testarray1[2] == cpu_to_be32(0xffffffe0)); /* re-init input arrays after clobbering */ init_PB32_arrays(testarray0, testarray1); @@ -1487,7 +1591,7 @@ void test_put_n_bits32(void) TEST_ASSERT_EQUAL_INT(rval, 96); TEST_ASSERT(testarray0[0] == 0); TEST_ASSERT(testarray0[1] == 0); - TEST_ASSERT(testarray0[2] == 0x0000001f); + TEST_ASSERT(testarray0[2] == cpu_to_be32(0x0000001f)); rval = put_n_bits32(v, n, o, testarray1, l); TEST_ASSERT_EQUAL_INT(rval, 96); @@ -1533,8 +1637,8 @@ void test_put_n_bits32(void) rval = put_n_bits32(v, n, o, testarray1, l); TEST_ASSERT_EQUAL_INT(rval, 67); TEST_ASSERT(testarray1[0] == 0xffffffff); - TEST_ASSERT(testarray1[1] == 0xfffffffc); - TEST_ASSERT(testarray1[2] == 0x1fffffff); + TEST_ASSERT(testarray1[1] == cpu_to_be32(0xfffffffc)); + TEST_ASSERT(testarray1[2] == cpu_to_be32(0x1fffffff)); /* re-init input arrays after clobbering */ init_PB32_arrays(testarray0, testarray1); @@ -1543,8 +1647,8 @@ void test_put_n_bits32(void) rval = put_n_bits32(v, n, o, testarray0, l); TEST_ASSERT_EQUAL_INT(rval, 67); TEST_ASSERT(testarray0[0] == 0); - TEST_ASSERT(testarray0[1] == 3); - TEST_ASSERT(testarray0[2] == 0xe0000000); + TEST_ASSERT(testarray0[1] == cpu_to_be32(3)); + TEST_ASSERT(testarray0[2] == cpu_to_be32(0xe0000000)); rval = put_n_bits32(v, n, o, testarray1, l); TEST_ASSERT_EQUAL_INT(rval, 67); @@ -1563,8 +1667,8 @@ void test_put_n_bits32(void) rval = put_n_bits32(v, n, o, testarray1, l); TEST_ASSERT_EQUAL_INT(rval, 33); - TEST_ASSERT(testarray1[0] == 0x80000000); - TEST_ASSERT(testarray1[1] == 0x7fffffff); + TEST_ASSERT(testarray1[0] == cpu_to_be32(0x80000000)); + TEST_ASSERT(testarray1[1] == cpu_to_be32(0x7fffffff)); /* re-init input arrays after clobbering */ init_PB32_arrays(testarray0, testarray1); @@ -1572,8 +1676,8 @@ void test_put_n_bits32(void) v = 0xffffffff; n = 32; o = 1; rval = put_n_bits32(v, n, o, testarray0, l); TEST_ASSERT_EQUAL_INT(rval, 33); - TEST_ASSERT(testarray0[0] == 0x7fffffff); - TEST_ASSERT(testarray0[1] == 0x80000000); + TEST_ASSERT(testarray0[0] == cpu_to_be32(0x7fffffff)); + TEST_ASSERT(testarray0[1] == cpu_to_be32(0x80000000)); rval = put_n_bits32(v, n, o, testarray1, l); TEST_ASSERT_EQUAL_INT(rval, 33); @@ -1603,7 +1707,7 @@ void test_put_n_bits32(void) v = 0x7f; n = 6; o = 10; rval = put_n_bits32(v, n, o, testarray0, l); TEST_ASSERT_EQUAL_INT(16, rval); - TEST_ASSERT(testarray0[0] == 0x003f0000); + TEST_ASSERT(testarray0[0] == cpu_to_be32(0x003f0000)); TEST_ASSERT(testarray0[1] == 0); rval = put_n_bits32(v, n, o, testarray1, l); @@ -1619,7 +1723,7 @@ void test_put_n_bits32(void) v = 0xffffffff; n = 6; o = 10; rval = put_n_bits32(v, n, o, testarray0, l); TEST_ASSERT_EQUAL_INT(16, rval); - TEST_ASSERT(testarray0[0] == 0x003f0000); + TEST_ASSERT(testarray0[0] == cpu_to_be32(0x003f0000)); TEST_ASSERT(testarray0[1] == 0); rval = put_n_bits32(v, n, o, testarray1, l); @@ -1697,7 +1801,7 @@ void test_rice_encoder(void) const uint32_t MAX_GOLOMB_PAR = 0x80000000; /* test minimum Golomb parameter */ - value = 0; log2_g_par = (uint32_t)ilog_2(MIN_NON_IMA_GOLOMB_PAR); g_par = 1U << log2_g_par; cw = ~0U; + value = 0; log2_g_par = ilog_2(MIN_NON_IMA_GOLOMB_PAR); g_par = 1U << log2_g_par; cw = ~0U; cw_len = rice_encoder(value, g_par, log2_g_par, &cw); TEST_ASSERT_EQUAL_INT(1, cw_len); TEST_ASSERT_EQUAL_HEX(0x0, cw); @@ -1734,7 +1838,7 @@ void test_rice_encoder(void) TEST_ASSERT_EQUAL_HEX(0xFFFFFFEF, cw); /* test maximum Golomb parameter for rice_encoder */ - value = 0; log2_g_par = (uint32_t)ilog_2(MAX_GOLOMB_PAR); g_par = 1U << log2_g_par; cw = ~0U; + value = 0; log2_g_par = ilog_2(MAX_GOLOMB_PAR); g_par = 1U << log2_g_par; cw = ~0U; cw_len = rice_encoder(value, g_par, log2_g_par, &cw); TEST_ASSERT_EQUAL_INT(32, cw_len); TEST_ASSERT_EQUAL_HEX(0x0, cw); @@ -1766,7 +1870,7 @@ void test_golomb_encoder(void) const uint32_t MAX_GOLOMB_PAR = 0x80000000; /* test minimum Golomb parameter */ - value = 0; g_par = MIN_NON_IMA_GOLOMB_PAR; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U; + value = 0; g_par = MIN_NON_IMA_GOLOMB_PAR; log2_g_par = ilog_2(g_par); cw = ~0U; cw_len = golomb_encoder(value, g_par, log2_g_par, &cw); TEST_ASSERT_EQUAL_INT(1, cw_len); TEST_ASSERT_EQUAL_HEX(0x0, cw); @@ -1776,9 +1880,25 @@ void test_golomb_encoder(void) TEST_ASSERT_EQUAL_INT(32, cw_len); TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, cw); + /* error case: value larger than allowed */ + value = 32; g_par = 1; log2_g_par = ilog_2(g_par); cw = ~0U; + cw_len = golomb_encoder(value, g_par, log2_g_par, &cw); + TEST_ASSERT_GREATER_THAN_UINT(32, cw_len); + + /* error case: value larger than allowed */ + value = 33; g_par = 1; log2_g_par = ilog_2(g_par); cw = ~0U; + cw_len = golomb_encoder(value, g_par, log2_g_par, &cw); + TEST_ASSERT_GREATER_THAN_UINT(32, cw_len); + +#if 0 + /* error case: value larger than allowed overflow in returned len */ + value = UINT32_MAX; g_par = 1; log2_g_par = ilog_2(g_par); cw = ~0U; + cw_len = golomb_encoder(value, g_par, log2_g_par, &cw); + TEST_ASSERT_GREATER_THAN_UINT(32, cw_len); +#endif /* test some arbitrary values with g_par = 16 */ - value = 0; g_par = 16; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U; + value = 0; g_par = 16; log2_g_par = ilog_2(g_par); cw = ~0U; cw_len = golomb_encoder(value, g_par, log2_g_par, &cw); TEST_ASSERT_EQUAL_INT(5, cw_len); TEST_ASSERT_EQUAL_HEX(0x0, cw); @@ -1805,7 +1925,7 @@ void test_golomb_encoder(void) /* test some arbitrary values with g_par = 3 */ - value = 0; g_par = 3; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U; + value = 0; g_par = 3; log2_g_par = ilog_2(g_par); cw = ~0U; cw_len = golomb_encoder(value, g_par, log2_g_par, &cw); TEST_ASSERT_EQUAL_INT(2, cw_len); TEST_ASSERT_EQUAL_HEX(0x0, cw); @@ -1835,14 +1955,34 @@ void test_golomb_encoder(void) TEST_ASSERT_EQUAL_INT(32, cw_len); TEST_ASSERT_EQUAL_HEX(0xFFFFFFFB, cw); + /* test some arbitrary values with g_par = 0x7FFFFFFF */ + value = 0; g_par = 0x7FFFFFFF; log2_g_par = ilog_2(g_par); cw = ~0U; + cw_len = golomb_encoder(value, g_par, log2_g_par, &cw); + TEST_ASSERT_EQUAL_INT(31, cw_len); + TEST_ASSERT_EQUAL_HEX(0x0, cw); + + value = 1; + cw_len = golomb_encoder(value, g_par, log2_g_par, &cw); + TEST_ASSERT_EQUAL_INT(32, cw_len); + TEST_ASSERT_EQUAL_HEX(0x2, cw); + + value = 0x7FFFFFFE; + cw_len = golomb_encoder(value, g_par, log2_g_par, &cw); + TEST_ASSERT_EQUAL_INT(32, cw_len); + TEST_ASSERT_EQUAL_HEX(0x7FFFFFFF, cw); + + value = 0x7FFFFFFF; + cw_len = golomb_encoder(value, g_par, log2_g_par, &cw); + TEST_ASSERT_EQUAL_INT(32, cw_len); + TEST_ASSERT_EQUAL_HEX(0x80000000, cw); /* test maximum Golomb parameter for golomb_encoder */ - value = 0; g_par = MAX_GOLOMB_PAR; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U; + value = 0; g_par = MAX_GOLOMB_PAR; log2_g_par = ilog_2(g_par); cw = ~0U; cw_len = golomb_encoder(value, g_par, log2_g_par, &cw); TEST_ASSERT_EQUAL_INT(32, cw_len); TEST_ASSERT_EQUAL_HEX(0x0, cw); - value = 1; g_par = MAX_GOLOMB_PAR; log2_g_par = (uint32_t)ilog_2(g_par); cw = ~0U; + value = 1; g_par = MAX_GOLOMB_PAR; log2_g_par = ilog_2(g_par); cw = ~0U; cw_len = golomb_encoder(value, g_par, log2_g_par, &cw); TEST_ASSERT_EQUAL_INT(32, cw_len); TEST_ASSERT_EQUAL_HEX(0x1, cw); @@ -1856,6 +1996,11 @@ void test_golomb_encoder(void) cw_len = golomb_encoder(value, g_par, log2_g_par, &cw); TEST_ASSERT_EQUAL_INT(32, cw_len); TEST_ASSERT_EQUAL_HEX(0x7FFFFFFF, cw); + + value = 0; g_par = 0xFFFFFFFF; log2_g_par = ilog_2(g_par); cw = ~0U; + cw_len = golomb_encoder(value, g_par, log2_g_par, &cw); + TEST_ASSERT_EQUAL_INT(32, cw_len); + TEST_ASSERT_EQUAL_HEX(0x0, cw); } @@ -1872,7 +2017,7 @@ void test_encode_value_zero(void) /* setup the setup */ setup.encoder_par1 = 1; - setup.encoder_par2 = (uint32_t)ilog_2(setup.encoder_par1); + setup.encoder_par2 = ilog_2(setup.encoder_par1); setup.spillover_par = 32; setup.max_data_bits = 32; setup.generate_cw_f = rice_encoder; @@ -1884,41 +2029,41 @@ void test_encode_value_zero(void) data = 0; model = 0; stream_len = encode_value_zero(data, model, stream_len, &setup); TEST_ASSERT_EQUAL_INT(2, stream_len); - TEST_ASSERT_EQUAL_HEX(0x80000000, bitstream[0]); - TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]); - TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]); + TEST_ASSERT_EQUAL_HEX(0x80000000, be32_to_cpu(bitstream[0])); + TEST_ASSERT_EQUAL_HEX(0x00000000, be32_to_cpu(bitstream[1])); + TEST_ASSERT_EQUAL_HEX(0x00000000, be32_to_cpu(bitstream[2])); data = 5; model = 0; stream_len = encode_value_zero(data, model, stream_len, &setup); TEST_ASSERT_EQUAL_INT(14, stream_len); - TEST_ASSERT_EQUAL_HEX(0xBFF80000, bitstream[0]); - TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]); - TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]); + TEST_ASSERT_EQUAL_HEX(0xBFF80000, be32_to_cpu(bitstream[0])); + TEST_ASSERT_EQUAL_HEX(0x00000000, be32_to_cpu(bitstream[1])); + TEST_ASSERT_EQUAL_HEX(0x00000000, be32_to_cpu(bitstream[2])); data = 2; model = 7; stream_len = encode_value_zero(data, model, stream_len, &setup); TEST_ASSERT_EQUAL_INT(25, stream_len); - TEST_ASSERT_EQUAL_HEX(0xBFFBFF00, bitstream[0]); - TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]); - TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]); + TEST_ASSERT_EQUAL_HEX(0xBFFBFF00, be32_to_cpu(bitstream[0])); + TEST_ASSERT_EQUAL_HEX(0x00000000, be32_to_cpu(bitstream[1])); + TEST_ASSERT_EQUAL_HEX(0x00000000, be32_to_cpu(bitstream[2])); /* zero escape mechanism */ data = 100; model = 42; /* (100-42)*2+1=117 -> cw 0 + 0x0000_0000_0000_0075 */ stream_len = encode_value_zero(data, model, stream_len, &setup); TEST_ASSERT_EQUAL_INT(58, stream_len); - TEST_ASSERT_EQUAL_HEX(0xBFFBFF00, bitstream[0]); - TEST_ASSERT_EQUAL_HEX(0x00001D40, bitstream[1]); - TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]); + TEST_ASSERT_EQUAL_HEX(0xBFFBFF00, be32_to_cpu(bitstream[0])); + TEST_ASSERT_EQUAL_HEX(0x00001D40, be32_to_cpu(bitstream[1])); + TEST_ASSERT_EQUAL_HEX(0x00000000, be32_to_cpu(bitstream[2])); /* test overflow */ - data = INT32_MIN; model = 0; + data = (uint32_t)INT32_MIN; model = 0; /* (INT32_MIN)*-2-1+1=0(overflow) -> cw 0 + 0x0000_0000_0000_0000 */ stream_len = encode_value_zero(data, model, stream_len, &setup); TEST_ASSERT_EQUAL_INT(91, stream_len); - TEST_ASSERT_EQUAL_HEX(0xBFFBFF00, bitstream[0]); - TEST_ASSERT_EQUAL_HEX(0x00001D40, bitstream[1]); - TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]); + TEST_ASSERT_EQUAL_HEX(0xBFFBFF00, be32_to_cpu(bitstream[0])); + TEST_ASSERT_EQUAL_HEX(0x00001D40, be32_to_cpu(bitstream[1])); + TEST_ASSERT_EQUAL_HEX(0x00000000, be32_to_cpu(bitstream[2])); /* small buffer error */ data = 23; model = 26; @@ -1938,33 +2083,33 @@ void test_encode_value_zero(void) data = 53; model = 38; stream_len = encode_value_zero(data, model, stream_len, &setup); TEST_ASSERT_EQUAL_INT(32, stream_len); - TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, bitstream[0]); - TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[1]); - TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[2]); + TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, be32_to_cpu(bitstream[0])); + TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, be32_to_cpu(bitstream[1])); + TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, be32_to_cpu(bitstream[2])); /* lowest value with zero encoding */ data = 0; model = 16; stream_len = encode_value_zero(data, model, stream_len, &setup); TEST_ASSERT_EQUAL_INT(39, stream_len); - TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, bitstream[0]); - TEST_ASSERT_EQUAL_HEX(0x41FFFFFF, bitstream[1]); - TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[2]); + TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, be32_to_cpu(bitstream[0])); + TEST_ASSERT_EQUAL_HEX(0x41FFFFFF, be32_to_cpu(bitstream[1])); + TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, be32_to_cpu(bitstream[2])); /* maximum positive value to encode */ data = 31; model = 0; stream_len = encode_value_zero(data, model, stream_len, &setup); TEST_ASSERT_EQUAL_INT(46, stream_len); - TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, bitstream[0]); - TEST_ASSERT_EQUAL_HEX(0x40FFFFFF, bitstream[1]); - TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[2]); + TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, be32_to_cpu(bitstream[0])); + TEST_ASSERT_EQUAL_HEX(0x40FFFFFF, be32_to_cpu(bitstream[1])); + TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, be32_to_cpu(bitstream[2])); /* maximum negative value to encode */ data = 0; model = 32; stream_len = encode_value_zero(data, model, stream_len, &setup); TEST_ASSERT_EQUAL_INT(53, stream_len); - TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, bitstream[0]); - TEST_ASSERT_EQUAL_HEX(0x40FC07FF, bitstream[1]); - TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[2]); + TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, be32_to_cpu(bitstream[0])); + TEST_ASSERT_EQUAL_HEX(0x40FC07FF, be32_to_cpu(bitstream[1])); + TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, be32_to_cpu(bitstream[2])); /* small buffer error when creating the zero escape symbol*/ bitstream[0] = 0; @@ -1975,9 +2120,9 @@ void test_encode_value_zero(void) data = 31; model = 0; stream_len = encode_value_zero(data, model, stream_len, &setup); TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, stream_len); - TEST_ASSERT_EQUAL_HEX(0, bitstream[0]); - TEST_ASSERT_EQUAL_HEX(0, bitstream[1]); - TEST_ASSERT_EQUAL_HEX(0, bitstream[2]); + TEST_ASSERT_EQUAL_HEX(0, be32_to_cpu(bitstream[0])); + TEST_ASSERT_EQUAL_HEX(0, be32_to_cpu(bitstream[1])); + TEST_ASSERT_EQUAL_HEX(0, be32_to_cpu(bitstream[2])); } @@ -1994,7 +2139,7 @@ void test_encode_value_multi(void) /* setup the setup */ setup.encoder_par1 = 1; - setup.encoder_par2 = (uint32_t)ilog_2(setup.encoder_par1); + setup.encoder_par2 = ilog_2(setup.encoder_par1); setup.spillover_par = 16; setup.max_data_bits = 32; setup.generate_cw_f = golomb_encoder; @@ -2006,53 +2151,53 @@ void test_encode_value_multi(void) data = 0; model = 0; stream_len = encode_value_multi(data, model, stream_len, &setup); TEST_ASSERT_EQUAL_INT(1, stream_len); - TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[0]); - TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]); - TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]); - TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[3]); + TEST_ASSERT_EQUAL_HEX(0x00000000, be32_to_cpu(bitstream[0])); + TEST_ASSERT_EQUAL_HEX(0x00000000, be32_to_cpu(bitstream[1])); + TEST_ASSERT_EQUAL_HEX(0x00000000, be32_to_cpu(bitstream[2])); + TEST_ASSERT_EQUAL_HEX(0x00000000, be32_to_cpu(bitstream[3])); data = 0; model = 1; stream_len = encode_value_multi(data, model, stream_len, &setup); TEST_ASSERT_EQUAL_INT(3, stream_len); - TEST_ASSERT_EQUAL_HEX(0x40000000, bitstream[0]); - TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]); - TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]); - TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[3]); + TEST_ASSERT_EQUAL_HEX(0x40000000, be32_to_cpu(bitstream[0])); + TEST_ASSERT_EQUAL_HEX(0x00000000, be32_to_cpu(bitstream[1])); + TEST_ASSERT_EQUAL_HEX(0x00000000, be32_to_cpu(bitstream[2])); + TEST_ASSERT_EQUAL_HEX(0x00000000, be32_to_cpu(bitstream[3])); data = 1+23; model = 0+23; stream_len = encode_value_multi(data, model, stream_len, &setup); TEST_ASSERT_EQUAL_INT(6, stream_len); - TEST_ASSERT_EQUAL_HEX(0x58000000, bitstream[0]); - TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]); - TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]); - TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[3]); + TEST_ASSERT_EQUAL_HEX(0x58000000, be32_to_cpu(bitstream[0])); + TEST_ASSERT_EQUAL_HEX(0x00000000, be32_to_cpu(bitstream[1])); + TEST_ASSERT_EQUAL_HEX(0x00000000, be32_to_cpu(bitstream[2])); + TEST_ASSERT_EQUAL_HEX(0x00000000, be32_to_cpu(bitstream[3])); /* highest value without multi outlier encoding */ data = 0+42; model = 8+42; stream_len = encode_value_multi(data, model, stream_len, &setup); TEST_ASSERT_EQUAL_INT(22, stream_len); - TEST_ASSERT_EQUAL_HEX(0x5BFFF800, bitstream[0]); - TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[1]); - TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]); - TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[3]); + TEST_ASSERT_EQUAL_HEX(0x5BFFF800, be32_to_cpu(bitstream[0])); + TEST_ASSERT_EQUAL_HEX(0x00000000, be32_to_cpu(bitstream[1])); + TEST_ASSERT_EQUAL_HEX(0x00000000, be32_to_cpu(bitstream[2])); + TEST_ASSERT_EQUAL_HEX(0x00000000, be32_to_cpu(bitstream[3])); /* lowest value with multi outlier encoding */ data = 8+42; model = 0+42; stream_len = encode_value_multi(data, model, stream_len, &setup); TEST_ASSERT_EQUAL_INT(41, stream_len); - TEST_ASSERT_EQUAL_HEX(0x5BFFFBFF, bitstream[0]); - TEST_ASSERT_EQUAL_HEX(0xFC000000, bitstream[1]); - TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[2]); - TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[3]); + TEST_ASSERT_EQUAL_HEX(0x5BFFFBFF, be32_to_cpu(bitstream[0])); + TEST_ASSERT_EQUAL_HEX(0xFC000000, be32_to_cpu(bitstream[1])); + TEST_ASSERT_EQUAL_HEX(0x00000000, be32_to_cpu(bitstream[2])); + TEST_ASSERT_EQUAL_HEX(0x00000000, be32_to_cpu(bitstream[3])); /* highest value with multi outlier encoding */ - data = INT32_MIN; model = 0; + data = (uint32_t)INT32_MIN; model = 0; stream_len = encode_value_multi(data, model, stream_len, &setup); TEST_ASSERT_EQUAL_INT(105, stream_len); - TEST_ASSERT_EQUAL_HEX(0x5BFFFBFF, bitstream[0]); - TEST_ASSERT_EQUAL_HEX(0xFC7FFFFF, bitstream[1]); - TEST_ASSERT_EQUAL_HEX(0xFF7FFFFF, bitstream[2]); - TEST_ASSERT_EQUAL_HEX(0xF7800000, bitstream[3]); + TEST_ASSERT_EQUAL_HEX(0x5BFFFBFF, be32_to_cpu(bitstream[0])); + TEST_ASSERT_EQUAL_HEX(0xFC7FFFFF, be32_to_cpu(bitstream[1])); + TEST_ASSERT_EQUAL_HEX(0xFF7FFFFF, be32_to_cpu(bitstream[2])); + TEST_ASSERT_EQUAL_HEX(0xF7800000, be32_to_cpu(bitstream[3])); /* small buffer error */ data = 0; model = 38; @@ -2116,8 +2261,8 @@ void test_encode_value(void) cmp_size = encode_value(data, model, cmp_size, &setup); TEST_ASSERT_EQUAL_INT(96, cmp_size); TEST_ASSERT_EQUAL_HEX(0, bitstream[0]); - TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[1]); - TEST_ASSERT_EQUAL_HEX(0x7FFFFFFF, bitstream[2]); + TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, be32_to_cpu(bitstream[1])); + TEST_ASSERT_EQUAL_HEX(0x7FFFFFFF, be32_to_cpu(bitstream[2])); TEST_ASSERT_EQUAL_HEX(0, bitstream[3]); setup.lossy_par = 2; @@ -2126,7 +2271,7 @@ void test_encode_value(void) TEST_ASSERT_EQUAL_INT(128, cmp_size); TEST_ASSERT_EQUAL_HEX(0, bitstream[0]); TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[1]); - TEST_ASSERT_EQUAL_HEX(0x7FFFFFFF, bitstream[2]); + TEST_ASSERT_EQUAL_HEX(0x7FFFFFFF, be32_to_cpu(bitstream[2])); TEST_ASSERT_EQUAL_HEX(0x00000000, bitstream[3]); /* small buffer error bitstream can not hold more data*/ @@ -2156,8 +2301,8 @@ void test_encode_value(void) data = 0x7FFFFFFF; model = 0; cmp_size = encode_value(data, model, cmp_size, &setup); TEST_ASSERT_EQUAL_INT(62, cmp_size); - TEST_ASSERT_EQUAL_HEX(0x00000001, bitstream[0]); - TEST_ASSERT_EQUAL_HEX(0xFFFFFFFC, bitstream[1]); + TEST_ASSERT_EQUAL_HEX(0x00000001, be32_to_cpu(bitstream[0])); + TEST_ASSERT_EQUAL_HEX(0xFFFFFFFC, be32_to_cpu(bitstream[1])); TEST_ASSERT_EQUAL_HEX(0, bitstream[2]); TEST_ASSERT_EQUAL_HEX(0, bitstream[3]); @@ -2166,9 +2311,9 @@ void test_encode_value(void) data = UINT32_MAX; model = UINT32_MAX; cmp_size = encode_value(data, model, cmp_size, &setup); TEST_ASSERT_EQUAL_INT(93, cmp_size); - TEST_ASSERT_EQUAL_HEX(0x00000001, bitstream[0]); - TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, bitstream[1]); - TEST_ASSERT_EQUAL_HEX(0xFFFFFFF8, bitstream[2]); + TEST_ASSERT_EQUAL_HEX(0x00000001, be32_to_cpu(bitstream[0])); + TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, be32_to_cpu(bitstream[1])); + TEST_ASSERT_EQUAL_HEX(0xFFFFFFF8, be32_to_cpu(bitstream[2])); TEST_ASSERT_EQUAL_HEX(0, bitstream[3]); /* data are bigger than max_data_bits */ @@ -2186,194 +2331,6 @@ void test_encode_value(void) } -/** - * @test configure_encoder_setup - */ - -void test_configure_encoder_setup(void) -{ - struct encoder_setupt setup; - uint32_t cmp_par; - uint32_t spillover; - uint32_t lossy_par; - uint32_t max_data_bits; - struct cmp_cfg cfg; - int error; - - /* test Golomb encoder zero escape mechanism */ - cmp_par = 42; - spillover = 23; - lossy_par = 0; - max_data_bits = 15; - cfg.data_type = DATA_TYPE_IMAGETTE; - cfg.cmp_mode = CMP_MODE_MODEL_ZERO; - cfg.icu_output_buf = (void *)123; - cfg.buffer_length = 2; - error = configure_encoder_setup(&setup, cmp_par, spillover, lossy_par, - max_data_bits, &cfg); - TEST_ASSERT_FALSE(error); - TEST_ASSERT_EQUAL(golomb_encoder, setup.generate_cw_f); /* pointer to the code word encoder */ - TEST_ASSERT_EQUAL(encode_value_zero, setup.encode_method_f); /* pointer to the encoding function */ - TEST_ASSERT_EQUAL(123, setup.bitstream_adr); /* start address of the compressed data bitstream */ - TEST_ASSERT_EQUAL_INT(32, setup.max_stream_len); /* maximum length of the bitstream/icu_output_buf in bits */ - TEST_ASSERT_EQUAL_INT(42, setup.encoder_par1); /* encoding parameter 1 */ - TEST_ASSERT_EQUAL_INT(5, setup.encoder_par2); /* encoding parameter 2 */ - TEST_ASSERT_EQUAL_INT(23, setup.spillover_par); /* outlier parameter */ - TEST_ASSERT_EQUAL_INT(0, setup.lossy_par); /* lossy compression parameter */ - TEST_ASSERT_EQUAL_INT(15, setup.max_data_bits); /* how many bits are needed to represent the highest possible value */ - memset(&setup, 0, sizeof(setup)); - - /* test Rice encoder multi escape mechanism */ - cmp_par = 32; - spillover = 23; - lossy_par = 0; - max_data_bits = 32; - cfg.data_type = DATA_TYPE_IMAGETTE; - cfg.cmp_mode = CMP_MODE_DIFF_MULTI; - cfg.icu_output_buf = (void *)123; - cfg.buffer_length = 2; - error = configure_encoder_setup(&setup, cmp_par, spillover, lossy_par, - max_data_bits, &cfg); - TEST_ASSERT_FALSE(error); - TEST_ASSERT_EQUAL(rice_encoder, setup.generate_cw_f); /* pointer to the code word encoder */ - TEST_ASSERT_EQUAL(encode_value_multi, setup.encode_method_f); /* pointer to the encoding function */ - TEST_ASSERT_EQUAL(123, setup.bitstream_adr); /* start address of the compressed data bitstream */ - TEST_ASSERT_EQUAL_INT(32, setup.max_stream_len); /* maximum length of the bitstream/icu_output_buf in bits */ - TEST_ASSERT_EQUAL_INT(32, setup.encoder_par1); /* encoding parameter 1 */ - TEST_ASSERT_EQUAL_INT(5, setup.encoder_par2); /* encoding parameter 2 */ - TEST_ASSERT_EQUAL_INT(23, setup.spillover_par); /* outlier parameter */ - TEST_ASSERT_EQUAL_INT(0, setup.lossy_par); /* lossy compression parameter */ - TEST_ASSERT_EQUAL_INT(32, setup.max_data_bits); /* how many bits are needed to represent the highest possible value */ - memset(&setup, 0, sizeof(setup)); - - /* test CMP_MODE_STUFF */ - cmp_par = 32; - spillover = ~0U; - lossy_par = 1; - max_data_bits = 32; - cfg.data_type = DATA_TYPE_IMAGETTE; - cfg.cmp_mode = CMP_MODE_STUFF; - cfg.icu_output_buf = (void *)123; - cfg.buffer_length = 2; - error = configure_encoder_setup(&setup, cmp_par, spillover, lossy_par, - max_data_bits, &cfg); - TEST_ASSERT_FALSE(error); - TEST_ASSERT_EQUAL(NULL, setup.generate_cw_f); /* pointer to the code word encoder */ - TEST_ASSERT_EQUAL(encode_value_none, setup.encode_method_f); /* pointer to the encoding function */ - TEST_ASSERT_EQUAL(123, setup.bitstream_adr); /* start address of the compressed data bitstream */ - TEST_ASSERT_EQUAL_INT(32, setup.max_stream_len); /* maximum length of the bitstream/icu_output_buf in bits */ - TEST_ASSERT_EQUAL_INT(32, setup.encoder_par1); /* encoding parameter 1 */ - TEST_ASSERT_EQUAL_INT(0, setup.encoder_par2); /* encoding parameter 2 */ - TEST_ASSERT_EQUAL_INT(0, setup.spillover_par); /* outlier parameter */ - TEST_ASSERT_EQUAL_INT(1, setup.lossy_par); /* lossy compression parameter */ - TEST_ASSERT_EQUAL_INT(32, setup.max_data_bits); /* how many bits are needed to represent the highest possible value */ - memset(&setup, 0, sizeof(setup)); - - /* test max_used_bits = 33 */ - cmp_par = 32; - spillover = 23; - lossy_par = 0; - max_data_bits = 33; - cfg.data_type = DATA_TYPE_IMAGETTE; - cfg.cmp_mode = CMP_MODE_DIFF_MULTI; - cfg.icu_output_buf = (void *)123; - cfg.buffer_length = 2; - error = configure_encoder_setup(&setup, cmp_par, spillover, lossy_par, - max_data_bits, &cfg); - TEST_ASSERT_TRUE(error); - memset(&setup, 0, sizeof(setup)); - - /* cmp_par = 0 test */ - cmp_par = 0; - spillover = 23; - lossy_par = 0; - max_data_bits = 32; - cfg.data_type = DATA_TYPE_IMAGETTE; - cfg.cmp_mode = CMP_MODE_DIFF_MULTI; - cfg.icu_output_buf = (void *)123; - cfg.buffer_length = 2; - error = configure_encoder_setup(&setup, cmp_par, spillover, lossy_par, - max_data_bits, &cfg); - TEST_ASSERT_TRUE(error); - memset(&setup, 0, sizeof(setup)); - - /* cmp_par = 0 test STUFF MODE this should work*/ - cmp_par = 0; - spillover = 23; - lossy_par = 0; - max_data_bits = 32; - cfg.data_type = DATA_TYPE_IMAGETTE; - cfg.cmp_mode = CMP_MODE_STUFF; - cfg.icu_output_buf = (void *)123; - cfg.buffer_length = 2; - error = configure_encoder_setup(&setup, cmp_par, spillover, lossy_par, - max_data_bits, &cfg); - TEST_ASSERT_FALSE(error); - TEST_ASSERT_EQUAL(NULL, setup.generate_cw_f); /* pointer to the code word encoder */ - TEST_ASSERT_EQUAL(encode_value_none, setup.encode_method_f); /* pointer to the encoding function */ - TEST_ASSERT_EQUAL(123, setup.bitstream_adr); /* start address of the compressed data bitstream */ - TEST_ASSERT_EQUAL_INT(32, setup.max_stream_len); /* maximum length of the bitstream/icu_output_buf in bits */ - TEST_ASSERT_EQUAL_INT(0, setup.encoder_par1); /* encoding parameter 1 */ - TEST_ASSERT_EQUAL_INT(0, setup.encoder_par2); /* encoding parameter 2 */ - TEST_ASSERT_EQUAL_INT(0, setup.spillover_par); /* outlier parameter */ - TEST_ASSERT_EQUAL_INT(0, setup.lossy_par); /* lossy compression parameter */ - TEST_ASSERT_EQUAL_INT(0, setup.max_data_bits); /* how many bits are needed to represent the highest possible value */ - memset(&setup, 0, sizeof(setup)); - - /* cmp_mode = STUFF_MODE +1 */ - cmp_par = 32; - spillover = 23; - lossy_par = 0; - max_data_bits = 1; - cfg.data_type = DATA_TYPE_IMAGETTE; - cfg.cmp_mode = CMP_MODE_STUFF+1; - cfg.icu_output_buf = (void *)123; - cfg.buffer_length = 2; - error = configure_encoder_setup(&setup, cmp_par, spillover, lossy_par, - max_data_bits, &cfg); - TEST_ASSERT_TRUE(error); - memset(&setup, 0, sizeof(setup)); - - /* setup = NULL test */ - cmp_par = 42; - spillover = 23; - lossy_par = 0; - max_data_bits = 15; - cfg.data_type = DATA_TYPE_IMAGETTE; - cfg.cmp_mode = CMP_MODE_MODEL_ZERO; - cfg.icu_output_buf = (void *)123; - cfg.buffer_length = 2; - error = configure_encoder_setup(NULL, cmp_par, spillover, lossy_par, - max_data_bits, &cfg); - TEST_ASSERT_TRUE(error); - memset(&setup, 0, sizeof(setup)); - - /* error case: cmp_mode = CMP_MODE_RAW test */ - cmp_par = 42; - spillover = 23; - lossy_par = 0; - max_data_bits = 15; - cfg.data_type = DATA_TYPE_IMAGETTE; - cfg.cmp_mode = CMP_MODE_RAW; - cfg.icu_output_buf = (void *)123; - cfg.buffer_length = 2; - error = configure_encoder_setup(&setup, cmp_par, spillover, lossy_par, - max_data_bits, &cfg); - TEST_ASSERT_TRUE(error); - memset(&setup, 0, sizeof(setup)); - - /* cfg = NULL test */ - cmp_par = 42; - spillover = 23; - lossy_par = 0; - max_data_bits = 15; - error = configure_encoder_setup(&setup, cmp_par, spillover, lossy_par, - max_data_bits, NULL); - TEST_ASSERT_TRUE(error); - memset(&setup, 0, sizeof(setup)); -} - - /** * @test compress_imagette */ @@ -2514,8 +2471,9 @@ void test_compress_imagette_stuff(void) void test_compress_imagette_raw(void) { - uint16_t data[] = {0x0, 0x1, 0x23, 0x42, INT16_MIN, INT16_MAX, UINT16_MAX}; - uint16_t output_buf[7] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + uint16_t data[] = {0x0, 0x1, 0x23, 0x42, (uint16_t)INT16_MIN, INT16_MAX, UINT16_MAX}; + void *output_buf = malloc(7*sizeof(uint16_t)); + uint16_t cmp_data[7]; struct cmp_cfg cfg = {0}; int cmp_size; @@ -2524,18 +2482,19 @@ void test_compress_imagette_raw(void) cfg.model_buf = NULL; cfg.input_buf = data; cfg.samples = 7; - cfg.icu_output_buf = (uint32_t *)output_buf; + cfg.icu_output_buf = output_buf; cfg.buffer_length = 7; cmp_size = icu_compress_data(&cfg); + memcpy(cmp_data, output_buf, sizeof(cmp_data)); TEST_ASSERT_EQUAL_INT(7*16, cmp_size); - TEST_ASSERT_EQUAL_HEX16(0x0, be16_to_cpu(output_buf[0])); - TEST_ASSERT_EQUAL_HEX16(0x1, be16_to_cpu(output_buf[1])); - TEST_ASSERT_EQUAL_HEX16(0x23, be16_to_cpu(output_buf[2])); - TEST_ASSERT_EQUAL_HEX16(0x42, be16_to_cpu(output_buf[3])); - TEST_ASSERT_EQUAL_HEX16(INT16_MIN, be16_to_cpu(output_buf[4])); - TEST_ASSERT_EQUAL_HEX16(INT16_MAX, be16_to_cpu(output_buf[5])); - TEST_ASSERT_EQUAL_HEX16(UINT16_MAX, be16_to_cpu(output_buf[6])); + TEST_ASSERT_EQUAL_HEX16(0x0, be16_to_cpu(cmp_data[0])); + TEST_ASSERT_EQUAL_HEX16(0x1, be16_to_cpu(cmp_data[1])); + TEST_ASSERT_EQUAL_HEX16(0x23, be16_to_cpu(cmp_data[2])); + TEST_ASSERT_EQUAL_HEX16(0x42, be16_to_cpu(cmp_data[3])); + TEST_ASSERT_EQUAL_HEX16(INT16_MIN, be16_to_cpu(cmp_data[4])); + TEST_ASSERT_EQUAL_HEX16(INT16_MAX, be16_to_cpu(cmp_data[5])); + TEST_ASSERT_EQUAL_HEX16(UINT16_MAX, be16_to_cpu(cmp_data[6])); /* compressed data buf = NULL test */ @@ -2556,7 +2515,7 @@ void test_compress_imagette_raw(void) cfg.data_type = DATA_TYPE_IMAGETTE; cfg.input_buf = NULL; /* no data to compress */ cfg.samples = 7; - cfg.icu_output_buf = (uint32_t *)output_buf; + cfg.icu_output_buf = output_buf; cfg.buffer_length = 7; cfg.max_used_bits = &MAX_USED_BITS_SAFE; @@ -2569,12 +2528,14 @@ void test_compress_imagette_raw(void) cfg.data_type = DATA_TYPE_IMAGETTE; cfg.input_buf = data; cfg.samples = 7; - cfg.icu_output_buf = (uint32_t *)output_buf; + cfg.icu_output_buf = output_buf; cfg.buffer_length = 6; /* the buffer is to small */ cfg.max_used_bits = &MAX_USED_BITS_SAFE; cmp_size = icu_compress_data(&cfg); TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, cmp_size); + + free(output_buf); } @@ -2587,7 +2548,7 @@ void test_compress_imagette_error_cases(void) uint16_t data[] = {0xFFFF, 1, 0, 42, 0x8000, 0x7FFF, 0xFFFF}; uint32_t output_buf[2] = {0xFFFF, 0xFFFF}; struct cmp_cfg cfg = {0}; - int cmp_size, error; + int cmp_size; struct cmp_max_used_bits my_max_used_bits; cfg.data_type = DATA_TYPE_IMAGETTE; @@ -2649,11 +2610,11 @@ void test_compress_imagette_error_cases(void) cmp_size = icu_compress_data(&cfg); TEST_ASSERT_EQUAL_INT(-1, cmp_size); - /* error in setup */ + /* error my_max_used_bits.nc_imagette value is to high */ my_max_used_bits = MAX_USED_BITS_SAFE; my_max_used_bits.nc_imagette = 33; - error = cmp_cfg_icu_max_used_bits(&cfg, &my_max_used_bits); - TEST_ASSERT_TRUE(error); + + cfg.max_used_bits = &my_max_used_bits; cfg.data_type = DATA_TYPE_IMAGETTE; cfg.cmp_mode = CMP_MODE_DIFF_ZERO; cfg.input_buf = data; @@ -2662,25 +2623,85 @@ void test_compress_imagette_error_cases(void) cfg.spill = 8; cfg.icu_output_buf = (uint32_t *)output_buf; cfg.buffer_length = 4; + + cmp_size = icu_compress_data(&cfg); + TEST_ASSERT_EQUAL_INT(-1, cmp_size); + + /* error my_max_used_bits.saturated_imagette value is to high */ + my_max_used_bits = MAX_USED_BITS_SAFE; + my_max_used_bits.saturated_imagette = 17; + cfg.max_used_bits = &my_max_used_bits; + cfg.data_type = DATA_TYPE_SAT_IMAGETTE_ADAPTIVE; + cfg.cmp_mode = CMP_MODE_DIFF_ZERO; + cfg.input_buf = data; + cfg.samples = 2; + cfg.golomb_par = 1; + cfg.spill = 8; + cfg.icu_output_buf = (uint32_t *)output_buf; + cfg.buffer_length = 4; cmp_size = icu_compress_data(&cfg); TEST_ASSERT_EQUAL_INT(-1, cmp_size); -} + /* error my_max_used_bits.fc_imagette value is to high */ + my_max_used_bits = MAX_USED_BITS_SAFE; + my_max_used_bits.fc_imagette = 17; + + cfg.max_used_bits = &my_max_used_bits; + cfg.data_type = DATA_TYPE_F_CAM_IMAGETTE; + cfg.cmp_mode = CMP_MODE_DIFF_ZERO; + cfg.input_buf = data; + cfg.samples = 2; + cfg.golomb_par = 1; + cfg.spill = 8; + cfg.icu_output_buf = (uint32_t *)output_buf; + cfg.buffer_length = 4; + + cmp_size = icu_compress_data(&cfg); + TEST_ASSERT_EQUAL_INT(-1, cmp_size); + + /* test unknown cmp_mode */ + cfg.max_used_bits = &MAX_USED_BITS_SAFE; + cfg.data_type = DATA_TYPE_F_CAM_IMAGETTE; + cfg.cmp_mode = CMP_MODE_STUFF+1; + cfg.input_buf = data; + cfg.samples = 2; + cfg.golomb_par = 1; + cfg.spill = 8; + cfg.icu_output_buf = (uint32_t *)output_buf; + cfg.buffer_length = 4; + + cmp_size = icu_compress_data(&cfg); + TEST_ASSERT_EQUAL_INT(-1, cmp_size); + + /* test golomb_par = 0 */ + cfg.max_used_bits = &MAX_USED_BITS_SAFE; + cfg.data_type = DATA_TYPE_F_CAM_IMAGETTE; + cfg.cmp_mode = CMP_MODE_DIFF_ZERO; + cfg.input_buf = data; + cfg.samples = 2; + cfg.golomb_par = 0; + cfg.spill = 8; + cfg.icu_output_buf = (uint32_t *)output_buf; + cfg.buffer_length = 4; + cmp_size = icu_compress_data(&cfg); + TEST_ASSERT_EQUAL_INT(-1, cmp_size); +} +#if 0 /** * @test compress_multi_entry_hdr */ -void test_compress_multi_entry_hdr(void) +void no_test_compress_multi_entry_hdr(void) { int stream_len; - uint8_t data[MULTI_ENTRY_HDR_SIZE]; - uint8_t model[MULTI_ENTRY_HDR_SIZE]; - uint8_t up_model[MULTI_ENTRY_HDR_SIZE]; - uint8_t cmp_data[MULTI_ENTRY_HDR_SIZE]; + uint8_t data[COLLECTION_HDR_SIZE]; + uint8_t model[COLLECTION_HDR_SIZE]; + uint8_t up_model[COLLECTION_HDR_SIZE]; + uint8_t cmp_data[COLLECTION_HDR_SIZE]; uint8_t *data_p = NULL; uint8_t *model_p = NULL; uint8_t *up_model_p = NULL; @@ -2698,8 +2719,8 @@ void test_compress_multi_entry_hdr(void) stream_len = compress_multi_entry_hdr((void **)&data_p, (void **)&model_p, (void **)&up_model_p, cmp_data); TEST_ASSERT_EQUAL_INT(96, stream_len); - TEST_ASSERT_FALSE(memcmp(cmp_data, data, MULTI_ENTRY_HDR_SIZE)); - TEST_ASSERT_EQUAL(data_p-data, MULTI_ENTRY_HDR_SIZE); + TEST_ASSERT_FALSE(memcmp(cmp_data, data, COLLECTION_HDR_SIZE)); + TEST_ASSERT_EQUAL(data_p-data, COLLECTION_HDR_SIZE); /* no up_model */ memset(cmp_data, 0, sizeof(cmp_data)); @@ -2709,9 +2730,9 @@ void test_compress_multi_entry_hdr(void) stream_len = compress_multi_entry_hdr((void **)&data_p, (void **)&model_p, (void **)&up_model_p, cmp_data); TEST_ASSERT_EQUAL_INT(96, stream_len); - TEST_ASSERT_FALSE(memcmp(cmp_data, data, MULTI_ENTRY_HDR_SIZE)); - TEST_ASSERT_EQUAL(data_p-data, MULTI_ENTRY_HDR_SIZE); - TEST_ASSERT_EQUAL(model_p-model, MULTI_ENTRY_HDR_SIZE); + TEST_ASSERT_FALSE(memcmp(cmp_data, data, COLLECTION_HDR_SIZE)); + TEST_ASSERT_EQUAL(data_p-data, COLLECTION_HDR_SIZE); + TEST_ASSERT_EQUAL(model_p-model, COLLECTION_HDR_SIZE); /* all buffer test */ memset(cmp_data, 0, sizeof(cmp_data)); @@ -2721,11 +2742,11 @@ void test_compress_multi_entry_hdr(void) stream_len = compress_multi_entry_hdr((void **)&data_p, (void **)&model_p, (void **)&up_model_p, cmp_data); TEST_ASSERT_EQUAL_INT(96, stream_len); - TEST_ASSERT_FALSE(memcmp(cmp_data, data, MULTI_ENTRY_HDR_SIZE)); - TEST_ASSERT_FALSE(memcmp(up_model, data, MULTI_ENTRY_HDR_SIZE)); - TEST_ASSERT_EQUAL(data_p-data, MULTI_ENTRY_HDR_SIZE); - TEST_ASSERT_EQUAL(model_p-model, MULTI_ENTRY_HDR_SIZE); - TEST_ASSERT_EQUAL(up_model_p-up_model, MULTI_ENTRY_HDR_SIZE); + TEST_ASSERT_FALSE(memcmp(cmp_data, data, COLLECTION_HDR_SIZE)); + TEST_ASSERT_FALSE(memcmp(up_model, data, COLLECTION_HDR_SIZE)); + TEST_ASSERT_EQUAL(data_p-data, COLLECTION_HDR_SIZE); + TEST_ASSERT_EQUAL(model_p-model, COLLECTION_HDR_SIZE); + TEST_ASSERT_EQUAL(up_model_p-up_model, COLLECTION_HDR_SIZE); /* all buffer test; no cmp_data */ memset(cmp_data, 0, sizeof(cmp_data)); @@ -2735,10 +2756,10 @@ void test_compress_multi_entry_hdr(void) stream_len = compress_multi_entry_hdr((void **)&data_p, (void **)&model_p, (void **)&up_model_p, NULL); TEST_ASSERT_EQUAL_INT(96, stream_len); - TEST_ASSERT_FALSE(memcmp(up_model, data, MULTI_ENTRY_HDR_SIZE)); - TEST_ASSERT_EQUAL(data_p-data, MULTI_ENTRY_HDR_SIZE); - TEST_ASSERT_EQUAL(model_p-model, MULTI_ENTRY_HDR_SIZE); - TEST_ASSERT_EQUAL(up_model_p-up_model, MULTI_ENTRY_HDR_SIZE); + TEST_ASSERT_FALSE(memcmp(up_model, data, COLLECTION_HDR_SIZE)); + TEST_ASSERT_EQUAL(data_p-data, COLLECTION_HDR_SIZE); + TEST_ASSERT_EQUAL(model_p-model, COLLECTION_HDR_SIZE); + TEST_ASSERT_EQUAL(up_model_p-up_model, COLLECTION_HDR_SIZE); /* no data, use up_model test */ memset(cmp_data, 0, sizeof(cmp_data)); @@ -2748,9 +2769,10 @@ void test_compress_multi_entry_hdr(void) stream_len = compress_multi_entry_hdr((void **)&data_p, (void **)&model_p, (void **)&up_model_p, NULL); TEST_ASSERT_EQUAL_INT(96, stream_len); - TEST_ASSERT_EQUAL(model_p-model, MULTI_ENTRY_HDR_SIZE); - TEST_ASSERT_EQUAL(up_model_p-up_model, MULTI_ENTRY_HDR_SIZE); + TEST_ASSERT_EQUAL(model_p-model, COLLECTION_HDR_SIZE); + TEST_ASSERT_EQUAL(up_model_p-up_model, COLLECTION_HDR_SIZE); } +#endif void test_compress_s_fx_raw(void) @@ -2759,7 +2781,7 @@ void test_compress_s_fx_raw(void) struct cmp_cfg cfg = {0}; int cmp_size, cmp_size_exp; size_t i; - struct multi_entry_hdr *hdr; + struct collection_hdr *hdr; cfg.data_type = DATA_TYPE_S_FX; cfg.model_buf = NULL; @@ -2779,24 +2801,26 @@ void test_compress_s_fx_raw(void) data[3].exp_flags = 0x3; data[3].fx = 0x42; data[4].exp_flags = 0x0; - data[4].fx = INT32_MIN; + data[4].fx = (uint32_t)INT32_MIN; data[5].exp_flags = 0x3; data[5].fx = INT32_MAX; data[6].exp_flags = 0x1; data[6].fx = UINT32_MAX; hdr = cfg.input_buf; - memset(hdr, 0x42, sizeof(struct multi_entry_hdr)); + memset(hdr, 0x42, sizeof(struct collection_hdr)); memcpy(hdr->entry, data, sizeof(data)); cmp_size = icu_compress_data(&cfg); - cmp_size_exp = (sizeof(data) + sizeof(struct multi_entry_hdr)) * CHAR_BIT; + cmp_size_exp = (sizeof(data) + sizeof(struct collection_hdr)) * CHAR_BIT; TEST_ASSERT_EQUAL_INT(cmp_size_exp, cmp_size); for (i = 0; i < ARRAY_SIZE(data); i++) { - hdr = (struct multi_entry_hdr *)cfg.icu_output_buf; - struct s_fx *p = (struct s_fx *)hdr->entry; + struct s_fx *p; + + hdr = (struct collection_hdr *)cfg.icu_output_buf; + p = (struct s_fx *)hdr->entry; TEST_ASSERT_EQUAL_HEX(data[i].exp_flags, p[i].exp_flags); TEST_ASSERT_EQUAL_HEX(data[i].fx, cpu_to_be32(p[i].fx)); @@ -2812,7 +2836,7 @@ void test_compress_s_fx_staff(void) struct s_fx data[5]; struct cmp_cfg cfg = {0}; int cmp_size, cmp_size_exp; - struct multi_entry_hdr *hdr; + struct collection_hdr *hdr; uint32_t *cmp_data; /* setup configuration */ @@ -2831,7 +2855,7 @@ void test_compress_s_fx_staff(void) /* generate input data */ hdr = cfg.input_buf; /* use dummy data for the header */ - memset(hdr, 0x42, sizeof(struct multi_entry_hdr)); + memset(hdr, 0x42, sizeof(struct collection_hdr)); data[0].exp_flags = 0x0; data[0].fx = 0x0; data[1].exp_flags = 0x1; @@ -2846,16 +2870,18 @@ void test_compress_s_fx_staff(void) cmp_size = icu_compress_data(&cfg); - cmp_size_exp = 5 * (2 + 21) + MULTI_ENTRY_HDR_SIZE * CHAR_BIT; + cmp_size_exp = 5 * (2 + 21) + COLLECTION_HDR_SIZE * CHAR_BIT; TEST_ASSERT_EQUAL_INT(cmp_size_exp, cmp_size); - TEST_ASSERT_FALSE(memcmp(cfg.input_buf, cfg.icu_output_buf, MULTI_ENTRY_HDR_SIZE)); + TEST_ASSERT_FALSE(memcmp(cfg.input_buf, cfg.icu_output_buf, COLLECTION_HDR_SIZE)); hdr = (void *)cfg.icu_output_buf; - cmp_data = (uint32_t *)hdr->entry; + cmp_data = calloc(4, sizeof(*cmp_data)); + memcpy(cmp_data, hdr->entry, 4 * sizeof(*cmp_data)); TEST_ASSERT_EQUAL_HEX(0x00000080, be32_to_cpu(cmp_data[0])); TEST_ASSERT_EQUAL_HEX(0x00060001, be32_to_cpu(cmp_data[1])); TEST_ASSERT_EQUAL_HEX(0x1E000423, be32_to_cpu(cmp_data[2])); TEST_ASSERT_EQUAL_HEX(0xFFFFE000, be32_to_cpu(cmp_data[3])); + free(cmp_data); free(cfg.input_buf); free(cfg.icu_output_buf); } @@ -2867,7 +2893,7 @@ void test_compress_s_fx_model_multi(void) struct s_fx *up_model_buf; struct cmp_cfg cfg = {0}; int cmp_size; - struct multi_entry_hdr *hdr; + struct collection_hdr *hdr; uint32_t *cmp_data; struct cmp_max_used_bits my_max_used_bits; @@ -2894,7 +2920,7 @@ void test_compress_s_fx_model_multi(void) /* generate input data */ hdr = cfg.input_buf; /* use dummy data for the header */ - memset(hdr, 0x42, sizeof(struct multi_entry_hdr)); + memset(hdr, 0x42, sizeof(struct collection_hdr)); data[0].exp_flags = 0x0; data[0].fx = 0x0; data[1].exp_flags = 0x1; @@ -2912,7 +2938,7 @@ void test_compress_s_fx_model_multi(void) /* generate model data */ hdr = cfg.model_buf; /* use dummy data for the header */ - memset(hdr, 0x41, sizeof(struct multi_entry_hdr)); + memset(hdr, 0x41, sizeof(struct collection_hdr)); model[0].exp_flags = 0x0; model[0].fx = 0x0; model[1].exp_flags = 0x3; @@ -2935,15 +2961,15 @@ void test_compress_s_fx_model_multi(void) cmp_size = icu_compress_data(&cfg); TEST_ASSERT_EQUAL_INT(166, cmp_size); - TEST_ASSERT_FALSE(memcmp(cfg.input_buf, cfg.icu_output_buf, MULTI_ENTRY_HDR_SIZE)); - cmp_data = &cfg.icu_output_buf[MULTI_ENTRY_HDR_SIZE/sizeof(uint32_t)]; + TEST_ASSERT_FALSE(memcmp(cfg.input_buf, cfg.icu_output_buf, COLLECTION_HDR_SIZE)); + cmp_data = &cfg.icu_output_buf[COLLECTION_HDR_SIZE/sizeof(uint32_t)]; TEST_ASSERT_EQUAL_HEX(0x1C77FFA6, be32_to_cpu(cmp_data[0])); TEST_ASSERT_EQUAL_HEX(0xAFFF4DE5, be32_to_cpu(cmp_data[1])); TEST_ASSERT_EQUAL_HEX(0xCC000000, be32_to_cpu(cmp_data[2])); hdr = cfg.icu_new_model_buf; up_model_buf = (struct s_fx *)hdr->entry; - TEST_ASSERT_FALSE(memcmp(hdr, cfg.icu_output_buf, MULTI_ENTRY_HDR_SIZE)); + TEST_ASSERT_FALSE(memcmp(hdr, cfg.icu_output_buf, COLLECTION_HDR_SIZE)); TEST_ASSERT_EQUAL_HEX(0x0, up_model_buf[0].exp_flags); TEST_ASSERT_EQUAL_HEX(0x0, up_model_buf[0].fx); TEST_ASSERT_EQUAL_HEX(0x2, up_model_buf[1].exp_flags); @@ -2970,16 +2996,17 @@ void test_compress_s_fx_model_multi(void) void test_compress_s_fx_error_cases(void) { - int error, cmp_bits, compressed_data_size; + int error, cmp_bits; + uint32_t compressed_data_size; struct cmp_cfg cfg = {0}; uint32_t cmp_par_exp_flags = MAX_NON_IMA_GOLOMB_PAR; uint32_t spillover_exp_flags = 6; uint32_t cmp_par_fx = 2; uint32_t spillover_fx = 8; - uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+3*sizeof(struct s_fx)] = {0}; - uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct s_fx)] = {0}; + uint8_t data_to_compress[COLLECTION_HDR_SIZE+3*sizeof(struct s_fx)] = {0}; + uint8_t compressed_data[COLLECTION_HDR_SIZE+1*sizeof(struct s_fx)] = {0}; struct cmp_max_used_bits my_max_used_bits = MAX_USED_BITS_SAFE; - struct s_fx *data_p = (struct s_fx *)&data_to_compress[MULTI_ENTRY_HDR_SIZE]; + struct s_fx *data_p = (struct s_fx *)&data_to_compress[COLLECTION_HDR_SIZE]; cfg = cmp_cfg_icu_create(DATA_TYPE_S_FX, CMP_MODE_DIFF_ZERO, 0, CMP_LOSSLESS); TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKNOWN); @@ -3031,7 +3058,8 @@ void test_compress_s_fx_error_cases(void) void test_compress_s_fx_efx_error_cases(void) { - int error, cmp_bits, compressed_data_size; + int error, cmp_bits; + uint32_t compressed_data_size; struct cmp_cfg cfg = {0}; uint32_t cmp_par_exp_flags = 2; uint32_t spillover_exp_flags = 6; @@ -3039,10 +3067,10 @@ void test_compress_s_fx_efx_error_cases(void) uint32_t spillover_fx = 8; uint32_t cmp_par_efx = MAX_NON_IMA_GOLOMB_PAR; uint32_t spillover_efx = cmp_icu_max_spill(MAX_NON_IMA_GOLOMB_PAR); - uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+2*sizeof(struct s_fx_efx)] = {0}; - uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct s_fx_efx)] = {0}; + uint8_t data_to_compress[COLLECTION_HDR_SIZE+2*sizeof(struct s_fx_efx)] = {0}; + uint8_t compressed_data[COLLECTION_HDR_SIZE+1*sizeof(struct s_fx_efx)] = {0}; struct cmp_max_used_bits my_max_used_bits = MAX_USED_BITS_SAFE; - struct s_fx_efx *data_p = (struct s_fx_efx *)&data_to_compress[MULTI_ENTRY_HDR_SIZE]; + struct s_fx_efx *data_p = (struct s_fx_efx *)&data_to_compress[COLLECTION_HDR_SIZE]; cfg = cmp_cfg_icu_create(DATA_TYPE_S_FX_EFX, CMP_MODE_DIFF_MULTI, 0, CMP_LOSSLESS); TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKNOWN); @@ -3079,20 +3107,20 @@ void test_compress_s_fx_efx_error_cases(void) cmp_bits = icu_compress_data(&cfg); TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits); - /* error case exp_flag setup */ + /* error case exp_flag */ my_max_used_bits.s_exp_flags = 33; cmp_cfg_icu_max_used_bits(&cfg, &my_max_used_bits); cmp_bits = icu_compress_data(&cfg); TEST_ASSERT_EQUAL_INT(-1, cmp_bits); - /* error case fx setup */ + /* error case fx */ my_max_used_bits.s_exp_flags = 2; my_max_used_bits.s_fx = 33; cmp_cfg_icu_max_used_bits(&cfg, &my_max_used_bits); cmp_bits = icu_compress_data(&cfg); TEST_ASSERT_EQUAL_INT(-1, cmp_bits); - /* error case efx setup */ + /* error case efx */ my_max_used_bits.s_fx = 21; my_max_used_bits.s_efx = 33; cmp_cfg_icu_max_used_bits(&cfg, &my_max_used_bits); @@ -3107,7 +3135,8 @@ void test_compress_s_fx_efx_error_cases(void) void test_compress_s_fx_ncob_error_cases(void) { - int error, cmp_bits, compressed_data_size; + int error, cmp_bits; + uint32_t compressed_data_size; struct cmp_cfg cfg = {0}; uint32_t cmp_par_exp_flags = 3; uint32_t spillover_exp_flags = 6; @@ -3115,11 +3144,11 @@ void test_compress_s_fx_ncob_error_cases(void) uint32_t spillover_fx = 8; uint32_t cmp_par_ncob = MAX_NON_IMA_GOLOMB_PAR; uint32_t spillover_ncob = cmp_icu_max_spill(MAX_NON_IMA_GOLOMB_PAR); - uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+3*sizeof(struct s_fx_ncob)] = {0}; - uint8_t model_data[MULTI_ENTRY_HDR_SIZE+3*sizeof(struct s_fx_ncob)] = {0}; - uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct s_fx_ncob)] = {0}; + uint8_t data_to_compress[COLLECTION_HDR_SIZE+3*sizeof(struct s_fx_ncob)] = {0}; + uint8_t model_data[COLLECTION_HDR_SIZE+3*sizeof(struct s_fx_ncob)] = {0}; + uint8_t compressed_data[COLLECTION_HDR_SIZE+1*sizeof(struct s_fx_ncob)] = {0}; struct cmp_max_used_bits my_max_used_bits = MAX_USED_BITS_SAFE; - struct s_fx_ncob *data_p = (struct s_fx_ncob *)&data_to_compress[MULTI_ENTRY_HDR_SIZE]; + struct s_fx_ncob *data_p = (struct s_fx_ncob *)&data_to_compress[COLLECTION_HDR_SIZE]; my_max_used_bits.s_exp_flags = 2; @@ -3162,20 +3191,20 @@ void test_compress_s_fx_ncob_error_cases(void) TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits); data_p[0].ncob_y = 0x7FFFFFFF; /* value to high */ - /* error case exp_flag setup */ + /* error case exp_flag */ my_max_used_bits.s_exp_flags = 33; cmp_cfg_icu_max_used_bits(&cfg, &my_max_used_bits); cmp_bits = icu_compress_data(&cfg); TEST_ASSERT_EQUAL_INT(-1, cmp_bits); - /* error case fx setup */ + /* error case fx */ my_max_used_bits.s_exp_flags = 2; my_max_used_bits.s_fx = 33; cmp_cfg_icu_max_used_bits(&cfg, &my_max_used_bits); cmp_bits = icu_compress_data(&cfg); TEST_ASSERT_EQUAL_INT(-1, cmp_bits); - /* error case efx setup */ + /* error case efx */ my_max_used_bits.s_fx = 21; my_max_used_bits.s_ncob = 33; cmp_cfg_icu_max_used_bits(&cfg, &my_max_used_bits); @@ -3190,7 +3219,8 @@ void test_compress_s_fx_ncob_error_cases(void) void test_compress_s_fx_efx_ncob_ecob_error_cases(void) { - int error, cmp_bits, compressed_data_size; + int error, cmp_bits; + uint32_t compressed_data_size; struct cmp_cfg cfg = {0}; uint32_t cmp_par_exp_flags = 3; uint32_t spillover_exp_flags = 6; @@ -3202,11 +3232,11 @@ void test_compress_s_fx_efx_ncob_ecob_error_cases(void) uint32_t spillover_efx = cmp_icu_max_spill(MAX_NON_IMA_GOLOMB_PAR); uint32_t cmp_par_ecob = 23; uint32_t spillover_ecob = cmp_icu_max_spill(23); - uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+3*sizeof(struct s_fx_efx_ncob_ecob)] = {0}; - uint8_t model_data[MULTI_ENTRY_HDR_SIZE+3*sizeof(struct s_fx_efx_ncob_ecob)] = {0}; - uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct s_fx_efx_ncob_ecob)] = {0}; + uint8_t data_to_compress[COLLECTION_HDR_SIZE+3*sizeof(struct s_fx_efx_ncob_ecob)] = {0}; + uint8_t model_data[COLLECTION_HDR_SIZE+3*sizeof(struct s_fx_efx_ncob_ecob)] = {0}; + uint8_t compressed_data[COLLECTION_HDR_SIZE+1*sizeof(struct s_fx_efx_ncob_ecob)] = {0}; struct cmp_max_used_bits my_max_used_bits = MAX_USED_BITS_SAFE; - struct s_fx_efx_ncob_ecob *data_p = (struct s_fx_efx_ncob_ecob *)&data_to_compress[MULTI_ENTRY_HDR_SIZE]; + struct s_fx_efx_ncob_ecob *data_p = (struct s_fx_efx_ncob_ecob *)&data_to_compress[COLLECTION_HDR_SIZE]; cfg = cmp_cfg_icu_create(DATA_TYPE_S_FX_EFX_NCOB_ECOB, CMP_MODE_MODEL_ZERO, 0, CMP_LOSSLESS); @@ -3266,20 +3296,20 @@ void test_compress_s_fx_efx_ncob_ecob_error_cases(void) TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits); data_p[1].ecob_y = 0x7F; - /* error case exp_flag setup */ + /* error case exp_flag */ my_max_used_bits.s_exp_flags = 33; cmp_cfg_icu_max_used_bits(&cfg, &my_max_used_bits); cmp_bits = icu_compress_data(&cfg); TEST_ASSERT_EQUAL_INT(-1, cmp_bits); - /* error case fx setup */ + /* error case fx */ my_max_used_bits.s_exp_flags = 32; my_max_used_bits.s_fx = 33; cmp_cfg_icu_max_used_bits(&cfg, &my_max_used_bits); cmp_bits = icu_compress_data(&cfg); TEST_ASSERT_EQUAL_INT(-1, cmp_bits); - /* error case efx setup */ + /* error case efx */ my_max_used_bits.s_fx = 32; my_max_used_bits.s_ncob = 33; cmp_cfg_icu_max_used_bits(&cfg, &my_max_used_bits); @@ -3307,12 +3337,13 @@ void test_compress_s_fx_efx_ncob_ecob_error_cases(void) void test_compress_f_fx_error_cases(void) { - int error, cmp_bits, compressed_data_size; + int error, cmp_bits; + uint32_t compressed_data_size; struct cmp_cfg cfg = {0}; uint32_t cmp_par_fx = MAX_NON_IMA_GOLOMB_PAR; uint32_t spillover_fx = 8; - uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+3*sizeof(struct f_fx)] = {0}; - uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct f_fx)] = {0}; + uint8_t data_to_compress[COLLECTION_HDR_SIZE+3*sizeof(struct f_fx)] = {0}; + uint8_t compressed_data[COLLECTION_HDR_SIZE+1*sizeof(struct f_fx)] = {0}; struct cmp_max_used_bits my_max_used_bits = MAX_USED_BITS_SAFE; my_max_used_bits.f_fx = 23; @@ -3348,16 +3379,17 @@ void test_compress_f_fx_error_cases(void) void test_compress_f_fx_efx_error_cases(void) { - int error, cmp_bits, compressed_data_size; + int error, cmp_bits; + uint32_t compressed_data_size; struct cmp_cfg cfg = {0}; uint32_t cmp_par_fx = 1; uint32_t spillover_fx = 8; uint32_t cmp_par_efx = 1; uint32_t spillover_efx = 8; - uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+2*sizeof(struct f_fx_efx)] = {0}; - uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct f_fx_efx)] = {0}; + uint8_t data_to_compress[COLLECTION_HDR_SIZE+2*sizeof(struct f_fx_efx)] = {0}; + uint8_t compressed_data[COLLECTION_HDR_SIZE+1*sizeof(struct f_fx_efx)] = {0}; struct cmp_max_used_bits my_max_used_bits = MAX_USED_BITS_SAFE; - struct f_fx_efx *data_p = (struct f_fx_efx *)&data_to_compress[MULTI_ENTRY_HDR_SIZE]; + struct f_fx_efx *data_p = (struct f_fx_efx *)&data_to_compress[COLLECTION_HDR_SIZE]; my_max_used_bits.f_fx = 23; my_max_used_bits.f_efx = 31; @@ -3383,6 +3415,13 @@ void test_compress_f_fx_efx_error_cases(void) cmp_bits = icu_compress_data(&cfg); TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, cmp_bits); + /* fx value is to big for the max used bits values */ + data_p[0].fx = 0x800000; + cmp_cfg_icu_max_used_bits(&cfg, &my_max_used_bits); + cmp_bits = icu_compress_data(&cfg); + TEST_ASSERT_EQUAL_INT(CMP_ERROR_HIGH_VALUE, cmp_bits); + data_p[0].fx = 0x7FFFFF; + /* efx value is to big for the max used bits values */ data_p[0].efx = 0x80000000; cmp_cfg_icu_max_used_bits(&cfg, &my_max_used_bits); @@ -3409,16 +3448,17 @@ void test_compress_f_fx_efx_error_cases(void) void test_compress_f_fx_ncob_error_cases(void) { - int error, cmp_bits, compressed_data_size; + int error, cmp_bits; + uint32_t compressed_data_size; struct cmp_cfg cfg = {0}; uint32_t cmp_par_fx = MAX_NON_IMA_GOLOMB_PAR; uint32_t spillover_fx = 8; uint32_t cmp_par_ncob = 1; uint32_t spillover_ncob = 8; - uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+2*sizeof(struct f_fx_ncob)] = {0}; - uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct f_fx_ncob)] = {0}; + uint8_t data_to_compress[COLLECTION_HDR_SIZE+2*sizeof(struct f_fx_ncob)] = {0}; + uint8_t compressed_data[COLLECTION_HDR_SIZE+1*sizeof(struct f_fx_ncob)] = {0}; struct cmp_max_used_bits my_max_used_bits = MAX_USED_BITS_SAFE; - struct f_fx_ncob *data_p = (struct f_fx_ncob *)&data_to_compress[MULTI_ENTRY_HDR_SIZE]; + struct f_fx_ncob *data_p = (struct f_fx_ncob *)&data_to_compress[COLLECTION_HDR_SIZE]; my_max_used_bits.f_fx = 31; my_max_used_bits.f_ncob = 23; @@ -3473,7 +3513,8 @@ void test_compress_f_fx_ncob_error_cases(void) void test_compress_f_fx_efx_ncob_ecob(void) { - int error, cmp_bits, compressed_data_size; + int error, cmp_bits; + uint32_t compressed_data_size; struct cmp_cfg cfg = {0}; uint32_t cmp_par_fx = 1; uint32_t spillover_fx = 8; @@ -3483,10 +3524,10 @@ void test_compress_f_fx_efx_ncob_ecob(void) uint32_t spillover_efx = 44; uint32_t cmp_par_ecob = 5; uint32_t spillover_ecob = 55; - uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+4*sizeof(struct f_fx_efx_ncob_ecob)] = {0}; - uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct f_fx_efx_ncob_ecob)] = {0}; + uint8_t data_to_compress[COLLECTION_HDR_SIZE+4*sizeof(struct f_fx_efx_ncob_ecob)] = {0}; + uint8_t compressed_data[COLLECTION_HDR_SIZE+1*sizeof(struct f_fx_efx_ncob_ecob)] = {0}; struct cmp_max_used_bits my_max_used_bits = MAX_USED_BITS_SAFE; - struct f_fx_efx_ncob_ecob *data_p = (struct f_fx_efx_ncob_ecob *)&data_to_compress[MULTI_ENTRY_HDR_SIZE]; + struct f_fx_efx_ncob_ecob *data_p = (struct f_fx_efx_ncob_ecob *)&data_to_compress[COLLECTION_HDR_SIZE]; cfg = cmp_cfg_icu_create(DATA_TYPE_F_FX_EFX_NCOB_ECOB, CMP_MODE_DIFF_ZERO, 0, CMP_LOSSLESS); TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKNOWN); @@ -3569,7 +3610,8 @@ void test_compress_f_fx_efx_ncob_ecob(void) void test_compress_l_fx_error_cases(void) { - int error, cmp_bits, compressed_data_size; + int error, cmp_bits; + uint32_t compressed_data_size; struct cmp_cfg cfg = {0}; uint32_t cmp_par_exp_flags = 3; uint32_t spillover_exp_flags = 10; @@ -3577,10 +3619,10 @@ void test_compress_l_fx_error_cases(void) uint32_t spillover_fx = 8; uint32_t cmp_par_fx_cob_variance = 30; uint32_t spillover_fx_cob_variance = 8; - uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+3*sizeof(struct l_fx)] = {0}; - uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct l_fx)] = {0}; + uint8_t data_to_compress[COLLECTION_HDR_SIZE+3*sizeof(struct l_fx)] = {0}; + uint8_t compressed_data[COLLECTION_HDR_SIZE+1*sizeof(struct l_fx)] = {0}; struct cmp_max_used_bits my_max_used_bits = MAX_USED_BITS_SAFE; - struct l_fx *data_p = (struct l_fx *)&data_to_compress[MULTI_ENTRY_HDR_SIZE]; + struct l_fx *data_p = (struct l_fx *)&data_to_compress[COLLECTION_HDR_SIZE]; cfg = cmp_cfg_icu_create(DATA_TYPE_L_FX, CMP_MODE_DIFF_ZERO, 0, CMP_LOSSLESS); TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKNOWN); @@ -3643,7 +3685,8 @@ void test_compress_l_fx_error_cases(void) void test_compress_l_fx_efx_error_cases(void) { - int error, cmp_bits, compressed_data_size; + int error, cmp_bits; + uint32_t compressed_data_size; struct cmp_cfg cfg = {0}; uint32_t cmp_par_exp_flags = MAX_NON_IMA_GOLOMB_PAR; uint32_t spillover_exp_flags = cmp_icu_max_spill(cmp_par_exp_flags); @@ -3653,10 +3696,10 @@ void test_compress_l_fx_efx_error_cases(void) uint32_t spillover_efx = 44; uint32_t cmp_par_fx_cob_variance = 30; uint32_t spillover_fx_cob_variance = 8; - uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+3*sizeof(struct l_fx_efx)] = {0}; - uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct l_fx_efx)] = {0}; + uint8_t data_to_compress[COLLECTION_HDR_SIZE+3*sizeof(struct l_fx_efx)] = {0}; + uint8_t compressed_data[COLLECTION_HDR_SIZE+1*sizeof(struct l_fx_efx)] = {0}; struct cmp_max_used_bits my_max_used_bits = MAX_USED_BITS_SAFE; - struct l_fx_efx *data_p = (struct l_fx_efx *)&data_to_compress[MULTI_ENTRY_HDR_SIZE]; + struct l_fx_efx *data_p = (struct l_fx_efx *)&data_to_compress[COLLECTION_HDR_SIZE]; cfg = cmp_cfg_icu_create(DATA_TYPE_L_FX_EFX, CMP_MODE_DIFF_ZERO, 0, CMP_LOSSLESS); TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKNOWN); @@ -3730,7 +3773,8 @@ void test_compress_l_fx_efx_error_cases(void) void test_compress_l_fx_ncob_error_cases(void) { - int error, cmp_bits, compressed_data_size; + int error, cmp_bits; + uint32_t compressed_data_size; struct cmp_cfg cfg = {0}; uint32_t cmp_par_exp_flags = MAX_NON_IMA_GOLOMB_PAR; uint32_t spillover_exp_flags = cmp_icu_max_spill(cmp_par_exp_flags); @@ -3740,10 +3784,10 @@ void test_compress_l_fx_ncob_error_cases(void) uint32_t spillover_ncob = 10; uint32_t cmp_par_fx_cob_variance = 30; uint32_t spillover_fx_cob_variance = 8; - uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+3*sizeof(struct l_fx_ncob)] = {0}; - uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct l_fx_ncob)] = {0}; + uint8_t data_to_compress[COLLECTION_HDR_SIZE+3*sizeof(struct l_fx_ncob)] = {0}; + uint8_t compressed_data[COLLECTION_HDR_SIZE+1*sizeof(struct l_fx_ncob)] = {0}; struct cmp_max_used_bits my_max_used_bits = MAX_USED_BITS_SAFE; - struct l_fx_ncob *data_p = (struct l_fx_ncob *)&data_to_compress[MULTI_ENTRY_HDR_SIZE]; + struct l_fx_ncob *data_p = (struct l_fx_ncob *)&data_to_compress[COLLECTION_HDR_SIZE]; cfg = cmp_cfg_icu_create(DATA_TYPE_L_FX_NCOB, CMP_MODE_DIFF_ZERO, 0, CMP_LOSSLESS); TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKNOWN); @@ -3839,7 +3883,8 @@ void test_compress_l_fx_ncob_error_cases(void) void test_compress_l_fx_efx_ncob_ecob_error_cases(void) { - int error, cmp_bits, compressed_data_size; + int error, cmp_bits; + uint32_t compressed_data_size; struct cmp_cfg cfg = {0}; uint32_t cmp_par_exp_flags = MAX_NON_IMA_GOLOMB_PAR; uint32_t spillover_exp_flags = cmp_icu_max_spill(cmp_par_exp_flags); @@ -3853,10 +3898,10 @@ void test_compress_l_fx_efx_ncob_ecob_error_cases(void) uint32_t spillover_ecob = 55; uint32_t cmp_par_fx_cob_variance = 30; uint32_t spillover_fx_cob_variance = 8; - uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+3*sizeof(struct l_fx_efx_ncob_ecob)] = {0}; - uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct l_fx_efx_ncob_ecob)] = {0}; + uint8_t data_to_compress[COLLECTION_HDR_SIZE+3*sizeof(struct l_fx_efx_ncob_ecob)] = {0}; + uint8_t compressed_data[COLLECTION_HDR_SIZE+1*sizeof(struct l_fx_efx_ncob_ecob)] = {0}; struct cmp_max_used_bits my_max_used_bits = MAX_USED_BITS_SAFE; - struct l_fx_efx_ncob_ecob *data_p = (struct l_fx_efx_ncob_ecob *)&data_to_compress[MULTI_ENTRY_HDR_SIZE]; + struct l_fx_efx_ncob_ecob *data_p = (struct l_fx_efx_ncob_ecob *)&data_to_compress[COLLECTION_HDR_SIZE]; cfg = cmp_cfg_icu_create(DATA_TYPE_L_FX_EFX_NCOB_ECOB, CMP_MODE_DIFF_ZERO, 0, CMP_LOSSLESS); TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKNOWN); @@ -3976,21 +4021,22 @@ void test_compress_l_fx_efx_ncob_ecob_error_cases(void) /** - * @test compress_nc_offset + * @test compress_offset */ -void test_compress_nc_offset_error_cases(void) +void test_compress_offset_error_cases(void) { - int error, cmp_bits, compressed_data_size; + int error, cmp_bits; + uint32_t compressed_data_size; struct cmp_cfg cfg = {0}; uint32_t cmp_par_mean = 1; uint32_t spillover_mean = 2; uint32_t cmp_par_variance = MAX_NON_IMA_GOLOMB_PAR; uint32_t spillover_variance = cmp_icu_max_spill(MAX_NON_IMA_GOLOMB_PAR); - uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+3*sizeof(struct nc_offset)] = {0}; - uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct nc_offset)] = {0}; + uint8_t data_to_compress[COLLECTION_HDR_SIZE+3*sizeof(struct offset)] = {0}; + uint8_t compressed_data[COLLECTION_HDR_SIZE+1*sizeof(struct offset)] = {0}; struct cmp_max_used_bits my_max_used_bits = MAX_USED_BITS_SAFE; - struct nc_offset *data_p = (struct nc_offset *)&data_to_compress[MULTI_ENTRY_HDR_SIZE]; + struct offset *data_p = (struct offset *)&data_to_compress[COLLECTION_HDR_SIZE]; cfg = cmp_cfg_icu_create(DATA_TYPE_OFFSET, CMP_MODE_DIFF_MULTI, 0, CMP_LOSSLESS); TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKNOWN); @@ -4030,16 +4076,30 @@ void test_compress_nc_offset_error_cases(void) cmp_cfg_icu_max_used_bits(&cfg, &my_max_used_bits); cmp_bits = icu_compress_data(&cfg); TEST_ASSERT_EQUAL_INT(-1, cmp_bits); + + + cfg.data_type = DATA_TYPE_F_CAM_OFFSET; + my_max_used_bits.fc_offset_mean = 33; /* more than 32 bits are not allowed */ + cmp_cfg_icu_max_used_bits(&cfg, &my_max_used_bits); + cmp_bits = icu_compress_data(&cfg); + TEST_ASSERT_EQUAL_INT(-1, cmp_bits); + + my_max_used_bits.fc_offset_mean = 32; + my_max_used_bits.fc_offset_variance = 33; /* more than 32 bits are not allowed */ + cmp_cfg_icu_max_used_bits(&cfg, &my_max_used_bits); + cmp_bits = icu_compress_data(&cfg); + TEST_ASSERT_EQUAL_INT(-1, cmp_bits); } /** - * @test compress_nc_background + * @test compress_background */ -void test_compress_nc_background_error_cases(void) +void test_compress_background_error_cases(void) { - int error, cmp_bits, compressed_data_size; + int error, cmp_bits; + uint32_t compressed_data_size; struct cmp_cfg cfg = {0}; uint32_t cmp_par_mean = 1; uint32_t spillover_mean = 2; @@ -4047,10 +4107,10 @@ void test_compress_nc_background_error_cases(void) uint32_t spillover_variance = cmp_icu_max_spill(MAX_NON_IMA_GOLOMB_PAR); uint32_t cmp_par_pixels_error = 23; uint32_t spillover_pixels_error = 42; - uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+3*sizeof(struct nc_background)] = {0}; - uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct nc_background)] = {0}; + uint8_t data_to_compress[COLLECTION_HDR_SIZE+3*sizeof(struct background)] = {0}; + uint8_t compressed_data[COLLECTION_HDR_SIZE+1*sizeof(struct background)] = {0}; struct cmp_max_used_bits my_max_used_bits = MAX_USED_BITS_SAFE; - struct nc_background *data_p = (struct nc_background *)&data_to_compress[MULTI_ENTRY_HDR_SIZE]; + struct background *data_p = (struct background *)&data_to_compress[COLLECTION_HDR_SIZE]; cfg = cmp_cfg_icu_create(DATA_TYPE_BACKGROUND, CMP_MODE_DIFF_MULTI, 0, CMP_LOSSLESS); TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKNOWN); @@ -4102,6 +4162,25 @@ void test_compress_nc_background_error_cases(void) cmp_cfg_icu_max_used_bits(&cfg, &my_max_used_bits); cmp_bits = icu_compress_data(&cfg); TEST_ASSERT_EQUAL_INT(-1, cmp_bits); + + + cfg.data_type = DATA_TYPE_F_CAM_BACKGROUND; + my_max_used_bits.fc_background_mean = 33; /* more than 32 bits are not allowed */ + cmp_cfg_icu_max_used_bits(&cfg, &my_max_used_bits); + cmp_bits = icu_compress_data(&cfg); + TEST_ASSERT_EQUAL_INT(-1, cmp_bits); + + my_max_used_bits.fc_background_mean = 32; + my_max_used_bits.fc_background_variance = 33; /* more than 32 bits are not allowed */ + cmp_cfg_icu_max_used_bits(&cfg, &my_max_used_bits); + cmp_bits = icu_compress_data(&cfg); + TEST_ASSERT_EQUAL_INT(-1, cmp_bits); + + my_max_used_bits.fc_background_variance = 32; + my_max_used_bits.fc_background_outlier_pixels = 33; /* more than 32 bits are not allowed */ + cmp_cfg_icu_max_used_bits(&cfg, &my_max_used_bits); + cmp_bits = icu_compress_data(&cfg); + TEST_ASSERT_EQUAL_INT(-1, cmp_bits); } @@ -4111,7 +4190,8 @@ void test_compress_nc_background_error_cases(void) void test_compress_smearing_error_cases(void) { - int error, cmp_bits, compressed_data_size; + int error, cmp_bits; + uint32_t compressed_data_size; struct cmp_cfg cfg = {0}; uint32_t cmp_par_mean = 1; uint32_t spillover_mean = 2; @@ -4119,10 +4199,10 @@ void test_compress_smearing_error_cases(void) uint32_t spillover_variance = cmp_icu_max_spill(MAX_NON_IMA_GOLOMB_PAR); uint32_t cmp_par_pixels_error = 23; uint32_t spillover_pixels_error = 42; - uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+3*sizeof(struct smearing)] = {0}; - uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct smearing)] = {0}; + uint8_t data_to_compress[COLLECTION_HDR_SIZE+3*sizeof(struct smearing)] = {0}; + uint8_t compressed_data[COLLECTION_HDR_SIZE+1*sizeof(struct smearing)] = {0}; struct cmp_max_used_bits my_max_used_bits = MAX_USED_BITS_SAFE; - struct smearing *data_p = (struct smearing *)&data_to_compress[MULTI_ENTRY_HDR_SIZE]; + struct smearing *data_p = (struct smearing *)&data_to_compress[COLLECTION_HDR_SIZE]; cfg = cmp_cfg_icu_create(DATA_TYPE_SMEARING, CMP_MODE_DIFF_MULTI, 0, CMP_LOSSLESS); TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKNOWN); @@ -4192,7 +4272,7 @@ void test_pad_bitstream(void) memset(cmp_data, 0xFF, sizeof(cmp_data)); cfg.icu_output_buf = cmp_data; cfg.data_type = DATA_TYPE_IMAGETTE; /* 16 bit samples */ - cfg.buffer_length = 6; /* 6 * 16 bit samples -> 3 * 32 bit */ + cfg.buffer_length = sizeof(cmp_data); /* 6 * 16 bit samples -> 3 * 32 bit */ /* test negative cmp_size */ cmp_size = -1; @@ -4242,7 +4322,7 @@ void test_pad_bitstream(void) /* error case the rest of the compressed data are to small dor a 32 bit * access */ - cfg.buffer_length = 5; + cfg.buffer_length -= 1; cmp_size = 64; cmp_size = put_n_bits32(0, 1, cmp_size, cfg.icu_output_buf, MAX_BIT_LEN); cmp_size_return = pad_bitstream(&cfg, cmp_size); @@ -4251,18 +4331,338 @@ void test_pad_bitstream(void) /** - * @test cmp_data_to_big_endian + * @test compress_chunk */ -void test_cmp_data_to_big_endian_error_cases(void) +void test_compress_chunk_raw_singel_col(void) +{ + enum { DATA_SIZE = 2*sizeof(struct s_fx), + CHUNK_SIZE = COLLECTION_HDR_SIZE + DATA_SIZE + }; + uint8_t chunk[CHUNK_SIZE]; + struct collection_hdr *col = (struct collection_hdr *)chunk; + struct s_fx *data = (struct s_fx *)col->entry; + struct cmp_par cmp_par = {0}; + uint32_t *dst; + int cmp_size; + size_t dst_capacity = 43; /* random non zero value */ + + /* create a chunk with a single collection */ + memset(col, 0, COLLECTION_HDR_SIZE); + TEST_ASSERT_FALSE(cmp_col_set_subservice(col, SST_NCxx_S_SCIENCE_S_FX)); + TEST_ASSERT_FALSE(cmp_col_set_data_length(col, DATA_SIZE)); + data[0].exp_flags = 0; + data[0].fx = 1; + data[1].exp_flags = 0xF0; + data[1].fx = 0xABCDE0FF; + + + /* compress the data */ + cmp_par.cmp_mode = CMP_MODE_RAW; + dst = NULL; + + cmp_size = compress_chunk(chunk, CHUNK_SIZE, NULL, NULL, dst, + dst_capacity, &cmp_par); + TEST_ASSERT_EQUAL_INT(GENERIC_HEADER_SIZE + CHUNK_SIZE, cmp_size); + dst_capacity = (size_t)cmp_size; + dst = malloc(dst_capacity); TEST_ASSERT_NOT_NULL(dst); + cmp_size = compress_chunk(chunk, CHUNK_SIZE, NULL, NULL, dst, + dst_capacity, &cmp_par); + TEST_ASSERT_EQUAL_INT(GENERIC_HEADER_SIZE + CHUNK_SIZE, cmp_size); + + /* test results */ + { struct cmp_entity *ent = (struct cmp_entity *)dst; + struct s_fx *raw_cmp_data = (struct s_fx *)( + (uint8_t *)cmp_ent_get_data_buf(ent) + COLLECTION_HDR_SIZE); + + TEST_ASSERT_EQUAL_UINT(CHUNK_SIZE, cmp_ent_get_cmp_data_size(ent)); + TEST_ASSERT_EQUAL_UINT(CHUNK_SIZE, cmp_ent_get_original_size(ent)); + TEST_ASSERT_EQUAL_UINT(cmp_par.cmp_mode, cmp_ent_get_cmp_mode(ent)); + TEST_ASSERT_TRUE(cmp_ent_get_data_type_raw_bit(ent)); + TEST_ASSERT_EQUAL_INT(DATA_TYPE_CHUNK, cmp_ent_get_data_type(ent)); + + TEST_ASSERT_EQUAL_HEX8_ARRAY(col, cmp_ent_get_data_buf(ent), COLLECTION_HDR_SIZE); + + TEST_ASSERT_EQUAL_HEX(data[0].exp_flags, raw_cmp_data[0].exp_flags); + TEST_ASSERT_EQUAL_HEX(data[0].fx, be32_to_cpu(raw_cmp_data[0].fx)); + TEST_ASSERT_EQUAL_HEX(data[1].exp_flags, raw_cmp_data[1].exp_flags); + TEST_ASSERT_EQUAL_HEX(data[1].fx, be32_to_cpu(raw_cmp_data[1].fx)); + } + free(dst); + + /* error case: dst buffer to small */ + dst_capacity -= 1; + dst = malloc(dst_capacity); TEST_ASSERT_NOT_NULL(dst); + cmp_size = compress_chunk(chunk, CHUNK_SIZE, NULL, NULL, dst, + dst_capacity, &cmp_par); + TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, cmp_size); + free(dst); +} + + +void test_compress_chunk_raw_two_col(void) +{ + enum { DATA_SIZE_1 = 2*sizeof(struct s_fx), + DATA_SIZE_2 = 3*sizeof(struct s_fx_efx_ncob_ecob), + CHUNK_SIZE = 2*COLLECTION_HDR_SIZE + DATA_SIZE_1 + DATA_SIZE_2 + }; + uint8_t chunk[CHUNK_SIZE]; + struct collection_hdr *col1 = (struct collection_hdr *)chunk; + struct collection_hdr *col2; + struct s_fx *data1 = (struct s_fx *)col1->entry; + struct s_fx_efx_ncob_ecob *data2; + struct cmp_par cmp_par = {0}; + uint32_t *dst; + int cmp_size; + size_t dst_capacity = 0; + + /* create a chunk with two collection */ + memset(col1, 0, COLLECTION_HDR_SIZE); + TEST_ASSERT_FALSE(cmp_col_set_subservice(col1, SST_NCxx_S_SCIENCE_S_FX)); + TEST_ASSERT_FALSE(cmp_col_set_data_length(col1, DATA_SIZE_1)); + data1[0].exp_flags = 0; + data1[0].fx = 1; + data1[1].exp_flags = 0xF0; + data1[1].fx = 0xABCDE0FF; + col2 = (struct collection_hdr *)(chunk + COLLECTION_HDR_SIZE + DATA_SIZE_1); + memset(col2, 0, COLLECTION_HDR_SIZE); + TEST_ASSERT_FALSE(cmp_col_set_subservice(col2, SST_NCxx_S_SCIENCE_S_FX_EFX_NCOB_ECOB)); + TEST_ASSERT_FALSE(cmp_col_set_data_length(col2, DATA_SIZE_2)); + data2 = (struct s_fx_efx_ncob_ecob *)col2->entry; + data2[0].exp_flags = 1; + data2[0].fx = 2; + data2[0].efx = 3; + data2[0].ncob_x = 4; + data2[0].ncob_y = 5; + data2[0].ecob_x = 6; + data2[0].ecob_y = 7; + data2[1].exp_flags = 0; + data2[1].fx = 0; + data2[1].efx = 0; + data2[1].ncob_x = 0; + data2[1].ncob_y = 0; + data2[1].ecob_x = 0; + data2[1].ecob_y = 0; + data2[2].exp_flags = 0xF; + data2[2].fx = ~0U; + data2[2].efx = ~0U; + data2[2].ncob_x = ~0U; + data2[2].ncob_y = ~0U; + data2[2].ecob_x = ~0U; + data2[2].ecob_y = ~0U; + + /* compress the data */ + cmp_par.cmp_mode = CMP_MODE_RAW; + dst = NULL; + + cmp_size = compress_chunk(chunk, CHUNK_SIZE, NULL, NULL, dst, + dst_capacity, &cmp_par); + TEST_ASSERT_EQUAL_INT(GENERIC_HEADER_SIZE + CHUNK_SIZE, cmp_size); + dst_capacity = (size_t)cmp_size; + dst = malloc(dst_capacity); TEST_ASSERT_NOT_NULL(dst); + cmp_size = compress_chunk(chunk, CHUNK_SIZE, NULL, NULL, dst, + dst_capacity, &cmp_par); + TEST_ASSERT_EQUAL_INT(GENERIC_HEADER_SIZE + CHUNK_SIZE, cmp_size); + + /* test results */ + { struct cmp_entity *ent = (struct cmp_entity *)dst; + struct s_fx *raw_cmp_data1 = (struct s_fx *)( + (uint8_t *)cmp_ent_get_data_buf(ent) + COLLECTION_HDR_SIZE); + struct s_fx_efx_ncob_ecob *raw_cmp_data2 = (struct s_fx_efx_ncob_ecob *)( + (uint8_t *)cmp_ent_get_data_buf(ent) + 2*COLLECTION_HDR_SIZE + + DATA_SIZE_1); + int i; + TEST_ASSERT_EQUAL_UINT(CHUNK_SIZE, cmp_ent_get_cmp_data_size(ent)); + TEST_ASSERT_EQUAL_UINT(CHUNK_SIZE, cmp_ent_get_original_size(ent)); + TEST_ASSERT_EQUAL_UINT(cmp_par.cmp_mode, cmp_ent_get_cmp_mode(ent)); + TEST_ASSERT_TRUE(cmp_ent_get_data_type_raw_bit(ent)); + TEST_ASSERT_EQUAL_INT(DATA_TYPE_CHUNK, cmp_ent_get_data_type(ent)); + + TEST_ASSERT_EQUAL_HEX8_ARRAY(col1, cmp_ent_get_data_buf(ent), COLLECTION_HDR_SIZE); + + for (i = 0; i < 2; i++) { + TEST_ASSERT_EQUAL_HEX(data1[i].exp_flags, raw_cmp_data1[i].exp_flags); + TEST_ASSERT_EQUAL_HEX(data1[i].fx, be32_to_cpu(raw_cmp_data1[i].fx)); + } + + TEST_ASSERT_EQUAL_HEX8_ARRAY(col1, cmp_ent_get_data_buf(ent), COLLECTION_HDR_SIZE); + + for (i = 0; i < 2; i++) { + TEST_ASSERT_EQUAL_HEX(data1[i].exp_flags, raw_cmp_data1[i].exp_flags); + TEST_ASSERT_EQUAL_HEX(data1[i].fx, be32_to_cpu(raw_cmp_data1[i].fx)); + } + + TEST_ASSERT_EQUAL_HEX8_ARRAY(col2, (uint8_t *)cmp_ent_get_data_buf(ent)+cmp_col_get_size(col1), COLLECTION_HDR_SIZE); + + for (i = 0; i < 2; i++) { + TEST_ASSERT_EQUAL_HEX(data2[i].exp_flags, raw_cmp_data2[i].exp_flags); + TEST_ASSERT_EQUAL_HEX(data2[i].fx, be32_to_cpu(raw_cmp_data2[i].fx)); + TEST_ASSERT_EQUAL_HEX(data2[i].efx, be32_to_cpu(raw_cmp_data2[i].efx)); + TEST_ASSERT_EQUAL_HEX(data2[i].ncob_x, be32_to_cpu(raw_cmp_data2[i].ncob_x)); + TEST_ASSERT_EQUAL_HEX(data2[i].ncob_y, be32_to_cpu(raw_cmp_data2[i].ncob_y)); + TEST_ASSERT_EQUAL_HEX(data2[i].ecob_x, be32_to_cpu(raw_cmp_data2[i].ecob_x)); + TEST_ASSERT_EQUAL_HEX(data2[i].ecob_y, be32_to_cpu(raw_cmp_data2[i].ecob_y)); + } + } + free(dst); + + /* error case: dst buffer to small */ + dst_capacity -= 1; + dst = malloc(dst_capacity); TEST_ASSERT_NOT_NULL(dst); + cmp_size = compress_chunk(chunk, CHUNK_SIZE, NULL, NULL, dst, + dst_capacity, &cmp_par); + TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, cmp_size); + free(dst); +} + +void NOOO_test_compress_chunk_model(void) +{ + enum { DATA_SIZE_1 = 1*sizeof(struct background), + DATA_SIZE_2 = 2*sizeof(struct offset), + CHUNK_SIZE = 2*COLLECTION_HDR_SIZE + DATA_SIZE_1 + DATA_SIZE_2 + }; + uint8_t chunk[CHUNK_SIZE]; + uint8_t chunk_model[CHUNK_SIZE]; + uint8_t chunk_up_model[CHUNK_SIZE]; + struct collection_hdr *col1 = (struct collection_hdr *)chunk; + struct collection_hdr *col2; + struct background *data1 = (struct background *)col1->entry; + struct offset *data2; + struct cmp_par cmp_par = {0}; + uint32_t *dst; + int cmp_size; + size_t dst_capacity = 0; + + /* create a chunk with two collection */ + memset(col1, 0, COLLECTION_HDR_SIZE); + TEST_ASSERT_FALSE(cmp_col_set_subservice(col1, SST_NCxx_S_SCIENCE_BACKGROUND)); + TEST_ASSERT_FALSE(cmp_col_set_data_length(col1, DATA_SIZE_1)); + data1[0].mean = 0; + data1[0].variance = 1; + data1[0].outlier_pixels = 0xF0; + col2 = (struct collection_hdr *)(chunk + COLLECTION_HDR_SIZE + DATA_SIZE_1); + memset(col2, 0, COLLECTION_HDR_SIZE); + TEST_ASSERT_FALSE(cmp_col_set_subservice(col2, SST_NCxx_S_SCIENCE_OFFSET)); + TEST_ASSERT_FALSE(cmp_col_set_data_length(col2, DATA_SIZE_2)); + data2 = (struct offset *)col2->entry; + data2[0].mean = 1; + data2[0].variance = 2; + data2[1].mean = 3; + data2[1].variance = 4; + + /* create a model with two collection */ + col1 = (struct collection_hdr *)chunk_model; + memset(col1, 0, COLLECTION_HDR_SIZE); + TEST_ASSERT_FALSE(cmp_col_set_subservice(col1, SST_NCxx_S_SCIENCE_BACKGROUND)); + TEST_ASSERT_FALSE(cmp_col_set_data_length(col1, DATA_SIZE_1)); + data1[0].mean = 1; + data1[0].variance = 2; + data1[0].outlier_pixels = 0xFFFF; + col2 = (struct collection_hdr *)(chunk + COLLECTION_HDR_SIZE + DATA_SIZE_1); + memset(col2, 0, COLLECTION_HDR_SIZE); + TEST_ASSERT_FALSE(cmp_col_set_subservice(col2, SST_NCxx_S_SCIENCE_OFFSET)); + TEST_ASSERT_FALSE(cmp_col_set_data_length(col2, DATA_SIZE_2)); + data2 = (struct offset *)col2->entry; + data2[0].mean = 0; + data2[0].variance = 0; + data2[1].mean = 0; + data2[1].variance = 0xEFFFFFFF; + + /* compress the data */ + cmp_par.cmp_mode = CMP_MODE_MODEL_ZERO; + cmp_par.model_value = 14; + cmp_par.nc_offset_mean = 1; + cmp_par.nc_offset_variance = 2; + cmp_par.nc_background_mean = 3; + cmp_par.nc_background_variance = 4; + cmp_par.nc_background_outlier_pixels = 5; + dst = NULL; + + uint32_t chunk_size = COLLECTION_HDR_SIZE + DATA_SIZE_1; + /* chunk_size = CHUNK_SIZE; */ + /* int */ + + cmp_size = compress_chunk(chunk, chunk_size, chunk_model, chunk_up_model, dst, + dst_capacity, &cmp_par); + TEST_ASSERT_EQUAL_INT(NON_IMAGETTE_HEADER_SIZE + COLLECTION_HDR_SIZE + 4, cmp_size); + dst_capacity = (size_t)cmp_size; + dst = malloc(dst_capacity); TEST_ASSERT_NOT_NULL(dst); + cmp_size = compress_chunk(chunk, CHUNK_SIZE, NULL, NULL, dst, + dst_capacity, &cmp_par); + TEST_ASSERT_EQUAL_INT(GENERIC_HEADER_SIZE + CHUNK_SIZE, cmp_size); + + /* test results */ + { struct cmp_entity *ent = (struct cmp_entity *)dst; + struct s_fx *raw_cmp_data1 = (struct s_fx *)( + (uint8_t *)cmp_ent_get_data_buf(ent) + COLLECTION_HDR_SIZE); + struct s_fx_efx_ncob_ecob *raw_cmp_data2 = (struct s_fx_efx_ncob_ecob *)( + (uint8_t *)cmp_ent_get_data_buf(ent) + 2*COLLECTION_HDR_SIZE + + DATA_SIZE_1); + int i; + TEST_ASSERT_EQUAL_UINT(CHUNK_SIZE, cmp_ent_get_cmp_data_size(ent)); + TEST_ASSERT_EQUAL_UINT(CHUNK_SIZE, cmp_ent_get_original_size(ent)); + TEST_ASSERT_EQUAL_UINT(cmp_par.cmp_mode, cmp_ent_get_cmp_mode(ent)); + TEST_ASSERT_TRUE(cmp_ent_get_data_type_raw_bit(ent)); + TEST_ASSERT_EQUAL_INT(DATA_TYPE_CHUNK, cmp_ent_get_data_type(ent)); + + TEST_ASSERT_EQUAL_HEX8_ARRAY(col1, cmp_ent_get_data_buf(ent), COLLECTION_HDR_SIZE); + +#if 0 + for (i = 0; i < 2; i++) { + TEST_ASSERT_EQUAL_HEX(data1[i].exp_flags, raw_cmp_data1[i].exp_flags); + TEST_ASSERT_EQUAL_HEX(data1[i].fx, be32_to_cpu(raw_cmp_data1[i].fx)); + } + + TEST_ASSERT_EQUAL_HEX8_ARRAY(col1, cmp_ent_get_data_buf(ent), COLLECTION_HDR_SIZE); + + for (i = 0; i < 2; i++) { + TEST_ASSERT_EQUAL_HEX(data1[i].exp_flags, raw_cmp_data1[i].exp_flags); + TEST_ASSERT_EQUAL_HEX(data1[i].fx, be32_to_cpu(raw_cmp_data1[i].fx)); + } + + TEST_ASSERT_EQUAL_HEX8_ARRAY(col2, (uint8_t *)cmp_ent_get_data_buf(ent)+cmp_col_get_size(col1), COLLECTION_HDR_SIZE); + + for (i = 0; i < 2; i++) { + TEST_ASSERT_EQUAL_HEX(data2[i].exp_flags, raw_cmp_data2[i].exp_flags); + TEST_ASSERT_EQUAL_HEX(data2[i].fx, be32_to_cpu(raw_cmp_data2[i].fx)); + TEST_ASSERT_EQUAL_HEX(data2[i].efx, be32_to_cpu(raw_cmp_data2[i].efx)); + TEST_ASSERT_EQUAL_HEX(data2[i].ncob_x, be32_to_cpu(raw_cmp_data2[i].ncob_x)); + TEST_ASSERT_EQUAL_HEX(data2[i].ncob_y, be32_to_cpu(raw_cmp_data2[i].ncob_y)); + TEST_ASSERT_EQUAL_HEX(data2[i].ecob_x, be32_to_cpu(raw_cmp_data2[i].ecob_x)); + TEST_ASSERT_EQUAL_HEX(data2[i].ecob_y, be32_to_cpu(raw_cmp_data2[i].ecob_y)); + } +#endif + } + free(dst); + + /* error case: dst buffer to small */ + dst_capacity -= 1; + dst = malloc(dst_capacity); TEST_ASSERT_NOT_NULL(dst); + cmp_size = compress_chunk(chunk, CHUNK_SIZE, NULL, NULL, dst, + dst_capacity, &cmp_par); + TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, cmp_size); + free(dst); +} +/* TODO: chunk tests + * collection with 0 length; + * collection with wrong mix collections; + */ + +/** + * @test cmp_data_to_big_endian + */ +#if 0 +void notest_cmp_data_to_big_endian_error_cases(void) { struct cmp_cfg cfg = {0}; int cmp_size; int cmp_size_return; uint16_t cmp_data[3] = {0x0123, 0x4567, 0x89AB}; + uint32_t output_buf[2] = {0}; uint8_t *p; - cfg.icu_output_buf = (uint32_t *)cmp_data; + memcpy(output_buf, cmp_data, sizeof(cmp_data)); + cfg.icu_output_buf = output_buf; /* this should work */ cfg.data_type = DATA_TYPE_IMAGETTE; @@ -4306,6 +4706,7 @@ void test_cmp_data_to_big_endian_error_cases(void) cmp_size_return = cmp_data_to_big_endian(&cfg, cmp_size); TEST_ASSERT_EQUAL_INT(cmp_size_return, -1); } +#endif /** @@ -4334,7 +4735,7 @@ void test_icu_compress_data_error_cases(void) void test_zero_escape_mech_is_used(void) { - int cmp_mode; + enum cmp_mode cmp_mode; for (cmp_mode = 0; cmp_mode <= CMP_MODE_STUFF; cmp_mode++) { int res = zero_escape_mech_is_used(cmp_mode); @@ -4350,9 +4751,12 @@ void test_zero_escape_mech_is_used(void) void test_support_function_call_NULL(void) { + struct cmp_cfg cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_DIFF_ZERO, 16, CMP_LOSSLESS); + TEST_ASSERT_TRUE(cmp_cfg_gen_par_is_invalid(NULL, ICU_CHECK)); + TEST_ASSERT_TRUE(cmp_cfg_gen_par_is_invalid(&cfg, RDCU_CHECK+1)); TEST_ASSERT_TRUE(cmp_cfg_icu_buffers_is_invalid(NULL)); - TEST_ASSERT_TRUE(cmp_cfg_imagette_is_invalid(NULL, ICU_CHECK)); + TEST_ASSERT_TRUE(cmp_cfg_imagette_is_invalid(NULL, RDCU_CHECK)); TEST_ASSERT_TRUE(cmp_cfg_fx_cob_is_invalid(NULL)); TEST_ASSERT_TRUE(cmp_cfg_aux_is_invalid(NULL)); TEST_ASSERT_TRUE(cmp_cfg_icu_is_invalid(NULL)); diff --git a/test/cmp_icu/test_decmp.c b/test/cmp_icu/test_decmp.c deleted file mode 100644 index 86993365c45170f68db75095ba7e167deebc7545..0000000000000000000000000000000000000000 --- a/test/cmp_icu/test_decmp.c +++ /dev/null @@ -1,1473 +0,0 @@ -/** - * @file test_decmp.c - * @author Dominik Loidolt (dominik.loidolt@univie.ac.at) - * @date 2022 - * - * @copyright GPLv2 - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * @brief decompression tests - */ - - -#include <string.h> -#include <stdlib.h> - -#if defined __has_include -# if __has_include(<time.h>) -# include <time.h> -# include <unistd.h> -# define HAS_TIME_H 1 -# endif -#endif - -#include "unity.h" - -#include "compiler.h" -#include "cmp_debug.h" -#include "cmp_entity.h" -#include "../../lib/cmp_icu.c" /* .c file included to test static functions */ -#include "../../lib/decmp.c" /* .c file included to test static functions */ - - -#define IMAX_BITS(m) ((m)/((m)%255+1) / 255%255*8 + 7-86/((m)%255+12)) -#define RAND_MAX_WIDTH IMAX_BITS(RAND_MAX) - -/* TODO: clean up this file */ - -/** - * @brief generate a uint32_t random number - * - * @return a "random" uint32_t value - * @see https://stackoverflow.com/a/33021408 - */ - -uint32_t rand32(void) -{ - int i; - uint32_t r = 0; - - for (i = 0; i < 32; i += RAND_MAX_WIDTH) { - r <<= RAND_MAX_WIDTH; - r ^= (unsigned int) rand(); - } - return r; -} - - -/** - * returns the needed size of the compression entry header plus the max size of the - * compressed data if ent == NULL if ent is set the size of the compression - * entry (entity header + compressed data) - */ -size_t icu_compress_data_entity(struct cmp_entity *ent, const struct cmp_cfg *cfg) -{ - size_t s; - struct cmp_cfg cfg_cpy; - int cmp_size_bits; - - if (!cfg) - return 0; - - if (cfg->icu_output_buf) - debug_print("Warning the set buffer for the compressed data is ignored! The compressed data are write to the compression entry."); - - s = cmp_cal_size_of_data(cfg->buffer_length, cfg->data_type); - if (!s) - return 0; - /* we round down to the next 4-byte allied address because we access the - * cmp_buffer in uint32_t words - */ - if (cfg->cmp_mode != CMP_MODE_RAW) - s &= ~0x3U; - - s = cmp_ent_create(ent, cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW, s); - - if (!ent || !s) - return s; - - cfg_cpy = *cfg; - cfg_cpy.icu_output_buf = cmp_ent_get_data_buf(ent); - if (!cfg_cpy.icu_output_buf) - return 0; - cmp_size_bits = icu_compress_data(&cfg_cpy); - if (cmp_size_bits < 0) - return 0; - - /* XXX overwrite the size of the compression entity with the size of the actual - * size of the compressed data; not all allocated memory is normally used */ - s = cmp_ent_create(ent, cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW, - cmp_bit_to_4byte(cmp_size_bits)); - - if (cmp_ent_write_cmp_pars(ent, cfg, cmp_size_bits)) - return 0; - - - return s; -} - - -void test_cmp_decmp_n_imagette_raw(void) -{ - int cmp_size; - size_t s, i; - struct cmp_cfg cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_RAW, 0, CMP_LOSSLESS); - uint16_t data[] = {0, 1, 2, 0x42, INT16_MIN, INT16_MAX, UINT16_MAX}; - uint32_t *compressed_data; - uint16_t *decompressed_data; - struct cmp_entity *ent; - - s = cmp_cfg_icu_buffers(&cfg, data, ARRAY_SIZE(data), NULL, NULL, - NULL, ARRAY_SIZE(data)); - TEST_ASSERT_TRUE(s); - compressed_data = malloc(s); - TEST_ASSERT_TRUE(compressed_data); - s = cmp_cfg_icu_buffers(&cfg, data, ARRAY_SIZE(data), NULL, NULL, - compressed_data, ARRAY_SIZE(data)); - TEST_ASSERT_TRUE(s); - - cmp_size = icu_compress_data(&cfg); - TEST_ASSERT_EQUAL_INT(sizeof(data)*CHAR_BIT, cmp_size); - - s = cmp_ent_build(NULL, 0, 0, 0, 0, 0, &cfg, cmp_bit_to_4byte(cmp_size)); - TEST_ASSERT_TRUE(s); - ent = malloc(s); - TEST_ASSERT_TRUE(ent); - s = cmp_ent_build(ent, 0, 0, 0, 0, 0, &cfg, cmp_bit_to_4byte(cmp_size)); - TEST_ASSERT_TRUE(s); - memcpy(cmp_ent_get_data_buf(ent), compressed_data, (cmp_size+7)/8); - - s = decompress_cmp_entiy(ent, NULL, NULL, NULL); - TEST_ASSERT_EQUAL_INT(sizeof(data), s); - decompressed_data = malloc(s); - TEST_ASSERT_TRUE(decompressed_data); - s = decompress_cmp_entiy(ent, NULL, NULL, decompressed_data); - TEST_ASSERT_EQUAL_INT(sizeof(data), s); - - for (i = 0; i < ARRAY_SIZE(data); ++i) - TEST_ASSERT_EQUAL_INT(data[i], decompressed_data[i]); - - - free(compressed_data); - free(ent); - free(decompressed_data); -} - - -/** - * @test count_leading_ones - */ - -void test_count_leading_ones(void) -{ - unsigned int n_leading_bit; - uint32_t value; - - value = 0; - n_leading_bit = count_leading_ones(value); - TEST_ASSERT_EQUAL_INT(0, n_leading_bit); - - value = 0x7FFFFFFF; - n_leading_bit = count_leading_ones(value); - TEST_ASSERT_EQUAL_INT(0, n_leading_bit); - - value = 0x80000000; - n_leading_bit = count_leading_ones(value); - TEST_ASSERT_EQUAL_INT(1, n_leading_bit); - - value = 0xBFFFFFFF; - n_leading_bit = count_leading_ones(value); - TEST_ASSERT_EQUAL_INT(1, n_leading_bit); - - value = 0xFFFF0000; - n_leading_bit = count_leading_ones(value); - TEST_ASSERT_EQUAL_INT(16, n_leading_bit); - - value = 0xFFFF7FFF; - n_leading_bit = count_leading_ones(value); - TEST_ASSERT_EQUAL_INT(16, n_leading_bit); - - value = 0xFFFFFFFF; - n_leading_bit = count_leading_ones(value); - TEST_ASSERT_EQUAL_INT(32, n_leading_bit); -} - - -/** - * @test rice_decoder - */ - -void test_rice_decoder(void) -{ - int cw_len; - uint32_t code_word; - unsigned int m = ~0; /* we don't need this value */ - unsigned int log2_m; - uint32_t decoded_cw; - - /* test log_2 to big */ - code_word = 0xE0000000; - log2_m = 33; - cw_len = rice_decoder(code_word, m, log2_m, &decoded_cw); - TEST_ASSERT_EQUAL(0, cw_len); - log2_m = UINT_MAX; - cw_len = rice_decoder(code_word, m, log2_m, &decoded_cw); - TEST_ASSERT_EQUAL(0, cw_len); -} - - -/** - * @test re_map_to_pos - */ - -void test_re_map_to_pos(void) -{ - int j; - uint32_t input, result; - unsigned int max_value_bits; - - input = INT32_MIN; - result = re_map_to_pos(map_to_pos(input, 32)); - TEST_ASSERT_EQUAL_INT32(input, result); - - input = INT32_MAX; - result = re_map_to_pos(map_to_pos(input, 32)); - TEST_ASSERT_EQUAL_INT32(input, result); - - input = -1; - result = re_map_to_pos(map_to_pos(input, 32)); - TEST_ASSERT_EQUAL_INT32(input, result); - - input = 0; - result = re_map_to_pos(map_to_pos(input, 32)); - TEST_ASSERT_EQUAL_INT32(input, result); - - input = 1; max_value_bits = 6; - result = re_map_to_pos(map_to_pos(input, max_value_bits)); - TEST_ASSERT_EQUAL_INT32(input, result); - - for (j = -16; j < 15; j++) { - uint32_t map_val = map_to_pos(j, 16) & 0x3F; - result = re_map_to_pos(map_val); - TEST_ASSERT_EQUAL_INT32(j, result); - } - - for (j = INT16_MIN; j < INT16_MAX; j++) { - uint32_t map_val = map_to_pos(j, 16) & 0xFFFF; - - result = re_map_to_pos(map_val); - TEST_ASSERT_EQUAL_INT32(j, result); - } -#if 0 - for (j = INT32_MIN; j < INT32_MAX; j++) { - result = re_map_to_pos(map_to_pos(j, 32)); - TEST_ASSERT_EQUAL_INT32(j, result); - } -#endif -} - - -void test_decode_normal(void) -{ - uint32_t decoded_value = ~0; - int stream_pos, sample; - /* compressed data from 0 to 6; */ - uint32_t cmp_data[1] = {0x5BBDF7E0}; - struct decoder_setup setup = {0}; - - cpu_to_be32s(cmp_data); - - setup.decode_cw_f = rice_decoder; - setup.encoder_par1 = 1; - setup.encoder_par2 = ilog_2(setup.encoder_par1); - setup.bitstream_adr = cmp_data; - setup.max_stream_len = 32; - - stream_pos = 0; - for (sample = 0; sample < 7; sample++) { - stream_pos = decode_normal(&decoded_value, stream_pos, &setup); - TEST_ASSERT_EQUAL_HEX(sample, decoded_value); - } - - /* TODO error case: negative stream_pos */ -} - - -void test_decode_zero(void) -{ - uint32_t decoded_value = ~0; - int stream_pos; - uint32_t cmp_data[] = {0x88449FE0}; - struct decoder_setup setup = {0}; - struct cmp_cfg cfg = {0}; - - cpu_to_be32s(cmp_data); - - cfg.data_type = DATA_TYPE_IMAGETTE; - cfg.cmp_mode = CMP_MODE_DIFF_ZERO; - cfg.icu_output_buf = cmp_data; - cfg.buffer_length = 4; - - int err = configure_decoder_setup(&setup, 1, 8, CMP_LOSSLESS, 16, &cfg); - TEST_ASSERT_FALSE(err); - - stream_pos = 0; - - stream_pos = decode_zero(&decoded_value, stream_pos, &setup); - TEST_ASSERT_EQUAL_HEX(0, decoded_value); - stream_pos = decode_zero(&decoded_value, stream_pos, &setup); - TEST_ASSERT_EQUAL_HEX(0x4223, decoded_value); - stream_pos = decode_zero(&decoded_value, stream_pos, &setup); - TEST_ASSERT_EQUAL_HEX(7, decoded_value); - TEST_ASSERT_EQUAL_INT(28, stream_pos); - - /* TODO error case: negative stream_pos */ -} - -void test_decode_multi(void) -{ - uint32_t decoded_value = ~0; - int stream_pos; - uint32_t cmp_data[] = {0x16B66DF8, 0x84360000}; - struct decoder_setup setup = {0}; - struct cmp_cfg cfg = {0}; - int err; - - cpu_to_be32s(&cmp_data[0]); - cpu_to_be32s(&cmp_data[1]); - - cfg.data_type = DATA_TYPE_IMAGETTE; - cfg.cmp_mode = CMP_MODE_DIFF_MULTI; - cfg.icu_output_buf = cmp_data; - cfg.buffer_length = 8; - - err = configure_decoder_setup(&setup, 3, 8, CMP_LOSSLESS, 16, &cfg); - TEST_ASSERT_FALSE(err); - - stream_pos = 0; - - stream_pos = decode_multi(&decoded_value, stream_pos, &setup); - TEST_ASSERT_EQUAL_HEX(0, decoded_value); - stream_pos = decode_multi(&decoded_value, stream_pos, &setup); - TEST_ASSERT_EQUAL_HEX(1, decoded_value); - stream_pos = decode_multi(&decoded_value, stream_pos, &setup); - TEST_ASSERT_EQUAL_HEX(7, decoded_value); - stream_pos = decode_multi(&decoded_value, stream_pos, &setup); - TEST_ASSERT_EQUAL_HEX(8, decoded_value); - stream_pos = decode_multi(&decoded_value, stream_pos, &setup); - TEST_ASSERT_EQUAL_HEX(9, decoded_value); - stream_pos = decode_multi(&decoded_value, stream_pos, &setup); - TEST_ASSERT_EQUAL_HEX(0x4223, decoded_value); - TEST_ASSERT_EQUAL_INT(47, stream_pos); - -} - - -void test_decompress_imagette_model(void) -{ - uint16_t data[5] = {0}; - uint16_t model[5] = {0, 1, 2, 3, 4}; - uint16_t up_model[5] = {0}; - uint32_t cmp_data[] = {0}; - struct cmp_cfg cfg = {0}; - int stream_pos; - - cmp_data[0] = cpu_to_be32(0x49240000); - - cfg.data_type = DATA_TYPE_IMAGETTE; - cfg.cmp_mode = CMP_MODE_MODEL_MULTI; - cfg.input_buf = data; - cfg.model_buf = model; - cfg.icu_new_model_buf = up_model; - cfg.icu_output_buf = cmp_data; - cfg.buffer_length = 4; - cfg.samples = 5; - cfg.model_value = 16; - cfg.golomb_par = 4; - cfg.spill = 48; - cfg.max_used_bits = &MAX_USED_BITS_SAFE; - - stream_pos = decompress_imagette(&cfg); - TEST_ASSERT_EQUAL_INT(15, stream_pos); - TEST_ASSERT_EQUAL_HEX(1, data[0]); - TEST_ASSERT_EQUAL_HEX(2, data[1]); - TEST_ASSERT_EQUAL_HEX(3, data[2]); - TEST_ASSERT_EQUAL_HEX(4, data[3]); - TEST_ASSERT_EQUAL_HEX(5, data[4]); - - TEST_ASSERT_EQUAL_HEX(0, up_model[0]); - TEST_ASSERT_EQUAL_HEX(1, up_model[1]); - TEST_ASSERT_EQUAL_HEX(2, up_model[2]); - TEST_ASSERT_EQUAL_HEX(3, up_model[3]); - TEST_ASSERT_EQUAL_HEX(4, up_model[4]); -} - - - -#define DATA_SAMPLES 5 -void test_cmp_decmp_s_fx_diff(void) -{ - size_t s; - int err; - - struct cmp_entity *ent; - const uint32_t MAX_VALUE = ~(~0U << MAX_USED_BITS_V1.s_fx); - struct s_fx data_entry[DATA_SAMPLES] = { - {0, 0}, {1, 23}, {2, 42}, {3, MAX_VALUE}, {3, MAX_VALUE>>1} }; - uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE + sizeof(data_entry)]; - struct s_fx *decompressed_data = NULL; - /* uint32_t *compressed_data = NULL; */ - uint32_t compressed_data_len_samples = DATA_SAMPLES; - struct cmp_cfg cfg; - - for (s = 0; s < MULTI_ENTRY_HDR_SIZE; s++) - data_to_compress[s] = s; - memcpy(&data_to_compress[MULTI_ENTRY_HDR_SIZE], data_entry, sizeof(data_entry)); - - cfg = cmp_cfg_icu_create(DATA_TYPE_S_FX, CMP_MODE_DIFF_MULTI, - CMP_PAR_UNUSED, CMP_LOSSLESS); - TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKNOWN); - - s = cmp_cfg_icu_buffers(&cfg, data_to_compress, DATA_SAMPLES, NULL, NULL, - NULL, compressed_data_len_samples); - TEST_ASSERT_TRUE(s); - - err = cmp_cfg_fx_cob(&cfg, 2, 6, 4, 14, CMP_PAR_UNUSED, CMP_PAR_UNUSED, - CMP_PAR_UNUSED, CMP_PAR_UNUSED, CMP_PAR_UNUSED, - CMP_PAR_UNUSED, CMP_PAR_UNUSED, CMP_PAR_UNUSED); - TEST_ASSERT_FALSE(err); - - s = icu_compress_data_entity(NULL, &cfg); - TEST_ASSERT_TRUE(s); - ent = malloc(s); TEST_ASSERT_TRUE(ent); - s = icu_compress_data_entity(ent, &cfg); - TEST_ASSERT_TRUE(s); - - /* now decompress the data */ - s = decompress_cmp_entiy(ent, NULL, NULL, decompressed_data); - TEST_ASSERT_EQUAL_INT(cmp_cal_size_of_data(cfg.samples, cfg.data_type), s); - decompressed_data = malloc(s); TEST_ASSERT_TRUE(decompressed_data); - s = decompress_cmp_entiy(ent, NULL, NULL, decompressed_data); - TEST_ASSERT_EQUAL_INT(cmp_cal_size_of_data(cfg.samples, cfg.data_type), s); - - TEST_ASSERT_FALSE(memcmp(data_to_compress, decompressed_data, s)); - /* for (i = 0; i < samples; ++i) { */ - /* printf("%u == %u (round: %u)\n", data[i], decompressed_data[i], round); */ - /* uint32_t mask = ~0U << round; */ - /* if ((data[i]&mask) != (decompressed_data[i]&mask)) */ - /* TEST_ASSERT(0); */ - /* if (model_mode_is_used(cmp_mode)) */ - /* if (up_model[i] != de_up_model[i]) */ - /* TEST_ASSERT(0); */ - /* } */ - free(ent); - free(decompressed_data); -} -#undef DATA_SAMPLES - - -int my_random(unsigned int min, unsigned int max) -{ - TEST_ASSERT(min < max); - if (max-min < RAND_MAX) - return min + rand() / (RAND_MAX / (max - min + 1ULL) + 1); - else - return min + rand32() / (UINT32_MAX / (max - min + 1ULL) + 1); - -} - -/* #include <cmp_io.h> */ -/* void test_imagette_1(void) */ -/* { */ -/* size_t i; */ - -/* enum cmp_mode cmp_mode = 1; */ -/* uint16_t model_value = 10; */ -/* struct cmp_cfg cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, cmp_mode, model_value, CMP_LOSSLESS); */ -/* unsigned int samples = 1; */ -/* uint16_t data[1] = {0x8000}; */ -/* uint16_t model[1] = {0}; */ -/* uint16_t up_model[1] = {0}; */ -/* uint16_t de_up_model[1] = {0}; */ -/* uint32_t compressed_data[1]; */ - -/* size_t s = cmp_cfg_buffers(&cfg, data, samples, model, up_model, */ -/* compressed_data, 2*samples); */ -/* TEST_ASSERT(s > 0); */ - -/* uint32_t golomb_par = 9; */ -/* uint32_t spill = 44; */ - -/* cfg.spill = spill; */ -/* cfg.golomb_par = golomb_par; */ -/* /1* print_cfg(&cfg, 0); *1/ */ -/* int cmp_size = icu_compress_data(&cfg, NULL); */ -/* TEST_ASSERT(cmp_size > 0); */ - - -/* s = cmp_ent_build(NULL, 0, 0, 0, 0, 0, &cfg, cmp_size); */ -/* TEST_ASSERT_TRUE(s); */ -/* struct cmp_entity *ent = malloc(s); */ -/* TEST_ASSERT_TRUE(ent); */ -/* s = cmp_ent_build(ent, 0, 0, 0, 0, 0, &cfg, cmp_size); */ -/* TEST_ASSERT_TRUE(s); */ -/* memcpy(cmp_ent_get_data_buf(ent), compressed_data, cmp_bit_to_4byte(cmp_size)); */ - -/* s = decompress_cmp_entiy(ent, model, de_up_model, NULL); */ -/* TEST_ASSERT_EQUAL_INT(samples * sizeof(*data), s); */ -/* uint16_t *decompressed_data = malloc(s); */ -/* TEST_ASSERT_TRUE(decompressed_data); */ -/* s = decompress_cmp_entiy(ent, model, de_up_model, decompressed_data); */ -/* TEST_ASSERT_EQUAL_INT(samples * sizeof(*data), s); */ - -/* for (i = 0; i < samples; ++i) { */ -/* if (data[i] != decompressed_data[i]) */ -/* TEST_ASSERT(0); */ -/* /1* TEST_ASSERT_EQUAL_HEX16(data[i], decompressed_data[i]); *1/ */ -/* /1* TEST_ASSERT_EQUAL_HEX16(up_model[i], de_up_model[i]); *1/ */ -/* } */ - - -/* free(ent); */ -/* free(decompressed_data); */ -/* } */ - -#include <unistd.h> -#include "cmp_io.h" - -void test_imagette_random(void) -{ - unsigned int seed; - size_t i, s, cmp_data_size; - int error; - struct cmp_cfg cfg; - struct cmp_entity *ent; - - enum cmp_mode cmp_mode = my_random(0, 4); - enum cmp_data_type data_type = DATA_TYPE_IMAGETTE; - uint16_t model_value = my_random(0, MAX_MODEL_VALUE); - uint32_t round = my_random(0, 3); - uint32_t samples, compressed_data_len_samples; - uint16_t *data, *model = NULL, *up_model = NULL, *de_up_model = NULL; - - /* Seeds the pseudo-random number generator used by rand() */ -#if HAS_TIME_H - seed = time(NULL) * getpid(); -#else - seed = 1; -#endif - srand(seed); - printf("seed: %u\n", seed); - - /* create random test _data */ - samples = my_random(1, 100000); - s = cmp_cal_size_of_data(samples, data_type); - data = malloc(s); TEST_ASSERT_TRUE(data); - for (i = 0; i < samples; ++i) { - data[i] = my_random(0, UINT16_MAX); - } - if (model_mode_is_used(cmp_mode)) { - model = malloc(s); TEST_ASSERT_TRUE(model); - up_model = malloc(s); TEST_ASSERT_TRUE(up_model); - de_up_model = malloc(s); TEST_ASSERT(de_up_model); - for (i = 0; i < samples; ++i) { - model[i] = my_random(0, UINT16_MAX); - } - } - compressed_data_len_samples = 6*samples; - - /* create a compression configuration */ - cfg = cmp_cfg_icu_create(data_type, cmp_mode, model_value, round); - TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKNOWN); - - - cmp_data_size = cmp_cfg_icu_buffers(&cfg, data, samples, model, up_model, - NULL, compressed_data_len_samples); - TEST_ASSERT_TRUE(cmp_data_size); - - uint32_t golomb_par = my_random(MIN_IMA_GOLOMB_PAR, MAX_IMA_GOLOMB_PAR); - uint32_t max_spill = cmp_ima_max_spill(golomb_par); - TEST_ASSERT(max_spill > 1); - uint32_t spill = my_random(2, max_spill); - - error = cmp_cfg_icu_imagette(&cfg, golomb_par, spill); - TEST_ASSERT_FALSE(error); - - error = cmp_cfg_icu_max_used_bits(&cfg, &MAX_USED_BITS_V1); - TEST_ASSERT_FALSE(error); - - /* print_cfg(&cfg, 0); */ - s = icu_compress_data_entity(NULL, &cfg); - TEST_ASSERT_TRUE(s); - ent = malloc(s); TEST_ASSERT_TRUE(ent); - s = icu_compress_data_entity(ent, &cfg); - TEST_ASSERT_TRUE(s); - - s = decompress_cmp_entiy(ent, model, de_up_model, NULL); - TEST_ASSERT_EQUAL_INT(samples * sizeof(*data), s); - uint16_t *decompressed_data = malloc(s); - TEST_ASSERT_TRUE(decompressed_data); - s = decompress_cmp_entiy(ent, model, de_up_model, decompressed_data); - TEST_ASSERT_EQUAL_INT(samples * sizeof(*data), s); - - for (i = 0; i < samples; ++i) { - /* printf("%u == %u (round: %u)\n", data[i], decompressed_data[i], round); */ - uint32_t mask = ~0U << round; - if ((data[i]&mask) != (decompressed_data[i]&mask)) - TEST_ASSERT(0); - if (model_mode_is_used(cmp_mode)) - if (up_model[i] != de_up_model[i]) - TEST_ASSERT(0); - } - - free(data); - free(model); - free(up_model); - free(de_up_model); - free(ent); - free(decompressed_data); -} - - -void test_s_fx_diff(void) -{ - size_t s, i; - uint8_t cmp_entity[88] = { - 0x80, 0x00, 0x00, 0x09, 0x00, 0x00, 0x58, 0x00, 0x00, 0x20, 0x04, 0xEE, 0x21, 0xBD, 0xB0, 0x1C, 0x04, 0xEE, 0x21, 0xBD, 0xB0, 0x41, 0x00, 0x08, 0x02, 0x08, 0xD0, 0x10, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0xAE, 0xDE, 0x00, 0x00, 0x00, 0x73, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x00, - }; - - uint8_t result_data[32] = {0}; - struct multi_entry_hdr *hdr = (struct multi_entry_hdr *)result_data; - struct s_fx *data = (struct s_fx *)hdr->entry; - /* put some dummy data in the header*/ - for (i = 0; i < sizeof(*hdr); i++) - result_data[i] = i; - data[0].exp_flags = 0; - data[0].fx = 0; - data[1].exp_flags = 1; - data[1].fx = 0xFFFFFF; - data[2].exp_flags = 3; - data[2].fx = 0x7FFFFF; - data[3].exp_flags = 0; - data[3].fx = 0; - - s = decompress_cmp_entiy((void *)cmp_entity, NULL, NULL, NULL); - TEST_ASSERT_EQUAL_INT(sizeof(result_data), s); - uint8_t *decompressed_data = malloc(s); - TEST_ASSERT_TRUE(decompressed_data); - s = decompress_cmp_entiy((void *)cmp_entity, NULL, NULL, decompressed_data); - TEST_ASSERT_EQUAL_INT(sizeof(result_data), s); - for (i = 0; i < s; ++i) { - TEST_ASSERT_EQUAL(result_data[i], decompressed_data[i]); - } - free(decompressed_data); -} - - -void test_s_fx_model(void) -{ - size_t s, i; - uint8_t compressed_data_buf[92] = { - 0x80, 0x00, 0x00, 0x09, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x20, 0x04, 0xF0, 0xC2, 0xD3, 0x47, 0xE4, 0x04, 0xF0, 0xC2, 0xD3, 0x48, 0x16, 0x00, 0x08, 0x03, 0x08, 0xD0, 0x10, 0x01, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x3B, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0x5B, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0x5D, 0x80, 0x00, 0x00, - }; - struct cmp_entity *cmp_entity = (struct cmp_entity *)compressed_data_buf; - - uint8_t model_buf[32]; - uint8_t decompressed_data[32]; - uint8_t up_model_buf[32]; - uint8_t exp_data_buf[32] = {0}; /* expected uncompressed data */ - uint8_t exp_up_model_buf[32] = {0}; - - struct multi_entry_hdr *model_collection = (struct multi_entry_hdr *)model_buf; - struct s_fx *model_data = (struct s_fx *)model_collection->entry; - - memset(model_collection, 0xFF, sizeof(*model_collection)); - model_data[0].exp_flags = 0; - model_data[0].fx = 0; - model_data[1].exp_flags = 3; - model_data[1].fx = 0x7FFFFF; - model_data[2].exp_flags = 0; - model_data[2].fx = 0xFFFFFF; - model_data[3].exp_flags = 3; - model_data[3].fx = 0xFFFFFF; - - struct multi_entry_hdr *exp_data_collection = (struct multi_entry_hdr *)exp_data_buf; - struct s_fx *exp_data = (struct s_fx *)exp_data_collection->entry; - /* put some dummy data in the header */ - for (i = 0; i < sizeof(*exp_data_collection); i++) - exp_data_buf[i] = i; - exp_data[0].exp_flags = 0; - exp_data[0].fx = 0; - exp_data[1].exp_flags = 1; - exp_data[1].fx = 0xFFFFFF; - exp_data[2].exp_flags = 3; - exp_data[2].fx = 0x7FFFFF; - exp_data[3].exp_flags = 0; - exp_data[3].fx = 0; - - struct multi_entry_hdr *exp_up_model_collection = (struct multi_entry_hdr *)exp_up_model_buf; - struct s_fx *exp_updated_model_data = (struct s_fx *)exp_up_model_collection->entry; - /* put some dummy data in the header*/ - for (i = 0; i < sizeof(*exp_up_model_collection); i++) - exp_up_model_buf[i] = i; - exp_updated_model_data[0].exp_flags = 0; - exp_updated_model_data[0].fx = 0; - exp_updated_model_data[1].exp_flags = 2; - exp_updated_model_data[1].fx = 0xBFFFFF; - exp_updated_model_data[2].exp_flags = 1; - exp_updated_model_data[2].fx = 0xBFFFFF; - exp_updated_model_data[3].exp_flags = 1; - exp_updated_model_data[3].fx = 0x7FFFFF; - - s = decompress_cmp_entiy(cmp_entity, model_buf, up_model_buf, decompressed_data); - TEST_ASSERT_EQUAL_INT(sizeof(exp_data_buf), s); - - TEST_ASSERT_FALSE(memcmp(exp_data_buf, decompressed_data, s)); - TEST_ASSERT_FALSE(memcmp(exp_up_model_buf, up_model_buf, s)); -} - -/* TODO: implement this! */ -void generate_random_test_data(void *data, int samples, - enum cmp_data_type data_type) -{ - uint32_t s = cmp_cal_size_of_data(samples, data_type); - memset(data, 0x0, s); -} - - -void test_random_compression_decompression(void) -{ - size_t s; - struct cmp_cfg cfg = {0}; - struct cmp_entity *cmp_ent; - void *decompressed_data; - void *decompressed_up_model = NULL; - int error; - - puts("--------------------------------------------------------------"); - - /* for (cfg.data_type = DATA_TYPE_IMAGETTE; TODO:!! implement this */ - /* cfg.data_type < DATA_TYPE_F_CAM_BACKGROUND+1; cfg.data_type++) { */ - for (cfg.data_type = DATA_TYPE_IMAGETTE; - cfg.data_type < DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE+1; cfg.data_type++) { - error = cmp_cfg_icu_max_used_bits(&cfg, &MAX_USED_BITS_V1); - TEST_ASSERT_FALSE(error); - cfg.samples = my_random(1, 0x30000); - cfg.buffer_length = (CMP_ENTITY_MAX_SIZE - NON_IMAGETTE_HEADER_SIZE - MULTI_ENTRY_HDR_SIZE)/size_of_a_sample(cfg.data_type);; - s = cmp_cal_size_of_data(cfg.samples, cfg.data_type); - printf("%s\n", data_type2string(cfg.data_type)); - TEST_ASSERT_TRUE(s); - cfg.input_buf = calloc(1, s); - TEST_ASSERT_NOT_NULL(cfg.input_buf); - cfg.model_buf = calloc(1, s); - TEST_ASSERT_TRUE(cfg.model_buf); - decompressed_data = calloc(1, s); - TEST_ASSERT_NOT_NULL(decompressed_data); - cfg.icu_new_model_buf = calloc(1, s); - TEST_ASSERT_TRUE(cfg.icu_new_model_buf); - decompressed_up_model = calloc(1, s); - TEST_ASSERT_TRUE(decompressed_up_model); - cmp_ent = calloc(1, CMP_ENTITY_MAX_SIZE); - - generate_random_test_data(cfg.input_buf, cfg.samples, cfg.data_type); - generate_random_test_data(cfg.model_buf, cfg.samples, cfg.data_type); - - cfg.model_value = my_random(0, 16); - /* cfg.round = my_random(0,3); /1* XXX *1/ */ - cfg.round = 0; - - cfg.golomb_par = my_random(MIN_IMA_GOLOMB_PAR, MAX_IMA_GOLOMB_PAR); - cfg.ap1_golomb_par = my_random(MIN_IMA_GOLOMB_PAR, MAX_IMA_GOLOMB_PAR); - cfg.ap2_golomb_par = my_random(MIN_IMA_GOLOMB_PAR, MAX_IMA_GOLOMB_PAR); - cfg.cmp_par_exp_flags = my_random(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - cfg.cmp_par_fx = my_random(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - cfg.cmp_par_ncob = my_random(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - cfg.cmp_par_efx = my_random(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - cfg.cmp_par_ecob = my_random(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - cfg.cmp_par_fx_cob_variance = my_random(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - cfg.cmp_par_mean = my_random(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - cfg.cmp_par_variance = my_random(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - cfg.cmp_par_pixels_error = my_random(MIN_NON_IMA_GOLOMB_PAR, MAX_NON_IMA_GOLOMB_PAR); - - cfg.spill = my_random(MIN_IMA_SPILL, cmp_ima_max_spill(cfg.golomb_par)); - cfg.ap1_spill = my_random(MIN_IMA_SPILL, cmp_ima_max_spill(cfg.ap1_golomb_par)); - cfg.ap2_spill = my_random(MIN_IMA_SPILL, cmp_ima_max_spill(cfg.ap2_golomb_par)); - if (!rdcu_supported_data_type_is_used(cfg.data_type)) { - cfg.spill_exp_flags = my_random(MIN_NON_IMA_SPILL, cmp_icu_max_spill(cfg.cmp_par_exp_flags)); - cfg.spill_fx = my_random(MIN_NON_IMA_SPILL, cmp_icu_max_spill(cfg.cmp_par_fx)); - cfg.spill_ncob = my_random(MIN_NON_IMA_SPILL, cmp_icu_max_spill(cfg.cmp_par_ncob)); - cfg.spill_efx = my_random(MIN_NON_IMA_SPILL, cmp_icu_max_spill(cfg.cmp_par_efx)); - cfg.spill_ecob = my_random(MIN_NON_IMA_SPILL, cmp_icu_max_spill(cfg.cmp_par_ecob)); - cfg.spill_fx_cob_variance = my_random(MIN_NON_IMA_SPILL, cmp_icu_max_spill(cfg.cmp_par_fx_cob_variance)); - cfg.spill_mean = my_random(MIN_NON_IMA_SPILL, cmp_icu_max_spill(cfg.cmp_par_mean)); - cfg.spill_variance = my_random(MIN_NON_IMA_SPILL, cmp_icu_max_spill(cfg.cmp_par_variance)); - cfg.spill_pixels_error = my_random(MIN_NON_IMA_SPILL, cmp_icu_max_spill(cfg.cmp_par_pixels_error)); - } - - for (cfg.cmp_mode = CMP_MODE_RAW; cfg.cmp_mode < CMP_MODE_STUFF; cfg.cmp_mode++) { - int cmp_size, decompress_size; - - cmp_size = icu_compress_data_entity(cmp_ent, &cfg); - if (cmp_size <= 0) { - printf("cmp_size: %i\n", cmp_size); - cmp_cfg_print(&cfg); - } - TEST_ASSERT_GREATER_THAN(0, cmp_size); - - /* now decompress the data */ - decompress_size = decompress_cmp_entiy(cmp_ent, cfg.model_buf, - decompressed_up_model, decompressed_data); - - TEST_ASSERT_EQUAL_INT(s, decompress_size); - if (memcmp(cfg.input_buf, decompressed_data, s)) { - cmp_cfg_print(&cfg); - TEST_ASSERT_FALSE(memcmp(cfg.input_buf, decompressed_data, s)); - } - if (model_mode_is_used(cfg.cmp_mode)) - TEST_ASSERT_FALSE(memcmp(cfg.icu_new_model_buf, decompressed_up_model, s)); - - memset(cmp_ent, 0, CMP_ENTITY_MAX_SIZE); - memset(decompressed_data, 0, s); - memset(decompressed_up_model, 0, s); - memset(cfg.icu_new_model_buf, 0, s); - } - - free(cfg.model_buf); - cfg.model_buf = NULL; - free(cfg.input_buf); - cfg.input_buf = NULL; - free(cfg.icu_new_model_buf); - cfg.icu_new_model_buf = NULL; - free(cmp_ent); - cmp_ent = NULL; - free(decompressed_data); - decompressed_data = NULL; - free(decompressed_up_model); - decompressed_up_model = NULL; - - } -} - - -/** - * @test cmp_ent_write_cmp_pars - * @test cmp_ent_read_header - */ - -void test_cmp_ent_write_cmp_pars(void) -{ - int error; - struct cmp_entity *ent; - struct cmp_cfg cfg = {0}, cfg_read = {0}; - int cmp_size_bits; - uint32_t size; - struct cmp_max_used_bits max_used_bits = MAX_USED_BITS_SAFE; - - /* set up max used bit version */ - max_used_bits.version = 42; - cmp_max_used_bits_list_add(&max_used_bits); - - cmp_size_bits = 93; - /** RAW mode test **/ - /* create imagette raw mode configuration */ - cfg.data_type = DATA_TYPE_IMAGETTE; - cfg.cmp_mode = CMP_MODE_RAW; - cfg.model_value = 11; - cfg.round = 2; - cfg.samples = 9; - cfg.max_used_bits = cmp_max_used_bits_list_get(42); - - /* create a compression entity */ - size = cmp_ent_create(NULL, cfg.data_type, cfg.cmp_mode == CMP_MODE_RAW, 12); - TEST_ASSERT_NOT_EQUAL_INT(0, size); - ent = malloc(size); TEST_ASSERT_NOT_NULL(ent); - size = cmp_ent_create(ent, cfg.data_type, cfg.cmp_mode == CMP_MODE_RAW, 12); - TEST_ASSERT_NOT_EQUAL_INT(0, size); - - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_FALSE(error); - - TEST_ASSERT_EQUAL_INT(cfg.data_type, cmp_ent_get_data_type(ent)); - TEST_ASSERT_EQUAL_INT(1, cmp_ent_get_data_type_raw_bit(ent)); - TEST_ASSERT_EQUAL_INT(12, cmp_ent_get_cmp_data_size(ent)); - - TEST_ASSERT_EQUAL_INT(cmp_cal_size_of_data(cfg.samples, cfg.data_type), cmp_ent_get_original_size(ent)); - TEST_ASSERT_EQUAL_INT(cfg.cmp_mode, cmp_ent_get_cmp_mode(ent)); - TEST_ASSERT_EQUAL_INT(cfg.model_value, cmp_ent_get_model_value(ent)); - TEST_ASSERT_EQUAL_INT(max_used_bits.version, cmp_ent_get_max_used_bits_version(ent)); - TEST_ASSERT_EQUAL_INT(cfg.round, cmp_ent_get_lossy_cmp_par(ent)); - - error = cmp_ent_read_header(ent, &cfg_read); - TEST_ASSERT_FALSE(error); - cfg.icu_output_buf = cmp_ent_get_data_buf(ent); /* quick fix that both cfg are equal */ - cfg.buffer_length = 12; /* quick fix that both cfg are equal */ - TEST_ASSERT_EQUAL_MEMORY(&cfg, &cfg_read, sizeof(struct cmp_cfg)); - - free(ent); - memset(&cfg, 0, sizeof(struct cmp_cfg)); - memset(&cfg_read, 0, sizeof(struct cmp_cfg)); - - /** imagette test **/ - /* create imagette mode configuration */ - cfg.data_type = DATA_TYPE_IMAGETTE; - cfg.cmp_mode = CMP_MODE_MODEL_ZERO; - cfg.model_value = 11; - cfg.round = 2; - cfg.samples = 9; - cfg.spill = MIN_IMA_SPILL; - cfg.golomb_par = MAX_IMA_GOLOMB_PAR; - cfg.max_used_bits = cmp_max_used_bits_list_get(42); - - /* create a compression entity */ - size = cmp_ent_create(NULL, cfg.data_type, cfg.cmp_mode == CMP_MODE_RAW, 12); - TEST_ASSERT_NOT_EQUAL_INT(0, size); - ent = malloc(size); TEST_ASSERT_NOT_NULL(ent); - size = cmp_ent_create(ent, cfg.data_type, cfg.cmp_mode == CMP_MODE_RAW, 12); - TEST_ASSERT_NOT_EQUAL_INT(0, size); - - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_FALSE(error); - - TEST_ASSERT_EQUAL_INT(cfg.data_type, cmp_ent_get_data_type(ent)); - TEST_ASSERT_EQUAL_INT(0, cmp_ent_get_data_type_raw_bit(ent)); - TEST_ASSERT_EQUAL_INT(12, cmp_ent_get_cmp_data_size(ent)); - - TEST_ASSERT_EQUAL_INT(cmp_cal_size_of_data(cfg.samples, cfg.data_type), cmp_ent_get_original_size(ent)); - TEST_ASSERT_EQUAL_INT(cfg.cmp_mode, cmp_ent_get_cmp_mode(ent)); - TEST_ASSERT_EQUAL_INT(cfg.model_value, cmp_ent_get_model_value(ent)); - TEST_ASSERT_EQUAL_INT(cfg.max_used_bits->version, cmp_ent_get_max_used_bits_version(ent)); - TEST_ASSERT_EQUAL_INT(cfg.round, cmp_ent_get_lossy_cmp_par(ent)); - - TEST_ASSERT_EQUAL_INT(cfg.spill, cmp_ent_get_ima_spill(ent)); - TEST_ASSERT_EQUAL_INT(cfg.golomb_par, cmp_ent_get_ima_golomb_par(ent)); - - error = cmp_ent_read_header(ent, &cfg_read); - TEST_ASSERT_FALSE(error); - cfg.icu_output_buf = cmp_ent_get_data_buf(ent); /* quick fix that both cfg are equal */ - cfg.buffer_length = 12; /* quick fix that both cfg are equal */ - TEST_ASSERT_EQUAL_MEMORY(&cfg, &cfg_read, sizeof(struct cmp_cfg)); - - free(ent); - memset(&cfg, 0, sizeof(struct cmp_cfg)); - memset(&cfg_read, 0, sizeof(struct cmp_cfg)); - - /** adaptive imagette test **/ - /* create a configuration */ - cfg.data_type = DATA_TYPE_IMAGETTE_ADAPTIVE; - cfg.cmp_mode = CMP_MODE_MODEL_ZERO; - cfg.model_value = 11; - cfg.round = 2; - cfg.samples = 9; - cfg.spill = MIN_IMA_SPILL; - cfg.golomb_par = MAX_IMA_GOLOMB_PAR; - cfg.ap1_spill = 555; - cfg.ap1_golomb_par = 14; - cfg.ap2_spill = 333; - cfg.ap2_golomb_par = 43; - cfg.max_used_bits = cmp_max_used_bits_list_get(42); - - /* create a compression entity */ - size = cmp_ent_create(NULL, cfg.data_type, cfg.cmp_mode == CMP_MODE_RAW, 12); - TEST_ASSERT_NOT_EQUAL_INT(0, size); - ent = malloc(size); TEST_ASSERT_NOT_NULL(ent); - size = cmp_ent_create(ent, cfg.data_type, cfg.cmp_mode == CMP_MODE_RAW, 12); - TEST_ASSERT_NOT_EQUAL_INT(0, size); - - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_FALSE(error); - - TEST_ASSERT_EQUAL_INT(cfg.data_type, cmp_ent_get_data_type(ent)); - TEST_ASSERT_EQUAL_INT(0, cmp_ent_get_data_type_raw_bit(ent)); - TEST_ASSERT_EQUAL_INT(12, cmp_ent_get_cmp_data_size(ent)); - - TEST_ASSERT_EQUAL_INT(cmp_cal_size_of_data(cfg.samples, cfg.data_type), cmp_ent_get_original_size(ent)); - TEST_ASSERT_EQUAL_INT(cfg.cmp_mode, cmp_ent_get_cmp_mode(ent)); - TEST_ASSERT_EQUAL_INT(cfg.model_value, cmp_ent_get_model_value(ent)); - TEST_ASSERT_EQUAL_INT(max_used_bits.version, cmp_ent_get_max_used_bits_version(ent)); - TEST_ASSERT_EQUAL_INT(cfg.round, cmp_ent_get_lossy_cmp_par(ent)); - - TEST_ASSERT_EQUAL_INT(cfg.spill, cmp_ent_get_ima_spill(ent)); - TEST_ASSERT_EQUAL_INT(cfg.golomb_par, cmp_ent_get_ima_golomb_par(ent)); - TEST_ASSERT_EQUAL_INT(cfg.ap1_spill, cmp_ent_get_ima_ap1_spill(ent)); - TEST_ASSERT_EQUAL_INT(cfg.ap1_golomb_par, cmp_ent_get_ima_ap1_golomb_par(ent)); - TEST_ASSERT_EQUAL_INT(cfg.ap2_spill, cmp_ent_get_ima_ap2_spill(ent)); - TEST_ASSERT_EQUAL_INT(cfg.ap2_golomb_par, cmp_ent_get_ima_ap2_golomb_par(ent)); - - error = cmp_ent_read_header(ent, &cfg_read); - TEST_ASSERT_FALSE(error); - cfg.icu_output_buf = cmp_ent_get_data_buf(ent); /* quick fix that both cfg are equal */ - cfg.buffer_length = 12; /* quick fix that both cfg are equal */ - TEST_ASSERT_EQUAL_MEMORY(&cfg, &cfg_read, sizeof(struct cmp_cfg)); - - free(ent); - memset(&cfg, 0, sizeof(struct cmp_cfg)); - memset(&cfg_read, 0, sizeof(struct cmp_cfg)); - - /** flux cob data type test **/ - /* create configuration */ - cfg.data_type = DATA_TYPE_S_FX_EFX_NCOB_ECOB; - cfg.cmp_mode = CMP_MODE_MODEL_ZERO; - cfg.model_value = 11; - cfg.round = 2; - cfg.samples = 9; - cfg.spill_exp_flags = 1; - cfg.spill_fx = 2; - cfg.spill_ncob = 3; - cfg.spill_efx = 4; - cfg.spill_ecob = 5; - cfg.spill_fx_cob_variance = 6; - cfg.cmp_par_exp_flags = 7; - cfg.cmp_par_fx = 8; - cfg.cmp_par_ncob = 9; - cfg.cmp_par_efx = 10; - cfg.cmp_par_ecob = 11; - cfg.cmp_par_fx_cob_variance = 12; - cfg.max_used_bits = cmp_max_used_bits_list_get(42); - - /* create a compression entity */ - size = cmp_ent_create(NULL, cfg.data_type, cfg.cmp_mode == CMP_MODE_RAW, 12); - TEST_ASSERT_NOT_EQUAL_INT(0, size); - ent = malloc(size); TEST_ASSERT_NOT_NULL(ent); - size = cmp_ent_create(ent, cfg.data_type, cfg.cmp_mode == CMP_MODE_RAW, 12); - TEST_ASSERT_NOT_EQUAL_INT(0, size); - - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_FALSE(error); - - TEST_ASSERT_EQUAL_INT(cfg.data_type, cmp_ent_get_data_type(ent)); - TEST_ASSERT_EQUAL_INT(0, cmp_ent_get_data_type_raw_bit(ent)); - TEST_ASSERT_EQUAL_INT(12, cmp_ent_get_cmp_data_size(ent)); - - TEST_ASSERT_EQUAL_INT(cmp_cal_size_of_data(cfg.samples, cfg.data_type), cmp_ent_get_original_size(ent)); - TEST_ASSERT_EQUAL_INT(cfg.cmp_mode, cmp_ent_get_cmp_mode(ent)); - TEST_ASSERT_EQUAL_INT(cfg.model_value, cmp_ent_get_model_value(ent)); - TEST_ASSERT_EQUAL_INT(max_used_bits.version, cmp_ent_get_max_used_bits_version(ent)); - TEST_ASSERT_EQUAL_INT(cfg.round, cmp_ent_get_lossy_cmp_par(ent)); - - - TEST_ASSERT_EQUAL_INT(cfg.spill_exp_flags, cmp_ent_get_non_ima_spill1(ent)); - TEST_ASSERT_EQUAL_INT(cfg.spill_fx, cmp_ent_get_non_ima_spill2(ent)); - TEST_ASSERT_EQUAL_INT(cfg.spill_ncob, cmp_ent_get_non_ima_spill3(ent)); - TEST_ASSERT_EQUAL_INT(cfg.spill_efx, cmp_ent_get_non_ima_spill4(ent)); - TEST_ASSERT_EQUAL_INT(cfg.spill_ecob, cmp_ent_get_non_ima_spill5(ent)); - TEST_ASSERT_EQUAL_INT(cfg.spill_fx_cob_variance, cmp_ent_get_non_ima_spill6(ent)); - TEST_ASSERT_EQUAL_INT(cfg.cmp_par_exp_flags, cmp_ent_get_non_ima_cmp_par1(ent)); - TEST_ASSERT_EQUAL_INT(cfg.cmp_par_fx, cmp_ent_get_non_ima_cmp_par2(ent)); - TEST_ASSERT_EQUAL_INT(cfg.cmp_par_ncob, cmp_ent_get_non_ima_cmp_par3(ent)); - TEST_ASSERT_EQUAL_INT(cfg.cmp_par_efx, cmp_ent_get_non_ima_cmp_par4(ent)); - TEST_ASSERT_EQUAL_INT(cfg.cmp_par_ecob, cmp_ent_get_non_ima_cmp_par5(ent)); - TEST_ASSERT_EQUAL_INT(cfg.cmp_par_fx_cob_variance, cmp_ent_get_non_ima_cmp_par6(ent)); - - error = cmp_ent_read_header(ent, &cfg_read); - TEST_ASSERT_FALSE(error); - cfg.icu_output_buf = cmp_ent_get_data_buf(ent); /* quick fix that both cfg are equal */ - cfg.buffer_length = 12; /* quick fix that both cfg are equal */ - TEST_ASSERT_EQUAL_MEMORY(&cfg, &cfg_read, sizeof(struct cmp_cfg)); - - free(ent); - memset(&cfg, 0, sizeof(struct cmp_cfg)); - memset(&cfg_read, 0, sizeof(struct cmp_cfg)); - - /** auxiliary data data_type test **/ - /* create configuration */ - cfg.data_type = DATA_TYPE_SMEARING; - cfg.cmp_mode = CMP_MODE_MODEL_ZERO; - cfg.model_value = 11; - cfg.round = 2; - cfg.samples = 9; - cfg.spill_mean = 1; - cfg.spill_variance = 2; - cfg.spill_pixels_error = 3; - cfg.cmp_par_mean = 7; - cfg.cmp_par_variance = 8; - cfg.cmp_par_pixels_error = 9; - cfg.max_used_bits = cmp_max_used_bits_list_get(42); - - /* create a compression entity */ - size = cmp_ent_create(NULL, cfg.data_type, cfg.cmp_mode == CMP_MODE_RAW, 12); - TEST_ASSERT_NOT_EQUAL_INT(0, size); - ent = malloc(size); TEST_ASSERT_NOT_NULL(ent); - size = cmp_ent_create(ent, cfg.data_type, cfg.cmp_mode == CMP_MODE_RAW, 12); - TEST_ASSERT_NOT_EQUAL_INT(0, size); - - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_FALSE(error); - - TEST_ASSERT_EQUAL_INT(cfg.data_type, cmp_ent_get_data_type(ent)); - TEST_ASSERT_EQUAL_INT(0, cmp_ent_get_data_type_raw_bit(ent)); - TEST_ASSERT_EQUAL_INT(12, cmp_ent_get_cmp_data_size(ent)); - - TEST_ASSERT_EQUAL_INT(cmp_cal_size_of_data(cfg.samples, cfg.data_type), cmp_ent_get_original_size(ent)); - TEST_ASSERT_EQUAL_INT(cfg.cmp_mode, cmp_ent_get_cmp_mode(ent)); - TEST_ASSERT_EQUAL_INT(cfg.model_value, cmp_ent_get_model_value(ent)); - TEST_ASSERT_EQUAL_INT(max_used_bits.version, cmp_ent_get_max_used_bits_version(ent)); - TEST_ASSERT_EQUAL_INT(cfg.round, cmp_ent_get_lossy_cmp_par(ent)); - - - TEST_ASSERT_EQUAL_INT(cfg.spill_mean, cmp_ent_get_non_ima_spill1(ent)); - TEST_ASSERT_EQUAL_INT(cfg.spill_variance, cmp_ent_get_non_ima_spill2(ent)); - TEST_ASSERT_EQUAL_INT(cfg.spill_pixels_error, cmp_ent_get_non_ima_spill3(ent)); - TEST_ASSERT_EQUAL_INT(0, cmp_ent_get_non_ima_spill4(ent)); - TEST_ASSERT_EQUAL_INT(0, cmp_ent_get_non_ima_spill5(ent)); - TEST_ASSERT_EQUAL_INT(0, cmp_ent_get_non_ima_spill6(ent)); - TEST_ASSERT_EQUAL_INT(cfg.cmp_par_mean, cmp_ent_get_non_ima_cmp_par1(ent)); - TEST_ASSERT_EQUAL_INT(cfg.cmp_par_variance, cmp_ent_get_non_ima_cmp_par2(ent)); - TEST_ASSERT_EQUAL_INT(cfg.cmp_par_pixels_error, cmp_ent_get_non_ima_cmp_par3(ent)); - TEST_ASSERT_EQUAL_INT(0, cmp_ent_get_non_ima_cmp_par4(ent)); - TEST_ASSERT_EQUAL_INT(0, cmp_ent_get_non_ima_cmp_par5(ent)); - TEST_ASSERT_EQUAL_INT(0, cmp_ent_get_non_ima_cmp_par6(ent)); - - error = cmp_ent_read_header(ent, &cfg_read); - TEST_ASSERT_FALSE(error); - cfg.icu_output_buf = cmp_ent_get_data_buf(ent); /* quick fix that both cfg are equal */ - cfg.buffer_length = 12; /* quick fix that both cfg are equal */ - TEST_ASSERT_EQUAL_MEMORY(&cfg, &cfg_read, sizeof(struct cmp_cfg)); - - free(ent); - memset(&cfg, 0, sizeof(struct cmp_cfg)); - memset(&cfg_read, 0, sizeof(struct cmp_cfg)); - - /** Error Cases **/ - /* create imagette raw mode configuration */ - cfg.data_type = DATA_TYPE_IMAGETTE; - cfg.cmp_mode = CMP_MODE_MODEL_ZERO; - cfg.model_value = 11; - cfg.round = 2; - cfg.samples = 9; - cfg.max_used_bits = cmp_max_used_bits_list_get(42); - - /* create a compression entity */ - size = cmp_ent_create(NULL, cfg.data_type, cfg.cmp_mode == CMP_MODE_RAW, 12); - TEST_ASSERT_NOT_EQUAL_INT(0, size); - ent = malloc(size); TEST_ASSERT_NOT_NULL(ent); - size = cmp_ent_create(ent, cfg.data_type, cfg.cmp_mode == CMP_MODE_RAW, 12); - TEST_ASSERT_NOT_EQUAL_INT(0, size); - - - /* ent = NULL */ - error = cmp_ent_write_cmp_pars(NULL, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - - /* cfg = NULL */ - error = cmp_ent_write_cmp_pars(ent, NULL, cmp_size_bits); - TEST_ASSERT_TRUE(error); - - /* cmp_size_bits negative */ - error = cmp_ent_write_cmp_pars(ent, &cfg, -1); - TEST_ASSERT_TRUE(error); - - /* data_type mismatch */ - cfg.data_type = DATA_TYPE_S_FX; - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - cfg.data_type = DATA_TYPE_IMAGETTE; - - /* compressed data to big for compression entity */ - error = cmp_ent_write_cmp_pars(ent, &cfg, 97); - TEST_ASSERT_TRUE(error); - - /* original_size to high */ - cfg.samples = 0x800000; - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - cfg.samples = 0x7FFFFF; - - /* cmp_mode to high */ - cfg.cmp_mode = 0x100; - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - cfg.cmp_mode = 0xFF; - - /* max model_value to high */ - cfg.model_value = 0x100; - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - cfg.model_value = 0xFF; - - /* max used bit version to high */ - TEST_ASSERT_EQUAL_INT(1, sizeof(max_used_bits.version)); - - /* max lossy_cmp_par to high */ - cfg.round = 0x10000; - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - cfg.round = 0xFFFF; - - /* The entity's raw data bit is not set, but the configuration contains raw data */ - cfg.cmp_mode = CMP_MODE_RAW; - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - cfg.cmp_mode = CMP_MODE_MODEL_MULTI; - - /* The entity's raw data bit is set, but the configuration contains no raw data */ - cmp_ent_set_data_type(ent, cfg.data_type, 1); /* set raw bit */ - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - cmp_ent_set_data_type(ent, cfg.data_type, 0); - - /* spill to high */ - cfg.spill = 0x10000; - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - cfg.spill = 0xFFFF; - - /* golomb_par to high */ - cfg.golomb_par = 0x100; - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - cfg.golomb_par = 0xFF; - - - cmp_ent_set_data_type(ent, DATA_TYPE_SAT_IMAGETTE_ADAPTIVE, 0); - cfg.data_type = DATA_TYPE_SAT_IMAGETTE_ADAPTIVE; - cmp_size_bits = 1; - /* adaptive 1 spill to high */ - cfg.ap1_spill = 0x10000; - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - cfg.ap1_spill = 0xFFFF; - - /* adaptive 1 golomb_par to high */ - cfg.ap1_golomb_par = 0x100; - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - cfg.ap1_golomb_par = 0xFF; - - /* adaptive 2 spill to high */ - cfg.ap2_spill = 0x10000; - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - cfg.ap2_spill = 0xFFFF; - - /* adaptive 2 golomb_par to high */ - cfg.ap2_golomb_par = 0x100; - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - cfg.ap2_golomb_par = 0xFF; - - cmp_ent_set_data_type(ent, DATA_TYPE_OFFSET, 0); - cfg.data_type = DATA_TYPE_OFFSET; - - free(ent); - - /* create a compression entity */ - cfg.data_type = DATA_TYPE_OFFSET; - cfg.samples = 9; - size = cmp_ent_create(NULL, cfg.data_type, cfg.cmp_mode == CMP_MODE_RAW, 12); - TEST_ASSERT_NOT_EQUAL_INT(0, size); - ent = malloc(size); TEST_ASSERT_NOT_NULL(ent); - size = cmp_ent_create(ent, cfg.data_type, cfg.cmp_mode == CMP_MODE_RAW, 12); - TEST_ASSERT_NOT_EQUAL_INT(0, size); - - /* mean cmp_par to high */ - cfg.cmp_par_mean = 0x10000; - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - cfg.cmp_par_mean = 0xFFFF; - - /* mean spill to high */ - cfg.spill_mean = 0x1000000; - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - cfg.spill_mean = 0xFFFFFF; - - /* variance cmp_par to high */ - cfg.cmp_par_variance = 0x10000; - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - cfg.cmp_par_variance = 0xFFFF; - - /* variance spill to high */ - cfg.spill_variance = 0x1000000; - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - cfg.spill_variance = 0xFFFFFF; - - /* pixels_error cmp_par to high */ - cfg.cmp_par_pixels_error = 0x10000; - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - cfg.cmp_par_pixels_error = 0xFFFF; - - /* pixels_error spill to high */ - cfg.spill_pixels_error = 0x1000000; - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - cfg.spill_pixels_error = 0xFFFFFF; - - - cmp_ent_set_data_type(ent, DATA_TYPE_F_FX_EFX_NCOB_ECOB, 0); - cfg.data_type = DATA_TYPE_F_FX_EFX_NCOB_ECOB; - - /* exp_flags cmp_par to high */ - cfg.cmp_par_exp_flags = 0x10000; - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - cfg.cmp_par_exp_flags = 0xFFFF; - - /* exp_flags spill to high */ - cfg.spill_exp_flags = 0x1000000; - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - cfg.spill_exp_flags = 0xFFFFFF; - - /* fx cmp_par to high */ - cfg.cmp_par_fx = 0x10000; - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - cfg.cmp_par_fx = 0xFFFF; - - /* fx spill to high */ - cfg.spill_fx = 0x1000000; - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - cfg.spill_fx = 0xFFFFFF; - - /* ncob cmp_par to high */ - cfg.cmp_par_ncob = 0x10000; - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - cfg.cmp_par_ncob = 0xFFFF; - - /* ncob spill to high */ - cfg.spill_ncob = 0x1000000; - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - cfg.spill_ncob = 0xFFFFFF; - - /* efx cmp_par to high */ - cfg.cmp_par_efx = 0x10000; - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - cfg.cmp_par_efx = 0xFFFF; - - /* efx spill to high */ - cfg.spill_efx = 0x1000000; - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - cfg.spill_efx = 0xFFFFFF; - - /* ecob cmp_par to high */ - cfg.cmp_par_ecob = 0x10000; - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - cfg.cmp_par_ecob = 0xFFFF; - - /* ecob spill to high */ - cfg.spill_ecob = 0x1000000; - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - cfg.spill_ecob = 0xFFFFFF; - - /* fx_cob_variance cmp_par to high */ - cfg.cmp_par_fx_cob_variance = 0x10000; - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - cfg.cmp_par_fx_cob_variance = 0xFFFF; - - /* fx_cob_variance spill to high */ - cfg.spill_fx_cob_variance = 0x1000000; - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - cfg.spill_fx_cob_variance = 0xFFFFFF; - - /* test data type = DATA_TYPE_UNKNOWN */ - cmp_ent_set_data_type(ent, DATA_TYPE_UNKNOWN, 0); - cfg.data_type = DATA_TYPE_UNKNOWN; - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - - /* test data type = DATA_TYPE_F_CAM_BACKGROUND +1 */ - cmp_ent_set_data_type(ent, DATA_TYPE_F_CAM_BACKGROUND + 1, 0); - cfg.data_type = DATA_TYPE_F_CAM_BACKGROUND + 1; - error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); - TEST_ASSERT_TRUE(error); - free(ent); - cmp_max_used_bits_list_empty(); -} - - -/** - * @test cmp_ent_read_header - */ - -void test_cmp_ent_read_header_error_cases(void) - -{ - int error; - uint32_t size; - struct cmp_entity *ent; - struct cmp_cfg cfg; - - /* create a entity */ - size = cmp_ent_create(NULL, DATA_TYPE_IMAGETTE, 1, 10); - TEST_ASSERT_EQUAL_UINT32(sizeof(struct cmp_entity), size); - ent = malloc(size); TEST_ASSERT_NOT_NULL(ent); - size = cmp_ent_create(ent, DATA_TYPE_IMAGETTE, 1, 10); - TEST_ASSERT_EQUAL_UINT32(sizeof(struct cmp_entity), size); - - /* ent = NULL */ - error = cmp_ent_read_header(NULL, &cfg); - TEST_ASSERT_TRUE(error); - /* this should work */ - error = cmp_ent_read_header(ent, &cfg); - TEST_ASSERT_FALSE(error); - - /* cfg = NULL */ - error = cmp_ent_read_header(ent, NULL); - TEST_ASSERT_TRUE(error); - /* this should work */ - error = cmp_ent_read_header(ent, &cfg); - TEST_ASSERT_FALSE(error); - - /* unknown data type */ - cmp_ent_set_data_type(ent, DATA_TYPE_UNKNOWN, 1); - error = cmp_ent_read_header(ent, &cfg); - TEST_ASSERT_TRUE(error); - /* unknown data type */ - cmp_ent_set_data_type(ent, DATA_TYPE_F_CAM_BACKGROUND+1, 1); - error = cmp_ent_read_header(ent, &cfg); - TEST_ASSERT_TRUE(error); - /* this should work */ - cmp_ent_set_data_type(ent, DATA_TYPE_IMAGETTE, 1); - error = cmp_ent_read_header(ent, &cfg); - TEST_ASSERT_FALSE(error); - - /* cmp_mode CMP_MODE_RAW and no raw data bit */ - cmp_ent_set_data_type(ent, DATA_TYPE_IMAGETTE, 0); - error = cmp_ent_read_header(ent, &cfg); - TEST_ASSERT_TRUE(error); - /* this should work */ - cmp_ent_set_data_type(ent, DATA_TYPE_IMAGETTE, 1); - error = cmp_ent_read_header(ent, &cfg); - TEST_ASSERT_FALSE(error); - - /* original_size and data product type not compatible */ - cmp_ent_set_original_size(ent, 11); - error = cmp_ent_read_header(ent, &cfg); - TEST_ASSERT_TRUE(error); - /* this should work */ - cmp_ent_set_original_size(ent, 12); - error = cmp_ent_read_header(ent, &cfg); - TEST_ASSERT_FALSE(error); - - free(ent); -} - - -void test_decompression_error_cases(void) -{ - /* error cases model decompression without a model Buffer */ - /* error cases wrong cmp parameter; model value; usw */ -} diff --git a/test/cmp_max_used_bits/test_cmp_max_used_bits_list.c b/test/cmp_max_used_bits/test_cmp_max_used_bits_list.c index 2ee2677fed07127a2efd6a517e17880c0041188d..2557d827a1505219c5d7c7d7f71bab7e5766af51 100644 --- a/test/cmp_max_used_bits/test_cmp_max_used_bits_list.c +++ b/test/cmp_max_used_bits/test_cmp_max_used_bits_list.c @@ -23,6 +23,35 @@ #include <cmp_max_used_bits_list.h> +#ifndef __sparc__ +/* if set the mock malloc will fail (return NULL) */ +static int malloc_fail; + + +/* + * mock of the malloc function; can controlled with the global malloc_fail variable + * see:https://jayconrod.com/posts/23/tutorial--function-interposition-in-linux + */ +#include <dlfcn.h> + +void* malloc(size_t size) +{ + static void* (*real_malloc)(size_t size) = NULL; + + if(malloc_fail) + return NULL; + + if (!real_malloc) { + *(void **)(&real_malloc) = dlsym(RTLD_NEXT, "malloc"); + /* The cast removes a gcc warning https://stackoverflow.com/a/31528674 */ + TEST_ASSERT_NOT_NULL(real_malloc); + } + + fprintf(stderr, "malloc(%zu)\n", size); + return real_malloc(size); +} +#endif + /** * @test cmp_max_used_bits_list_add @@ -33,31 +62,31 @@ void test_cmp_max_used_bits_list(void) { - struct cmp_max_used_bits i_17, i_21, i_22, i_23, i_255, i_0; - struct cmp_max_used_bits *p; + struct cmp_max_used_bits i_32, i_34, i_35, i_36, i_255, i_0; + const struct cmp_max_used_bits *p; int return_val; /* set up max_used_bits item */ - memset(&i_17, 17, sizeof(struct cmp_max_used_bits)); - i_17.version = 17; - memset(&i_21, 21, sizeof(struct cmp_max_used_bits)); - i_21.version = 21; - memset(&i_22, 22, sizeof(struct cmp_max_used_bits)); - i_22.version = 22; - memset(&i_23, 23, sizeof(struct cmp_max_used_bits)); - i_23.version = 23; + memset(&i_32, 32, sizeof(struct cmp_max_used_bits)); + i_32.version = 32; + memset(&i_34, 34, sizeof(struct cmp_max_used_bits)); + i_34.version = 34; + memset(&i_35, 35, sizeof(struct cmp_max_used_bits)); + i_35.version = 35; + memset(&i_36, 36, sizeof(struct cmp_max_used_bits)); + i_36.version = 36; memset(&i_255, 0xFF, sizeof(struct cmp_max_used_bits)); i_255.version = 255; memset(&i_0, 0, sizeof(struct cmp_max_used_bits)); i_0.version = 0; - return_val = cmp_max_used_bits_list_add(&i_17); + return_val = cmp_max_used_bits_list_add(&i_32); TEST_ASSERT_EQUAL_INT(return_val, 0); - return_val = cmp_max_used_bits_list_add(&i_21); + return_val = cmp_max_used_bits_list_add(&i_34); TEST_ASSERT_EQUAL_INT(return_val, 0); - return_val = cmp_max_used_bits_list_add(&i_22); + return_val = cmp_max_used_bits_list_add(&i_35); TEST_ASSERT_EQUAL_INT(return_val, 0); - return_val = cmp_max_used_bits_list_add(&i_23); + return_val = cmp_max_used_bits_list_add(&i_36); TEST_ASSERT_EQUAL_INT(return_val, 0); return_val = cmp_max_used_bits_list_add(&i_255); TEST_ASSERT_EQUAL_INT(return_val, 0); @@ -67,29 +96,29 @@ void test_cmp_max_used_bits_list(void) TEST_ASSERT_EQUAL_INT(return_val, -1); return_val = cmp_max_used_bits_list_add(&i_0); TEST_ASSERT_EQUAL_INT(return_val, -1); - i_0.version = 16; + i_0.version = CMP_MAX_USED_BITS_RESERVED_VERSIONS-1; return_val = cmp_max_used_bits_list_add(&i_0); TEST_ASSERT_EQUAL_INT(return_val, -1); - p = cmp_max_used_bits_list_get(17); - TEST_ASSERT_EQUAL_INT(p->version, 17); - TEST_ASSERT(!memcmp(p, &i_17, sizeof(struct cmp_max_used_bits))); + p = cmp_max_used_bits_list_get(32); + TEST_ASSERT_EQUAL_INT(p->version, 32); + TEST_ASSERT(!memcmp(p, &i_32, sizeof(struct cmp_max_used_bits))); - p = cmp_max_used_bits_list_get(23); - TEST_ASSERT_EQUAL_INT(p->version, 23); - TEST_ASSERT(!memcmp(p, &i_23, sizeof(struct cmp_max_used_bits))); + p = cmp_max_used_bits_list_get(36); + TEST_ASSERT_EQUAL_INT(p->version, 36); + TEST_ASSERT(!memcmp(p, &i_36, sizeof(struct cmp_max_used_bits))); - p = cmp_max_used_bits_list_get(22); - TEST_ASSERT_EQUAL_INT(p->version, 22); - TEST_ASSERT(!memcmp(p, &i_22, sizeof(struct cmp_max_used_bits))); + p = cmp_max_used_bits_list_get(35); + TEST_ASSERT_EQUAL_INT(p->version, 35); + TEST_ASSERT(!memcmp(p, &i_35, sizeof(struct cmp_max_used_bits))); p = cmp_max_used_bits_list_get(255); TEST_ASSERT_EQUAL_INT(p->version, 255); TEST_ASSERT(!memcmp(p, &i_255, sizeof(struct cmp_max_used_bits))); - p = cmp_max_used_bits_list_get(21); - TEST_ASSERT_EQUAL_INT(p->version, 21); - TEST_ASSERT(!memcmp(p, &i_21, sizeof(struct cmp_max_used_bits))); + p = cmp_max_used_bits_list_get(34); + TEST_ASSERT_EQUAL_INT(p->version, 34); + TEST_ASSERT(!memcmp(p, &i_34, sizeof(struct cmp_max_used_bits))); p = cmp_max_used_bits_list_get(0); TEST_ASSERT_EQUAL_INT(p->version, 0); @@ -108,30 +137,30 @@ void test_cmp_max_used_bits_list(void) /* overwrite a list item */ - memset(&i_22, 0x42, sizeof(struct cmp_max_used_bits)); - i_22.version = 22; - return_val = cmp_max_used_bits_list_add(&i_22); + memset(&i_35, 0x42, sizeof(struct cmp_max_used_bits)); + i_35.version = 35; + return_val = cmp_max_used_bits_list_add(&i_35); TEST_ASSERT_EQUAL_INT(return_val, 1); - p = cmp_max_used_bits_list_get(22); - TEST_ASSERT_EQUAL_INT(p->version, 22); - TEST_ASSERT(!memcmp(p, &i_22, sizeof(struct cmp_max_used_bits))); + p = cmp_max_used_bits_list_get(35); + TEST_ASSERT_EQUAL_INT(p->version, 35); + TEST_ASSERT(!memcmp(p, &i_35, sizeof(struct cmp_max_used_bits))); /* delete item */ - cmp_max_used_bits_list_delet(22); - p = cmp_max_used_bits_list_get(22); + cmp_max_used_bits_list_delet(35); + p = cmp_max_used_bits_list_get(35); TEST_ASSERT_NULL(p); - cmp_max_used_bits_list_delet(21); - p = cmp_max_used_bits_list_get(21); + cmp_max_used_bits_list_delet(34); + p = cmp_max_used_bits_list_get(34); TEST_ASSERT_NULL(p); /* empty item */ cmp_max_used_bits_list_empty(); - p = cmp_max_used_bits_list_get(23); + p = cmp_max_used_bits_list_get(36); TEST_ASSERT_NULL(p); cmp_max_used_bits_list_empty(); - p = cmp_max_used_bits_list_get(21); + p = cmp_max_used_bits_list_get(34); TEST_ASSERT_NULL(p); p = cmp_max_used_bits_list_get(0); @@ -142,12 +171,20 @@ void test_cmp_max_used_bits_list(void) TEST_ASSERT_EQUAL_INT(p->version, 1); TEST_ASSERT(!memcmp(p, &MAX_USED_BITS_V1, sizeof(struct cmp_max_used_bits))); - return_val = cmp_max_used_bits_list_add(&i_23); + return_val = cmp_max_used_bits_list_add(&i_36); TEST_ASSERT_EQUAL_INT(return_val, 0); - p = cmp_max_used_bits_list_get(23); - TEST_ASSERT_EQUAL_INT(p->version, 23); - TEST_ASSERT(!memcmp(p, &i_23, sizeof(struct cmp_max_used_bits))); + p = cmp_max_used_bits_list_get(36); + TEST_ASSERT_EQUAL_INT(p->version, 36); + TEST_ASSERT(!memcmp(p, &i_36, sizeof(struct cmp_max_used_bits))); cmp_max_used_bits_list_empty(); + + /* error case */ +#ifndef __sparc__ + malloc_fail = 1; + return_val = cmp_max_used_bits_list_add(&i_36); + TEST_ASSERT_EQUAL_INT(return_val, -1); + malloc_fail = 0; +#endif } diff --git a/test/cmp_rdcu_cfg/test_cmp_rdcu_cfg.c b/test/cmp_rdcu_cfg/test_cmp_rdcu_cfg.c index a59ecfdd0ee68af4f063abd13a2bc70c7ac4ef82..36645f357b929ab8e22e4fb5fb0c0f48a6842d1f 100644 --- a/test/cmp_rdcu_cfg/test_cmp_rdcu_cfg.c +++ b/test/cmp_rdcu_cfg/test_cmp_rdcu_cfg.c @@ -637,12 +637,58 @@ void test_rdcu_cfg_imagette(void) TEST_ASSERT_EQUAL(ap1_golomb_par, cfg.ap1_golomb_par); TEST_ASSERT_EQUAL(ap1_spillover_par, cfg.ap1_spill); TEST_ASSERT_EQUAL(ap2_golomb_par, cfg.ap2_golomb_par); - TEST_ASSERT_EQUAL(ap2_spillover_par, cfg.ap2_spill); /* cfg = NULL test */ error = rdcu_cfg_imagette(NULL, golomb_par, spillover_par, + TEST_ASSERT_EQUAL(ap2_spillover_par, cfg.ap2_spill); + + /* cfg = NULL test */ + error = rdcu_cfg_imagette(NULL, golomb_par, spillover_par, ap1_golomb_par, ap1_spillover_par, ap2_golomb_par, ap2_spillover_par); TEST_ASSERT_EQUAL(-1, error); } +/** + * @test rdcu_cfg_imagette_default + */ + +void test_rdcu_cfg_imagette_default(void) +{ + int error; + struct cmp_cfg cfg; + + /* 1d configuration */ + cfg = rdcu_cfg_create(DATA_TYPE_IMAGETTE, CMP_MODE_DIFF_ZERO, 0, CMP_LOSSLESS); + TEST_ASSERT_NOT_EQUAL(DATA_TYPE_UNKNOWN, cfg.data_type); + + error = rdcu_cfg_imagette_default(&cfg); + TEST_ASSERT_FALSE(error); + + TEST_ASSERT_EQUAL(CMP_DEF_IMA_DIFF_GOLOMB_PAR, cfg.golomb_par); + TEST_ASSERT_EQUAL(CMP_DEF_IMA_DIFF_SPILL_PAR, cfg.spill); + TEST_ASSERT_EQUAL(CMP_DEF_IMA_DIFF_AP1_GOLOMB_PAR, cfg.ap1_golomb_par); + TEST_ASSERT_EQUAL(CMP_DEF_IMA_DIFF_AP1_SPILL_PAR, cfg.ap1_spill); + TEST_ASSERT_EQUAL(CMP_DEF_IMA_DIFF_AP2_GOLOMB_PAR, cfg.ap2_golomb_par); + TEST_ASSERT_EQUAL(CMP_DEF_IMA_DIFF_AP2_SPILL_PAR, cfg.ap2_spill); + + /* 1d configuration */ + cfg = rdcu_cfg_create(DATA_TYPE_IMAGETTE_ADAPTIVE, CMP_MODE_MODEL_MULTI, 0, CMP_LOSSLESS); + TEST_ASSERT_NOT_EQUAL(DATA_TYPE_UNKNOWN, cfg.data_type); + + error = rdcu_cfg_imagette_default(&cfg); + TEST_ASSERT_FALSE(error); + + TEST_ASSERT_EQUAL(CMP_DEF_IMA_MODEL_GOLOMB_PAR, cfg.golomb_par); + TEST_ASSERT_EQUAL(CMP_DEF_IMA_MODEL_SPILL_PAR, cfg.spill); + TEST_ASSERT_EQUAL(CMP_DEF_IMA_MODEL_AP1_GOLOMB_PAR, cfg.ap1_golomb_par); + TEST_ASSERT_EQUAL(CMP_DEF_IMA_MODEL_AP1_SPILL_PAR, cfg.ap1_spill); + TEST_ASSERT_EQUAL(CMP_DEF_IMA_MODEL_AP2_GOLOMB_PAR, cfg.ap2_golomb_par); + TEST_ASSERT_EQUAL(CMP_DEF_IMA_MODEL_AP2_SPILL_PAR, cfg.ap2_spill); + + /* error case */ + error = rdcu_cfg_imagette_default(NULL); + TEST_ASSERT_TRUE(error); +} + + /** * @test rdcu_cmp_cfg_is_invalid */ diff --git a/test/cmp_tool/cmp_tool_integration_test.py b/test/cmp_tool/cmp_tool_integration_test.py index cf8309529cb7eb5625cbc1872f1796dff9c8c7a3..5cadbf231cc39ebe8f12c13d95b9a791df00c7cf 100755 --- a/test/cmp_tool/cmp_tool_integration_test.py +++ b/test/cmp_tool/cmp_tool_integration_test.py @@ -26,7 +26,7 @@ NON_IMAGETTE_HEADER_SIZE = GENERIC_HEADER_SIZE+32 WINE_TEST_SETUP = False my_env=None if sys.platform != 'win32' and sys.platform != 'cygwin': - if Path('cmp_tool.exe').exists(): + if Path('programs/cmp_tool.exe').exists(): # try to detect cross compile setup # and use wine to run windows executable WINE_TEST_SETUP = True @@ -36,9 +36,9 @@ if sys.platform != 'win32' and sys.platform != 'cygwin': def call_cmp_tool(args): if WINE_TEST_SETUP: - args = shlex.split("wine64 cmp_tool.exe " + args) + args = shlex.split("wine64 programs/cmp_tool.exe " + args) else: - args = shlex.split("./cmp_tool " + args) + args = shlex.split("./programs/cmp_tool " + args) print(args) try: @@ -207,7 +207,7 @@ assert(returncode == EXIT_SUCCESS) assert(stderr == "") VERSION = stdout.split()[2] -#get cmp_tool parth +#get cmp_tool path returncode, stdout, stderr = call_cmp_tool("") assert(returncode == EXIT_FAILURE) assert(stderr == "") @@ -425,11 +425,11 @@ def test_compression_diff(): if arg == " --no_header" else "")(add_arg)) ) # check compressed data - cmp_data = "44 44 40 00 \n" + cmp_data = "44 44 40 \n" with open(output_prefix+".cmp", encoding='utf-8') as f: if add_arg == " --no_header": # check compressed data file - assert(f.read() == "44 44 40 00 \n") + assert(f.read() == cmp_data) # check info file with open(output_prefix+".info", encoding='utf-8') as f: info = parse_key_value(f.read()) @@ -444,7 +444,7 @@ def test_compression_diff(): else: header = read_in_cmp_header(f.read()) assert(header['asw_version_id']['value'] == VERSION.split('-')[0]) - assert(header['cmp_ent_size']['value'] == IMAGETTE_HEADER_SIZE+4) + assert(header['cmp_ent_size']['value'] == IMAGETTE_HEADER_SIZE+3) assert(header['original_size']['value'] == 10) # todo assert(header['start_time']['value'] < cuc_timestamp(datetime.utcnow())) @@ -458,7 +458,7 @@ def test_compression_diff(): assert(header['lossy_cmp_par_used']['value'] == 0) assert(header['spill_used']['value'] == 60) assert(header['golomb_par_used']['value'] == 7) - assert(header['compressed_data']['value'] == "44444000") + assert(header['compressed_data']['value'] == "444440") # decompression if add_arg == " --no_header": @@ -553,7 +553,7 @@ def test_model_compression(): if "--no_header" in add_arg: # check compressed data with open(output_prefix1+".cmp", encoding='utf-8') as f: - assert(f.read() == "49 24 00 00 \n") + assert(f.read() == "49 24 \n") # check info file with open(output_prefix1+".info", encoding='utf-8') as f: info = parse_key_value(f.read()) @@ -579,7 +579,7 @@ def test_model_compression(): header = read_in_cmp_header(bytearray(f.read()).hex()) assert(header['asw_version_id']['value'] == VERSION.split('-')[0]) - assert(header['cmp_ent_size']['value'] == IMAGETTE_ADAPTIVE_HEADER_SIZE+4) + assert(header['cmp_ent_size']['value'] == IMAGETTE_ADAPTIVE_HEADER_SIZE+2) assert(header['original_size']['value'] == 10) # todo assert(header['start_time']['value'] < cuc_timestamp(datetime.utcnow())) @@ -593,7 +593,7 @@ def test_model_compression(): assert(header['lossy_cmp_par_used']['value'] == int(cfg['round'])) assert(header['spill_used']['value'] == int(cfg['spill'])) assert(header['golomb_par_used']['value'] == int(cfg['golomb_par'])) - assert(header['compressed_data']['value'] == "49240000") + assert(header['compressed_data']['value'] == "4924") # decompression if "--no_header" in add_arg: @@ -688,7 +688,7 @@ def test_raw_mode_compression(): else: header = read_in_cmp_header(f.read()) assert(header['asw_version_id']['value'] == VERSION.split('-')[0]) - assert(header['cmp_ent_size']['value'] == GENERIC_HEADER_SIZE+12) + assert(header['cmp_ent_size']['value'] == GENERIC_HEADER_SIZE+10) assert(header['original_size']['value'] == 10) # todo assert(header['start_time']['value'] < cuc_timestamp(datetime.utcnow())) @@ -702,7 +702,7 @@ def test_raw_mode_compression(): assert(header['lossy_cmp_par_used']['value'] == 0) # assert(header['spill_used']['value'] == 60) # assert(header['golomb_par_used']['value'] == 7) - assert(header['compressed_data']['value'] == data[:-1].replace(" ","")+"0000") + assert(header['compressed_data']['value'] == data[:-1].replace(" ","")) # decompression if "--no_header" in arg: @@ -768,13 +768,13 @@ def test_guess_option(): exp_out = ('', '2', '', '7.27') elif sub_test == 'guess_RDCU_model': exp_out = ( - 'Importing model file model.dat ... DONE\n', '2', '', str(round((5*2)/(IMAGETTE_ADAPTIVE_HEADER_SIZE + 4), 2))) - #cmp_size:15bit-> 4byte cmp_data + 40byte header -> 16bit*5/(44Byte*8) '5.33' + 'Importing model file model.dat ... DONE\n', '2', '', str(round((5*2)/(IMAGETTE_ADAPTIVE_HEADER_SIZE + 2), 2))) + #cmp_size:15bit-> 2byte cmp_data + 40byte header -> 16bit*5/(42Byte*8) elif sub_test == 'guess_level_3': exp_out = ( '', '3', ' 0%... 6%... 13%... 19%... 25%... 32%... 38%... 44%... 50%... 57%... 64%... 72%... 80%... 88%... 94%... 100%', - str(round((5*2)/(IMAGETTE_HEADER_SIZE + 4), 2))) #11.43 - # cmp_size:7 bit -> 4byte cmp_data + 34 byte header -> 16bit*5/(40Byte*8) + str(round((5*2)/(IMAGETTE_HEADER_SIZE + 1), 3))) #11.43 + # cmp_size:7 bit -> 1byte cmp_data + 34 byte header -> 16bit*5/(35Byte*8) else: exp_out = ('', '', '') @@ -1068,7 +1068,7 @@ def test_sample_used_is_to_big(): "Importing compressed data file %s ... DONE\n" % (cmp_file_name) + "Decompress data ... FAILED\n") - assert(stderr == "Error: Buffer overflow detected.\n") + assert(stderr == "Error: The end of the compressed bit stream has been exceeded. Please check that the compression parameters match those used to compress the data and that the compressed data are not corrupted.\n") assert(returncode == EXIT_FAILURE) finally: @@ -1081,7 +1081,7 @@ def test_cmp_entity_not_4_byte_aligned(): version_id = 0x8001_0042 cmp_ent_size = IMAGETTE_HEADER_SIZE + len(cmp_data)//2 - original_size = 0xA + original_size = 0xC start_time = cuc_timestamp(datetime.utcnow()) end_time = cuc_timestamp(datetime.utcnow()) @@ -1103,9 +1103,9 @@ def test_cmp_entity_not_4_byte_aligned(): ima_header = build_imagette_header(spill_used, golomb_par_used) cmp_data_header = generic_header + ima_header + cmp_data - data_exp = '00 01 00 02 00 03 00 04 00 05 \n' + data_exp = '00 01 00 02 00 03 00 04 00 05 00 06 \n' info = ("cmp_size = 20\n" + "golomb_par_used = 7\n" + "spill_used = 60\n" - + "cmp_mode_used = 2\n" +"samples_used=5\n") + + "cmp_mode_used = 2\n" +"samples_used=6\n") cmp_file_name = 'unaligned_cmp_size.cmp' info_file_name = 'unaligned_cmp_size.info' @@ -1136,9 +1136,7 @@ def test_cmp_entity_not_4_byte_aligned(): "Write decompressed data to file %s.dat ... DONE\n" % (output_prefix)) else: assert(stdout == CMP_START_STR_DECMP + - "Importing compressed data file %s ... \n" % (cmp_file_name) + - "The size of the compression entity is not a multiple of 4 bytes. Padding the compression entity to a multiple of 4 bytes.\n" + - "DONE\n" + + "Importing compressed data file %s ... DONE\n" % (cmp_file_name) + "Decompress data ... DONE\n"+ "Write decompressed data to file %s.dat ... DONE\n" % (output_prefix)) @@ -1173,7 +1171,7 @@ def test_header_wrong_formatted(): def test_header_read_in(): cmp_file_name = 'test_header_read_in.cmp' - cmp_data = '44444400' + cmp_data = '444444' version_id = 0x8001_0042 cmp_ent_size = IMAGETTE_HEADER_SIZE + len(cmp_data)//2 @@ -1209,7 +1207,7 @@ def test_header_read_in(): "Importing compressed data file %s ... FAILED\n" % (cmp_file_name)) assert(stderr == "cmp_tool: %s: The size of the compression entity set in the " "header of the compression entity is not the same size as the read-in " - "file has. Expected: 0x28, has 0x26.\n" %(cmp_file_name)) + "file has. Expected: 0x27, has 0x25.\n" %(cmp_file_name)) # false data type data_type = 0x7FFE @@ -1246,7 +1244,7 @@ def test_header_read_in(): assert(stdout == CMP_START_STR_DECMP + "Importing compressed data file %s ... DONE\n" % (cmp_file_name) + "Decompress data ... FAILED\n" ) - assert(stderr == "Error: Compression mode not supported.\n") + assert(stderr == "Error: The compression mode is not supported.\n") finally: del_file(cmp_file_name) @@ -1380,7 +1378,7 @@ def test_rdcu_pkt(): # check compressed data with open(output_prefix1+".cmp", encoding='utf-8') as f: - assert(f.read() == "49 24 00 00 \n") + assert(f.read() == "49 24 \n") # check info file with open(output_prefix1+".info", encoding='utf-8') as f: info = parse_key_value(f.read()) diff --git a/test/cmp_tool/test_read_file8_1.txt b/test/cmp_tool/test_read_file8_1.txt deleted file mode 100644 index c700aa60c35b1f2c5b7ca42082d62054511e025d..0000000000000000000000000000000000000000 --- a/test/cmp_tool/test_read_file8_1.txt +++ /dev/null @@ -1,2 +0,0 @@ -00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 -11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 diff --git a/test/cmp_tool/test_read_file8_2.txt b/test/cmp_tool/test_read_file8_2.txt deleted file mode 100644 index d8122a861aad099273fb76ab6a8e3d87ba8b80c5..0000000000000000000000000000000000000000 --- a/test/cmp_tool/test_read_file8_2.txt +++ /dev/null @@ -1,10 +0,0 @@ -# test file to the read_file8 function -00 -01 02 -03 04 05 -06 07 08 09 - -0A 0B 0C 0D 0E -0F 10 11 12 13 14 -# skip this line! -15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 diff --git a/test/cmp_tool/test_read_file8_3.txt b/test/cmp_tool/test_read_file8_3.txt deleted file mode 100644 index 808a543aedc2ce35ebe1fa3726c5a582f1385431..0000000000000000000000000000000000000000 --- a/test/cmp_tool/test_read_file8_3.txt +++ /dev/null @@ -1,9 +0,0 @@ -# 2nd test file to the read_file8 function -# to test the error case when data are wrong encoded -00 01 02 03 04 05 -06 07 08 09 0A 0B -0C 0D 0E 0F 10 11 -12 13 14 15 16 17 -18 19 1A 1B 1C 1D -1E1F 20 -#^ this is the wrong formating diff --git a/test/cmp_tool/test_read_file8_4.txt b/test/cmp_tool/test_read_file8_4.txt deleted file mode 100644 index 8dcdd2a5818bafc3ffb5c8a93cb511b8920cde9a..0000000000000000000000000000000000000000 --- a/test/cmp_tool/test_read_file8_4.txt +++ /dev/null @@ -1,9 +0,0 @@ -# 2nd test file to the read_file8 function -# to test the error case when data are wrong encoded -00 01 02 03 04 05 -06 07 08 09 0A 0B -0C 0D 0E 0F 10 11 -12 13 14 15 16 17 -18 19 1A 1B 1C 1D -1L 1F 20 -#^ this is the wrong formating diff --git a/test/cmp_tool/test_read_file8_5.txt b/test/cmp_tool/test_read_file8_5.txt deleted file mode 100644 index eac4d84af102ae56ad7c9d905f50db8f2fe5cc3a..0000000000000000000000000000000000000000 --- a/test/cmp_tool/test_read_file8_5.txt +++ /dev/null @@ -1 +0,0 @@ -�� diff --git a/test/decmp/meson.build b/test/decmp/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..4c7778a171aaf083705dadea4b7904fb168dea01 --- /dev/null +++ b/test/decmp/meson.build @@ -0,0 +1,12 @@ +test_case = files('test_decmp.c') +test_runner = test_runner_generator.process(test_case) + +test_decmp = executable('test_decmp', + test_case, test_runner, + include_directories : incdir, + link_with : cmp_lib, + dependencies : unity_dep, + build_by_default : false +) + +test('Decompression Unit Tests', test_decmp) diff --git a/test/decmp/test_decmp.c b/test/decmp/test_decmp.c new file mode 100644 index 0000000000000000000000000000000000000000..8e9fb8720c4d666388e219fe08932d618951d5c2 --- /dev/null +++ b/test/decmp/test_decmp.c @@ -0,0 +1,2039 @@ +/** + * @file test_decmp.c + * @author Dominik Loidolt (dominik.loidolt@univie.ac.at) + * @date 2022 + * + * @copyright GPLv2 + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * @brief decompression tests + */ + + +#include <string.h> +#include <stdlib.h> + +#include <unity.h> + +#include <compiler.h> +#include <cmp_entity.h> +#include "../../lib/icu_compress/cmp_icu.c" /* .c file included to test static functions */ +#include "../../lib/decompress/decmp.c" /* .c file included to test static functions */ + +#define MAX_VALID_CW_LEM 32 + + +void test_bitstream(void) +{ + uint8_t i, data[12]; + struct bit_decoder dec; + size_t ret; + int status; + uint32_t read_bits; + + for (i = 0; i < sizeof(data); ++i) + data[i] = i; + + ret = bit_init_decoder(&dec, data, sizeof(data)); + TEST_ASSERT_EQUAL_size_t(sizeof(data), ret); + + read_bits = bit_read_bits32(&dec, 31); + TEST_ASSERT_EQUAL_HEX32(0x00010203>>1, read_bits); + TEST_ASSERT_EQUAL_INT(31, dec.bits_consumed); + + status = bit_refill(&dec); + TEST_ASSERT_EQUAL_INT(BIT_UNFINISHED, status); + TEST_ASSERT_EQUAL_INT(7, dec.bits_consumed); + status = bit_refill(&dec); + TEST_ASSERT_EQUAL_INT(BIT_UNFINISHED, status); + TEST_ASSERT_EQUAL_INT(7, dec.bits_consumed); + TEST_ASSERT_FALSE(bit_end_of_stream(&dec)); + + read_bits = bit_read_bits32(&dec, 32); + TEST_ASSERT_EQUAL_HEX32(0x82028303, read_bits); + TEST_ASSERT_EQUAL_INT(39, dec.bits_consumed); + read_bits = bit_read_bits32(&dec, 1); + TEST_ASSERT_EQUAL_HEX32(1, read_bits); + TEST_ASSERT_EQUAL_INT(40, dec.bits_consumed); + + status = bit_refill(&dec); + TEST_ASSERT_EQUAL_INT(BIT_END_OF_BUFFER, status); + TEST_ASSERT_EQUAL_INT(32, dec.bits_consumed); + status = bit_refill(&dec); + TEST_ASSERT_EQUAL_INT(BIT_END_OF_BUFFER, status); + TEST_ASSERT_EQUAL_INT(32,dec.bits_consumed); + TEST_ASSERT_FALSE(bit_end_of_stream(&dec)); + + read_bits = bit_read_bits32(&dec, 32); + TEST_ASSERT_EQUAL_HEX32(0x08090A0B, read_bits); + status = bit_refill(&dec); + TEST_ASSERT_EQUAL_INT(BIT_ALL_READ_IN, status); + status = bit_refill(&dec); + TEST_ASSERT_EQUAL_INT(BIT_ALL_READ_IN, status); + TEST_ASSERT_TRUE(bit_end_of_stream(&dec)); + + bit_read_bits32(&dec, 1); + status = bit_refill(&dec); + TEST_ASSERT_EQUAL_INT(BIT_OVERFLOW, status); + status = bit_refill(&dec); + TEST_ASSERT_EQUAL_INT(BIT_OVERFLOW, status); + TEST_ASSERT_FALSE(bit_end_of_stream(&dec)); + + bit_read_bits(&dec, 57); + status = bit_refill(&dec); + TEST_ASSERT_EQUAL_INT(BIT_OVERFLOW, status); + bit_read_bits(&dec, 57); + bit_read_bits(&dec, 57); + bit_read_bits(&dec, 57); + bit_read_bits(&dec, 57); + TEST_ASSERT_EQUAL_INT(BIT_OVERFLOW, status); + + + + { + uint8_t k, j; + uint8_t buf[9]; + size_t s; + + for (k = 0; k < 8; k++) { + memset(data, 0, sizeof(data)); + for (j = 0; j < k; j++) + buf[j] = j; + s = bit_init_decoder(&dec, buf, j); + TEST_ASSERT_EQUAL_size_t(j, s); + for (j = 0; j < k; j++) + TEST_ASSERT_EQUAL_UINT(j, bit_read_bits(&dec, 8)); + TEST_ASSERT_TRUE(bit_end_of_stream(&dec)); + TEST_ASSERT_EQUAL_INT(BIT_ALL_READ_IN, bit_refill(&dec)); + } + } +} + + +/** + * @test unary_decoder + */ + +void test_unary_decoder(void) +{ + uint32_t leading_ones; + struct bit_decoder dec; + uint32_t unused_1 = 0; + uint32_t unused_2 = 0; + uint32_t value; + size_t ret; + + + value = 0; + ret = bit_init_decoder(&dec, &value, sizeof(value)); + TEST_ASSERT_EQUAL_size_t(sizeof(value), ret); + leading_ones = unary_decoder(&dec, unused_1, unused_2); + TEST_ASSERT_EQUAL_INT(0, leading_ones); + leading_ones = unary_decoder(&dec, unused_1, unused_2); + TEST_ASSERT_EQUAL_INT(0, leading_ones); + TEST_ASSERT_EQUAL_INT(BIT_END_OF_BUFFER, bit_refill(&dec)); + + value = be32_to_cpu(0x7FFFFFFF); + ret = bit_init_decoder(&dec, &value, sizeof(value)); + TEST_ASSERT_EQUAL_size_t(sizeof(value), ret); + leading_ones = unary_decoder(&dec, unused_1, unused_2); + TEST_ASSERT_EQUAL_INT(0, leading_ones); + leading_ones = unary_decoder(&dec, unused_1, unused_2); + TEST_ASSERT_EQUAL_INT(31, leading_ones); + TEST_ASSERT_EQUAL_INT(BIT_OVERFLOW, bit_refill(&dec)); + + value = be32_to_cpu(0x80000000); + ret = bit_init_decoder(&dec, &value, sizeof(value)); + TEST_ASSERT_EQUAL_size_t(sizeof(value), ret); + leading_ones = unary_decoder(&dec, unused_1, unused_2); + TEST_ASSERT_EQUAL_INT(1, leading_ones); + TEST_ASSERT_EQUAL_INT(BIT_END_OF_BUFFER, bit_refill(&dec)); + leading_ones = unary_decoder(&dec, unused_1, unused_2); + TEST_ASSERT_EQUAL_INT(0, leading_ones); + TEST_ASSERT_EQUAL_INT(BIT_END_OF_BUFFER, bit_refill(&dec)); + + value = be32_to_cpu(0xBFFFFFFF); + ret = bit_init_decoder(&dec, &value, sizeof(value)); + TEST_ASSERT_EQUAL_size_t(sizeof(value), ret); + leading_ones = unary_decoder(&dec, unused_1, unused_2); + TEST_ASSERT_EQUAL_INT(1, leading_ones); + TEST_ASSERT_EQUAL_INT(BIT_END_OF_BUFFER, bit_refill(&dec)); + leading_ones = unary_decoder(&dec, unused_1, unused_2); + TEST_ASSERT_EQUAL_INT(30, leading_ones); + TEST_ASSERT_EQUAL_INT(BIT_OVERFLOW, bit_refill(&dec)); + + value = be32_to_cpu(0xFFFF0000); + ret = bit_init_decoder(&dec, &value, sizeof(value)); + TEST_ASSERT_EQUAL_size_t(sizeof(value), ret); + leading_ones = unary_decoder(&dec, unused_1, unused_2); + TEST_ASSERT_EQUAL_INT(16, leading_ones); + TEST_ASSERT_EQUAL_INT(BIT_END_OF_BUFFER, bit_refill(&dec)); + + value = be32_to_cpu(0xFFFF7FFF); + ret = bit_init_decoder(&dec, &value, sizeof(value)); + TEST_ASSERT_EQUAL_size_t(sizeof(value), ret); + leading_ones = unary_decoder(&dec, unused_1, unused_2); + TEST_ASSERT_EQUAL_INT(16, leading_ones); + TEST_ASSERT_EQUAL_INT(BIT_END_OF_BUFFER, bit_refill(&dec)); + + value = be32_to_cpu(0xFFFFFFFE); + ret = bit_init_decoder(&dec, &value, sizeof(value)); + TEST_ASSERT_EQUAL_size_t(sizeof(value), ret); + leading_ones = unary_decoder(&dec, unused_1, unused_2); + TEST_ASSERT_EQUAL_INT(31, leading_ones); + TEST_ASSERT_EQUAL_INT(BIT_ALL_READ_IN, bit_refill(&dec)); + + value = be32_to_cpu(0xFFFFFFFF); + ret = bit_init_decoder(&dec, &value, sizeof(value)); + TEST_ASSERT_EQUAL_size_t(sizeof(value), ret); + leading_ones = unary_decoder(&dec, unused_1, unused_2); + TEST_ASSERT_EQUAL_INT(32, leading_ones); + TEST_ASSERT_EQUAL_INT(BIT_OVERFLOW, bit_refill(&dec)); + + { + uint64_t value64 = ~0ULL; + ret = bit_init_decoder(&dec, &value64, sizeof(value64)); + TEST_ASSERT_EQUAL_size_t(sizeof(value64), ret); + leading_ones = unary_decoder(&dec, unused_1, unused_2); + TEST_ASSERT_EQUAL_INT(64, leading_ones); + TEST_ASSERT_EQUAL_INT(BIT_OVERFLOW, bit_refill(&dec)); + + value64 = be64_to_cpu(0xFFFFFFFF00000000); + ret = bit_init_decoder(&dec, &value64, sizeof(value64)); + TEST_ASSERT_EQUAL_size_t(sizeof(value64), ret); + leading_ones = unary_decoder(&dec, unused_1, unused_2); + TEST_ASSERT_EQUAL_INT(32, leading_ones); + /* TEST_ASSERT_EQUAL_INT(BIT_OVERFLOW, bit_refill(&dec)); */ + } +} + + +/** + * @test rice_decoder + */ + +void test_rice_decoder(void) +{ + struct bit_decoder dec; + uint64_t bitstream; + uint32_t m, log2_m, decoded_cw; + size_t buf_size; + + /* log2_m = 0 test */ + log2_m = 0; m = 1U << log2_m; + + bitstream = 0; + buf_size = bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + TEST_ASSERT_EQUAL_size_t(sizeof(bitstream), buf_size); + decoded_cw = unary_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(1, dec.bits_consumed); + TEST_ASSERT_EQUAL(0, decoded_cw); + + bitstream = cpu_to_be64(0x7FFFFFFFFFFFFFFF); /* 0b0111...11 */ + buf_size = bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + TEST_ASSERT_EQUAL_size_t(sizeof(bitstream), buf_size); + decoded_cw = unary_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(1, dec.bits_consumed); + TEST_ASSERT_EQUAL(0, decoded_cw); + + bitstream = cpu_to_be64(0x8000000000000000); + buf_size = bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + TEST_ASSERT_EQUAL_size_t(sizeof(bitstream), buf_size); + decoded_cw = unary_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(2, dec.bits_consumed); + TEST_ASSERT_EQUAL(1, decoded_cw); + + bitstream = cpu_to_be64(0xFFFFFFFE00000000); + buf_size = bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + TEST_ASSERT_EQUAL_size_t(sizeof(bitstream), buf_size); + decoded_cw = unary_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(32, dec.bits_consumed); + TEST_ASSERT_EQUAL(31, decoded_cw); + + bitstream = cpu_to_be64(0xFFFFFFFFFFFFFFFE); + buf_size = bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + TEST_ASSERT_EQUAL_size_t(sizeof(bitstream), buf_size); + decoded_cw = unary_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(64, dec.bits_consumed); + TEST_ASSERT_EQUAL(63, decoded_cw); + TEST_ASSERT_EQUAL_INT(BIT_ALL_READ_IN, bit_refill(&dec)); + + bitstream = cpu_to_be64(0xFFFFFFFF00000000); + buf_size = bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + TEST_ASSERT_EQUAL_size_t(sizeof(bitstream), buf_size); + decoded_cw = unary_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(33, dec.bits_consumed); + TEST_ASSERT_EQUAL(32, decoded_cw); + + /* invalid code word (longer than 32 bit) */ + bitstream = cpu_to_be64(0xFFFFFFFFFFFFFFFF); + buf_size = bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + TEST_ASSERT_EQUAL_size_t(sizeof(bitstream), buf_size); + decoded_cw = unary_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(65, dec.bits_consumed); + TEST_ASSERT_EQUAL(64, decoded_cw); + TEST_ASSERT_EQUAL_INT(BIT_OVERFLOW, bit_refill(&dec)); + + /* log2_m = 1 test */ + log2_m = 1; m = 1U << log2_m; + + bitstream = 0; + buf_size = bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + TEST_ASSERT_EQUAL_size_t(sizeof(bitstream), buf_size); + decoded_cw = rice_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(2, dec.bits_consumed); + TEST_ASSERT_EQUAL(0, decoded_cw); + + bitstream = cpu_to_be64(0x4000000000000000); + buf_size = bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + TEST_ASSERT_EQUAL_size_t(sizeof(bitstream), buf_size); + decoded_cw = rice_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(2, dec.bits_consumed); + TEST_ASSERT_EQUAL(1, decoded_cw); + + bitstream = cpu_to_be64(0xFFFFFFFC00000000); + buf_size = bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + TEST_ASSERT_EQUAL_size_t(sizeof(bitstream), buf_size); + decoded_cw = rice_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(32, dec.bits_consumed); + TEST_ASSERT_EQUAL(60, decoded_cw); + + bitstream = cpu_to_be64(0xFFFFFFFD00000000); + buf_size = bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + TEST_ASSERT_EQUAL_size_t(sizeof(bitstream), buf_size); + decoded_cw = rice_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(32, dec.bits_consumed); + TEST_ASSERT_EQUAL(61, decoded_cw); + + /* invalid code word (longer than 32 bit) */ + bitstream = cpu_to_be64(0xFFFFFFFE00000000); + buf_size = bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + TEST_ASSERT_EQUAL_size_t(sizeof(bitstream), buf_size); + decoded_cw = rice_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(33, dec.bits_consumed); + TEST_ASSERT_EQUAL(62, decoded_cw); + TEST_ASSERT_GREATER_THAN_UINT(MAX_VALID_CW_LEM, dec.bits_consumed); + + /* log2_m = 31 test */ + log2_m = 31; m = 1U << log2_m; + + bitstream = 0; + buf_size = bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + TEST_ASSERT_EQUAL_size_t(sizeof(bitstream), buf_size); + decoded_cw = rice_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(32, dec.bits_consumed); + TEST_ASSERT_EQUAL(0, decoded_cw); + + bitstream = cpu_to_be64(0x0000000100000000); + buf_size = bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + TEST_ASSERT_EQUAL_size_t(sizeof(bitstream), buf_size); + decoded_cw = rice_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(32, dec.bits_consumed); + TEST_ASSERT_EQUAL(1, decoded_cw); + + bitstream = cpu_to_be64(0x7FFFFFFE00000000); + buf_size = bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + TEST_ASSERT_EQUAL_size_t(sizeof(bitstream), buf_size); + decoded_cw = rice_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(32, dec.bits_consumed); + TEST_ASSERT_EQUAL(0X7FFFFFFE, decoded_cw); + + bitstream = cpu_to_be64(0x7FFFFFFD00000000); + buf_size = bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + TEST_ASSERT_EQUAL_size_t(sizeof(bitstream), buf_size); + decoded_cw = rice_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(32, dec.bits_consumed); + TEST_ASSERT_EQUAL(0X7FFFFFFD, decoded_cw); + + /* invalid code word (longer than 32 bit) */ + bitstream = cpu_to_be64(0x8000000000000000); + buf_size = bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + TEST_ASSERT_EQUAL_size_t(sizeof(bitstream), buf_size); + rice_decoder(&dec, m, log2_m); + TEST_ASSERT_GREATER_THAN_UINT(MAX_VALID_CW_LEM, dec.bits_consumed); + +#if 0 +/* this case is prevented by an assert */ + + /* test log_2 to big */ + log2_m = 32; m = 1 << log2_m; + bitstream = 0x00000000; + buf_size = bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + decoded_cw = rice_decoder(&dec, m, log2_m); + TEST_ASSERT_GREATER_THAN_UINT(MAX_VALID_CW_LEM, dec.bits_consumed); + + bitstream = cpu_to_be32(0xE000000000000000); + log2_m = 33; m = 1 << log2_m; + decoded_cw = rice_decoder(&dec, m, log2_m); + TEST_ASSERT_GREATER_THAN_UINT(MAX_VALID_CW_LEM, dec.bits_consumed); + + + log2_m = UINT_MAX; m = 1 << log2_m; + decoded_cw = rice_decoder(&dec, m, log2_m); + TEST_ASSERT_GREATER_THAN_UINT(MAX_VALID_CW_LEM, dec.bits_consumed); +#endif +} + + +/** + * @test golomb_decoder + */ + +void test_golomb_decoder(void) +{ + struct bit_decoder dec; + uint32_t bitstream; + unsigned int m; + unsigned int log2_m; + uint32_t decoded_cw; + + /* m = 1 test */ + m = 1; + log2_m = ilog_2(m); + + bitstream = 0; + bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + decoded_cw = golomb_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(1, dec.bits_consumed-32); + TEST_ASSERT_EQUAL(0, decoded_cw); + + bitstream = cpu_to_be32(0x7FFFFFFF); /* 0b0111...11 */ + bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + decoded_cw = golomb_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(1, dec.bits_consumed-32); + TEST_ASSERT_EQUAL(0, decoded_cw); + + bitstream = cpu_to_be32(0x80000000); + bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + decoded_cw = golomb_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(2, dec.bits_consumed-32); + TEST_ASSERT_EQUAL(1, decoded_cw); + + bitstream = cpu_to_be32(0xFFFFFFFE); + bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + decoded_cw = golomb_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(32, dec.bits_consumed-32); + TEST_ASSERT_EQUAL(31, decoded_cw); + + /* invalid code word (longer than 32 bit) */ + bitstream = 0xFFFFFFFF; + golomb_decoder(&dec, m, log2_m); + TEST_ASSERT_GREATER_THAN_UINT(MAX_VALID_CW_LEM, dec.bits_consumed-32); + TEST_ASSERT_EQUAL_INT(BIT_OVERFLOW, bit_refill(&dec)); + + + /* m = 2 test */ + m = 2; + log2_m = ilog_2(m); + + bitstream = 0; + bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + decoded_cw = golomb_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(2, dec.bits_consumed-32); + TEST_ASSERT_EQUAL(0, decoded_cw); + + bitstream = cpu_to_be32(0x40000000); + bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + decoded_cw = golomb_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(2, dec.bits_consumed-32); + TEST_ASSERT_EQUAL(1, decoded_cw); + + bitstream = cpu_to_be32(0xFFFFFFFC); + bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + decoded_cw = golomb_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(32, dec.bits_consumed-32); + TEST_ASSERT_EQUAL(60, decoded_cw); + + bitstream = cpu_to_be32(0xFFFFFFFD); + bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + decoded_cw = golomb_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(32, dec.bits_consumed-32); + TEST_ASSERT_EQUAL(61, decoded_cw); + + /* invalid code word (longer than 32 bit) */ + bitstream = cpu_to_be32(0xFFFFFFFE); + bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + golomb_decoder(&dec, m, log2_m); + TEST_ASSERT_GREATER_THAN_UINT(MAX_VALID_CW_LEM, dec.bits_consumed-32); + TEST_ASSERT_EQUAL_INT(BIT_OVERFLOW, bit_refill(&dec)); + + + /* m = 3 test */ + m = 3; + log2_m = ilog_2(m); + + bitstream = 0; + bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + decoded_cw = golomb_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(2, dec.bits_consumed-32); + TEST_ASSERT_EQUAL(0, decoded_cw); + + bitstream = cpu_to_be32(0x40000000); + bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + decoded_cw = golomb_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(3, dec.bits_consumed-32); + TEST_ASSERT_EQUAL(1, decoded_cw); + + bitstream = cpu_to_be32(0x60000000); + bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + decoded_cw = golomb_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(3, dec.bits_consumed-32); + TEST_ASSERT_EQUAL(2, decoded_cw); + + bitstream = cpu_to_be32(0x80000000); + bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + decoded_cw = golomb_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(3, dec.bits_consumed-32); + TEST_ASSERT_EQUAL(3, decoded_cw); + + bitstream = cpu_to_be32(0xA0000000); + bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + decoded_cw = golomb_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(4, dec.bits_consumed-32); + TEST_ASSERT_EQUAL(4, decoded_cw); + + bitstream = cpu_to_be32(0xFFFFFFFB); + bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + decoded_cw = golomb_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(32, dec.bits_consumed-32); + TEST_ASSERT_EQUAL(89, decoded_cw); + + bitstream = cpu_to_be32(0xFFFFFFFC); + bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + decoded_cw = golomb_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(32, dec.bits_consumed-32); + TEST_ASSERT_EQUAL(90, decoded_cw); + + /* invalid code word (longer than 32 bit) */ + bitstream = cpu_to_be32(0xFFFFFFFD); + bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + golomb_decoder(&dec, m, log2_m); + TEST_ASSERT_GREATER_THAN_UINT(MAX_VALID_CW_LEM, dec.bits_consumed-32); + TEST_ASSERT_EQUAL_INT(BIT_OVERFLOW, bit_refill(&dec)); + + + + /* m = 0x7FFFFFFF test */ + m = 0x7FFFFFFF; + log2_m = ilog_2(m); + + bitstream = 0; + bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + decoded_cw = golomb_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(31, dec.bits_consumed-32); + TEST_ASSERT_EQUAL(0, decoded_cw); + + bitstream = cpu_to_be32(0x2); + bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + decoded_cw = golomb_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(32, dec.bits_consumed-32); + TEST_ASSERT_EQUAL(1, decoded_cw); + + bitstream = cpu_to_be32(0x7FFFFFFF); + bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + decoded_cw = golomb_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(32, dec.bits_consumed-32); + TEST_ASSERT_EQUAL(0x7FFFFFFE, decoded_cw); + + bitstream = cpu_to_be32(0x80000000); + bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + decoded_cw = golomb_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(32, dec.bits_consumed-32); + TEST_ASSERT_EQUAL(0x7FFFFFFF, decoded_cw); + + /* invalid code word (longer than 32 bit) */ + bitstream = cpu_to_be32(0X80000001); + bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + golomb_decoder(&dec, m, log2_m); + TEST_ASSERT_GREATER_THAN_UINT(MAX_VALID_CW_LEM, dec.bits_consumed-32); + TEST_ASSERT_EQUAL_INT(BIT_OVERFLOW, bit_refill(&dec)); + + + /* m = 0x80000000 test */ + m = 0x80000000; + log2_m = ilog_2(m); + + bitstream = 0; + bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + decoded_cw = golomb_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(32, dec.bits_consumed-32); + TEST_ASSERT_EQUAL(0, decoded_cw); + + bitstream = cpu_to_be32(1); + bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + decoded_cw = golomb_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(32, dec.bits_consumed-32); + TEST_ASSERT_EQUAL(1, decoded_cw); + + bitstream = cpu_to_be32(0x7FFFFFFE); + bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + decoded_cw = golomb_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(32, dec.bits_consumed-32); + TEST_ASSERT_EQUAL(0x7FFFFFFE, decoded_cw); + + bitstream = cpu_to_be32(0x7FFFFFFD); + bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + decoded_cw = golomb_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(32, dec.bits_consumed-32); + TEST_ASSERT_EQUAL(0x7FFFFFFD, decoded_cw); + + /* invalid code word (longer than 32 bit) */ + bitstream = cpu_to_be32(0x80000000); + bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + golomb_decoder(&dec, m, log2_m); + TEST_ASSERT_GREATER_THAN_UINT(MAX_VALID_CW_LEM, dec.bits_consumed-32); + TEST_ASSERT_EQUAL_INT(BIT_OVERFLOW, bit_refill(&dec)); + +#if 0 + this case is prevented by an assert + + /* test log_2 to big */ + bitstream = 0x00000000; + bit_init_decoder(&dec, &bitstream, sizeof(bitstream)); + log2_m = 33; + decoded_cw = golomb_decoder(&dec, m, log2_m); + TEST_ASSERT_EQUAL(0, dec.bits_consumed-32); +#endif +} + + +/** + * @test select_decoder + */ + +void test_select_decoder(void) +{ + decoder_ptr decoder; + uint32_t golomb_par; + + golomb_par = 1; + decoder = select_decoder(golomb_par); + TEST_ASSERT_EQUAL(unary_decoder, decoder); + + golomb_par = 0x80000000; + decoder = select_decoder(golomb_par); + TEST_ASSERT_EQUAL(rice_decoder, decoder); + + golomb_par = 3; + decoder = select_decoder(golomb_par); + TEST_ASSERT_EQUAL(golomb_decoder, decoder); + + golomb_par = 0x7FFFFFFF; + decoder = select_decoder(golomb_par); + TEST_ASSERT_EQUAL(golomb_decoder, decoder); + +#if 0 +this case is prevented by an assert + golomb_par = 0; + decoder = select_decoder(golomb_par); + TEST_ASSERT_EQUAL(NULL, decoder); +#endif +} + + +/** + * @test decode_zero + */ + +void test_decode_zero(void) +{ + uint32_t decoded_value = ~0U; + uint64_t cmp_data = {0x88449FC000800000}; + struct bit_decoder dec = {0}; + struct decoder_setup setup = {0}; + uint32_t spillover = 8; + int err; + + cpu_to_be64s(&cmp_data); + bit_init_decoder(&dec, &cmp_data, sizeof(cmp_data)); + configure_decoder_setup(&setup, &dec, CMP_MODE_DIFF_ZERO, 1, spillover, CMP_LOSSLESS, 16); + + + err = decode_zero(&setup, &decoded_value); + TEST_ASSERT_EQUAL_HEX(0, decoded_value); + TEST_ASSERT_FALSE(err); + err = decode_zero(&setup, &decoded_value); + TEST_ASSERT_EQUAL_HEX(0x4223, decoded_value); + TEST_ASSERT_FALSE(err); + err = decode_zero(&setup, &decoded_value); + TEST_ASSERT_FALSE(err); + TEST_ASSERT_EQUAL_HEX(6, decoded_value); + err = decode_zero(&setup, &decoded_value); + TEST_ASSERT_FALSE(err); + TEST_ASSERT_EQUAL_HEX(7, decoded_value); + err = decode_zero(&setup, &decoded_value); + TEST_ASSERT_EQUAL_HEX(0xFFFF, decoded_value); + TEST_ASSERT_FALSE(err); + TEST_ASSERT_EQUAL_INT(BIT_END_OF_BUFFER, bit_refill(&dec)); + + /* error case: read over the cmp_data buffer 1 */ + err = decode_zero(&setup, &decoded_value); + TEST_ASSERT_TRUE(err); + + /* error case: read over the cmp_data buffer 2 */ + cmp_data = cpu_to_be64(0x0001000000000000); /* 8 encoded > spill_over */ + bit_init_decoder(&dec, &cmp_data, sizeof(cmp_data)); + bit_consume_bits(&dec, 64); + err = decode_zero(&setup, &decoded_value); + TEST_ASSERT_TRUE(err); + + /* error case: decoded value larger than the outlier parameter */ + cmp_data = cpu_to_be64(0xFF00000000000000); /* 7 encoded > spill_over */ + bit_init_decoder(&dec, &cmp_data, sizeof(cmp_data)); + err = decode_zero(&setup, &decoded_value); + TEST_ASSERT_TRUE(err); + /* this should work */ + cmp_data = cpu_to_be64(0xFE00000000000000); /* 8 encoded > spill_over */ + bit_init_decoder(&dec, &cmp_data, sizeof(cmp_data)); + err = decode_zero(&setup, &decoded_value); + TEST_ASSERT_FALSE(err); + TEST_ASSERT_EQUAL_HEX(6, decoded_value); + + /* error case: value after escape symbol smaller that spillover */ + cmp_data = cpu_to_be64(0x003000000000000); /* 0 encoded + 6 unencoded < spill_over */ + bit_init_decoder(&dec, &cmp_data, sizeof(cmp_data)); + err = decode_zero(&setup, &decoded_value); + TEST_ASSERT_TRUE(err); + /* this should work */ + cmp_data = cpu_to_be64(0x004000000000000); /* 0 encoded + 7 unencoded < spill_over */ + bit_init_decoder(&dec, &cmp_data, sizeof(cmp_data)); + err = decode_zero(&setup, &decoded_value); + TEST_ASSERT_EQUAL_HEX(7, decoded_value); + TEST_ASSERT_FALSE(err); +} + + +/** + * @test decode_zero + */ + +void test_zero_refill_needed(void) +{ + uint32_t decoded_value = ~0U; + uint64_t cmp_data[] = {0x0000000200000003, 0xFFFFFFFC00000000}; + struct bit_decoder dec = {0}; + struct decoder_setup setup = {0}; + uint32_t spillover = 8; + uint32_t m = 1<<30; + int err; + + cpu_to_be64s(&cmp_data[0]); + cpu_to_be64s(&cmp_data[1]); + bit_init_decoder(&dec, cmp_data, sizeof(cmp_data)); + configure_decoder_setup(&setup, &dec, CMP_MODE_DIFF_ZERO, m, spillover, CMP_LOSSLESS, 32); + + err = decode_zero(&setup, &decoded_value); + TEST_ASSERT_EQUAL_HEX(0, decoded_value); + TEST_ASSERT_FALSE(err); + err = decode_zero(&setup, &decoded_value); + TEST_ASSERT_EQUAL_HEX(0xFFFFFFFE, decoded_value); + TEST_ASSERT_FALSE(err); +} + + +/** + * @test decode_multi + */ + +void test_decode_multi(void) +{ + uint32_t decoded_value = ~0U; + uint32_t cmp_data[] = {0x16B66DF8, 0x84360000}; + struct decoder_setup setup = {0}; + struct bit_decoder dec = {0}; + int err; + + cpu_to_be32s(&cmp_data[0]); + cpu_to_be32s(&cmp_data[1]); + + bit_init_decoder(&dec, cmp_data, sizeof(cmp_data)); + configure_decoder_setup(&setup, &dec, CMP_MODE_DIFF_MULTI, 3, 8, CMP_LOSSLESS, 16); + + + err = decode_multi(&setup, &decoded_value); + TEST_ASSERT_FALSE(err); + TEST_ASSERT_EQUAL_HEX(0, decoded_value); + err = decode_multi(&setup, &decoded_value); + TEST_ASSERT_FALSE(err); + TEST_ASSERT_EQUAL_HEX(1, decoded_value); + err = decode_multi(&setup, &decoded_value); + TEST_ASSERT_FALSE(err); + TEST_ASSERT_EQUAL_HEX(7, decoded_value); + err = decode_multi(&setup, &decoded_value); + TEST_ASSERT_FALSE(err); + TEST_ASSERT_EQUAL_HEX(8, decoded_value); + err = decode_multi(&setup, &decoded_value); + TEST_ASSERT_FALSE(err); + TEST_ASSERT_EQUAL_HEX(9, decoded_value); + err = decode_multi(&setup, &decoded_value); + TEST_ASSERT_FALSE(err); + TEST_ASSERT_EQUAL_HEX(0x4223, decoded_value); + /* TEST_ASSERT_EQUAL_INT(47, stream_pos); */ + + /* error cases unencoded_len > 32 */ + + configure_decoder_setup(&setup, &dec, CMP_MODE_DIFF_MULTI, 3, 8, CMP_LOSSLESS, 16); + + /* 0xFF -> 24 = spill(8)+16 -> unencoded_len = 34 bits */ + cmp_data[0] = cpu_to_be32(0xFF000000); + cmp_data[1] = cpu_to_be32(0x00000000); + bit_init_decoder(&dec, cmp_data, sizeof(cmp_data)); + + err = decode_multi(&setup, &decoded_value); + TEST_ASSERT_EQUAL_INT(-1, err); + + + /* 0xFA -> 16 = spill(8)+8 -> unencoded_len = 17 bits -> larger than + * 16 bit max_used_bits*/ + cmp_data[0] = cpu_to_be32(0xFA000000); + cmp_data[1] = cpu_to_be32(0x00000000); + bit_init_decoder(&dec, cmp_data, sizeof(cmp_data)); + + err = decode_multi(&setup, &decoded_value); + TEST_ASSERT_EQUAL_INT(-1, err); + + /* this should work */ + cmp_data[0] = cpu_to_be32(0xF9000200); + cmp_data[1] = cpu_to_be32(0x00000000); + bit_init_decoder(&dec, cmp_data, sizeof(cmp_data)); + + err = decode_multi(&setup, &decoded_value); + TEST_ASSERT_FALSE(err); + /* TEST_ASSERT_EQUAL_INT(7+16, stream_pos); */ + TEST_ASSERT_EQUAL_HEX(0x8001+8, decoded_value); + + /* error cases unencoded_val is not plausible */ + /* unencoded_len = 4; unencoded_val =0b0011 */ + cmp_data[0] = cpu_to_be32(0xEC000000); + cmp_data[1] = cpu_to_be32(0x00000000); + bit_init_decoder(&dec, cmp_data, sizeof(cmp_data)); + + err = decode_multi(&setup, &decoded_value); + TEST_ASSERT_EQUAL_INT(-1, err); + + /* unencoded_len = 16; unencoded_val =0x3FFF */ + cmp_data[0] = cpu_to_be32(0xF87FFE00); + cmp_data[1] = cpu_to_be32(0x00000000); + bit_init_decoder(&dec, cmp_data, sizeof(cmp_data)); + + err = decode_multi(&setup, &decoded_value); + TEST_ASSERT_EQUAL_INT(-1, err); + /* unencoded_len = 16; unencoded_val =0x3FFF */ + cmp_data[0] = cpu_to_be32(0xF87FFE00); + cmp_data[1] = cpu_to_be32(0x00000000); + bit_init_decoder(&dec, cmp_data, sizeof(cmp_data)); + + err = decode_multi(&setup, &decoded_value); + TEST_ASSERT_EQUAL_INT(-1, err); + + /* decoded value smaller that outlier */ + cmp_data[0] = cpu_to_be32(0xF9FFFE00); + cmp_data[1] = cpu_to_be32(0x00000000); + bit_init_decoder(&dec, cmp_data, sizeof(cmp_data)); + + err = decode_multi(&setup, &decoded_value); + TEST_ASSERT_EQUAL_INT(-1, err); +} + + +/** + * @test decode_multi + */ + +void test_multi_refill_needed(void) +{ + uint32_t decoded_value = ~0U; + uint8_t cmp_data[] = {0x7F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}; + uint32_t cmp_data2[2]; + struct bit_decoder dec = {0}; + struct decoder_setup setup = {0}; + uint32_t spillover = 16; + uint32_t m = 1; + int err; + + bit_init_decoder(&dec, cmp_data, sizeof(cmp_data)); + configure_decoder_setup(&setup, &dec, CMP_MODE_DIFF_ZERO, m, spillover, CMP_LOSSLESS, 32); + + err = decode_multi(&setup, &decoded_value); + TEST_ASSERT_FALSE(err); + TEST_ASSERT_EQUAL_HEX(0, decoded_value); + /* this only works with a 2nd refill */ + err = decode_multi(&setup, &decoded_value); + TEST_ASSERT_FALSE(err); + TEST_ASSERT_EQUAL_HEX(0xFFFFFFFF, decoded_value); + /* 2nd refill should fail */ + err = decode_multi(&setup, &decoded_value); + TEST_ASSERT_TRUE(err); + + + /* decoded value smaller that outlier */ + configure_decoder_setup(&setup, &dec, CMP_MODE_DIFF_ZERO, m, spillover, CMP_LOSSLESS, 16); + cmp_data2[0] = cpu_to_be32(0xFF7FFFFF); + cmp_data2[1] = cpu_to_be32(0x7FFF8000); + bit_init_decoder(&dec, cmp_data2, 6); /* bitstream is to short */ + + err = decode_multi(&setup, &decoded_value); + TEST_ASSERT_FALSE(err); + TEST_ASSERT_EQUAL_HEX(8, decoded_value); + + /* 2nd refill should fail and outlier small than the outlier trigger */ + err = decode_multi(&setup, &decoded_value); + TEST_ASSERT_EQUAL_INT(CORRUPTION_DETECTED, err); +} + +/** + * @test re_map_to_pos + */ + +void test_re_map_to_pos(void) +{ + int j; + uint32_t input, result; + unsigned int max_value_bits; + + input = (uint32_t)INT32_MIN; + result = re_map_to_pos(map_to_pos(input, 32)); + TEST_ASSERT_EQUAL_INT32(input, result); + + input = INT32_MAX; + result = re_map_to_pos(map_to_pos(input, 32)); + TEST_ASSERT_EQUAL_INT32(input, result); + + input = -1U; + result = re_map_to_pos(map_to_pos(input, 32)); + TEST_ASSERT_EQUAL_INT32(input, result); + + input = 0; + result = re_map_to_pos(map_to_pos(input, 32)); + TEST_ASSERT_EQUAL_INT32(input, result); + + input = 1; max_value_bits = 6; + result = re_map_to_pos(map_to_pos(input, max_value_bits)); + TEST_ASSERT_EQUAL_INT32(input, result); + + for (j = -16; j < 15; j++) { + uint32_t map_val = map_to_pos((uint32_t)j, 16) & 0x3F; + result = re_map_to_pos(map_val); + TEST_ASSERT_EQUAL_INT32(j, result); + } + + for (j = INT16_MIN; j < INT16_MAX; j++) { + uint32_t map_val = map_to_pos((uint32_t)j, 16) & 0xFFFF; + + result = re_map_to_pos(map_val); + TEST_ASSERT_EQUAL_INT32(j, result); + } +#if 0 + for (j = INT32_MIN; j < INT32_MAX; j++) { + result = re_map_to_pos(map_to_pos((uint32_t)j, 32)); + TEST_ASSERT_EQUAL_INT32(j, result); + } +#endif +} + + +/** + * returns the needed size of the compression entry header plus the max size of the + * compressed data if ent == NULL if ent is set the size of the compression + * entry (entity header + compressed data) + */ + +size_t icu_compress_data_entity(struct cmp_entity *ent, const struct cmp_cfg *cfg) +{ + uint32_t s; + struct cmp_cfg cfg_cpy; + int cmp_size_bits; + + if (!cfg) + return 0; + + if (cfg->icu_output_buf) + debug_print("Warning the set buffer for the compressed data is ignored! The compressed data are write to the compression entry."); + + s = cmp_cal_size_of_data(cfg->buffer_length, cfg->data_type); + if (!s) + return 0; + /* we round down to the next 4-byte allied address because we access the + * cmp_buffer in uint32_t words + */ + if (cfg->cmp_mode != CMP_MODE_RAW) + s &= ~0x3U; + + s = cmp_ent_create(ent, cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW, s); + + if (!ent || !s) + return s; + + cfg_cpy = *cfg; + cfg_cpy.icu_output_buf = cmp_ent_get_data_buf(ent); + if (!cfg_cpy.icu_output_buf) + return 0; + cmp_size_bits = icu_compress_data(&cfg_cpy); + if (cmp_size_bits < 0) + return 0; + + /* XXX overwrite the size of the compression entity with the size of the actual + * size of the compressed data; not all allocated memory is normally used */ + s = cmp_ent_create(ent, cfg->data_type, cfg->cmp_mode == CMP_MODE_RAW, + cmp_bit_to_byte((unsigned int)cmp_size_bits)); + + if (cmp_ent_write_cmp_pars(ent, cfg, cmp_size_bits)) + return 0; + + return s; +} + + +void test_cmp_decmp_n_imagette_raw(void) +{ + int cmp_size, decmp_size; + size_t s, i; + struct cmp_cfg cfg = cmp_cfg_icu_create(DATA_TYPE_IMAGETTE, CMP_MODE_RAW, 0, CMP_LOSSLESS); + uint16_t data[] = {0, 1, 2, 0x42, (uint16_t)INT16_MIN, INT16_MAX, UINT16_MAX}; + uint32_t *compressed_data; + uint16_t *decompressed_data; + struct cmp_entity *ent; + + s = cmp_cfg_icu_buffers(&cfg, data, ARRAY_SIZE(data), NULL, NULL, + NULL, ARRAY_SIZE(data)); + TEST_ASSERT_TRUE(s); + compressed_data = malloc(s); + TEST_ASSERT_TRUE(compressed_data); + s = cmp_cfg_icu_buffers(&cfg, data, ARRAY_SIZE(data), NULL, NULL, + compressed_data, ARRAY_SIZE(data)); + TEST_ASSERT_TRUE(s); + + cmp_size = icu_compress_data(&cfg); + TEST_ASSERT_EQUAL_INT(sizeof(data)*CHAR_BIT, cmp_size); + + s = cmp_ent_build(NULL, 0, 0, 0, 0, 0, &cfg, cmp_size); + TEST_ASSERT_TRUE(s); + ent = malloc(s); + TEST_ASSERT_TRUE(ent); + s = cmp_ent_build(ent, 0, 0, 0, 0, 0, &cfg, cmp_size); + TEST_ASSERT_TRUE(s); + memcpy(cmp_ent_get_data_buf(ent), compressed_data, ((unsigned int)cmp_size+7)/8); + + decmp_size = decompress_cmp_entiy(ent, NULL, NULL, NULL); + TEST_ASSERT_EQUAL_INT(sizeof(data), decmp_size); + decompressed_data = malloc((size_t)decmp_size); + TEST_ASSERT_TRUE(decompressed_data); + decmp_size = decompress_cmp_entiy(ent, NULL, NULL, decompressed_data); + TEST_ASSERT_EQUAL_INT(sizeof(data), decmp_size); + + for (i = 0; i < ARRAY_SIZE(data); ++i) + TEST_ASSERT_EQUAL_INT(data[i], decompressed_data[i]); + + + free(compressed_data); + free(ent); + free(decompressed_data); +} + + +void test_decompress_imagette_model(void) +{ + uint16_t data[5] = {0}; + uint16_t model[5] = {0, 1, 2, 3, 4}; + uint16_t up_model[5] = {0}; + uint32_t cmp_data[2] = {0}; + struct cmp_cfg cfg = {0}; + struct bit_decoder dec; + int err; + + cmp_data[0] = cpu_to_be32(0x49240000); + + cfg.data_type = DATA_TYPE_IMAGETTE; + cfg.cmp_mode = CMP_MODE_MODEL_MULTI; + cfg.input_buf = data; + cfg.model_buf = model; + cfg.icu_new_model_buf = up_model; + cfg.icu_output_buf = cmp_data; + cfg.buffer_length = 4; + cfg.samples = 5; + cfg.model_value = 16; + cfg.golomb_par = 4; + cfg.spill = 48; + cfg.max_used_bits = &MAX_USED_BITS_SAFE; + + bit_init_decoder(&dec, cfg.icu_output_buf, cfg.buffer_length); + + err = decompress_imagette(&cfg, &dec); + /* TEST_ASSERT_EQUAL_INT(15, stream_pos); */ + TEST_ASSERT_FALSE(err); + TEST_ASSERT_EQUAL_HEX(1, data[0]); + TEST_ASSERT_EQUAL_HEX(2, data[1]); + TEST_ASSERT_EQUAL_HEX(3, data[2]); + TEST_ASSERT_EQUAL_HEX(4, data[3]); + TEST_ASSERT_EQUAL_HEX(5, data[4]); + + TEST_ASSERT_EQUAL_HEX(0, up_model[0]); + TEST_ASSERT_EQUAL_HEX(1, up_model[1]); + TEST_ASSERT_EQUAL_HEX(2, up_model[2]); + TEST_ASSERT_EQUAL_HEX(3, up_model[3]); + TEST_ASSERT_EQUAL_HEX(4, up_model[4]); +} + + +#define DATA_SAMPLES 5 +void test_cmp_decmp_s_fx_diff(void) +{ + size_t s; + int err, decmp_size; + + struct cmp_entity *ent; + const uint32_t MAX_VALUE = ~(~0U << MAX_USED_BITS_V1.s_fx); + struct s_fx data_entry[DATA_SAMPLES]; + uint8_t data_to_compress[COLLECTION_HDR_SIZE + sizeof(data_entry)]; + struct s_fx *decompressed_data = NULL; + uint32_t compressed_data_len_samples = DATA_SAMPLES; + struct cmp_cfg cfg; + + data_entry[0].exp_flags = 0; + data_entry[0].fx = 0; + data_entry[1].exp_flags = 1; + data_entry[1].fx = 23; + data_entry[2].exp_flags = 2; + data_entry[2].fx = 42; + data_entry[3].exp_flags = 3; + data_entry[3].fx = MAX_VALUE; + data_entry[4].exp_flags = 3; + data_entry[4].fx = MAX_VALUE>>1; + + for (s = 0; s < COLLECTION_HDR_SIZE; s++) + data_to_compress[s] = (uint8_t)s; + memcpy(&data_to_compress[COLLECTION_HDR_SIZE], data_entry, sizeof(data_entry)); + + cfg = cmp_cfg_icu_create(DATA_TYPE_S_FX, CMP_MODE_DIFF_MULTI, + CMP_PAR_UNUSED, CMP_LOSSLESS); + TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKNOWN); + + s = cmp_cfg_icu_buffers(&cfg, data_to_compress, DATA_SAMPLES, NULL, NULL, + NULL, compressed_data_len_samples); + TEST_ASSERT_TRUE(s); + + err = cmp_cfg_fx_cob(&cfg, 2, 6, 4, 14, CMP_PAR_UNUSED, CMP_PAR_UNUSED, + CMP_PAR_UNUSED, CMP_PAR_UNUSED, CMP_PAR_UNUSED, + CMP_PAR_UNUSED, CMP_PAR_UNUSED, CMP_PAR_UNUSED); + TEST_ASSERT_FALSE(err); + + s = icu_compress_data_entity(NULL, &cfg); + TEST_ASSERT_TRUE(s); + ent = malloc(s); TEST_ASSERT_TRUE(ent); + s = icu_compress_data_entity(ent, &cfg); + TEST_ASSERT_TRUE(s); + + /* now decompress the data */ + decmp_size = decompress_cmp_entiy(ent, NULL, NULL, decompressed_data); + TEST_ASSERT_EQUAL_INT(cmp_cal_size_of_data(cfg.samples, cfg.data_type), decmp_size); + decompressed_data = malloc((size_t)decmp_size); TEST_ASSERT_TRUE(decompressed_data); + decmp_size = decompress_cmp_entiy(ent, NULL, NULL, decompressed_data); + TEST_ASSERT_EQUAL_INT(cmp_cal_size_of_data(cfg.samples, cfg.data_type), decmp_size); + + TEST_ASSERT_EQUAL_HEX8_ARRAY(data_to_compress, decompressed_data, decmp_size); + /* TEST_ASSERT_FALSE(memcmp(data_to_compress, decompressed_data, (size_t)decmp_size)); */ + /* for (i = 0; i < samples; ++i) { */ + /* printf("%u == %u (round: %u)\n", data[i], decompressed_data[i], round); */ + /* uint32_t mask = ~0U << round; */ + /* if ((data[i]&mask) != (decompressed_data[i]&mask)) */ + /* TEST_ASSERT(0); */ + /* if (model_mode_is_used(cmp_mode)) */ + /* if (up_model[i] != de_up_model[i]) */ + /* TEST_ASSERT(0); */ + /* } */ + free(ent); + free(decompressed_data); +} +#undef DATA_SAMPLES + + +void test_s_fx_diff(void) +{ + size_t i; + int s; + uint8_t cmp_entity[88] = { + 0x80, 0x00, 0x00, 0x09, 0x00, 0x00, 0x58, 0x00, 0x00, 0x20, 0x04, 0xEE, 0x21, 0xBD, 0xB0, 0x1C, 0x04, 0xEE, 0x21, 0xBD, 0xB0, 0x41, 0x00, 0x08, 0x02, 0x08, 0xD0, 0x10, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0xAE, 0xDE, 0x00, 0x00, 0x00, 0x73, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x00, + }; + + uint8_t result_data[32] = {0}; + struct collection_hdr *hdr = (struct collection_hdr *)result_data; + struct s_fx *data = (struct s_fx *)hdr->entry; + uint8_t *decompressed_data; + + /* put some dummy data in the header*/ + for (i = 0; i < sizeof(*hdr); i++) + result_data[i] = (uint8_t)i; + data[0].exp_flags = 0; + data[0].fx = 0; + data[1].exp_flags = 1; + data[1].fx = 0xFFFFFF; + data[2].exp_flags = 3; + data[2].fx = 0x7FFFFF; + data[3].exp_flags = 0; + data[3].fx = 0; + + s = decompress_cmp_entiy((void *)cmp_entity, NULL, NULL, NULL); + TEST_ASSERT_EQUAL_INT(sizeof(result_data), s); + decompressed_data = malloc((size_t)s); + TEST_ASSERT_TRUE(decompressed_data); + s = decompress_cmp_entiy((void *)cmp_entity, NULL, NULL, decompressed_data); + TEST_ASSERT_EQUAL_INT(sizeof(result_data), s); + for (i = 0; i < (size_t)s; ++i) { + TEST_ASSERT_EQUAL(result_data[i], decompressed_data[i]); + } + free(decompressed_data); +} + + +void test_s_fx_model(void) +{ + size_t i; + int s; + uint8_t compressed_data_buf[92] = { + 0x80, 0x00, 0x00, 0x09, 0x00, 0x00, 0x5C, 0x00, 0x00, 0x20, 0x04, 0xF0, 0xC2, 0xD3, 0x47, 0xE4, 0x04, 0xF0, 0xC2, 0xD3, 0x48, 0x16, 0x00, 0x08, 0x03, 0x08, 0xD0, 0x10, 0x01, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x3B, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0x5B, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0x5D, 0x80, 0x00, 0x00, + }; + struct cmp_entity *cmp_entity = (struct cmp_entity *)compressed_data_buf; + + uint8_t model_buf[32]; + uint8_t decompressed_data[32]; + uint8_t up_model_buf[32]; + uint8_t exp_data_buf[32] = {0}; /* expected uncompressed data */ + uint8_t exp_up_model_buf[32] = {0}; + + struct collection_hdr *model_collection = (struct collection_hdr *)model_buf; + struct s_fx *model_data = (struct s_fx *)model_collection->entry; + + struct collection_hdr *exp_data_collection; + struct s_fx *exp_data; + struct collection_hdr *exp_up_model_collection; + struct s_fx *exp_updated_model_data; + + memset(model_collection, 0xFF, sizeof(*model_collection)); + model_data[0].exp_flags = 0; + model_data[0].fx = 0; + model_data[1].exp_flags = 3; + model_data[1].fx = 0x7FFFFF; + model_data[2].exp_flags = 0; + model_data[2].fx = 0xFFFFFF; + model_data[3].exp_flags = 3; + model_data[3].fx = 0xFFFFFF; + + exp_data_collection = (struct collection_hdr *)exp_data_buf; + exp_data = (struct s_fx *)exp_data_collection->entry; + /* put some dummy data in the header */ + for (i = 0; i < sizeof(*exp_data_collection); i++) + exp_data_buf[i] = (uint8_t)i; + exp_data[0].exp_flags = 0; + exp_data[0].fx = 0; + exp_data[1].exp_flags = 1; + exp_data[1].fx = 0xFFFFFF; + exp_data[2].exp_flags = 3; + exp_data[2].fx = 0x7FFFFF; + exp_data[3].exp_flags = 0; + exp_data[3].fx = 0; + + exp_up_model_collection = (struct collection_hdr *)exp_up_model_buf; + exp_updated_model_data = (struct s_fx *)exp_up_model_collection->entry; + /* put some dummy data in the header*/ + for (i = 0; i < sizeof(*exp_up_model_collection); i++) + exp_up_model_buf[i] = (uint8_t)i; + exp_updated_model_data[0].exp_flags = 0; + exp_updated_model_data[0].fx = 0; + exp_updated_model_data[1].exp_flags = 2; + exp_updated_model_data[1].fx = 0xBFFFFF; + exp_updated_model_data[2].exp_flags = 1; + exp_updated_model_data[2].fx = 0xBFFFFF; + exp_updated_model_data[3].exp_flags = 1; + exp_updated_model_data[3].fx = 0x7FFFFF; + + s = decompress_cmp_entiy(cmp_entity, model_buf, up_model_buf, decompressed_data); + TEST_ASSERT_EQUAL_INT(sizeof(exp_data_buf), s); + + TEST_ASSERT_FALSE(memcmp(exp_data_buf, decompressed_data, sizeof(exp_data_buf))); + TEST_ASSERT_FALSE(memcmp(exp_up_model_buf, up_model_buf, sizeof(exp_up_model_buf))); +} + + +/** + * @test cmp_ent_write_cmp_pars + * @test cmp_ent_read_header + */ + +void test_cmp_ent_write_cmp_pars(void) +{ + int error; + struct cmp_entity *ent; + struct cmp_cfg cfg = {0}, cfg_read = {0}; + int cmp_size_bits; + uint32_t size; + struct cmp_max_used_bits max_used_bits = MAX_USED_BITS_SAFE; + + /* set up max used bit version */ + max_used_bits.version = 42; + cmp_max_used_bits_list_add(&max_used_bits); + + cmp_size_bits = 93; + /** RAW mode test **/ + /* create imagette raw mode configuration */ + cfg.data_type = DATA_TYPE_IMAGETTE; + cfg.cmp_mode = CMP_MODE_RAW; + cfg.model_value = 11; + cfg.round = 2; + cfg.samples = 9; + cfg.max_used_bits = cmp_max_used_bits_list_get(42); + + /* create a compression entity */ + size = cmp_ent_create(NULL, cfg.data_type, cfg.cmp_mode == CMP_MODE_RAW, cmp_cal_size_of_data(cfg.samples, cfg.data_type)); + TEST_ASSERT_NOT_EQUAL_INT(0, size); + ent = malloc(size); TEST_ASSERT_NOT_NULL(ent); + size = cmp_ent_create(ent, cfg.data_type, cfg.cmp_mode == CMP_MODE_RAW, cmp_cal_size_of_data(cfg.samples, cfg.data_type)); + TEST_ASSERT_NOT_EQUAL_INT(0, size); + + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_FALSE(error); + + TEST_ASSERT_EQUAL_INT(cfg.data_type, cmp_ent_get_data_type(ent)); + TEST_ASSERT_EQUAL_INT(1, cmp_ent_get_data_type_raw_bit(ent)); + TEST_ASSERT_EQUAL_INT(cmp_cal_size_of_data(cfg.samples, cfg.data_type), cmp_ent_get_cmp_data_size(ent)); + + TEST_ASSERT_EQUAL_INT(cmp_cal_size_of_data(cfg.samples, cfg.data_type), cmp_ent_get_original_size(ent)); + TEST_ASSERT_EQUAL_INT(cfg.cmp_mode, cmp_ent_get_cmp_mode(ent)); + TEST_ASSERT_EQUAL_INT(cfg.model_value, cmp_ent_get_model_value(ent)); + TEST_ASSERT_EQUAL_INT(max_used_bits.version, cmp_ent_get_max_used_bits_version(ent)); + TEST_ASSERT_EQUAL_INT(cfg.round, cmp_ent_get_lossy_cmp_par(ent)); + + error = cmp_ent_read_header(ent, &cfg_read); + TEST_ASSERT_FALSE(error); + cfg.icu_output_buf = cmp_ent_get_data_buf(ent); /* quick fix that both cfg are equal */ + cfg.buffer_length = 18; /* quick fix that both cfg are equal */ + TEST_ASSERT_EQUAL_MEMORY(&cfg, &cfg_read, sizeof(struct cmp_cfg)); + + free(ent); + memset(&cfg, 0, sizeof(struct cmp_cfg)); + memset(&cfg_read, 0, sizeof(struct cmp_cfg)); + + /** imagette test **/ + /* create imagette mode configuration */ + cfg.data_type = DATA_TYPE_IMAGETTE; + cfg.cmp_mode = CMP_MODE_MODEL_ZERO; + cfg.model_value = 11; + cfg.round = 2; + cfg.samples = 9; + cfg.spill = MIN_IMA_SPILL; + cfg.golomb_par = MAX_IMA_GOLOMB_PAR; + cfg.max_used_bits = cmp_max_used_bits_list_get(42); + + /* create a compression entity */ + size = cmp_ent_create(NULL, cfg.data_type, cfg.cmp_mode == CMP_MODE_RAW, 12); + TEST_ASSERT_NOT_EQUAL_INT(0, size); + ent = malloc(size); TEST_ASSERT_NOT_NULL(ent); + size = cmp_ent_create(ent, cfg.data_type, cfg.cmp_mode == CMP_MODE_RAW, 12); + TEST_ASSERT_NOT_EQUAL_INT(0, size); + + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_FALSE(error); + + TEST_ASSERT_EQUAL_INT(cfg.data_type, cmp_ent_get_data_type(ent)); + TEST_ASSERT_EQUAL_INT(0, cmp_ent_get_data_type_raw_bit(ent)); + TEST_ASSERT_EQUAL_INT(12, cmp_ent_get_cmp_data_size(ent)); + + TEST_ASSERT_EQUAL_INT(cmp_cal_size_of_data(cfg.samples, cfg.data_type), cmp_ent_get_original_size(ent)); + TEST_ASSERT_EQUAL_INT(cfg.cmp_mode, cmp_ent_get_cmp_mode(ent)); + TEST_ASSERT_EQUAL_INT(cfg.model_value, cmp_ent_get_model_value(ent)); + TEST_ASSERT_EQUAL_INT(cfg.max_used_bits->version, cmp_ent_get_max_used_bits_version(ent)); + TEST_ASSERT_EQUAL_INT(cfg.round, cmp_ent_get_lossy_cmp_par(ent)); + + TEST_ASSERT_EQUAL_INT(cfg.spill, cmp_ent_get_ima_spill(ent)); + TEST_ASSERT_EQUAL_INT(cfg.golomb_par, cmp_ent_get_ima_golomb_par(ent)); + + error = cmp_ent_read_header(ent, &cfg_read); + TEST_ASSERT_FALSE(error); + cfg.icu_output_buf = cmp_ent_get_data_buf(ent); /* quick fix that both cfg are equal */ + cfg.buffer_length = 12; /* quick fix that both cfg are equal */ + TEST_ASSERT_EQUAL_MEMORY(&cfg, &cfg_read, sizeof(struct cmp_cfg)); + + free(ent); + memset(&cfg, 0, sizeof(struct cmp_cfg)); + memset(&cfg_read, 0, sizeof(struct cmp_cfg)); + + /** adaptive imagette test **/ + /* create a configuration */ + cfg.data_type = DATA_TYPE_IMAGETTE_ADAPTIVE; + cfg.cmp_mode = CMP_MODE_MODEL_ZERO; + cfg.model_value = 11; + cfg.round = 2; + cfg.samples = 9; + cfg.spill = MIN_IMA_SPILL; + cfg.golomb_par = MAX_IMA_GOLOMB_PAR; + cfg.ap1_spill = 555; + cfg.ap1_golomb_par = 14; + cfg.ap2_spill = 333; + cfg.ap2_golomb_par = 43; + cfg.max_used_bits = NULL; /* no max_used_bits is set */ + + /* create a compression entity */ + size = cmp_ent_create(NULL, cfg.data_type, cfg.cmp_mode == CMP_MODE_RAW, 12); + TEST_ASSERT_NOT_EQUAL_INT(0, size); + ent = malloc(size); TEST_ASSERT_NOT_NULL(ent); + size = cmp_ent_create(ent, cfg.data_type, cfg.cmp_mode == CMP_MODE_RAW, 12); + TEST_ASSERT_NOT_EQUAL_INT(0, size); + + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_FALSE(error); + + TEST_ASSERT_EQUAL_INT(cfg.data_type, cmp_ent_get_data_type(ent)); + TEST_ASSERT_EQUAL_INT(0, cmp_ent_get_data_type_raw_bit(ent)); + TEST_ASSERT_EQUAL_INT(12, cmp_ent_get_cmp_data_size(ent)); + + TEST_ASSERT_EQUAL_INT(cmp_cal_size_of_data(cfg.samples, cfg.data_type), cmp_ent_get_original_size(ent)); + TEST_ASSERT_EQUAL_INT(cfg.cmp_mode, cmp_ent_get_cmp_mode(ent)); + TEST_ASSERT_EQUAL_INT(cfg.model_value, cmp_ent_get_model_value(ent)); + /* zero is expected when max_used_bits = NULL */ + TEST_ASSERT_EQUAL_INT(0, cmp_ent_get_max_used_bits_version(ent)); + TEST_ASSERT_EQUAL_INT(cfg.round, cmp_ent_get_lossy_cmp_par(ent)); + + TEST_ASSERT_EQUAL_INT(cfg.spill, cmp_ent_get_ima_spill(ent)); + TEST_ASSERT_EQUAL_INT(cfg.golomb_par, cmp_ent_get_ima_golomb_par(ent)); + TEST_ASSERT_EQUAL_INT(cfg.ap1_spill, cmp_ent_get_ima_ap1_spill(ent)); + TEST_ASSERT_EQUAL_INT(cfg.ap1_golomb_par, cmp_ent_get_ima_ap1_golomb_par(ent)); + TEST_ASSERT_EQUAL_INT(cfg.ap2_spill, cmp_ent_get_ima_ap2_spill(ent)); + TEST_ASSERT_EQUAL_INT(cfg.ap2_golomb_par, cmp_ent_get_ima_ap2_golomb_par(ent)); + + error = cmp_ent_read_header(ent, &cfg_read); + TEST_ASSERT_FALSE(error); + cfg.icu_output_buf = cmp_ent_get_data_buf(ent); /* quick fix that both cfg are equal */ + cfg.buffer_length = 12; /* quick fix that both cfg are equal */ + cfg.max_used_bits = &MAX_USED_BITS_SAFE; + TEST_ASSERT_EQUAL_MEMORY(&cfg, &cfg_read, sizeof(struct cmp_cfg)); + + free(ent); + memset(&cfg, 0, sizeof(struct cmp_cfg)); + memset(&cfg_read, 0, sizeof(struct cmp_cfg)); + + /** flux cob data type test **/ + /* create configuration */ + cfg.data_type = DATA_TYPE_S_FX_EFX_NCOB_ECOB; + cfg.cmp_mode = CMP_MODE_MODEL_ZERO; + cfg.model_value = 11; + cfg.round = 2; + cfg.samples = 9; + cfg.spill_exp_flags = 1; + cfg.spill_fx = 2; + cfg.spill_ncob = 3; + cfg.spill_efx = 4; + cfg.spill_ecob = 5; + cfg.spill_fx_cob_variance = 6; + cfg.cmp_par_exp_flags = 7; + cfg.cmp_par_fx = 8; + cfg.cmp_par_ncob = 9; + cfg.cmp_par_efx = 10; + cfg.cmp_par_ecob = 11; + cfg.cmp_par_fx_cob_variance = 12; + cfg.max_used_bits = cmp_max_used_bits_list_get(42); + + /* create a compression entity */ + size = cmp_ent_create(NULL, cfg.data_type, cfg.cmp_mode == CMP_MODE_RAW, 12); + TEST_ASSERT_NOT_EQUAL_INT(0, size); + ent = malloc(size); TEST_ASSERT_NOT_NULL(ent); + size = cmp_ent_create(ent, cfg.data_type, cfg.cmp_mode == CMP_MODE_RAW, 12); + TEST_ASSERT_NOT_EQUAL_INT(0, size); + + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_FALSE(error); + + TEST_ASSERT_EQUAL_INT(cfg.data_type, cmp_ent_get_data_type(ent)); + TEST_ASSERT_EQUAL_INT(0, cmp_ent_get_data_type_raw_bit(ent)); + TEST_ASSERT_EQUAL_INT(12, cmp_ent_get_cmp_data_size(ent)); + + TEST_ASSERT_EQUAL_INT(cmp_cal_size_of_data(cfg.samples, cfg.data_type), cmp_ent_get_original_size(ent)); + TEST_ASSERT_EQUAL_INT(cfg.cmp_mode, cmp_ent_get_cmp_mode(ent)); + TEST_ASSERT_EQUAL_INT(cfg.model_value, cmp_ent_get_model_value(ent)); + TEST_ASSERT_EQUAL_INT(max_used_bits.version, cmp_ent_get_max_used_bits_version(ent)); + TEST_ASSERT_EQUAL_INT(cfg.round, cmp_ent_get_lossy_cmp_par(ent)); + + + TEST_ASSERT_EQUAL_INT(cfg.spill_exp_flags, cmp_ent_get_non_ima_spill1(ent)); + TEST_ASSERT_EQUAL_INT(cfg.spill_fx, cmp_ent_get_non_ima_spill2(ent)); + TEST_ASSERT_EQUAL_INT(cfg.spill_ncob, cmp_ent_get_non_ima_spill3(ent)); + TEST_ASSERT_EQUAL_INT(cfg.spill_efx, cmp_ent_get_non_ima_spill4(ent)); + TEST_ASSERT_EQUAL_INT(cfg.spill_ecob, cmp_ent_get_non_ima_spill5(ent)); + TEST_ASSERT_EQUAL_INT(cfg.spill_fx_cob_variance, cmp_ent_get_non_ima_spill6(ent)); + TEST_ASSERT_EQUAL_INT(cfg.cmp_par_exp_flags, cmp_ent_get_non_ima_cmp_par1(ent)); + TEST_ASSERT_EQUAL_INT(cfg.cmp_par_fx, cmp_ent_get_non_ima_cmp_par2(ent)); + TEST_ASSERT_EQUAL_INT(cfg.cmp_par_ncob, cmp_ent_get_non_ima_cmp_par3(ent)); + TEST_ASSERT_EQUAL_INT(cfg.cmp_par_efx, cmp_ent_get_non_ima_cmp_par4(ent)); + TEST_ASSERT_EQUAL_INT(cfg.cmp_par_ecob, cmp_ent_get_non_ima_cmp_par5(ent)); + TEST_ASSERT_EQUAL_INT(cfg.cmp_par_fx_cob_variance, cmp_ent_get_non_ima_cmp_par6(ent)); + + error = cmp_ent_read_header(ent, &cfg_read); + TEST_ASSERT_FALSE(error); + cfg.icu_output_buf = cmp_ent_get_data_buf(ent); /* quick fix that both cfg are equal */ + cfg.buffer_length = 12; /* quick fix that both cfg are equal */ + TEST_ASSERT_EQUAL_MEMORY(&cfg, &cfg_read, sizeof(struct cmp_cfg)); + + free(ent); + memset(&cfg, 0, sizeof(struct cmp_cfg)); + memset(&cfg_read, 0, sizeof(struct cmp_cfg)); + + /** auxiliary data data_type test **/ + /* create configuration */ + cfg.data_type = DATA_TYPE_SMEARING; + cfg.cmp_mode = CMP_MODE_MODEL_ZERO; + cfg.model_value = 11; + cfg.round = 2; + cfg.samples = 9; + cfg.spill_smearing_mean = 1; + cfg.spill_smearing_variance = 2; + cfg.spill_smearing_pixels_error = 3; + cfg.cmp_par_smearing_mean = 7; + cfg.cmp_par_smearing_variance = 8; + cfg.cmp_par_smearing_pixels_error = 9; + cfg.max_used_bits = cmp_max_used_bits_list_get(42); + + /* create a compression entity */ + size = cmp_ent_create(NULL, cfg.data_type, cfg.cmp_mode == CMP_MODE_RAW, 12); + TEST_ASSERT_NOT_EQUAL_INT(0, size); + ent = malloc(size); TEST_ASSERT_NOT_NULL(ent); + size = cmp_ent_create(ent, cfg.data_type, cfg.cmp_mode == CMP_MODE_RAW, 12); + TEST_ASSERT_NOT_EQUAL_INT(0, size); + + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_FALSE(error); + + TEST_ASSERT_EQUAL_INT(cfg.data_type, cmp_ent_get_data_type(ent)); + TEST_ASSERT_EQUAL_INT(0, cmp_ent_get_data_type_raw_bit(ent)); + TEST_ASSERT_EQUAL_INT(12, cmp_ent_get_cmp_data_size(ent)); + + TEST_ASSERT_EQUAL_INT(cmp_cal_size_of_data(cfg.samples, cfg.data_type), cmp_ent_get_original_size(ent)); + TEST_ASSERT_EQUAL_INT(cfg.cmp_mode, cmp_ent_get_cmp_mode(ent)); + TEST_ASSERT_EQUAL_INT(cfg.model_value, cmp_ent_get_model_value(ent)); + TEST_ASSERT_EQUAL_INT(max_used_bits.version, cmp_ent_get_max_used_bits_version(ent)); + TEST_ASSERT_EQUAL_INT(cfg.round, cmp_ent_get_lossy_cmp_par(ent)); + + + TEST_ASSERT_EQUAL_INT(0, cmp_ent_get_non_ima_spill1(ent)); + TEST_ASSERT_EQUAL_INT(0, cmp_ent_get_non_ima_spill2(ent)); + TEST_ASSERT_EQUAL_INT(0, cmp_ent_get_non_ima_spill3(ent)); + TEST_ASSERT_EQUAL_INT(cfg.spill_smearing_mean, cmp_ent_get_non_ima_spill4(ent)); + TEST_ASSERT_EQUAL_INT(cfg.spill_smearing_variance, cmp_ent_get_non_ima_spill5(ent)); + TEST_ASSERT_EQUAL_INT(cfg.spill_smearing_pixels_error, cmp_ent_get_non_ima_spill6(ent)); + TEST_ASSERT_EQUAL_INT(0, cmp_ent_get_non_ima_cmp_par1(ent)); + TEST_ASSERT_EQUAL_INT(0, cmp_ent_get_non_ima_cmp_par2(ent)); + TEST_ASSERT_EQUAL_INT(0, cmp_ent_get_non_ima_cmp_par3(ent)); + TEST_ASSERT_EQUAL_INT(cfg.cmp_par_smearing_mean, cmp_ent_get_non_ima_cmp_par4(ent)); + TEST_ASSERT_EQUAL_INT(cfg.cmp_par_smearing_variance, cmp_ent_get_non_ima_cmp_par5(ent)); + TEST_ASSERT_EQUAL_INT(cfg.cmp_par_smearing_pixels_error, cmp_ent_get_non_ima_cmp_par6(ent)); + + error = cmp_ent_read_header(ent, &cfg_read); + TEST_ASSERT_FALSE(error); + cfg.icu_output_buf = cmp_ent_get_data_buf(ent); /* quick fix that both cfg are equal */ + cfg.buffer_length = 12; /* quick fix that both cfg are equal */ + TEST_ASSERT_EQUAL_MEMORY(&cfg, &cfg_read, sizeof(struct cmp_cfg)); + + free(ent); + memset(&cfg, 0, sizeof(struct cmp_cfg)); + memset(&cfg_read, 0, sizeof(struct cmp_cfg)); + + /** Error Cases **/ + /* create imagette raw mode configuration */ + cfg.data_type = DATA_TYPE_IMAGETTE; + cfg.cmp_mode = CMP_MODE_MODEL_ZERO; + cfg.model_value = 11; + cfg.round = 2; + cfg.samples = 9; + cfg.max_used_bits = cmp_max_used_bits_list_get(42); + + /* create a compression entity */ + size = cmp_ent_create(NULL, cfg.data_type, cfg.cmp_mode == CMP_MODE_RAW, 12); + TEST_ASSERT_NOT_EQUAL_INT(0, size); + ent = malloc(size); TEST_ASSERT_NOT_NULL(ent); + size = cmp_ent_create(ent, cfg.data_type, cfg.cmp_mode == CMP_MODE_RAW, 12); + TEST_ASSERT_NOT_EQUAL_INT(0, size); + + + /* ent = NULL */ + error = cmp_ent_write_cmp_pars(NULL, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + + /* cfg = NULL */ + error = cmp_ent_write_cmp_pars(ent, NULL, cmp_size_bits); + TEST_ASSERT_TRUE(error); + + /* cmp_size_bits negative */ + error = cmp_ent_write_cmp_pars(ent, &cfg, -1); + TEST_ASSERT_TRUE(error); + + /* data_type mismatch */ + cfg.data_type = DATA_TYPE_S_FX; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.data_type = DATA_TYPE_IMAGETTE; + + /* compressed data to big for compression entity */ + error = cmp_ent_write_cmp_pars(ent, &cfg, 97); + TEST_ASSERT_TRUE(error); + + /* original_size to high */ + cfg.samples = 0x800000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.samples = 0x7FFFFF; + + /* cmp_mode to high */ + cfg.cmp_mode = 0x100; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.cmp_mode = 0xFF; + + /* max model_value to high */ + cfg.model_value = 0x100; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.model_value = 0xFF; + + /* max used bit version to high */ + TEST_ASSERT_EQUAL_INT(1, sizeof(max_used_bits.version)); + + /* max lossy_cmp_par to high */ + cfg.round = 0x10000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.round = 0xFFFF; + + /* The entity's raw data bit is not set, but the configuration contains raw data */ + cfg.cmp_mode = CMP_MODE_RAW; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.cmp_mode = CMP_MODE_MODEL_MULTI; + + /* The entity's raw data bit is set, but the configuration contains no raw data */ + cmp_ent_set_data_type(ent, cfg.data_type, 1); /* set raw bit */ + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cmp_ent_set_data_type(ent, cfg.data_type, 0); + + /* spill to high */ + cfg.spill = 0x10000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.spill = 0xFFFF; + + /* golomb_par to high */ + cfg.golomb_par = 0x100; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.golomb_par = 0xFF; + + + cmp_ent_set_data_type(ent, DATA_TYPE_SAT_IMAGETTE_ADAPTIVE, 0); + cfg.data_type = DATA_TYPE_SAT_IMAGETTE_ADAPTIVE; + cmp_size_bits = 1; + /* adaptive 1 spill to high */ + cfg.ap1_spill = 0x10000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.ap1_spill = 0xFFFF; + + /* adaptive 1 golomb_par to high */ + cfg.ap1_golomb_par = 0x100; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.ap1_golomb_par = 0xFF; + + /* adaptive 2 spill to high */ + cfg.ap2_spill = 0x10000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.ap2_spill = 0xFFFF; + + /* adaptive 2 golomb_par to high */ + cfg.ap2_golomb_par = 0x100; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.ap2_golomb_par = 0xFF; + + cmp_ent_set_data_type(ent, DATA_TYPE_OFFSET, 0); + cfg.data_type = DATA_TYPE_OFFSET; + + free(ent); + + /* create a compression entity */ + cfg.data_type = DATA_TYPE_F_CAM_BACKGROUND; + cfg.samples = 9; + size = cmp_ent_create(NULL, cfg.data_type, cfg.cmp_mode == CMP_MODE_RAW, 12); + TEST_ASSERT_NOT_EQUAL_INT(0, size); + ent = malloc(size); TEST_ASSERT_NOT_NULL(ent); + size = cmp_ent_create(ent, cfg.data_type, cfg.cmp_mode == CMP_MODE_RAW, 12); + TEST_ASSERT_NOT_EQUAL_INT(0, size); + + /* mean cmp_par to high */ + cfg.cmp_par_background_mean = 0x10000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.cmp_par_background_mean = 0xFFFF; + + /* mean spill to high */ + cfg.spill_background_mean = 0x1000000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.spill_background_mean = 0xFFFFFF; + + /* variance cmp_par to high */ + cfg.cmp_par_background_variance = 0x10000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.cmp_par_background_variance = 0xFFFF; + + /* variance spill to high */ + cfg.spill_background_variance = 0x1000000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.spill_background_variance = 0xFFFFFF; + + /* pixels_error cmp_par to high */ + cfg.cmp_par_background_pixels_error = 0x10000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.cmp_par_background_pixels_error = 0xFFFF; + + /* pixels_error spill to high */ + cfg.spill_background_pixels_error = 0x1000000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.spill_background_pixels_error = 0xFFFFFF; + + + cmp_ent_set_data_type(ent, DATA_TYPE_F_FX_EFX_NCOB_ECOB, 0); + cfg.data_type = DATA_TYPE_F_FX_EFX_NCOB_ECOB; + + /* exp_flags cmp_par to high */ + cfg.cmp_par_exp_flags = 0x10000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.cmp_par_exp_flags = 0xFFFF; + + /* exp_flags spill to high */ + cfg.spill_exp_flags = 0x1000000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.spill_exp_flags = 0xFFFFFF; + + /* fx cmp_par to high */ + cfg.cmp_par_fx = 0x10000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.cmp_par_fx = 0xFFFF; + + /* fx spill to high */ + cfg.spill_fx = 0x1000000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.spill_fx = 0xFFFFFF; + + /* ncob cmp_par to high */ + cfg.cmp_par_ncob = 0x10000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.cmp_par_ncob = 0xFFFF; + + /* ncob spill to high */ + cfg.spill_ncob = 0x1000000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.spill_ncob = 0xFFFFFF; + + /* efx cmp_par to high */ + cfg.cmp_par_efx = 0x10000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.cmp_par_efx = 0xFFFF; + + /* efx spill to high */ + cfg.spill_efx = 0x1000000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.spill_efx = 0xFFFFFF; + + /* ecob cmp_par to high */ + cfg.cmp_par_ecob = 0x10000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.cmp_par_ecob = 0xFFFF; + + /* ecob spill to high */ + cfg.spill_ecob = 0x1000000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.spill_ecob = 0xFFFFFF; + + /* fx_cob_variance cmp_par to high */ + cfg.cmp_par_fx_cob_variance = 0x10000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.cmp_par_fx_cob_variance = 0xFFFF; + + /* fx_cob_variance spill to high */ + cfg.spill_fx_cob_variance = 0x1000000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.spill_fx_cob_variance = 0xFFFFFF; + + /* test data type = DATA_TYPE_UNKNOWN */ + cmp_ent_set_data_type(ent, DATA_TYPE_UNKNOWN, 0); + cfg.data_type = DATA_TYPE_UNKNOWN; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + + /* test data type = DATA_TYPE_F_CAM_BACKGROUND +1 */ + cmp_ent_set_data_type(ent, DATA_TYPE_F_CAM_BACKGROUND + 1, 0); + cfg.data_type = DATA_TYPE_F_CAM_BACKGROUND + 1; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + free(ent); + cmp_max_used_bits_list_empty(); +} + + +/** + * @test cmp_ent_read_header + */ + +void test_cmp_ent_read_header_error_cases(void) +{ + int error; + uint32_t size; + struct cmp_entity *ent; + struct cmp_cfg cfg; + int cmp_size_bits = 10*8; + + /* create a imagette entity */ + size = cmp_ent_create(NULL, DATA_TYPE_IMAGETTE, 0, 10); + /* created size smaller than max entity size -> returns max entity size */ + TEST_ASSERT_EQUAL_UINT32(sizeof(struct cmp_entity), size); + ent = malloc(size); TEST_ASSERT_NOT_NULL(ent); + size = cmp_ent_create(ent, DATA_TYPE_IMAGETTE, 0, 10); + TEST_ASSERT_EQUAL_UINT32(sizeof(struct cmp_entity), size); + error = cmp_ent_set_cmp_mode(ent, CMP_MODE_DIFF_ZERO); + TEST_ASSERT_FALSE(error); + + /* ent = NULL */ + error = cmp_ent_read_header(NULL, &cfg); + TEST_ASSERT_TRUE(error); + /* this should work */ + error = cmp_ent_read_header(ent, &cfg); + TEST_ASSERT_FALSE(error); + + /* cfg = NULL */ + error = cmp_ent_read_header(ent, NULL); + TEST_ASSERT_TRUE(error); + /* this should work */ + error = cmp_ent_read_header(ent, &cfg); + TEST_ASSERT_FALSE(error); + + /* unknown data type */ + cmp_ent_set_data_type(ent, DATA_TYPE_UNKNOWN, 0); + error = cmp_ent_read_header(ent, &cfg); + TEST_ASSERT_TRUE(error); + cmp_ent_set_data_type(ent, (enum cmp_data_type)1000, 0); + error = cmp_ent_read_header(ent, &cfg); + TEST_ASSERT_TRUE(error); + /* unknown data type */ + cmp_ent_set_data_type(ent, DATA_TYPE_F_CAM_BACKGROUND+1, 0); + error = cmp_ent_read_header(ent, &cfg); + TEST_ASSERT_TRUE(error); + /* this should work */ + cmp_ent_set_data_type(ent, DATA_TYPE_IMAGETTE, 0); + error = cmp_ent_read_header(ent, &cfg); + TEST_ASSERT_FALSE(error); + + /* original_size and data product type not compatible */ + cmp_ent_set_original_size(ent, 11); + error = cmp_ent_read_header(ent, &cfg); + TEST_ASSERT_TRUE(error); + + /* this should work */ + cmp_ent_set_original_size(ent, 12); + error = cmp_ent_read_header(ent, &cfg); + TEST_ASSERT_FALSE(error); + + + /* create a raw entity */ + size = cmp_ent_create(ent, DATA_TYPE_IMAGETTE, 1, 10); + TEST_ASSERT_NOT_EQUAL_INT(0, size); + + /* mean cmp_par to high */ + cfg.cmp_par_background_mean = 0x10000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.cmp_par_background_mean = 0xFFFF; + + /* mean spill to high */ + cfg.spill_background_mean = 0x1000000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.spill_background_mean = 0xFFFFFF; + + /* variance cmp_par to high */ + cfg.cmp_par_background_variance = 0x10000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.cmp_par_background_variance = 0xFFFF; + + /* variance spill to high */ + cfg.spill_background_variance = 0x1000000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.spill_background_variance = 0xFFFFFF; + + /* pixels_error cmp_par to high */ + cfg.cmp_par_background_pixels_error = 0x10000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.cmp_par_background_pixels_error = 0xFFFF; + + /* pixels_error spill to high */ + cfg.spill_background_pixels_error = 0x1000000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.spill_background_pixels_error = 0xFFFFFF; + + + cmp_ent_set_data_type(ent, DATA_TYPE_F_FX_EFX_NCOB_ECOB, 0); + cfg.data_type = DATA_TYPE_F_FX_EFX_NCOB_ECOB; + + /* exp_flags cmp_par to high */ + cfg.cmp_par_exp_flags = 0x10000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.cmp_par_exp_flags = 0xFFFF; + + /* exp_flags spill to high */ + cfg.spill_exp_flags = 0x1000000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.spill_exp_flags = 0xFFFFFF; + + /* fx cmp_par to high */ + cfg.cmp_par_fx = 0x10000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.cmp_par_fx = 0xFFFF; + + /* fx spill to high */ + cfg.spill_fx = 0x1000000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.spill_fx = 0xFFFFFF; + + /* ncob cmp_par to high */ + cfg.cmp_par_ncob = 0x10000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.cmp_par_ncob = 0xFFFF; + + /* ncob spill to high */ + cfg.spill_ncob = 0x1000000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.spill_ncob = 0xFFFFFF; + + /* efx cmp_par to high */ + cfg.cmp_par_efx = 0x10000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.cmp_par_efx = 0xFFFF; + + /* efx spill to high */ + cfg.spill_efx = 0x1000000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.spill_efx = 0xFFFFFF; + + /* ecob cmp_par to high */ + cfg.cmp_par_ecob = 0x10000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.cmp_par_ecob = 0xFFFF; + + /* ecob spill to high */ + cfg.spill_ecob = 0x1000000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.spill_ecob = 0xFFFFFF; + + /* fx_cob_variance cmp_par to high */ + cfg.cmp_par_fx_cob_variance = 0x10000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.cmp_par_fx_cob_variance = 0xFFFF; + + /* fx_cob_variance spill to high */ + cfg.spill_fx_cob_variance = 0x1000000; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + cfg.spill_fx_cob_variance = 0xFFFFFF; + + /* test data type = DATA_TYPE_UNKNOWN */ + cmp_ent_set_data_type(ent, DATA_TYPE_UNKNOWN, 0); + cfg.data_type = DATA_TYPE_UNKNOWN; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + + /* test data type = DATA_TYPE_F_CAM_BACKGROUND +1 */ + cmp_ent_set_data_type(ent, DATA_TYPE_F_CAM_BACKGROUND + 1, 0); + cfg.data_type = DATA_TYPE_F_CAM_BACKGROUND + 1; + error = cmp_ent_write_cmp_pars(ent, &cfg, cmp_size_bits); + TEST_ASSERT_TRUE(error); + free(ent); + ent = NULL; + cmp_max_used_bits_list_empty(); + + + /* create a imagette entity */ + size = cmp_ent_create(NULL, DATA_TYPE_IMAGETTE, 1, 10); + ent = malloc(size); TEST_ASSERT_NOT_NULL(ent); + size = cmp_ent_create(ent, DATA_TYPE_IMAGETTE, 1, 10); + TEST_ASSERT_NOT_EQUAL_INT(0, size); + cmp_ent_set_cmp_mode(ent, CMP_MODE_RAW); + cmp_ent_set_original_size(ent, 10); + + /* this should work */ + error = cmp_ent_read_header(ent, &cfg); + TEST_ASSERT_FALSE(error); + + /* cmp_mode CMP_MODE_RAW and no raw data bit */ + cmp_ent_set_data_type(ent, DATA_TYPE_IMAGETTE, 0); + error = cmp_ent_read_header(ent, &cfg); + TEST_ASSERT_TRUE(error); + + /* this should work */ + cmp_ent_set_data_type(ent, DATA_TYPE_IMAGETTE, 1); + error = cmp_ent_read_header(ent, &cfg); + TEST_ASSERT_FALSE(error); + + /* cmp_mode CMP_MODE_RAW cmp_data_size != original_size */ + cmp_ent_set_data_type(ent, DATA_TYPE_IMAGETTE, 0); + cmp_ent_set_original_size(ent, 8); + error = cmp_ent_read_header(ent, &cfg); + TEST_ASSERT_TRUE(error); + + free(ent); +} + + +void test_decompression_error_cases(void) +{ + /* TODO: error cases model decompression without a model Buffer */ + /* TODO: error cases wrong cmp parameter; model value; usw */ +} diff --git a/test/meson.build b/test/meson.build index db573585b6d5af10af9eccca4e1f056d75db6054..63da2db81129ecc31764b1bd5faf24b609fa0a2a 100644 --- a/test/meson.build +++ b/test/meson.build @@ -8,7 +8,8 @@ if checkpatch.found() '--ignore', 'SPDX_LICENSE_TAG,PREFER_DEFINED_ATTRIBUTE_MACRO,EMBEDDED_FILENAME,BLOCK_COMMENT_STYLE,EMBEDDED_FUNCTION_NAME', ] run_target('syntax-check', - command : [checkpatch, checkpatch_args, main, cmplib_sources]) + command : [checkpatch, checkpatch_args, main, common_sources, decompress_sources, + icu_compress_sources, rdcu_compress_sources]) endif # add cppcheck inspector target @@ -33,6 +34,8 @@ subdir('cmp_tool') unity_dep = dependency('unity', fallback : ['unity', 'unity_dep']) +subdir('test_common') +subdir('decmp') subdir('cmp_icu') subdir('cmp_decmp') subdir('cmp_data_types') diff --git a/test/test_common/meson.build b/test/test_common/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..56d233028906f36724e4d138c6ab98ceb218794a --- /dev/null +++ b/test/test_common/meson.build @@ -0,0 +1,8 @@ +pcg_proj = subproject('pcg-c-basic') +pcb_dep = pcg_proj.get_variable('libpcg_basic_dep') + +test_common_lib = static_library( + 'test_common', + 'test_common.c', + dependencies: pcb_dep, +) diff --git a/test/test_common/test_common.c b/test/test_common/test_common.c new file mode 100644 index 0000000000000000000000000000000000000000..37644a7f07c820cad0552069460cf8b48e400b89 --- /dev/null +++ b/test/test_common/test_common.c @@ -0,0 +1,41 @@ +#include <assert.h> + +#include "pcg_basic.h" + + +void cmp_rand_seed(uint64_t seed) +{ + pcg32_srandom(seed, 0); +} + + +uint32_t cmp_rand32(void) +{ + return pcg32_random(); +} + + +/** + * @brief generate a random number + * + * @param min minimum value (inclusive) + * @param max maximum value (inclusive) + * + * @returns "random" numbers in the range [M, N] + * + */ + +uint32_t cmp_rand_between(uint32_t min, uint32_t max) +{ + assert(min < max); + + return min + pcg32_boundedrand(max-min+1); +} + + +uint32_t cmp_rand_nbits(unsigned int nbits) +{ + assert(nbits > 0); + + return cmp_rand32() >> (32 - nbits); +} diff --git a/test/test_common/test_common.h b/test/test_common/test_common.h new file mode 100644 index 0000000000000000000000000000000000000000..f0fd84aea743cf4d2f6b3239949977c61b472943 --- /dev/null +++ b/test/test_common/test_common.h @@ -0,0 +1,14 @@ +#ifndef TEST_COMMON_H +#define TEST_COMMON_H + +#include <stdint.h> + +void cmp_rand_seed(uint64_t seed); + +uint32_t cmp_rand32(void); + +uint32_t cmp_rand_between(uint32_t min, uint32_t max); + +uint32_t cmp_rand_nbits(unsigned int nbits); + +#endif /* TEST_COMMON_H */ diff --git a/test/tools/meson.build b/test/tools/meson.build index 9c9f43761c09cd2f58813ca4513f9e99a6e4a3e9..194699721da7140cdb8383a92a726faf58559135 100644 --- a/test/tools/meson.build +++ b/test/tools/meson.build @@ -15,6 +15,6 @@ if checkpatch.found() '--ignore', 'SPDX_LICENSE_TAG,PREFER_DEFINED_ATTRIBUTE_MACRO,EMBEDDED_FILENAME,BLOCK_COMMENT_STYLE,EMBEDDED_FUNCTION_NAME', ] run_target('syntax-check', - command : [checkpatch, checkpatch_args, main, cmplib_sources]) + command : [checkpatch, checkpatch_args, cmp_tool_src, common_sources, decompress_sources, icu_compress_sources, rdcu_compress_sources]) endif