Select Git revision
decmp.c 67.13 KiB
/**
* @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 <stdlib.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_entity.h"
#define MAX_CW_LEN 32 /* maximum Golomb code word bit length */
/* maximum used bits registry */
extern struct cmp_max_used_bits max_used_bits;
/* function pointer to a code word decoder function */
typedef int (*decoder_ptr)(unsigned int, unsigned int, unsigned int, unsigned int *);
/* 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,
unsigned int *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(unsigned int code_word, unsigned int m,
unsigned int log2_m, unsigned int *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)
{
const unsigned int *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, 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, max_used_bits.s_exp_flags, cfg))
return -1;
if (configure_decoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
cfg->round, 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, max_used_bits.s_exp_flags, cfg))
return -1;
if (configure_decoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
cfg->round, max_used_bits.s_fx, cfg))
return -1;
if (configure_decoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx,
cfg->round, 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, max_used_bits.s_exp_flags, cfg))
return -1;
if (configure_decoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
cfg->round, max_used_bits.s_fx, cfg))
return -1;
if (configure_decoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob,
cfg->round, 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, max_used_bits.s_exp_flags, cfg))
return -1;
if (configure_decoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
cfg->round, max_used_bits.s_fx, cfg))
return -1;
if (configure_decoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob,
cfg->round, max_used_bits.s_ncob, cfg))
return -1;
if (configure_decoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx,
cfg->round, max_used_bits.s_efx, cfg))
return -1;
if (configure_decoder_setup(&setup_ecob, cfg->cmp_par_ecob, cfg->spill_ecob,
cfg->round, 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, 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, max_used_bits.f_fx, cfg))
return -1;
if (configure_decoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx,
cfg->round, 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, max_used_bits.f_fx, cfg))
return -1;
if (configure_decoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob,
cfg->round, 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, max_used_bits.f_fx, cfg))
return -1;
if (configure_decoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob,
cfg->round, max_used_bits.f_ncob, cfg))
return -1;
if (configure_decoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx,
cfg->round, max_used_bits.f_efx, cfg))
return -1;
if (configure_decoder_setup(&setup_ecob, cfg->cmp_par_ecob, cfg->spill_ecob,
cfg->round, 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, max_used_bits.l_exp_flags, cfg))
return -1;
if (configure_decoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
cfg->round, 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, 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, max_used_bits.l_exp_flags, cfg))
return -1;
if (configure_decoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
cfg->round, max_used_bits.l_fx, cfg))
return -1;
if (configure_decoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx,
cfg->round, 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, 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, max_used_bits.l_exp_flags, cfg))
return -1;
if (configure_decoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
cfg->round, max_used_bits.l_fx, cfg))
return -1;
if (configure_decoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob,
cfg->round, 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, 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, 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, max_used_bits.l_exp_flags, cfg))
return -1;
if (configure_decoder_setup(&setup_fx, cfg->cmp_par_fx, cfg->spill_fx,
cfg->round, max_used_bits.l_fx, cfg))
return -1;
if (configure_decoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob,
cfg->round, max_used_bits.l_ncob, cfg))
return -1;
if (configure_decoder_setup(&setup_efx, cfg->cmp_par_efx, cfg->spill_efx,
cfg->round, max_used_bits.l_efx, cfg))
return -1;
if (configure_decoder_setup(&setup_ecob, cfg->cmp_par_ecob, cfg->spill_ecob,
cfg->round, 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, 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, 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, max_used_bits.nc_offset_mean, cfg))
return -1;
if (configure_decoder_setup(&setup_var, cfg->cmp_par_variance, cfg->spill_variance,
cfg->round, 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, max_used_bits.nc_background_mean, cfg))
return -1;
if (configure_decoder_setup(&setup_var, cfg->cmp_par_variance, cfg->spill_variance,
cfg->round, 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, 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, max_used_bits.smearing_mean, cfg))
return -1;
if (configure_decoder_setup(&setup_var, cfg->cmp_par_variance, cfg->spill_variance,
cfg->round, 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, 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
*/
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;
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 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 updated_model 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 model_of_data pointer to model data buffer (can be NULL if no
* model compression mode is used)
* @param updated_model 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);
return decompressed_data_internal(&cfg);
}