/** * @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" #include "common/cmp_error_list.h" /* valid specific compression parameter ranges for chunk compression * (every parameter except cmp_mode, model_value, lossy_par) */ #define MIN_CHUNK_CMP_PAR 1U #define MAX_CHUNK_CMP_PAR UINT16_MAX /* the compression entity does not allow larger values */ #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 to compress * @param chunk_size size of the chunk in bytes * * @returns maximum compressed size for a chunk compression on success or an * error code if it fails (which can be tested with cmp_is_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 application software version identifier */ 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 rounded down * to a multiple of 4 * @returns the byte size of the compressed data or an error code if it * fails (which can be tested with cmp_is_error()) */ uint32_t compress_chunk(const void *chunk, uint32_t chunk_size, const 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 the byte size of the dst buffer (= dst_size) on success or an error * code if it fails (which can be tested with cmp_is_error()) */ uint32_t compress_chunk_set_model_id_and_counter(void *dst, uint32_t dst_size, uint16_t model_id, uint8_t model_counter); /** * @brief tells if a result is an error code * * @param code return value to check * * @returns non-zero if the code is an error */ unsigned int cmp_is_error(uint32_t code); /** * @brief provides a readable string from a compression return value (useful for debugging) * * @param code compression return value to describe * * @returns a pointer to a string literal that describes the error code. */ const char* cmp_get_error_name(uint32_t code); /** * @brief convert a function result into a cmp_error enum * * @param code compression return value to get the error code * * @returns error code */ enum cmp_error cmp_get_error_code(uint32_t code); /** * @brief get a string describing an error code * * @param code the error code to describe, obtain with cmp_get_error_code() * * @returns a pointer to a string literal that describes the error code. */ const char* cmp_get_error_string(enum cmp_error code); #endif /* CMP_CHUNK_H */