in libvmaf/src/feature/cambi.c [342:456]
static int init(VmafFeatureExtractor *fex, enum VmafPixelFormat pix_fmt,
unsigned bpc, unsigned w, unsigned h) {
(void)pix_fmt;
CambiState *s = fex->priv;
if (s->enc_bitdepth == 0) {
s->enc_bitdepth = bpc;
}
if (s->enc_width == 0 || s->enc_height == 0) {
s->enc_width = w;
s->enc_height = h;
}
if (s->src_width == 0 || s->src_height == 0) {
s->src_width = w;
s->src_height = h;
}
if (s->enc_width < CAMBI_MIN_WIDTH_HEIGHT && s->enc_height < CAMBI_MIN_WIDTH_HEIGHT) {
return -EINVAL;
}
if (s->src_width < CAMBI_MIN_WIDTH_HEIGHT && s->src_height < CAMBI_MIN_WIDTH_HEIGHT) {
return -EINVAL;
}
if (s->src_width > s->enc_width && s->src_height < s->enc_height) {
return -EINVAL;
}
if (s->src_width < s->enc_width && s->src_height > s->enc_height) {
return -EINVAL;
}
int alloc_w = s->full_ref ? MAX(s->src_width, s->enc_width) : s->enc_width;
int alloc_h = s->full_ref ? MAX(s->src_height, s->enc_height) : s->enc_height;
int err = 0;
for (unsigned i = 0; i < PICS_BUFFER_SIZE; i++) {
err |= vmaf_picture_alloc(&s->pics[i], VMAF_PIX_FMT_YUV400P, 10, alloc_w, alloc_h);
}
if (err) return err;
const int num_diffs = 1 << s->max_log_contrast;
set_contrast_arrays(num_diffs, &s->buffers.diffs_to_consider, &s->buffers.diff_weights, &s->buffers.all_diffs);
VmafLumaRange luma_range;
err = vmaf_luminance_init_luma_range(&luma_range, 10, VMAF_PIXEL_RANGE_LIMITED);
if (err) return err;
VmafEOTF eotf;
err = vmaf_luminance_init_eotf(&eotf, s->eotf);
if (err) return err;
s->buffers.tvi_for_diff = aligned_malloc(ALIGN_CEIL(sizeof(uint16_t)) * num_diffs, 16);
if (!s->buffers.tvi_for_diff) return -ENOMEM;
for (int d = 0; d < num_diffs; d++) {
s->buffers.tvi_for_diff[d] = get_tvi_for_diff(s->buffers.diffs_to_consider[d], s->tvi_threshold, 10, luma_range, eotf);
s->buffers.tvi_for_diff[d] += num_diffs;
}
s->src_window_size = s->window_size;
adjust_window_size(&s->window_size, s->enc_width, s->enc_height);
adjust_window_size(&s->src_window_size, s->src_width, s->src_height);
s->buffers.c_values = aligned_malloc(ALIGN_CEIL(alloc_w * sizeof(float)) * alloc_h, 32);
if (!s->buffers.c_values) return -ENOMEM;
const uint16_t num_bins = 1024 + (s->buffers.all_diffs[2 * num_diffs] - s->buffers.all_diffs[0]);
s->buffers.c_values_histograms = aligned_malloc(ALIGN_CEIL(alloc_w * num_bins * sizeof(uint16_t)), 32);
if (!s->buffers.c_values_histograms) return -ENOMEM;
int pad_size = MASK_FILTER_SIZE >> 1;
int dp_width = alloc_w + 2 * pad_size + 1;
int dp_height = 2 * pad_size + 2;
s->buffers.mask_dp = aligned_malloc(ALIGN_CEIL(dp_height * dp_width * sizeof(uint32_t)), 32);
if (!s->buffers.mask_dp) return -ENOMEM;
s->buffers.filter_mode_buffer = aligned_malloc(ALIGN_CEIL(3 * alloc_w * sizeof(uint16_t)), 32);
if (!s->buffers.filter_mode_buffer) return -ENOMEM;
s->buffers.derivative_buffer = aligned_malloc(ALIGN_CEIL(alloc_w * sizeof(uint16_t)), 32);
if (!s->buffers.derivative_buffer) return -ENOMEM;
if (s->heatmaps_path) {
int err = mkdirp(s->heatmaps_path, 0770);
if (err) return -EINVAL;
char path[1024] = { 0 };
int scaled_w = s->enc_width;
int scaled_h = s->enc_height;
for (int scale = 0; scale < NUM_SCALES; scale++) {
snprintf(path, sizeof(path), "%s%ccambi_heatmap_scale_%d_%dx%d_16b.gray",
s->heatmaps_path, PATH_SEPARATOR, scale, scaled_w, scaled_h);
s->heatmaps_files[scale] = fopen(path, "w");
if (!s->heatmaps_files[scale]) {
vmaf_log(VMAF_LOG_LEVEL_ERROR,
"cambi: could not open heatmaps_path: %s\n", path);
return -EINVAL;
}
scaled_w = (scaled_w + 1) >> 1;
scaled_h = (scaled_h + 1) >> 1;
}
}
s->inc_range_callback = increment_range;
s->dec_range_callback = decrement_range;
s->derivative_callback = get_derivative_data_for_row;
#if ARCH_X86
unsigned flags = vmaf_get_cpu_flags();
if (flags & VMAF_X86_CPU_FLAG_AVX2) {
s->inc_range_callback = cambi_increment_range_avx2;
s->dec_range_callback = cambi_decrement_range_avx2;
s->derivative_callback = get_derivative_data_for_row_avx2;
}
#endif
return err;
}