in libvmaf/src/feature/adm.c [71:292]
int compute_adm(const float *ref, const float *dis, int w, int h, int ref_stride, int dis_stride, double *score,
double *score_num, double *score_den, double *scores, double border_factor, double adm_enhn_gain_limit,
double adm_norm_view_dist, int adm_ref_display_height, int adm_csf_mode)
{
#ifdef ADM_OPT_SINGLE_PRECISION
double numden_limit = 1e-2 * (w * h) / (1920.0 * 1080.0);
#else
double numden_limit = 1e-10 * (w * h) / (1920.0 * 1080.0);
#endif
float *data_buf = 0;
char *data_top;
char *ind_buf_y = 0, *buf_y_orig = 0;
char *ind_buf_x = 0, *buf_x_orig = 0;
int *ind_y[4], *ind_x[4];
float *ref_scale;
float *dis_scale;
adm_dwt_band_t ref_dwt2;
adm_dwt_band_t dis_dwt2;
adm_dwt_band_t decouple_r;
adm_dwt_band_t decouple_a;
adm_dwt_band_t csf_a;
adm_dwt_band_t csf_f; //Store filtered coeffs
const float *curr_ref_scale = ref;
const float *curr_dis_scale = dis;
int curr_ref_stride = ref_stride;
int curr_dis_stride = dis_stride;
int orig_h = h;
int buf_stride = ALIGN_CEIL(((w + 1) / 2) * sizeof(float));
size_t buf_sz_one = (size_t)buf_stride * ((h + 1) / 2);
int ind_size_y = ALIGN_CEIL(((h + 1) / 2) * sizeof(int));
int ind_size_x = ALIGN_CEIL(((w + 1) / 2) * sizeof(int));
double num = 0;
double den = 0;
int scale;
int ret = 1;
// Code optimized to save on multiple buffer copies
// hence the reduction in the number of buffers required from 35 to 17
#define NUM_BUFS_ADM 20
if (SIZE_MAX / buf_sz_one < NUM_BUFS_ADM)
{
printf("error: SIZE_MAX / buf_sz_one < NUM_BUFS_ADM, buf_sz_one = %zu.\n", buf_sz_one);
fflush(stdout);
goto fail;
}
if (!(data_buf = aligned_malloc(buf_sz_one * NUM_BUFS_ADM, MAX_ALIGN)))
{
printf("error: aligned_malloc failed for data_buf.\n");
fflush(stdout);
goto fail;
}
data_top = (char *)data_buf;
data_top = init_dwt_band(&ref_dwt2, data_top, buf_sz_one);
data_top = init_dwt_band(&dis_dwt2, data_top, buf_sz_one);
data_top = init_dwt_band_hvd(&decouple_r, data_top, buf_sz_one);
data_top = init_dwt_band_hvd(&decouple_a, data_top, buf_sz_one);
data_top = init_dwt_band_hvd(&csf_a, data_top, buf_sz_one);
data_top = init_dwt_band_hvd(&csf_f, data_top, buf_sz_one);
if (!(buf_y_orig = aligned_malloc(ind_size_y * 4, MAX_ALIGN)))
{
printf("error: aligned_malloc failed for ind_buf_y.\n");
fflush(stdout);
goto fail;
}
ind_buf_y = buf_y_orig;
ind_y[0] = (int*)ind_buf_y; ind_buf_y += ind_size_y;
ind_y[1] = (int*)ind_buf_y; ind_buf_y += ind_size_y;
ind_y[2] = (int*)ind_buf_y; ind_buf_y += ind_size_y;
ind_y[3] = (int*)ind_buf_y; ind_buf_y += ind_size_y;
if (!(buf_x_orig = aligned_malloc(ind_size_x * 4, MAX_ALIGN)))
{
printf("error: aligned_malloc failed for ind_buf_x.\n");
fflush(stdout);
goto fail;
}
ind_buf_x = buf_x_orig;
ind_x[0] = (int*)ind_buf_x; ind_buf_x += ind_size_x;
ind_x[1] = (int*)ind_buf_x; ind_buf_x += ind_size_x;
ind_x[2] = (int*)ind_buf_x; ind_buf_x += ind_size_x;
ind_x[3] = (int*)ind_buf_x; ind_buf_x += ind_size_x;
for (scale = 0; scale < 4; ++scale) {
#ifdef ADM_OPT_DEBUG_DUMP
char pathbuf[256];
#endif
float num_scale = 0.0;
float den_scale = 0.0;
dwt2_src_indices_filt(ind_y, ind_x, w, h);
adm_dwt2(curr_ref_scale, &ref_dwt2, ind_y, ind_x, w, h, curr_ref_stride, buf_stride);
adm_dwt2(curr_dis_scale, &dis_dwt2, ind_y, ind_x, w, h, curr_dis_stride, buf_stride);
w = (w + 1) / 2;
h = (h + 1) / 2;
adm_decouple(&ref_dwt2, &dis_dwt2, &decouple_r, &decouple_a, w, h,
buf_stride, buf_stride, buf_stride, buf_stride, border_factor, adm_enhn_gain_limit);
den_scale = adm_csf_den_scale(&ref_dwt2, orig_h, scale, w, h,
buf_stride, border_factor,
adm_norm_view_dist, adm_ref_display_height, adm_csf_mode);
adm_csf(&decouple_a, &csf_a, &csf_f, orig_h, scale, w, h, buf_stride,
buf_stride, border_factor,
adm_norm_view_dist, adm_ref_display_height, adm_csf_mode);
num_scale = adm_cm(&decouple_r, &csf_f, &csf_a, w, h, buf_stride,
buf_stride, buf_stride, border_factor, scale,
adm_norm_view_dist, adm_ref_display_height, adm_csf_mode);
#ifdef ADM_OPT_DEBUG_DUMP
sprintf(pathbuf, "stage/ref[%d]_a.yuv", scale);
write_image(pathbuf, ref_dwt2.band_a, w, h, buf_stride, sizeof(float));
sprintf(pathbuf, "stage/ref[%d]_h.yuv", scale);
write_image(pathbuf, ref_dwt2.band_h, w, h, buf_stride, sizeof(float));
sprintf(pathbuf, "stage/ref[%d]_v.yuv", scale);
write_image(pathbuf, ref_dwt2.band_v, w, h, buf_stride, sizeof(float));
sprintf(pathbuf, "stage/ref[%d]_d.yuv", scale);
write_image(pathbuf, ref_dwt2.band_d, w, h, buf_stride, sizeof(float));
sprintf(pathbuf, "stage/dis[%d]_a.yuv", scale);
write_image(pathbuf, dis_dwt2.band_a, w, h, buf_stride, sizeof(float));
sprintf(pathbuf, "stage/dis[%d]_h.yuv", scale);
write_image(pathbuf, dis_dwt2.band_h, w, h, buf_stride, sizeof(float));
sprintf(pathbuf, "stage/dis[%d]_v.yuv", scale);
write_image(pathbuf, dis_dwt2.band_v, w, h, buf_stride, sizeof(float));
sprintf(pathbuf, "stage/dis[%d]_d.yuv", scale);
write_image(pathbuf, dis_dwt2.band_d, w, h, buf_stride, sizeof(float));
sprintf(pathbuf, "stage/r[%d]_h.yuv", scale);
write_image(pathbuf, decouple_r.band_h, w, h, buf_stride, sizeof(float));
sprintf(pathbuf, "stage/r[%d]_v.yuv", scale);
write_image(pathbuf, decouple_r.band_v, w, h, buf_stride, sizeof(float));
sprintf(pathbuf, "stage/r[%d]_d.yuv", scale);
write_image(pathbuf, decouple_r.band_d, w, h, buf_stride, sizeof(float));
sprintf(pathbuf, "stage/a[%d]_h.yuv", scale);
write_image(pathbuf, decouple_a.band_h, w, h, buf_stride, sizeof(float));
sprintf(pathbuf, "stage/a[%d]_v.yuv", scale);
write_image(pathbuf, decouple_a.band_v, w, h, buf_stride, sizeof(float));
sprintf(pathbuf, "stage/a[%d]_d.yuv", scale);
write_image(pathbuf, decouple_a.band_d, w, h, buf_stride, sizeof(float));
sprintf(pathbuf, "stage/csf_a[%d]_h.yuv", scale);
write_image(pathbuf, csf_a.band_h, w, h, buf_stride, sizeof(float));
sprintf(pathbuf, "stage/csf_a[%d]_v.yuv", scale);
write_image(pathbuf, csf_a.band_v, w, h, buf_stride, sizeof(float));
sprintf(pathbuf, "stage/csf_a[%d]_d.yuv", scale);
write_image(pathbuf, csf_a.band_d, w, h, buf_stride, sizeof(float));
#endif
num += num_scale;
den += den_scale;
ref_scale = ref_dwt2.band_a;
dis_scale = dis_dwt2.band_a;
curr_ref_scale = ref_scale;
curr_dis_scale = dis_scale;
curr_ref_stride = buf_stride;
curr_dis_stride = buf_stride;
#ifdef ADM_OPT_DEBUG_DUMP
PRINTF("num: %f\n", num);
PRINTF("den: %f\n", den);
#endif
scores[2 * scale + 0] = num_scale;
scores[2 * scale + 1] = den_scale;
}
num = num < numden_limit ? 0 : num;
den = den < numden_limit ? 0 : den;
if (den == 0.0)
{
*score = 1.0f;
}
else
{
*score = num / den;
}
*score_num = num;
*score_den = den;
ret = 0;
fail:
aligned_free(data_buf);
aligned_free(buf_y_orig);
aligned_free(buf_x_orig);
return ret;
}