#include "hdf5_stub.h"
#include <stdlib.h>
#include <assert.h>
#include "ebcc_codec.h"
#include "log.h"
#define H5Z_FILTER_EBCC 308
static size_t H5Z_filter_ebcc(unsigned int flags, size_t cd_nelmts, const unsigned int cd_values[], size_t nbytes, size_t *buf_size, void **buf);
const H5Z_class2_t H5Z_EBCC[1] = {{
H5Z_CLASS_T_VERS,
(H5Z_filter_t) H5Z_FILTER_EBCC,
1,
1,
"HDF5 EBCC filter L&L",
NULL,
NULL,
(H5Z_func_t) H5Z_filter_ebcc,
}};
H5PL_type_t H5PLget_plugin_type(void) { return H5PL_TYPE_FILTER; }
const void *H5PLget_plugin_info(void) { return H5Z_EBCC; }
float uint_ptr_to_float(const unsigned int *ptr) {
return *((float *) ptr);
}
float uint_ptr_to_double(const unsigned int *ptr) {
return *((double *) ptr);
}
void populate_config(codec_config_t *config, size_t cd_nelmts, const unsigned int cd_values[], size_t buf_size) {
config->dims[0] = buf_size / sizeof(float);
if (config->dims[0] < cd_values[0] * cd_values[1]) {
log_fatal("Buffer size %lu is smaller than the tile size %lu x %lu = %lu", config->dims[0], cd_values[0], cd_values[1], cd_values[0] * cd_values[1]);
exit(1);
}
if (config->dims[0] % (cd_values[0] * cd_values[1]) != 0) {
log_fatal("Buffer size %lu is not divisible by the tile size %lu x %lu = %lu", config->dims[0], cd_values[0], cd_values[1], cd_values[0] * cd_values[1]);
exit(1);
}
if (cd_values[0] < 32 || cd_values[1] < 32) {
log_fatal("Tile size %lu x %lu is too small, must be at least 32 x 32", cd_values[0], cd_values[1]);
exit(1);
}
for (size_t i = 0; i < 2; ++i) {
size_t cur = cd_values[i];
config->dims[0] /= cur;
config->dims[i + 1] = cur;
}
config->base_cr = uint_ptr_to_float(&cd_values[2]);
config->residual_compression_type = (residual_t) cd_values[3];
switch (config->residual_compression_type) {
case NONE:
assert(cd_nelmts == 4);
break;
case MAX_ERROR:
case RELATIVE_ERROR:
assert(cd_nelmts == 5);
config->error = uint_ptr_to_float(&cd_values[4]);
break;
}
}
static size_t H5Z_filter_ebcc(unsigned int flags, size_t cd_nelmts, const unsigned int cd_values[], size_t nbytes, size_t *buf_size, void **buf) {
if (flags & H5Z_FLAG_REVERSE) {
float *out_buffer = NULL;
*buf_size = ebcc_decode(*buf, nbytes, &out_buffer);
free_buffer(*buf);
*buf = out_buffer;
return *buf_size;
} else {
codec_config_t config;
populate_config(&config, cd_nelmts, cd_values, *buf_size);
uint8_t *out_buffer = NULL;
*buf_size = ebcc_encode(*buf, &config, &out_buffer);
free_buffer(*buf);
*buf = out_buffer;
return *buf_size;
}
}